fold instead of obliterating args

This commit is contained in:
Boxy 2022-12-12 14:28:08 +00:00
parent 37d7de3379
commit dd19656df3
3 changed files with 67 additions and 15 deletions

View file

@ -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 })
}

View file

@ -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
}

View file

@ -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`.