Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gce: fix typing_mode mismatch #133471

Merged
merged 1 commit into from
Nov 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 25 additions & 18 deletions compiler/rustc_trait_selection/src/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -551,8 +551,18 @@ pub fn try_evaluate_const<'tcx>(
| ty::ConstKind::Placeholder(_)
| ty::ConstKind::Expr(_) => Err(EvaluateConstErr::HasGenericsOrInfers),
ty::ConstKind::Unevaluated(uv) => {
// Postpone evaluation of constants that depend on generic parameters or inference variables.
let (args, param_env) = if tcx.features().generic_const_exprs()
// Postpone evaluation of constants that depend on generic parameters or
// inference variables.
//
// We use `TypingMode::PostAnalysis` here which is not *technically* correct
// to be revealing opaque types here as borrowcheck has not run yet. However,
// CTFE itself uses `TypingMode::PostAnalysis` unconditionally even during
// typeck and not doing so has a lot of (undesirable) fallout (#101478, #119821).
// As a result we always use a revealed env when resolving the instance to evaluate.
//
// FIXME: `const_eval_resolve_for_typeck` should probably just modify the env itself
// instead of having this logic here
let (args, typing_env) = if tcx.features().generic_const_exprs()
&& uv.has_non_region_infer()
{
// `feature(generic_const_exprs)` causes anon consts to inherit all parent generics. This can cause
Expand All @@ -568,13 +578,17 @@ pub fn try_evaluate_const<'tcx>(
// the generic arguments provided for it, then we should *not* attempt to evaluate it.
return Err(EvaluateConstErr::HasGenericsOrInfers);
} else {
(replace_param_and_infer_args_with_placeholder(tcx, uv.args), param_env)
let args = replace_param_and_infer_args_with_placeholder(tcx, uv.args);
let typing_env = infcx
.typing_env(tcx.erase_regions(param_env))
.with_post_analysis_normalized(tcx);
(args, typing_env)
}
}
Err(_) | Ok(None) => {
let args = GenericArgs::identity_for_item(tcx, uv.def);
let param_env = tcx.param_env(uv.def);
(args, param_env)
let typing_env = ty::TypingEnv::post_analysis(tcx, uv.def);
(args, typing_env)
}
}
} else if tcx.def_kind(uv.def) == DefKind::AnonConst && uv.has_non_region_infer() {
Expand All @@ -593,27 +607,20 @@ pub fn try_evaluate_const<'tcx>(
);

let args = GenericArgs::identity_for_item(tcx, uv.def);
let param_env = tcx.param_env(uv.def);
(args, param_env)
let typing_env = ty::TypingEnv::post_analysis(tcx, uv.def);
(args, typing_env)
} else {
// FIXME: This codepath is reachable under `associated_const_equality` and in the
// future will be reachable by `min_generic_const_args`. We should handle inference
// variables and generic parameters properly instead of doing nothing.
(uv.args, param_env)
let typing_env = infcx
.typing_env(tcx.erase_regions(param_env))
.with_post_analysis_normalized(tcx);
(uv.args, typing_env)
};
let uv = ty::UnevaluatedConst::new(uv.def, args);

// It's not *technically* correct to be revealing opaque types here as borrowcheck has
// not run yet. However, CTFE itself uses `TypingMode::PostAnalysis` unconditionally even
// during typeck and not doing so has a lot of (undesirable) fallout (#101478, #119821).
// As a result we always use a revealed env when resolving the instance to evaluate.
//
// FIXME: `const_eval_resolve_for_typeck` should probably just modify the env itself
// instead of having this logic here
let typing_env =
tcx.erase_regions(infcx.typing_env(param_env)).with_post_analysis_normalized(tcx);
let erased_uv = tcx.erase_regions(uv);

use rustc_middle::mir::interpret::ErrorHandled;
match tcx.const_eval_resolve_for_typeck(typing_env, erased_uv, DUMMY_SP) {
Ok(Ok(val)) => Ok(ty::Const::new_value(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Regression test for #133271.
BoxyUwU marked this conversation as resolved.
Show resolved Hide resolved
#![feature(generic_const_exprs)]
//~^ WARN the feature `generic_const_exprs` is incomplete

struct Foo;
impl<'a, const NUM: usize> std::ops::Add<&'a Foo> for Foo
//~^ ERROR the const parameter `NUM` is not constrained by the impl trait, self type, or predicates
where
[(); 1 + 0]: Sized,
{
fn unimplemented(self, _: &Foo) -> Self::Output {
//~^ ERROR method `unimplemented` is not a member of trait `std::ops::Add`
//~| ERROR type annotations needed
loop {}
}
}

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
error[E0407]: method `unimplemented` is not a member of trait `std::ops::Add`
--> $DIR/post-analysis-user-facing-param-env.rs:11:5
|
LL | / fn unimplemented(self, _: &Foo) -> Self::Output {
LL | |
LL | |
LL | | loop {}
LL | | }
| |_____^ not a member of trait `std::ops::Add`

warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/post-analysis-user-facing-param-env.rs:2:12
|
LL | #![feature(generic_const_exprs)]
| ^^^^^^^^^^^^^^^^^^^
|
= note: see issue #76560 </~https://github.com/rust-lang/rust/issues/76560> for more information
= note: `#[warn(incomplete_features)]` on by default

error[E0207]: the const parameter `NUM` is not constrained by the impl trait, self type, or predicates
--> $DIR/post-analysis-user-facing-param-env.rs:6:10
|
LL | impl<'a, const NUM: usize> std::ops::Add<&'a Foo> for Foo
| ^^^^^^^^^^^^^^^^ unconstrained const parameter
|
= note: expressions using a const parameter must map each value to a distinct output value
= note: proving the result of expressions other than the parameter are unique is not supported

error[E0284]: type annotations needed
--> $DIR/post-analysis-user-facing-param-env.rs:11:40
|
LL | fn unimplemented(self, _: &Foo) -> Self::Output {
| ^^^^^^^^^^^^ cannot infer the value of const parameter `NUM`
|
note: required for `Foo` to implement `Add<&'a Foo>`
--> $DIR/post-analysis-user-facing-param-env.rs:6:28
|
LL | impl<'a, const NUM: usize> std::ops::Add<&'a Foo> for Foo
| ---------------- ^^^^^^^^^^^^^^^^^^^^^^ ^^^
| |
| unsatisfied trait bound introduced here

error: aborting due to 3 previous errors; 1 warning emitted

Some errors have detailed explanations: E0207, E0284, E0407.
For more information about an error, try `rustc --explain E0207`.
Loading