Skip to content

Properly generalize unevaluated consts#154053

Open
khyperia wants to merge 2 commits intorust-lang:mainfrom
khyperia:generalize-unevaluated
Open

Properly generalize unevaluated consts#154053
khyperia wants to merge 2 commits intorust-lang:mainfrom
khyperia:generalize-unevaluated

Conversation

@khyperia
Copy link
Contributor

r? @BoxyUwU

@rustbot
Copy link
Collaborator

rustbot commented Mar 18, 2026

changes to the core type system

cc @lcnr

@rustbot rustbot added 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. WG-trait-system-refactor The Rustc Trait System Refactor Initiative (-Znext-solver) labels Mar 18, 2026
@rust-bors

This comment has been minimized.

@khyperia khyperia force-pushed the generalize-unevaluated branch from c14d5fa to ac88926 Compare March 21, 2026 12:48
@rustbot
Copy link
Collaborator

rustbot commented Mar 21, 2026

This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

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.

let normalized_alias = relation.try_eagerly_normalize_alias(alias);

if normalized_alias.is_ty_var() {
if term_vid(normalized_alias).is_some() {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
if term_vid(normalized_alias).is_some() {
if normalized_alias.is_infer() {

// with `ShallowStructurallyRelateAliases` so we treat the outermost alias as rigid,
// ensuring this is never a tyvar.
assert!(!generalized_ty.is_ty_var());
assert!(term_vid(generalized_term).is_none());
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
assert!(term_vid(generalized_term).is_none());
assert!(!generalized_term.is_infer());

}
}

fn term_vid<'tcx>(term: Term<'tcx>) -> Option<TermVid> {
Copy link
Member

Choose a reason for hiding this comment

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

can you move this to a method on Term

Copy link
Contributor Author

Choose a reason for hiding this comment

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

TermVid is defined locally in generalize.rs, which is the reason this is also locally here. Should I migrate TermVid to rustc_middle? Seems vaguely useful in general (ha) but I was trying to rein in my refactorings

Copy link
Member

Choose a reason for hiding this comment

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

oh, i see yeah if you could move TermVid to whether we define Term/AliasTerm/etc that'd be great

self.tcx.features().generic_const_exprs() && matches!(target_vid, TermVid::Const(_));

let generalized_term = if self.next_trait_solver()
&& !gce_const_fallback
Copy link
Member

Choose a reason for hiding this comment

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

GCE is incompatible with the new solver (we don't allow both to be used together) so this check probably doesn't do anything. should be able to remvoe gce_const_fallback

Copy link
Contributor Author

Choose a reason for hiding this comment

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

this check probably doesn't do anything

removing it causes this test to fail:

error[E0119]: conflicting implementations of trait `From<GenericStruct<{T + 1}>>` for type `GenericStruct<{T + 1}>`
  --> /d/rust/tests/ui/const-generics/issues/issue-89304.rs:8:1
   |
LL | impl<const T: usize> From<GenericStruct<T>> for GenericStruct<{T + 1}> {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: conflicting implementation in crate `core`:
           - impl<T> From<T> for T;

error[E0119]: conflicting implementations of trait `From<GenericStruct<_>>` for type `GenericStruct<_>`
  --> /d/rust/tests/ui/const-generics/issues/issue-89304.rs:14:1
   |
LL | impl<const T: usize> From<GenericStruct<{T + 1}>> for GenericStruct<T> {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: conflicting implementation in crate `core`:
           - impl<T> From<T> for T;

error: aborting due to 2 previous errors

to be honest, I'm not going to pretend I know what's going on.

Copy link
Member

Choose a reason for hiding this comment

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

aha coherence

Copy link
Member

Choose a reason for hiding this comment

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

yeah ok I guess the "gce isnt allowed with new solver" is wrong for coherence...

Copy link
Member

Choose a reason for hiding this comment

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

sure yeah seems fine to me to keep this

match source_term.kind() {
ty::TermKind::Ty(source_ty) => {
match source_ty.kind() {
&ty::Alias(ty::Projection, data) => {
Copy link
Member

Choose a reason for hiding this comment

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

we want to mirror this behaviour for projection consts, i.e. <T as Trait>::ASSOC_CONST under mGCA 🤔 Not quite sure what a test case would look like where this matters.

In general though I think instead of matching on the kind of the term and then on what kind of alias it is, we should match try convert to an AliasTerm and then match on the kind of that and handle ProjectionTy/ProjectionConst as one arm, and similarly for FreeTy/FreeConst/InherentConst/InherentTy etc

}

Ok(())
fn instantiate(&self, l: TermVid, r: ty::Term<'tcx>) {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
fn instantiate(&self, l: TermVid, r: ty::Term<'tcx>) {
fn instantiate_var_raw(&self, l: TermVid, r: ty::Term<'tcx>) {

and maybe a comment to indicate this is a thin wrapper around the actual var table instantiation methods. concerned that as is people might (wrongly) call this instead of instantiate_var or something since this sounds like it'd be the right thing to call but mostly isnt

source_ct,
generalized_ct,
)?;
fn equate(&self, l: TermVid, r: TermVid) {
Copy link
Member

Choose a reason for hiding this comment

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

similarly maybe fn union_vars instead 🤔 + a comment explaining its just a wrapper around the infer var tables

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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. WG-trait-system-refactor The Rustc Trait System Refactor Initiative (-Znext-solver)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[ICE]: Unevaluated ty::Const in MIR body

3 participants