Skip to content

Skip const-eval if evaluatable predicate is trivial #127242

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

Closed
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
25 changes: 23 additions & 2 deletions compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,17 @@ pub fn is_const_evaluatable<'tcx>(
| ty::ConstKind::Value(_, _)
| ty::ConstKind::Error(_) => return Ok(()),
ty::ConstKind::Infer(_) => return Err(NotConstEvaluatable::MentionsInfer),
};
}

if tcx.features().generic_const_exprs {
let ct = tcx.expand_abstract_consts(unexpanded_ct);

if trivially_satisfied_from_param_env(ct, param_env) {
Copy link
Member

@BoxyUwU BoxyUwU Jul 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would have had to go before the expand_abstract_consts call as otherwise its never going to find any matches in the env since abstract consts arent expanded in the ParamEnv :3

return Ok(());
}

let is_anon_ct = if let ty::ConstKind::Unevaluated(uv) = ct.kind() {
tcx.def_kind(uv.def) == DefKind::AnonConst
matches!(tcx.def_kind(uv.def), DefKind::AnonConst)
} else {
false
};
Expand Down Expand Up @@ -150,6 +154,23 @@ pub fn is_const_evaluatable<'tcx>(
}
}

fn trivially_satisfied_from_param_env<'tcx>(
ct: ty::Const<'tcx>,
param_env: ty::ParamEnv<'tcx>,
) -> bool {
for pred in param_env.caller_bounds() {
if let ty::ClauseKind::ConstEvaluatable(ce) = pred.kind().skip_binder() {
if let ty::ConstKind::Unevaluated(uv_env) = ce.kind()
&& let ty::ConstKind::Unevaluated(uv) = ct.kind()
&& uv == uv_env
{
return true;
}
}
}
false
}

#[instrument(skip(infcx, tcx), level = "debug")]
fn satisfied_from_param_env<'tcx>(
tcx: TyCtxt<'tcx>,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//@ known-bug: #123959
//@ check-pass
#![feature(generic_const_exprs)]
#![allow(incomplete_features)]

fn foo<T>(_: [(); std::mem::offset_of!((T,), 0)]) {}

pub fn main() {}
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ mod v20 {
//~^ ERROR cannot find value `v8` in this scope
//~| ERROR cannot find function `v6` in this scope
pub struct v17<const v10: usize, const v7: v11> {
//~^ WARN type `v17` should have an upper camel case name
//~| ERROR `[[usize; v4]; v4]` is forbidden as the type of a const generic parameter
//~^ WARN type `v17` should have an upper camel case name
//~| ERROR `[[usize; v4]; v4]` is forbidden as the type of a const generic parameter
_p: (),
}

Expand All @@ -25,10 +25,9 @@ mod v20 {
}

impl<const v10: usize> v17<v10, v2> {
//~^ ERROR maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#1}
//~| ERROR maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#1}
//~^ ERROR maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#1}
pub const fn v21() -> v18 {
//~^ ERROR cannot find type `v18` in this scope
//~^ ERROR cannot find type `v18` in this scope
v18 { _p: () }
//~^ ERROR cannot find struct, variant or union type `v18` in this scope
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error[E0432]: unresolved import `v20::v13`
--> $DIR/unevaluated-const-ice-119731.rs:37:15
--> $DIR/unevaluated-const-ice-119731.rs:36:15
|
LL | pub use v20::{v13, v17};
| ^^^
Expand All @@ -23,7 +23,7 @@ LL | pub const fn v21() -> v18 {}
| ^^^ help: a type alias with a similar name exists: `v11`

error[E0412]: cannot find type `v18` in this scope
--> $DIR/unevaluated-const-ice-119731.rs:30:31
--> $DIR/unevaluated-const-ice-119731.rs:29:31
|
LL | pub type v11 = [[usize; v4]; v4];
| --------------------------------- similarly named type alias `v11` defined here
Expand All @@ -32,7 +32,7 @@ LL | pub const fn v21() -> v18 {
| ^^^ help: a type alias with a similar name exists: `v11`

error[E0422]: cannot find struct, variant or union type `v18` in this scope
--> $DIR/unevaluated-const-ice-119731.rs:32:13
--> $DIR/unevaluated-const-ice-119731.rs:31:13
|
LL | pub type v11 = [[usize; v4]; v4];
| --------------------------------- similarly named type alias `v11` defined here
Expand Down Expand Up @@ -78,15 +78,7 @@ error: maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{consta
LL | impl<const v10: usize> v17<v10, v2> {
| ^^

error: maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#1}
--> $DIR/unevaluated-const-ice-119731.rs:27:37
|
LL | impl<const v10: usize> v17<v10, v2> {
| ^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error: aborting due to 9 previous errors; 2 warnings emitted
error: aborting due to 8 previous errors; 2 warnings emitted

Some errors have detailed explanations: E0412, E0422, E0425, E0432.
For more information about an error, try `rustc --explain E0412`.
Loading