Skip to content

GCI: Don't evaluate the initializer of free const items that have trivially unsatisfied predicates #142293

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
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

fmease
Copy link
Member

@fmease fmease commented Jun 10, 2025

Part of #113521.

@fmease fmease added the F-generic_const_items `#![feature(generic_const_items)]` label Jun 10, 2025
@rustbot rustbot added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Jun 10, 2025
@fmease fmease changed the title [early rough draft] GCI: Don't evaluate the free const items with impossible predicates [early rough draft] GCI: Don't evaluate free const items with impossible predicates Jun 10, 2025
@fmease
Copy link
Member Author

fmease commented Jun 10, 2025

@bors2 try @rust-timer queue

@rust-timer

This comment has been minimized.

@rust-bors
Copy link

rust-bors bot commented Jun 10, 2025

⌛ Trying commit 74ec3ea with merge 4151b9a

To cancel the try build, run the command @bors2 try cancel.

rust-bors bot added a commit that referenced this pull request Jun 10, 2025
[early rough draft] GCI: Don't evaluate free const items with impossible predicates
@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Jun 10, 2025
@fmease fmease moved this to In Progress in Generic Const Items (GCI) Jun 10, 2025
@rust-log-analyzer

This comment was marked as off-topic.

@fmease fmease added the rla-silenced Silences rust-log-analyzer postings to the PR it's added on. label Jun 10, 2025
@BoxyUwU BoxyUwU self-assigned this Jun 10, 2025
Copy link
Member

@BoxyUwU BoxyUwU left a comment

Choose a reason for hiding this comment

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

We should consider moving all of these call-site checks into ctfe itself, e.g. eval_to_const_value_raw_provider. This wont affect const patterns which go through _for_typeck versions of the CTFE entry points.

I also then think that the impossible predicates check in that place should ICE on predicates containing non region params as that shouldn't be reachable (and if it is, then we're evaluating generic constants in places we might not want to be).

@rust-bors
Copy link

rust-bors bot commented Jun 10, 2025

☀️ Try build successful (CI)
Build commit: 4151b9a (4151b9aaad261468f4260336981f34de2f05df15)

@rust-timer

This comment has been minimized.

@rust-timer
Copy link
Collaborator

Finished benchmarking commit (4151b9a): comparison URL.

Overall result: no relevant changes - no action needed

Benchmarking this pull request means it may be perf-sensitive – we'll automatically label it not fit for rolling up. You can override this, but we strongly advise not to, due to possible changes in compiler perf.

@bors rollup=never
@rustbot label: -S-waiting-on-perf -perf-regression

Instruction count

This benchmark run did not return any relevant results for this metric.

Max RSS (memory usage)

Results (primary -5.1%, secondary -2.1%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
3.5% [3.5%, 3.5%] 1
Improvements ✅
(primary)
-5.1% [-9.4%, -3.0%] 6
Improvements ✅
(secondary)
-2.3% [-4.3%, -1.1%] 21
All ❌✅ (primary) -5.1% [-9.4%, -3.0%] 6

Cycles

This benchmark run did not return any relevant results for this metric.

Binary size

This benchmark run did not return any relevant results for this metric.

Bootstrap: 753.145s -> 753.291s (0.02%)
Artifact size: 372.18 MiB -> 372.22 MiB (0.01%)

@rustbot rustbot removed the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Jun 11, 2025
Cargo.lock Outdated
Copy link
Member Author

Choose a reason for hiding this comment

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

I also then think that the impossible predicates check in that place should ICE on predicates containing non region params as that shouldn't be reachable (and if it is, then we're evaluating generic constants in places we might not want to be).

Adding debug_assert!(!predicates.has_non_region_param()); to fn impossible_predicates, lead to a whole slew of test failures (I didn't complete the test run). E.g.,

Some failing tests
tests/ui/associated-consts/associated-const-marks-live-code.rs
tests/ui/async-await/async-fn-size-moved-locals.rs
tests/ui/async-await/async-fn-size-uninit-locals.rs
tests/ui/async-await/repeat_count_const_in_async_fn.rs
tests/ui/binding/match-arm-statics.rs
tests/ui/const_prop/ice-issue-96944.rs
tests/ui/consts/const-autoderef.rs
tests/ui/consts/chained-constants-stackoverflow.rs
tests/ui/consts/const-blocks/const-repeat.rs
tests/ui/consts/const-const.rs
tests/ui/consts/const-enum-cast.rs
tests/ui/consts/const-eval/strlen.rs
tests/ui/consts/const-expr-in-fixed-length-vec.rs
tests/ui/consts/const-expr-in-vec-repeat.rs
tests/ui/consts/const-fn-method.rs
tests/ui/consts/const-trait-to-trait.rs
tests/ui/consts/ice-48279.rs
tests/ui/consts/min_const_fn/min_const_fn_libstd.rs
tests/ui/consts/offset_from.rs
tests/ui/consts/ptr_comparisons.rs
tests/ui/consts/ptr_is_null.rs

Copy link
Member Author

Choose a reason for hiding this comment

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

Adding debug_assert!(!predicates.has_non_region_param()); to fn impossible_predicates

I was wrong about that, it's actually completely fine 🤦 I must've had some other changes in the working tree... Sry bout the miscommunication there

Copy link
Member Author

@fmease fmease Jun 24, 2025

Choose a reason for hiding this comment

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

We should consider moving all of these call-site checks into ctfe itself, e.g. eval_to_const_value_raw_provider. This wont affect const patterns which go through _for_typeck versions of the CTFE entry points.

As discussed, long term, that would be the way to go. However, it makes me uncomfortable that eval_to_const_value_raw has so many transitive callers which I wasn't yet able to audit entirely. I know that you told me that this function should be safe to modify from a soundness perspective and you're probably right, I just haven't finished tracing the entire caller graph. WIP:

Caller graph (X called by Y)
+ eval_to_const_value_raw  [eval_to_const_value_raw_provider]  (???)
+-- check_crate/par_hir_body_owners/DefKind::Const  (OK)
+-- const_eval_global_id  (???)
    +-- eval_intrinsic  (OK)
    +-- const_eval_poly  (OK)
    |   +-- codegen_global_asm  (OK)
    |   +-- check_type_defn/variants/fields [default_field_values]  (OK)
    |   +-- check_type_defn/ty::VariantDiscr::Explicit  (OK)
    |   +-- eval_explicit_discr  (OK)
    |   +-- monomorphize/RootCollector/process_item/DefKind::Const  (OK)
    +-- const_eval_resolve  (???)
    |   +-- Const::eval  (???)
    |       +-- eval_mir_constant  (???)
    |       |   +... [~20 call sites]  (TODO)
    |       +-- inline_to_global_operand/InlineAsmOperand::Const  (OK)
    |       +-- push_stack_frame_raw/body.required_consts()  (???)
    |       +-- try_eval_scalar...  (TODO)
    |       +-- MIR transform/simplify_repeated_aggregate  (???)
    |       +-- eval_constant  (???)
    |           +-- eval_operand...  (TODO)
    |           +-- MIR transform/ConstPropagator/visit_const_operand  (???)
    |           +-- collect_items_of_instance/body.requires_consts()  (???)
    +-- const_eval_instance  (???)
        +-- codegen_regular_intrinsic_call  (OK)
        +-- codegen_intrinsic_call  (OK)
        +-- eval_instance  (???)
            +-- try_const_eval [SMIR]  (???)

Copy link
Member Author

Choose a reason for hiding this comment

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

(As an aside, even if we enriched eval_to_const_value_raw_provider with a call to impossible_predicates, here in mod reachable it would be of no use to us as it uses const_eval_poly_to_alloc which doesn't depend on that function)

@fmease fmease force-pushed the gci-dont-eval-the-impossible branch 2 times, most recently from 498b2e2 to 380088d Compare June 24, 2025 13:08
@fmease
Copy link
Member Author

fmease commented Jun 24, 2025

Mono collector now uses instantiate_and_check_impossible_predicates which filters out predicates with early-bound regions contrary to impossible_predicates, so might have a mismatch in behavior between mono collection, reachability analysis and typeck which seems problematic but I haven't thought about it any further (does IACIP assume erased lifetimes?).

Despite that, imma recheck perf cuz I removed the predicates.is_empty() "micro opt".
@bors2 try @rust-timer queue

@rust-timer

This comment has been minimized.

rust-bors bot added a commit that referenced this pull request Jun 24, 2025
[early rough draft] GCI: Don't evaluate free const items with impossible predicates
@rust-bors
Copy link

rust-bors bot commented Jun 24, 2025

⌛ Trying commit 380088d with merge 10bc814

To cancel the try build, run the command @bors2 try cancel.

@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Jun 24, 2025
if !self.tcx.generics_of(def_id).own_requires_monomorphization()
&& !self.tcx.instantiate_and_check_impossible_predicates((
def_id,
ty::GenericArgs::identity_for_item(self.tcx, def_id),
Copy link
Member

Choose a reason for hiding this comment

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

this should probably just copy the logic from DefKind::Enum/Struct/Union for checking impossible preds and constructing identity args

Copy link
Member Author

Choose a reason for hiding this comment

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

The const item branch now copies the relevant parts of the ADT branch 👍

let predicates = tcx.predicates_of(item_def_id);
let predicates = predicates.instantiate_identity(tcx).predicates;

// FIXME(fmease): May its result be 'incorrect' if the preds have ReEarlyBound?
Copy link
Member

Choose a reason for hiding this comment

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

Yeah I think you should be able to construct a case where an impossible pred isnt found due to a lifetime parameter. E.g. const _: usize where for<'b> [&'a u8]: Sized = ... probably will get evaluated unless you erase regions

Copy link
Member Author

Choose a reason for hiding this comment

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

We're now erasing in mono collector and as a consequence we no longer eval the initializer in your example 👍


// FIXME(fmease): May its result be 'incorrect' if the preds have ReEarlyBound?
if !traits::impossible_predicates(tcx, predicates) {
// FIXME(generic_const_items): Passing empty instead of identity args is fishy but
Copy link
Member

Choose a reason for hiding this comment

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

this should be fixed yeah 🤔 I don't think ctfe should have to handle there being instances with wrong args

Copy link
Member Author

Choose a reason for hiding this comment

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

Right, we should. If you're okay with it, I'd prefer to address this in a separate PR because this is super perf sensitive.

This used to be a call to fn const_eval_poly for the longest time which used to construct identity args etc. After a reshuffle (#121087), it was changed to the current no-args fully-mono version (#121387) to fix perf. Maybe the identity vs. no args isn't mega perf sensitive and it's paramenv norm that's the culprit but in #136429 I also did some tests, so it's unclear.

E.g., ea1cdda (perf results: #136429 (comment)) and 6f11489 (perf results: #136429 (comment)). Ofc, they also include unrelated changes to WF-check, so the results are skewed.

@rust-bors
Copy link

rust-bors bot commented Jun 24, 2025

☀️ Try build successful (CI)
Build commit: 10bc814 (10bc814a261100b40f7fa5feaa6a079876607337, parent: e4b9d0141fdd210fcceebd2b67f7be113401c461)

@rust-bors
Copy link

rust-bors bot commented Jun 25, 2025

⌛ Trying commit 0e9126c with merge cea506b

To cancel the try build, run the command @bors2 try cancel.

rust-bors bot added a commit that referenced this pull request Jun 25, 2025
GCI: Don't evaluate the initializer of free const items that have trivially unsatisfied predicates
@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Jun 25, 2025
@rust-bors
Copy link

rust-bors bot commented Jun 25, 2025

☀️ Try build successful (CI)
Build commit: cea506b (cea506b6d4e9d59bbdaea6b74051c551246bff6d, parent: e4b9d0141fdd210fcceebd2b67f7be113401c461)

@rust-timer

This comment has been minimized.

@rust-timer
Copy link
Collaborator

Finished benchmarking commit (cea506b): comparison URL.

Overall result: ❌ regressions - please read the text below

Benchmarking this pull request means it may be perf-sensitive – we'll automatically label it not fit for rolling up. You can override this, but we strongly advise not to, due to possible changes in compiler perf.

Next Steps: If you can justify the regressions found in this try perf run, please do so in sufficient writing along with @rustbot label: +perf-regression-triaged. If not, please fix the regressions and do another perf run. If its results are neutral or positive, the label will be automatically removed.

@bors rollup=never
@rustbot label: -S-waiting-on-perf +perf-regression

Instruction count

Our most reliable metric. Used to determine the overall result above. However, even this metric can be noisy.

mean range count
Regressions ❌
(primary)
0.7% [0.3%, 1.0%] 8
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) 0.7% [0.3%, 1.0%] 8

Max RSS (memory usage)

Results (primary 2.3%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
2.3% [1.7%, 2.9%] 2
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) 2.3% [1.7%, 2.9%] 2

Cycles

Results (secondary -3.6%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-3.6% [-4.1%, -3.0%] 2
All ❌✅ (primary) - - 0

Binary size

This benchmark run did not return any relevant results for this metric.

Bootstrap: 690.402s -> 687.107s (-0.48%)
Artifact size: 372.03 MiB -> 371.92 MiB (-0.03%)

@rustbot rustbot removed the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Jun 26, 2025
@bors

This comment was marked as resolved.

@bors bors added the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Jun 27, 2025
@fmease fmease force-pushed the gci-dont-eval-the-impossible branch from 0e9126c to 8d3bc94 Compare July 2, 2025 16:13
@fmease
Copy link
Member Author

fmease commented Jul 2, 2025

PR #142893 (which conflicted with this PR / made it unmergeable) heavily affected perf. Thus I'm now retrying if this PR is still sensitive.

@bors2 try @rust-timer queue

@rust-timer

This comment has been minimized.

@rust-bors
Copy link

rust-bors bot commented Jul 2, 2025

⌛ Trying commit 8d3bc94 with merge 41283df

To cancel the try build, run the command @bors2 try cancel.

rust-bors bot added a commit that referenced this pull request Jul 2, 2025
GCI: Don't evaluate the initializer of free const items that have trivially unsatisfied predicates

Part of #113521.
@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Jul 2, 2025
@rust-bors
Copy link

rust-bors bot commented Jul 2, 2025

☀️ Try build successful (CI)
Build commit: 41283df (41283df7b958f7c986dcf1d3920b6896ab276564, parent: b94bd12401d26ccf1c3b04ceb4e950b0ff7c8d29)

@rust-timer

This comment has been minimized.

@rust-timer
Copy link
Collaborator

Finished benchmarking commit (41283df): comparison URL.

Overall result: no relevant changes - no action needed

Benchmarking this pull request means it may be perf-sensitive – we'll automatically label it not fit for rolling up. You can override this, but we strongly advise not to, due to possible changes in compiler perf.

@bors rollup=never
@rustbot label: -S-waiting-on-perf -perf-regression

Instruction count

This benchmark run did not return any relevant results for this metric.

Max RSS (memory usage)

Results (primary 0.4%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
2.0% [1.5%, 2.4%] 2
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
-2.8% [-2.8%, -2.8%] 1
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) 0.4% [-2.8%, 2.4%] 3

Cycles

Results (primary -1.5%, secondary 8.2%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
2.3% [2.3%, 2.3%] 1
Regressions ❌
(secondary)
8.2% [0.7%, 13.3%] 10
Improvements ✅
(primary)
-2.7% [-5.1%, -1.0%] 3
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) -1.5% [-5.1%, 2.3%] 4

Binary size

This benchmark run did not return any relevant results for this metric.

Bootstrap: 462.452s -> 460.902s (-0.34%)
Artifact size: 372.20 MiB -> 372.15 MiB (-0.01%)

@rustbot rustbot removed S-waiting-on-perf Status: Waiting on a perf run to be completed. perf-regression Performance regression. labels Jul 3, 2025
@fmease fmease force-pushed the gci-dont-eval-the-impossible branch from 8d3bc94 to 569f3a3 Compare July 3, 2025 15:36
@fmease fmease force-pushed the gci-dont-eval-the-impossible branch from 569f3a3 to 3cddea4 Compare July 3, 2025 16:08

// FIXME(fmease): May its result be 'incorrect' if the preds have ReEarlyBound?
if !traits::impossible_predicates(tcx, predicates) {
// FIXME(generic_const_items): Passing empty instead of identity args is fishy but
Copy link
Member Author

Choose a reason for hiding this comment

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

Right, we should. If you're okay with it, I'd prefer to address this in a separate PR because this is super perf sensitive.

This used to be a call to fn const_eval_poly for the longest time which used to construct identity args etc. After a reshuffle (#121087), it was changed to the current no-args fully-mono version (#121387) to fix perf. Maybe the identity vs. no args isn't mega perf sensitive and it's paramenv norm that's the culprit but in #136429 I also did some tests, so it's unclear.

E.g., ea1cdda (perf results: #136429 (comment)) and 6f11489 (perf results: #136429 (comment)). Ofc, they also include unrelated changes to WF-check, so the results are skewed.

/// Evaluates a constant without providing any generic parameters.
///
/// This is useful to evaluate consts that can't take any generic arguments like enum
/// discriminants. If a non-region generic parameter is used within the constant
Copy link
Member Author

@fmease fmease Jul 3, 2025

Choose a reason for hiding this comment

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

(apart splitting of the synopsis / introductory paragraph, here & below I changed generic parameter to non-region generic parameter and dropped the mention of const items since they can be generic, GCI duh)

let predicates = tcx.predicates_of(item_def_id);
let predicates = predicates.instantiate_identity(tcx).predicates;

// FIXME(fmease): May its result be 'incorrect' if the preds have ReEarlyBound?
Copy link
Member Author

Choose a reason for hiding this comment

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

We're now erasing in mono collector and as a consequence we no longer eval the initializer in your example 👍

if !self.tcx.generics_of(def_id).own_requires_monomorphization()
&& !self.tcx.instantiate_and_check_impossible_predicates((
def_id,
ty::GenericArgs::identity_for_item(self.tcx, def_id),
Copy link
Member Author

Choose a reason for hiding this comment

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

The const item branch now copies the relevant parts of the ADT branch 👍

Comment on lines 1438 to 1446
if tcx.generics_of(def_id).own_requires_monomorphization() {
return;
}
let args = ty::GenericArgs::for_item(tcx, def_id, |param, _| {
expect_and_erase_regions(tcx, param)
});
if tcx.instantiate_and_check_impossible_predicates((def_id, args)) {
return;
}
Copy link
Member Author

Choose a reason for hiding this comment

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

This pattern occurs 3 times in this file: For ADTs, const items and impl blocks. However, I was unable to extract the code into a meaningful function. The only thing I was able to come up with was sth. like:

fn instantiate_erasing_regions_if_monomorphic_enough_and_check_impossible_predicates<'tcx>(
    tcx: TyCtxt<'tcx>,
    def_id: DefId,
) -> Option<ty::GenericArgs<'tcx>> {
    if !tcx.generics_of(def_id).requires_monomorphization(tcx)
        && let args =
            ty::GenericArgs::for_item(tcx, def_id, |param, _| expect_and_erase_regions(tcx, param))
        && !tcx.instantiate_and_check_impossible_predicates((def_id, args))
    {
        return Some(args);
    }

    None
}

and my eyes started bleeding 🩸🩸🩸

Cargo.lock Outdated
Copy link
Member Author

Choose a reason for hiding this comment

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

Adding debug_assert!(!predicates.has_non_region_param()); to fn impossible_predicates

I was wrong about that, it's actually completely fine 🤦 I must've had some other changes in the working tree... Sry bout the miscommunication there

@fmease fmease marked this pull request as ready for review July 3, 2025 16:13
@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jul 3, 2025
@rustbot
Copy link
Collaborator

rustbot commented Jul 3, 2025

Some changes occurred to the CTFE / Miri interpreter

cc @rust-lang/miri, @RalfJung, @oli-obk, @lcnr

@fmease
Copy link
Member Author

fmease commented Jul 3, 2025

@rustbot review

@@ -238,12 +238,18 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
check::maybe_check_static_with_link_section(tcx, item_def_id);
}
DefKind::Const if !tcx.generics_of(item_def_id).own_requires_monomorphization() => {
Copy link
Member

Choose a reason for hiding this comment

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

I would expect !own_requires_monomorphization means there are no generics to begin with? Or what does that function mean? It is sadly undocumented...

It does not make sense to me that we'd ever evaluate a generic free const item. How would we even pick the instance for the generic parameters...?

Copy link
Member

Choose a reason for hiding this comment

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

Ah, there was #136429 which I already forgot about. IMO the obvious fix is to just revert that PR...

... but I guess that wouldn't even be enough since even non-generic consts can have where clauses. Right. Uh, we may have to just skip all of those?

Copy link
Member Author

@fmease fmease Jul 3, 2025

Choose a reason for hiding this comment

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

own_requires_monomorphization is synonymous with "has non-region generic params" meaning we do eval lifetime-generic const exprs (more precisely early-bound-lifetime-generic).

Copy link
Member Author

@fmease fmease Jul 3, 2025

Choose a reason for hiding this comment

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

How would we even pick the instance for the generic parameters...?

That's obviously fine since we're only dealing with lifetime params since trait resolution etc. happens modulo non-late-bound regions / most if not all regions get fully erased. No problem there.

let predicates = tcx.predicates_of(item_def_id);
let predicates = predicates.instantiate_identity(tcx).predicates;

if !traits::impossible_predicates(tcx, predicates) {
Copy link
Member

@RalfJung RalfJung Jul 3, 2025

Choose a reason for hiding this comment

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

Is it guaranteed that !impossible means "possible"? Or at least, does the contract for impossible_predicates imply that a predicate considered "possible" will not ICE later when one does normal type system things and makes basic assumptions about primitive MIR ops, sizedness, and things like that?

(I feel I asked @BoxyUwU that same question already earlier this year in a different context and the answer was "yes it's fine", but I'm not sure...)

Copy link
Member Author

@fmease fmease Jul 3, 2025

Choose a reason for hiding this comment

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

Unfortunately I can't answer that with 100% confidence since I'm not super familiar with the innards and all the little details of const eval.

I know that layout computation has been made more robust against that somewhat recently but I'm not sure about the rest.

I know that the MIR pass ImpossiblePredicates replaces MIR bodies with Unreachable1 if the body has unsatisfiable ("trivially unsatisfied") global2 predicates. However, I don't actually know how early that pass gets run (and it doesn't affect e.g., layout computation unless I'm totally off base).

It's certainly a valid question and I need to have researched that before opening the RFC. Tho if my tired brain doesn't trick me right now, my change should in theory eliminate potential ICEs rather than introducing new ones because we eval less.

Footnotes

  1. These actually trigger during const eval on master.

  2. Meaning it disagrees with the 3 checks I've added in this PR when there are predicates containing ReEarlyBound (erasing wouldn't help because ReErased also turns a predicate non-global). My new checks should be stricter than the one used during said MIR pass, so that shouldn't be problematic (or at least not more problematic compared to master).

Copy link
Member

Choose a reason for hiding this comment

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

my change should in theory eliminate potential ICEs rather than introducing new ones because we eval less.
Footnotes

Yeah, definitely. I was just wondering if it evals less enough. ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
F-generic_const_items `#![feature(generic_const_items)]` rla-silenced Silences rust-log-analyzer postings to the PR it's added on. S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
Status: In Progress
Development

Successfully merging this pull request may close these issues.

7 participants