-
-
Notifications
You must be signed in to change notification settings - Fork 14.6k
GCI: During reachability analysis don't try to evaluate the initializer of overly generic free const items #153269
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
Open
fmease
wants to merge
1
commit into
rust-lang:main
Choose a base branch
from
fmease:gci-reach-no-eval
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
27 changes: 0 additions & 27 deletions
27
tests/codegen-llvm/dont_codegen_private_const_fn_only_used_in_const_eval.rs
This file was deleted.
Oops, something went wrong.
38 changes: 38 additions & 0 deletions
38
tests/codegen-llvm/private-const-fn-only-used-in-const-eval.rs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| // Check that we — where possible — don't codegen functions that are only used to evaluate | ||
| // static / const items, but never used in runtime code. | ||
|
|
||
| //@ compile-flags: --crate-type=lib -Copt-level=0 | ||
|
|
||
| #![feature(generic_const_items)] // only used in the last few test cases | ||
|
|
||
| pub static STATIC: () = func0(); | ||
| const fn func0() {} | ||
| // CHECK-NOT: define{{.*}}func0{{.*}} | ||
|
|
||
| pub const CONSTANT: () = func1(); | ||
| const fn func1() {} | ||
| // CHECK-NOT: define{{.*}}func1{{.*}} | ||
|
|
||
| // We generally don't want to evaluate the initializer of free const items if they have | ||
| // non-region params (and even if we did, const eval would fail anyway with "too polymorphic" | ||
| // if the initializer actually referenced such a param). | ||
| // | ||
| // As a result of not being able to look at the final value, during reachability analysis we | ||
| // can't tell for sure if for example certain functions end up in the final value or if they're | ||
| // only used during const eval. We fall back to a conservative HIR-based approach. | ||
|
|
||
| // `func2` isn't needed at runtime but the compiler can't tell for the reason mentioned above. | ||
| pub const POLY_CONST_0<const C: bool>: () = func2(); | ||
| const fn func2() {} | ||
| // CHECK: define{{.*}}func2{{.*}} | ||
|
|
||
| // `func3` isn't needed at runtime but the compiler can't tell for the reason mentioned above. | ||
| pub const POLY_CONST_1<const C: bool>: () = if C { func3() }; | ||
| const fn func3() {} | ||
| // CHECK: define{{.*}}func3{{.*}} | ||
|
|
||
| // `func4` *is* needed at runtime (here, the HIR-based approach gets it right). | ||
| pub const POLY_CONST_2<const C: bool>: Option<fn() /* or a TAIT */> = | ||
| if C { Some(func4) } else { None }; | ||
| const fn func4() {} | ||
| // CHECK: define{{.*}}func4{{.*}} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,15 +1,32 @@ | ||
| //! Test that we only evaluate free const items (their def site to be clear) | ||
| //! whose generics don't require monomorphization. | ||
| // Test that we don't evaluate the initializer of free const items if they have | ||
| // non-region generic parameters (i.e., ones that "require monomorphization"). | ||
| // | ||
| // To peek behind the curtains for a bit, at the time of writing there are three places where we | ||
| // usually evaluate the initializer: "analysis", mono item collection & reachability analysis. | ||
| // We must ensure that all of them take the generics into account. | ||
| // | ||
| //@ revisions: fail pass | ||
| //@[pass] check-pass | ||
|
|
||
| #![feature(generic_const_items)] | ||
| #![expect(incomplete_features)] | ||
| #![crate_type = "lib"] // (*) | ||
|
|
||
| //@ revisions: fail pass | ||
| //@[pass] check-pass | ||
| // All of these constants are intentionally unused since we want to test the | ||
| // behavior at the def site, not at use sites. | ||
|
|
||
| const _<_T>: () = panic!(); | ||
| const _<const _N: usize>: () = panic!(); | ||
|
|
||
| // Check *public* const items specifically to exercise reachability analysis which normally | ||
| // evaluates const initializers to look for function pointers in the final const value. | ||
| // | ||
| // (*): While reachability analysis also runs for purely binary crates (to find e.g., extern items) | ||
| // setting the crate type to library (1) makes the case below 'more realistic' since | ||
| // hypothetical downstream crates that require runtime MIR could actually exist. | ||
| // (2) It ensures that we exercise the relevant part of the compiler under test. | ||
| pub const K<_T>: () = panic!(); | ||
| pub const Q<const _N: usize>: () = loop {}; | ||
|
|
||
| #[cfg(fail)] | ||
| const _<'_a>: () = panic!(); //[fail]~ ERROR evaluation panicked: explicit panic | ||
|
|
||
| fn main() {} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Going off on a tangent, the whole "don't eval the initializer for non-lifetime-parametric free const items" thing doesn't apply to mGCA's type-level consts which I'm pretty sure is very intentional (IINM) and thus fine, it's also not GCI-specific, e.g.,
trait T { type const K: usize = const { panic!(); }; }(Selfin scope).I'm only concerned about const items with bodies anyway since the whole idea is to prevent const eval's "bespoke" handling of "too generic" consts "being user observable" / load-bearing for program correctness (the other motivation being consts should behave like fns in this specific scenario) or rephrased "type based" > "value based".