Skip to content

Commit b3ed7cc

Browse files
committed
fix gce typing_mode mismatch
1 parent 7db7489 commit b3ed7cc

File tree

3 files changed

+130
-58
lines changed

3 files changed

+130
-58
lines changed

compiler/rustc_trait_selection/src/traits/mod.rs

+66-58
Original file line numberDiff line numberDiff line change
@@ -551,69 +551,77 @@ pub fn try_evaluate_const<'tcx>(
551551
| ty::ConstKind::Placeholder(_)
552552
| ty::ConstKind::Expr(_) => Err(EvaluateConstErr::HasGenericsOrInfers),
553553
ty::ConstKind::Unevaluated(uv) => {
554-
// Postpone evaluation of constants that depend on generic parameters or inference variables.
555-
let (args, param_env) = if tcx.features().generic_const_exprs()
556-
&& uv.has_non_region_infer()
557-
{
558-
// `feature(generic_const_exprs)` causes anon consts to inherit all parent generics. This can cause
559-
// inference variables and generic parameters to show up in `ty::Const` even though the anon const
560-
// does not actually make use of them. We handle this case specially and attempt to evaluate anyway.
561-
match tcx.thir_abstract_const(uv.def) {
562-
Ok(Some(ct)) => {
563-
let ct = tcx.expand_abstract_consts(ct.instantiate(tcx, uv.args));
564-
if let Err(e) = ct.error_reported() {
565-
return Err(EvaluateConstErr::EvaluationFailure(e));
566-
} else if ct.has_non_region_infer() || ct.has_non_region_param() {
567-
// If the anon const *does* actually use generic parameters or inference variables from
568-
// the generic arguments provided for it, then we should *not* attempt to evaluate it.
569-
return Err(EvaluateConstErr::HasGenericsOrInfers);
570-
} else {
571-
(replace_param_and_infer_args_with_placeholder(tcx, uv.args), param_env)
572-
}
573-
}
574-
Err(_) | Ok(None) => {
575-
let args = GenericArgs::identity_for_item(tcx, uv.def);
576-
let param_env = tcx.param_env(uv.def);
577-
(args, param_env)
578-
}
579-
}
580-
} else if tcx.def_kind(uv.def) == DefKind::AnonConst && uv.has_non_region_infer() {
581-
// FIXME: remove this when `const_evaluatable_unchecked` is a hard error.
582-
//
583-
// Diagnostics will sometimes replace the identity args of anon consts in
584-
// array repeat expr counts with inference variables so we have to handle this
585-
// even though it is not something we should ever actually encounter.
586-
//
587-
// Array repeat expr counts are allowed to syntactically use generic parameters
588-
// but must not actually depend on them in order to evalaute succesfully. This means
589-
// that it is actually fine to evalaute them in their own environment rather than with
590-
// the actually provided generic arguments.
591-
tcx.dcx().delayed_bug(
592-
"Encountered anon const with inference variable args but no error reported",
593-
);
594-
595-
let args = GenericArgs::identity_for_item(tcx, uv.def);
596-
let param_env = tcx.param_env(uv.def);
597-
(args, param_env)
598-
} else {
599-
// FIXME: This codepath is reachable under `associated_const_equality` and in the
600-
// future will be reachable by `min_generic_const_args`. We should handle inference
601-
// variables and generic parameters properly instead of doing nothing.
602-
(uv.args, param_env)
603-
};
604-
let uv = ty::UnevaluatedConst::new(uv.def, args);
605-
606-
// It's not *technically* correct to be revealing opaque types here as borrowcheck has
607-
// not run yet. However, CTFE itself uses `TypingMode::PostAnalysis` unconditionally even
608-
// during typeck and not doing so has a lot of (undesirable) fallout (#101478, #119821).
554+
// Postpone evaluation of constants that depend on generic parameters or
555+
// inference variables.
556+
//
557+
// We use `TypingMode::PostAnalysis` here which is not *technically* correct
558+
// to be revealing opaque types here as borrowcheck has not run yet. However,
559+
// CTFE itself uses `TypingMode::PostAnalysis` unconditionally even during
560+
// typeck and not doing so has a lot of (undesirable) fallout (#101478, #119821).
609561
// As a result we always use a revealed env when resolving the instance to evaluate.
610562
//
611563
// FIXME: `const_eval_resolve_for_typeck` should probably just modify the env itself
612564
// instead of having this logic here
613-
let typing_env =
614-
tcx.erase_regions(infcx.typing_env(param_env)).with_post_analysis_normalized(tcx);
615-
let erased_uv = tcx.erase_regions(uv);
565+
let (args, typing_env) =
566+
if tcx.features().generic_const_exprs() && uv.has_non_region_infer() {
567+
// `feature(generic_const_exprs)` causes anon consts to inherit all parent generics. This can cause
568+
// inference variables and generic parameters to show up in `ty::Const` even though the anon const
569+
// does not actually make use of them. We handle this case specially and attempt to evaluate anyway.
570+
match tcx.thir_abstract_const(uv.def) {
571+
Ok(Some(ct)) => {
572+
let ct = tcx.expand_abstract_consts(ct.instantiate(tcx, uv.args));
573+
if let Err(e) = ct.error_reported() {
574+
return Err(EvaluateConstErr::EvaluationFailure(e));
575+
} else if ct.has_non_region_infer() || ct.has_non_region_param() {
576+
// If the anon const *does* actually use generic parameters or inference variables from
577+
// the generic arguments provided for it, then we should *not* attempt to evaluate it.
578+
return Err(EvaluateConstErr::HasGenericsOrInfers);
579+
} else {
580+
let typing_env = infcx
581+
.typing_env(tcx.erase_regions(param_env))
582+
.with_post_analysis_normalized(tcx);
583+
(
584+
replace_param_and_infer_args_with_placeholder(tcx, uv.args),
585+
typing_env,
586+
)
587+
}
588+
}
589+
Err(_) | Ok(None) => {
590+
let args = GenericArgs::identity_for_item(tcx, uv.def);
591+
let typing_env = ty::TypingEnv::post_analysis(tcx, uv.def);
592+
(args, typing_env)
593+
}
594+
}
595+
} else if tcx.def_kind(uv.def) == DefKind::AnonConst && uv.has_non_region_infer() {
596+
// FIXME: remove this when `const_evaluatable_unchecked` is a hard error.
597+
//
598+
// Diagnostics will sometimes replace the identity args of anon consts in
599+
// array repeat expr counts with inference variables so we have to handle this
600+
// even though it is not something we should ever actually encounter.
601+
//
602+
// Array repeat expr counts are allowed to syntactically use generic parameters
603+
// but must not actually depend on them in order to evalaute succesfully. This means
604+
// that it is actually fine to evalaute them in their own environment rather than with
605+
// the actually provided generic arguments.
606+
tcx.dcx().delayed_bug(
607+
"Encountered anon const with inference variable args but no error reported",
608+
);
616609

610+
let args = GenericArgs::identity_for_item(tcx, uv.def);
611+
let typing_env = ty::TypingEnv::post_analysis(tcx, uv.def);
612+
(args, typing_env)
613+
} else {
614+
// FIXME: This codepath is reachable under `associated_const_equality` and in the
615+
// future will be reachable by `min_generic_const_args`. We should handle inference
616+
// variables and generic parameters properly instead of doing nothing.
617+
let typing_env = infcx
618+
.typing_env(tcx.erase_regions(param_env))
619+
.with_post_analysis_normalized(tcx);
620+
(uv.args, typing_env)
621+
};
622+
let uv = ty::UnevaluatedConst::new(uv.def, args);
623+
624+
let erased_uv = tcx.erase_regions(uv);
617625
use rustc_middle::mir::interpret::ErrorHandled;
618626
match tcx.const_eval_resolve_for_typeck(typing_env, erased_uv, DUMMY_SP) {
619627
Ok(Ok(val)) => Ok(ty::Const::new_value(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Regression test for #133271.
2+
#![feature(generic_const_exprs)]
3+
//~^ WARN the feature `generic_const_exprs` is incomplete
4+
5+
struct Foo;
6+
impl<'a, const NUM: usize> std::ops::Add<&'a Foo> for Foo
7+
//~^ ERROR the const parameter `NUM` is not constrained by the impl trait, self type, or predicates
8+
where
9+
[(); 1 + 0]: Sized,
10+
{
11+
fn unimplemented(self, _: &Foo) -> Self::Output {
12+
//~^ ERROR method `unimplemented` is not a member of trait `std::ops::Add`
13+
//~| ERROR type annotations needed
14+
loop {}
15+
}
16+
}
17+
18+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
error[E0407]: method `unimplemented` is not a member of trait `std::ops::Add`
2+
--> $DIR/post-analysis-user-facing-param-env.rs:11:5
3+
|
4+
LL | / fn unimplemented(self, _: &Foo) -> Self::Output {
5+
LL | |
6+
LL | |
7+
LL | | loop {}
8+
LL | | }
9+
| |_____^ not a member of trait `std::ops::Add`
10+
11+
warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
12+
--> $DIR/post-analysis-user-facing-param-env.rs:2:12
13+
|
14+
LL | #![feature(generic_const_exprs)]
15+
| ^^^^^^^^^^^^^^^^^^^
16+
|
17+
= note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
18+
= note: `#[warn(incomplete_features)]` on by default
19+
20+
error[E0207]: the const parameter `NUM` is not constrained by the impl trait, self type, or predicates
21+
--> $DIR/post-analysis-user-facing-param-env.rs:6:10
22+
|
23+
LL | impl<'a, const NUM: usize> std::ops::Add<&'a Foo> for Foo
24+
| ^^^^^^^^^^^^^^^^ unconstrained const parameter
25+
|
26+
= note: expressions using a const parameter must map each value to a distinct output value
27+
= note: proving the result of expressions other than the parameter are unique is not supported
28+
29+
error[E0284]: type annotations needed
30+
--> $DIR/post-analysis-user-facing-param-env.rs:11:40
31+
|
32+
LL | fn unimplemented(self, _: &Foo) -> Self::Output {
33+
| ^^^^^^^^^^^^ cannot infer the value of const parameter `NUM`
34+
|
35+
note: required for `Foo` to implement `Add<&'a Foo>`
36+
--> $DIR/post-analysis-user-facing-param-env.rs:6:28
37+
|
38+
LL | impl<'a, const NUM: usize> std::ops::Add<&'a Foo> for Foo
39+
| ---------------- ^^^^^^^^^^^^^^^^^^^^^^ ^^^
40+
| |
41+
| unsatisfied trait bound introduced here
42+
43+
error: aborting due to 3 previous errors; 1 warning emitted
44+
45+
Some errors have detailed explanations: E0207, E0284, E0407.
46+
For more information about an error, try `rustc --explain E0207`.

0 commit comments

Comments
 (0)