diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 2ce7cd8beba98..996148a709087 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 0000000000000..e28ba3b1adab6 --- /dev/null +++ b/src/test/ui/const-generics/generic_const_exprs/issue-105608.rs @@ -0,0 +1,15 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +struct Combination; + +impl Combination { + fn and(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 0000000000000..0be4c43daacf8 --- /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`.