about summary refs log tree commit diff
path: root/tests/ui/const-generics/issues/issue-83765.rs
diff options
context:
space:
mode:
Diffstat (limited to 'tests/ui/const-generics/issues/issue-83765.rs')
-rw-r--r--tests/ui/const-generics/issues/issue-83765.rs116
1 files changed, 116 insertions, 0 deletions
diff --git a/tests/ui/const-generics/issues/issue-83765.rs b/tests/ui/const-generics/issues/issue-83765.rs
new file mode 100644
index 00000000000..71c164ab0a5
--- /dev/null
+++ b/tests/ui/const-generics/issues/issue-83765.rs
@@ -0,0 +1,116 @@
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+trait TensorDimension {
+    const DIM: usize;
+    //~^ ERROR cycle detected when resolving instance
+    // FIXME Given the current state of the compiler its expected that we cycle here,
+    // but the cycle is still wrong.
+    const ISSCALAR: bool = Self::DIM == 0;
+    fn is_scalar(&self) -> bool {
+        Self::ISSCALAR
+    }
+}
+
+trait TensorSize: TensorDimension {
+    fn size(&self) -> [usize; Self::DIM];
+    fn inbounds(&self, index: [usize; Self::DIM]) -> bool {
+        index.iter().zip(self.size().iter()).all(|(i, s)| i < s)
+    }
+}
+
+trait Broadcastable: TensorSize + Sized {
+    type Element;
+    fn bget(&self, index: [usize; Self::DIM]) -> Option<Self::Element>;
+    fn lazy_updim<const NEWDIM: usize>(
+        &self,
+        size: [usize; NEWDIM],
+    ) -> LazyUpdim<Self, { Self::DIM }, NEWDIM> {
+        assert!(
+            NEWDIM >= Self::DIM,
+            "Updimmed tensor cannot have fewer indices than the initial one."
+        );
+        LazyUpdim { size, reference: &self }
+    }
+    fn bmap<T, F: Fn(Self::Element) -> T>(&self, foo: F) -> BMap<T, Self, F, { Self::DIM }> {
+        BMap { reference: self, closure: foo }
+    }
+}
+
+struct LazyUpdim<'a, T: Broadcastable, const OLDDIM: usize, const DIM: usize> {
+    size: [usize; DIM],
+    reference: &'a T,
+}
+
+impl<'a, T: Broadcastable, const DIM: usize> TensorDimension for LazyUpdim<'a, T, { T::DIM }, DIM> {
+    const DIM: usize = DIM;
+}
+
+impl<'a, T: Broadcastable, const DIM: usize> TensorSize for LazyUpdim<'a, T, { T::DIM }, DIM> {
+    fn size(&self) -> [usize; DIM] {
+        self.size
+    }
+}
+
+impl<'a, T: Broadcastable, const DIM: usize> Broadcastable for LazyUpdim<'a, T, { T::DIM }, DIM> {
+    type Element = T::Element;
+    fn bget(&self, index: [usize; DIM]) -> Option<Self::Element> {
+        assert!(DIM >= T::DIM);
+        if !self.inbounds(index) {
+            return None;
+        }
+        let size = self.size();
+        let newindex: [usize; T::DIM] = Default::default();
+        self.reference.bget(newindex)
+    }
+}
+
+struct BMap<'a, R, T: Broadcastable, F: Fn(T::Element) -> R, const DIM: usize> {
+    reference: &'a T,
+    closure: F,
+}
+
+impl<'a, R, T: Broadcastable, F: Fn(T::Element) -> R, const DIM: usize> TensorDimension
+    for BMap<'a, R, T, F, DIM>
+{
+    const DIM: usize = DIM;
+}
+impl<'a, R, T: Broadcastable, F: Fn(T::Element) -> R, const DIM: usize> TensorSize
+    for BMap<'a, R, T, F, DIM>
+{
+    fn size(&self) -> [usize; DIM] {
+        self.reference.size()
+    }
+}
+
+impl<'a, R, T: Broadcastable, F: Fn(T::Element) -> R, const DIM: usize> Broadcastable
+    for BMap<'a, R, T, F, DIM>
+{
+    type Element = R;
+    fn bget(&self, index: [usize; DIM]) -> Option<Self::Element> {
+        self.reference.bget(index).map(&self.closure)
+    }
+}
+
+impl<T> TensorDimension for Vec<T> {
+    const DIM: usize = 1;
+}
+impl<T> TensorSize for Vec<T> {
+    fn size(&self) -> [usize; 1] {
+        [self.len()]
+    }
+}
+impl<T: Clone> Broadcastable for Vec<T> {
+    type Element = T;
+    fn bget(&self, index: [usize; 1]) -> Option<T> {
+        self.get(index[0]).cloned()
+    }
+}
+
+fn main() {
+    let v = vec![1, 2, 3];
+    let bv = v.lazy_updim([3, 4]);
+    let bbv = bv.bmap(|x| x * x);
+
+    println!("The size of v is {:?}", bbv.bget([0, 2]).expect("Out of bounds."));
+}