Rollup merge of #99618 - compiler-errors:uhh-idk, r=lcnr
handle consts with param/infer in `const_eval_resolve` better This PR addresses [this thread here](https://github.com/rust-lang/rust/pull/99449#discussion_r924141230). Was this the change you were looking for ``@lcnr?`` Interestingly, one test has begun to pass. Was that expected? r? ``@lcnr``
This commit is contained in:
commit
a39c00ee8d
@ -21,7 +21,7 @@
|
|||||||
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind, ToType};
|
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind, ToType};
|
||||||
use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult};
|
use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult};
|
||||||
use rustc_middle::traits::select;
|
use rustc_middle::traits::select;
|
||||||
use rustc_middle::ty::abstract_const::AbstractConst;
|
use rustc_middle::ty::abstract_const::{AbstractConst, FailureKind};
|
||||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||||
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
|
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
|
||||||
use rustc_middle::ty::relate::RelateResult;
|
use rustc_middle::ty::relate::RelateResult;
|
||||||
@ -1675,7 +1675,7 @@ pub fn try_const_eval_resolve(
|
|||||||
#[instrument(skip(self), level = "debug")]
|
#[instrument(skip(self), level = "debug")]
|
||||||
pub fn const_eval_resolve(
|
pub fn const_eval_resolve(
|
||||||
&self,
|
&self,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
mut param_env: ty::ParamEnv<'tcx>,
|
||||||
unevaluated: ty::Unevaluated<'tcx>,
|
unevaluated: ty::Unevaluated<'tcx>,
|
||||||
span: Option<Span>,
|
span: Option<Span>,
|
||||||
) -> EvalToValTreeResult<'tcx> {
|
) -> EvalToValTreeResult<'tcx> {
|
||||||
@ -1686,10 +1686,19 @@ pub fn const_eval_resolve(
|
|||||||
// variables
|
// variables
|
||||||
if substs.has_infer_types_or_consts() {
|
if substs.has_infer_types_or_consts() {
|
||||||
let ac = AbstractConst::new(self.tcx, unevaluated.shrink());
|
let ac = AbstractConst::new(self.tcx, unevaluated.shrink());
|
||||||
if let Ok(None) = ac {
|
match ac {
|
||||||
substs = InternalSubsts::identity_for_item(self.tcx, unevaluated.def.did);
|
Ok(None) => {
|
||||||
} else {
|
substs = InternalSubsts::identity_for_item(self.tcx, unevaluated.def.did);
|
||||||
return Err(ErrorHandled::TooGeneric);
|
param_env = self.tcx.param_env(unevaluated.def.did);
|
||||||
|
}
|
||||||
|
Ok(Some(ct)) => {
|
||||||
|
if ct.unify_failure_kind(self.tcx) == FailureKind::Concrete {
|
||||||
|
substs = replace_param_and_infer_substs_with_placeholder(self.tcx, substs);
|
||||||
|
} else {
|
||||||
|
return Err(ErrorHandled::TooGeneric);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(guar) => return Err(ErrorHandled::Reported(guar)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2000,3 +2009,43 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Replaces substs that reference param or infer variables with suitable
|
||||||
|
/// placeholders. This function is meant to remove these param and infer
|
||||||
|
/// substs when they're not actually needed to evaluate a constant.
|
||||||
|
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_param_types_or_consts() || arg.has_infer_types_or_consts() =>
|
||||||
|
{
|
||||||
|
tcx.mk_ty(ty::Placeholder(ty::PlaceholderType {
|
||||||
|
universe: ty::UniverseIndex::ROOT,
|
||||||
|
name: ty::BoundVar::from_usize(idx),
|
||||||
|
}))
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
GenericArgKind::Const(ct)
|
||||||
|
if ct.has_infer_types_or_consts() || ct.has_param_types_or_consts() =>
|
||||||
|
{
|
||||||
|
let ty = ct.ty();
|
||||||
|
// If the type references param or infer, replace that too...
|
||||||
|
if ty.has_param_types_or_consts() || ty.has_infer_types_or_consts() {
|
||||||
|
bug!("const `{ct}`'s type should not reference params or types");
|
||||||
|
}
|
||||||
|
tcx.mk_const(ty::ConstS {
|
||||||
|
ty,
|
||||||
|
kind: ty::ConstKind::Placeholder(ty::PlaceholderConst {
|
||||||
|
universe: ty::UniverseIndex::ROOT,
|
||||||
|
name: ty::BoundConst { ty, var: ty::BoundVar::from_usize(idx) },
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
_ => arg,
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
@ -185,21 +185,12 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
|
|||||||
}
|
}
|
||||||
let concrete = infcx.const_eval_resolve(param_env, uv.expand(), Some(span));
|
let concrete = infcx.const_eval_resolve(param_env, uv.expand(), Some(span));
|
||||||
match concrete {
|
match concrete {
|
||||||
Err(ErrorHandled::TooGeneric) => Err(if uv.has_infer_types_or_consts() {
|
Err(ErrorHandled::TooGeneric) => {
|
||||||
NotConstEvaluatable::MentionsInfer
|
Err(NotConstEvaluatable::Error(infcx.tcx.sess.delay_span_bug(
|
||||||
} else if uv.has_param_types_or_consts() {
|
|
||||||
infcx
|
|
||||||
.tcx
|
|
||||||
.sess
|
|
||||||
.delay_span_bug(span, &format!("unexpected `TooGeneric` for {:?}", uv));
|
|
||||||
NotConstEvaluatable::MentionsParam
|
|
||||||
} else {
|
|
||||||
let guar = infcx.tcx.sess.delay_span_bug(
|
|
||||||
span,
|
span,
|
||||||
format!("Missing value for constant, but no error reported?"),
|
format!("Missing value for constant, but no error reported?"),
|
||||||
);
|
)))
|
||||||
NotConstEvaluatable::Error(guar)
|
}
|
||||||
}),
|
|
||||||
Err(ErrorHandled::Linted) => {
|
Err(ErrorHandled::Linted) => {
|
||||||
let reported = infcx
|
let reported = infcx
|
||||||
.tcx
|
.tcx
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
// check-pass
|
||||||
|
|
||||||
#![feature(generic_const_exprs)]
|
#![feature(generic_const_exprs)]
|
||||||
#![allow(incomplete_features)]
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
@ -21,11 +23,6 @@ fn foo<T, const N: usize>(_: T) -> <() as Foo<{ N + 1 }>>::Assoc
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// FIXME(generic_const_exprs): We can't correctly infer `T` which requires
|
|
||||||
// evaluating `{ N + 1 }` which has substs containing an inference var
|
|
||||||
let mut _q = Default::default();
|
let mut _q = Default::default();
|
||||||
//~^ ERROR type annotations needed
|
|
||||||
|
|
||||||
_q = foo::<_, 2>(_q);
|
_q = foo::<_, 2>(_q);
|
||||||
//~^ ERROR type annotations needed
|
|
||||||
}
|
}
|
||||||
|
@ -1,38 +0,0 @@
|
|||||||
error[E0282]: type annotations needed
|
|
||||||
--> $DIR/const_eval_resolve_canonical.rs:26:9
|
|
||||||
|
|
|
||||||
LL | let mut _q = Default::default();
|
|
||||||
| ^^^^^^
|
|
||||||
|
|
|
||||||
help: consider giving `_q` an explicit type
|
|
||||||
|
|
|
||||||
LL | let mut _q: _ = Default::default();
|
|
||||||
| +++
|
|
||||||
|
|
||||||
error[E0283]: type annotations needed
|
|
||||||
--> $DIR/const_eval_resolve_canonical.rs:29:10
|
|
||||||
|
|
|
||||||
LL | _q = foo::<_, 2>(_q);
|
|
||||||
| ^^^^^^^^^^^ cannot infer the value of the constant `{ N + 1 }`
|
|
||||||
|
|
|
||||||
note: multiple `impl`s satisfying `(): Foo<{ N + 1 }>` found
|
|
||||||
--> $DIR/const_eval_resolve_canonical.rs:8:1
|
|
||||||
|
|
|
||||||
LL | impl Foo<0> for () {
|
|
||||||
| ^^^^^^^^^^^^^^^^^^
|
|
||||||
...
|
|
||||||
LL | impl Foo<3> for () {
|
|
||||||
| ^^^^^^^^^^^^^^^^^^
|
|
||||||
note: required by a bound in `foo`
|
|
||||||
--> $DIR/const_eval_resolve_canonical.rs:18:9
|
|
||||||
|
|
|
||||||
LL | fn foo<T, const N: usize>(_: T) -> <() as Foo<{ N + 1 }>>::Assoc
|
|
||||||
| --- required by a bound in this
|
|
||||||
LL | where
|
|
||||||
LL | (): Foo<{ N + 1 }>,
|
|
||||||
| ^^^^^^^^^^^^^^ required by this bound in `foo`
|
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
|
||||||
|
|
||||||
Some errors have detailed explanations: E0282, E0283.
|
|
||||||
For more information about an error, try `rustc --explain E0282`.
|
|
Loading…
Reference in New Issue
Block a user