summaryrefslogtreecommitdiffstats
path: root/src/test/ui/const-generics/issues/issue-83765.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/ui/const-generics/issues/issue-83765.rs')
-rw-r--r--src/test/ui/const-generics/issues/issue-83765.rs116
1 files changed, 116 insertions, 0 deletions
diff --git a/src/test/ui/const-generics/issues/issue-83765.rs b/src/test/ui/const-generics/issues/issue-83765.rs
new file mode 100644
index 000000000..71c164ab0
--- /dev/null
+++ b/src/test/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."));
+}