Rollup merge of #105611 - BoxyUwU:more_granular_placeholderification, r=wesleywiser
fold instead of obliterating args Fixes #105608 we call `const_eval_resolve` on the following constant: ``` def: playground::{impl#0}::and::{constant#0}, substs: [ ConstKind::Unevaluated { def: playground::{impl#0}::and::{constant#0}, substs: [ ConstKind::Value(0x0), _, ] } _, ], ``` when expanded out to `ConstKind::Expr` there are no infer vars so we attempt to evaluate it after replacing infer vars with garbage, however the current logic for replacing with garbage replaces _the whole arg containing the infer var_ rather than just the infer var. This means that after garbage replacement has occured we attempt to evaluate: ``` def: playground::{impl#0}::and::{constant#0}, substs: [ PLACEHOLDER, PLACEHOLDER, ], ``` Which then leads to ctfe being unable to evaluate the const. With this PR we attempt to evaluate: ``` def: playground::{impl#0}::and::{constant#0}, substs: [ ConstKind::Unevaluated { def: playground::{impl#0}::and::{constant#0}, substs: [ ConstKind::Value(0x0), PLACEHOLDER, ] } PLACEHOLDER, ], ``` which ctfe _can_ handle. I am not entirely sure why this function is supposed to replace params with placeholders rather than just inference vars 🤔
This commit is contained in:
commit
01469693de
3 changed files with 67 additions and 15 deletions
|
@ -2014,31 +2014,54 @@ fn replace_param_and_infer_substs_with_placeholder<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
substs: SubstsRef<'tcx>,
|
substs: SubstsRef<'tcx>,
|
||||||
) -> SubstsRef<'tcx> {
|
) -> SubstsRef<'tcx> {
|
||||||
tcx.mk_substs(substs.iter().enumerate().map(|(idx, arg)| {
|
struct ReplaceParamAndInferWithPlaceholder<'tcx> {
|
||||||
match arg.unpack() {
|
tcx: TyCtxt<'tcx>,
|
||||||
GenericArgKind::Type(_) if arg.has_non_region_param() || arg.has_non_region_infer() => {
|
idx: usize,
|
||||||
tcx.mk_ty(ty::Placeholder(ty::PlaceholderType {
|
}
|
||||||
|
|
||||||
|
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,
|
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() {
|
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 {
|
ty::PlaceholderConst {
|
||||||
universe: ty::UniverseIndex::ROOT,
|
universe: ty::UniverseIndex::ROOT,
|
||||||
name: ty::BoundVar::from_usize(idx),
|
name: ty::BoundVar::from_usize({
|
||||||
|
let idx = self.idx;
|
||||||
|
self.idx += 1;
|
||||||
|
idx
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
ty,
|
ty,
|
||||||
)
|
)
|
||||||
.into()
|
} else {
|
||||||
|
c.super_fold_with(self)
|
||||||
}
|
}
|
||||||
_ => arg,
|
|
||||||
}
|
}
|
||||||
}))
|
}
|
||||||
|
|
||||||
|
substs.fold_with(&mut ReplaceParamAndInferWithPlaceholder { tcx, idx: 0 })
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
#![feature(generic_const_exprs)]
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
|
@ -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`.
|
Loading…
Add table
Add a link
Reference in a new issue