Skip to content

Commit 74ec3ea

Browse files
committed
GCI: Don't eval the impossible
1 parent 40daf23 commit 74ec3ea

File tree

9 files changed

+68
-58
lines changed

9 files changed

+68
-58
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4197,6 +4197,7 @@ dependencies = [
41974197
"rustc_span",
41984198
"rustc_symbol_mangling",
41994199
"rustc_target",
4200+
"rustc_trait_selection",
42004201
"serde",
42014202
"serde_json",
42024203
"tracing",

compiler/rustc_hir_analysis/src/lib.rs

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -202,12 +202,23 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
202202
check::maybe_check_static_with_link_section(tcx, item_def_id);
203203
}
204204
DefKind::Const if !tcx.generics_of(item_def_id).own_requires_monomorphization() => {
205-
// FIXME(generic_const_items): Passing empty instead of identity args is fishy but
206-
// seems to be fine for now. Revisit this!
207-
let instance = ty::Instance::new_raw(item_def_id.into(), ty::GenericArgs::empty());
208-
let cid = GlobalId { instance, promoted: None };
209-
let typing_env = ty::TypingEnv::fully_monomorphized();
210-
tcx.ensure_ok().eval_to_const_value_raw(typing_env.as_query_input(cid));
205+
let predicates = tcx.predicates_of(item_def_id);
206+
207+
// FIXME: Calling impossible_predicates is likely incorrect.
208+
if predicates.predicates.is_empty()
209+
|| !rustc_trait_selection::traits::impossible_predicates(
210+
tcx,
211+
predicates.instantiate_identity(tcx).predicates,
212+
)
213+
{
214+
// FIXME(generic_const_items): Passing empty instead of identity args is fishy but
215+
// seems to be fine for now. Revisit this!
216+
let instance =
217+
ty::Instance::new_raw(item_def_id.into(), ty::GenericArgs::empty());
218+
let cid = GlobalId { instance, promoted: None };
219+
let typing_env = ty::TypingEnv::fully_monomorphized();
220+
tcx.ensure_ok().eval_to_const_value_raw(typing_env.as_query_input(cid));
221+
}
211222
}
212223
_ => (),
213224
}

compiler/rustc_monomorphize/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ rustc_session = { path = "../rustc_session" }
1818
rustc_span = { path = "../rustc_span" }
1919
rustc_symbol_mangling = { path = "../rustc_symbol_mangling" }
2020
rustc_target = { path = "../rustc_target" }
21+
rustc_trait_selection = { path = "../rustc_trait_selection" }
2122
serde = "1"
2223
serde_json = "1"
2324
tracing = "0.1"

compiler/rustc_monomorphize/src/collector.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1484,6 +1484,12 @@ impl<'v> RootCollector<'_, 'v> {
14841484
// But even just declaring them must collect the items they refer to
14851485
// unless their generics require monomorphization.
14861486
if !self.tcx.generics_of(id.owner_id).own_requires_monomorphization()
1487+
&& let predicates = self.tcx.predicates_of(id.owner_id)
1488+
&& (predicates.predicates.is_empty()
1489+
|| !rustc_trait_selection::traits::impossible_predicates(
1490+
self.tcx,
1491+
predicates.instantiate_identity(self.tcx).predicates,
1492+
))
14871493
&& let Ok(val) = self.tcx.const_eval_poly(id.owner_id.to_def_id())
14881494
{
14891495
collect_const_value(self.tcx, val, self.output);

compiler/rustc_passes/src/reachable.rs

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -205,22 +205,32 @@ impl<'tcx> ReachableContext<'tcx> {
205205
}
206206

207207
hir::ItemKind::Const(_, _, _, init) => {
208-
// Only things actually ending up in the final constant value are reachable
209-
// for codegen. Everything else is only needed during const-eval, so even if
210-
// const-eval happens in a downstream crate, all they need is
211-
// `mir_for_ctfe`.
212-
match self.tcx.const_eval_poly_to_alloc(item.owner_id.def_id.into()) {
213-
Ok(alloc) => {
214-
let alloc = self.tcx.global_alloc(alloc.alloc_id).unwrap_memory();
215-
self.propagate_from_alloc(alloc);
208+
let predicates = self.tcx.predicates_of(item.owner_id);
209+
210+
if predicates.predicates.is_empty()
211+
|| !rustc_trait_selection::traits::impossible_predicates(
212+
self.tcx,
213+
predicates.instantiate_identity(self.tcx).predicates,
214+
)
215+
{
216+
// Only things actually ending up in the final constant value are reachable
217+
// for codegen. Everything else is only needed during const-eval, so even if
218+
// const-eval happens in a downstream crate, all they need is
219+
// `mir_for_ctfe`.
220+
match self.tcx.const_eval_poly_to_alloc(item.owner_id.def_id.into()) {
221+
Ok(alloc) => {
222+
let alloc =
223+
self.tcx.global_alloc(alloc.alloc_id).unwrap_memory();
224+
self.propagate_from_alloc(alloc);
225+
}
226+
// We can't figure out which value the constant will evaluate to. In
227+
// lieu of that, we have to consider everything mentioned in the const
228+
// initializer reachable, since it *may* end up in the final value.
229+
Err(ErrorHandled::TooGeneric(_)) => self.visit_nested_body(init),
230+
// If there was an error evaluating the const, nothing can be reachable
231+
// via it, and anyway compilation will fail.
232+
Err(ErrorHandled::Reported(..)) => {}
216233
}
217-
// We can't figure out which value the constant will evaluate to. In
218-
// lieu of that, we have to consider everything mentioned in the const
219-
// initializer reachable, since it *may* end up in the final value.
220-
Err(ErrorHandled::TooGeneric(_)) => self.visit_nested_body(init),
221-
// If there was an error evaluating the const, nothing can be reachable
222-
// via it, and anyway compilation will fail.
223-
Err(ErrorHandled::Reported(..)) => {}
224234
}
225235
}
226236
hir::ItemKind::Static(..) => {

tests/ui/generic-const-items/trivially-unsatisfied-bounds-0.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
#![feature(generic_const_items, trivial_bounds)]
2-
#![allow(incomplete_features)]
1+
#![feature(generic_const_items)]
2+
#![expect(incomplete_features)]
33

44
// Ensure that we check if trivial bounds on const items hold or not.
55

6-
const UNUSABLE: () = () //~ ERROR entering unreachable code
6+
const UNUSABLE: () = ()
77
where
8-
String: Copy;
8+
for<'_delay> String: Copy;
99

1010
fn main() {
1111
let _ = UNUSABLE; //~ ERROR the trait bound `String: Copy` is not satisfied
Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,18 @@
1-
error[E0080]: entering unreachable code
2-
--> $DIR/trivially-unsatisfied-bounds-0.rs:6:1
3-
|
4-
LL | / const UNUSABLE: () = ()
5-
LL | | where
6-
LL | | String: Copy;
7-
| |_________________^ evaluation of `UNUSABLE` failed here
8-
91
error[E0277]: the trait bound `String: Copy` is not satisfied
102
--> $DIR/trivially-unsatisfied-bounds-0.rs:11:13
113
|
124
LL | let _ = UNUSABLE;
135
| ^^^^^^^^ the trait `Copy` is not implemented for `String`
146
|
157
note: required by a bound in `UNUSABLE`
16-
--> $DIR/trivially-unsatisfied-bounds-0.rs:8:13
8+
--> $DIR/trivially-unsatisfied-bounds-0.rs:8:26
179
|
1810
LL | const UNUSABLE: () = ()
1911
| -------- required by a bound in this constant
2012
LL | where
21-
LL | String: Copy;
22-
| ^^^^ required by this bound in `UNUSABLE`
13+
LL | for<'_delay> String: Copy;
14+
| ^^^^ required by this bound in `UNUSABLE`
2315

24-
error: aborting due to 2 previous errors
16+
error: aborting due to 1 previous error
2517

26-
Some errors have detailed explanations: E0080, E0277.
27-
For more information about an error, try `rustc --explain E0080`.
18+
For more information about this error, try `rustc --explain E0277`.

tests/ui/generic-const-items/trivially-unsatisfied-bounds-1.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1-
#![feature(generic_const_items, trivial_bounds)]
2-
#![allow(incomplete_features, dead_code, trivial_bounds)]
1+
//@ check-pass
2+
#![feature(generic_const_items)]
3+
#![expect(incomplete_features)]
4+
#![crate_type = "lib"]
35

4-
// FIXME(generic_const_items): This looks like a bug to me. I expected that we wouldn't emit any
5-
// errors. I thought we'd skip the evaluation of consts whose bounds don't hold.
6+
const _UNUSED: () = ()
7+
where
8+
for<'_delay> String: Copy;
69

7-
const UNUSED: () = ()
10+
pub const PUB: () = ()
811
where
9-
String: Copy;
10-
//~^^^ ERROR unreachable code
12+
for<'_delay> String: Copy;
1113

12-
fn main() {}

tests/ui/generic-const-items/trivially-unsatisfied-bounds-1.stderr

Lines changed: 0 additions & 11 deletions
This file was deleted.

0 commit comments

Comments
 (0)