about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs53
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/issue-105608.rs15
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/issue-105608.stderr14
3 files changed, 67 insertions, 15 deletions
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 2ce7cd8beba..996148a7090 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -2014,31 +2014,54 @@ fn replace_param_and_infer_substs_with_placeholder<'tcx>(
     tcx: TyCtxt<'tcx>,
     substs: SubstsRef<'tcx>,
 ) -> SubstsRef<'tcx> {
-    tcx.mk_substs(substs.iter().enumerate().map(|(idx, arg)| {
-        match arg.unpack() {
-            GenericArgKind::Type(_) if arg.has_non_region_param() || arg.has_non_region_infer() => {
-                tcx.mk_ty(ty::Placeholder(ty::PlaceholderType {
+    struct ReplaceParamAndInferWithPlaceholder<'tcx> {
+        tcx: TyCtxt<'tcx>,
+        idx: usize,
+    }
+
+    impl<'tcx> TypeFolder<'tcx> for ReplaceParamAndInferWithPlaceholder<'tcx> {
+        fn tcx(&self) -> TyCtxt<'tcx> {
+            self.tcx
+        }
+
+        fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
+            if let ty::Infer(_) = t.kind() {
+                self.tcx.mk_ty(ty::Placeholder(ty::PlaceholderType {
                     universe: ty::UniverseIndex::ROOT,
-                    name: ty::BoundVar::from_usize(idx),
+                    name: ty::BoundVar::from_usize({
+                        let idx = self.idx;
+                        self.idx += 1;
+                        idx
+                    }),
                 }))
-                .into()
+            } else {
+                t.super_fold_with(self)
             }
-            GenericArgKind::Const(ct) if ct.has_non_region_infer() || ct.has_non_region_param() => {
-                let ty = ct.ty();
-                // If the type references param or infer, replace that too...
+        }
+
+        fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> {
+            if let ty::ConstKind::Infer(_) = c.kind() {
+                let ty = c.ty();
+                // If the type references param or infer then ICE ICE ICE
                 if ty.has_non_region_param() || ty.has_non_region_infer() {
-                    bug!("const `{ct}`'s type should not reference params or types");
+                    bug!("const `{c}`'s type should not reference params or types");
                 }
-                tcx.mk_const(
+                self.tcx.mk_const(
                     ty::PlaceholderConst {
                         universe: ty::UniverseIndex::ROOT,
-                        name: ty::BoundVar::from_usize(idx),
+                        name: ty::BoundVar::from_usize({
+                            let idx = self.idx;
+                            self.idx += 1;
+                            idx
+                        }),
                     },
                     ty,
                 )
-                .into()
+            } else {
+                c.super_fold_with(self)
             }
-            _ => arg,
         }
-    }))
+    }
+
+    substs.fold_with(&mut ReplaceParamAndInferWithPlaceholder { tcx, idx: 0 })
 }
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-105608.rs b/src/test/ui/const-generics/generic_const_exprs/issue-105608.rs
new file mode 100644
index 00000000000..4c85abd5c1e
--- /dev/null
+++ b/src/test/ui/const-generics/generic_const_exprs/issue-105608.rs
@@ -0,0 +1,15 @@
+#![allow(incomplete_features, unstable_features)]
+#![feature(generic_const_exprs)]
+
+struct Combination<const STRATEGIES: usize>;
+
+impl<const STRATEGIES: usize> Combination<STRATEGIES> {
+    fn and<M>(self) -> Combination<{ STRATEGIES + 1 }> {
+        Combination
+    }
+}
+
+pub fn main() {
+    Combination::<0>.and::<_>().and::<_>();
+    //~^ ERROR: type annotations needed
+}
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-105608.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-105608.stderr
new file mode 100644
index 00000000000..0be4c43daac
--- /dev/null
+++ b/src/test/ui/const-generics/generic_const_exprs/issue-105608.stderr
@@ -0,0 +1,14 @@
+error[E0282]: type annotations needed
+  --> $DIR/issue-105608.rs:13:22
+   |
+LL |     Combination::<0>.and::<_>().and::<_>();
+   |                      ^^^ cannot infer type of the type parameter `M` declared on the associated function `and`
+   |
+help: consider specifying the generic argument
+   |
+LL |     Combination::<0>.and::<_>().and::<_>();
+   |                         ~~~~~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.