Skip to content

Set groundwork for proper const normalization #140549

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

Merged
merged 3 commits into from
May 4, 2025
Merged
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: 17 additions & 8 deletions compiler/rustc_infer/src/infer/projection.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::{self, Ty};
use rustc_middle::ty;

use super::InferCtxt;
use crate::infer::Term;
use crate::traits::{Obligation, PredicateObligations};

impl<'tcx> InferCtxt<'tcx> {
Expand All @@ -11,24 +12,32 @@ impl<'tcx> InferCtxt<'tcx> {
/// of the given projection. This allows us to proceed with projections
/// while they cannot be resolved yet due to missing information or
/// simply due to the lack of access to the trait resolution machinery.
pub fn projection_ty_to_infer(
pub fn projection_term_to_infer(
&self,
param_env: ty::ParamEnv<'tcx>,
projection_ty: ty::AliasTy<'tcx>,
alias_term: ty::AliasTerm<'tcx>,
cause: ObligationCause<'tcx>,
recursion_depth: usize,
obligations: &mut PredicateObligations<'tcx>,
) -> Ty<'tcx> {
) -> Term<'tcx> {
debug_assert!(!self.next_trait_solver());
let ty_var = self.next_ty_var(self.tcx.def_span(projection_ty.def_id));

let span = self.tcx.def_span(alias_term.def_id);
let infer_var = if alias_term.kind(self.tcx).is_type() {
self.next_ty_var(span).into()
} else {
self.next_const_var(span).into()
};

let projection =
ty::PredicateKind::Clause(ty::ClauseKind::Projection(ty::ProjectionPredicate {
projection_term: projection_ty.into(),
term: ty_var.into(),
projection_term: alias_term,
term: infer_var,
}));
let obligation =
Obligation::with_depth(self.tcx, cause, recursion_depth, param_env, projection);
obligations.push(obligation);
ty_var

infer_var
}
}
12 changes: 10 additions & 2 deletions compiler/rustc_middle/src/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -243,10 +243,18 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
ty::AliasTermKind::ProjectionTy
}
}
DefKind::AssocConst => {
if let DefKind::Impl { of_trait: false } = self.def_kind(self.parent(alias.def_id))
{
ty::AliasTermKind::InherentConst
} else {
ty::AliasTermKind::ProjectionConst
}
}
DefKind::OpaqueTy => ty::AliasTermKind::OpaqueTy,
DefKind::TyAlias => ty::AliasTermKind::FreeTy,
DefKind::AssocConst => ty::AliasTermKind::ProjectionConst,
DefKind::AnonConst | DefKind::Const | DefKind::Ctor(_, CtorKind::Const) => {
DefKind::Const => ty::AliasTermKind::FreeConst,
DefKind::AnonConst | DefKind::Ctor(_, CtorKind::Const) => {
ty::AliasTermKind::UnevaluatedConst
}
kind => bug!("unexpected DefKind in AliasTy: {kind:?}"),
Expand Down
5 changes: 3 additions & 2 deletions compiler/rustc_middle/src/ty/print/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3195,7 +3195,7 @@ define_print! {

ty::AliasTerm<'tcx> {
match self.kind(cx.tcx()) {
ty::AliasTermKind::InherentTy => p!(pretty_print_inherent_projection(*self)),
ty::AliasTermKind::InherentTy | ty::AliasTermKind::InherentConst => p!(pretty_print_inherent_projection(*self)),
ty::AliasTermKind::ProjectionTy => {
if !(cx.should_print_verbose() || with_reduced_queries())
&& cx.tcx().is_impl_trait_in_trait(self.def_id)
Expand All @@ -3205,7 +3205,8 @@ define_print! {
p!(print_def_path(self.def_id, self.args));
}
}
| ty::AliasTermKind::FreeTy
ty::AliasTermKind::FreeTy
| ty::AliasTermKind::FreeConst
| ty::AliasTermKind::OpaqueTy
| ty::AliasTermKind::UnevaluatedConst
| ty::AliasTermKind::ProjectionConst => {
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_middle/src/ty/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -966,7 +966,9 @@ impl<'tcx> TyCtxt<'tcx> {
}
ty::AliasTermKind::OpaqueTy => Some(self.variances_of(def_id)),
ty::AliasTermKind::InherentTy
| ty::AliasTermKind::InherentConst
| ty::AliasTermKind::FreeTy
| ty::AliasTermKind::FreeConst
| ty::AliasTermKind::UnevaluatedConst
| ty::AliasTermKind::ProjectionConst => None,
}
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_mir_build/src/thir/pattern/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {

// Lower the named constant to a THIR pattern.
let args = self.typeck_results.node_args(id);
// FIXME(mgca): we will need to special case IACs here to have type system compatible
// generic args, instead of how we represent them in body expressions.
let c = ty::Const::new_unevaluated(self.tcx, ty::UnevaluatedConst { def: def_id, args });
let mut pattern = self.const_to_pat(c, ty, id, span);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,25 @@ where
goal: Goal<I, ty::NormalizesTo<I>>,
) -> QueryResult<I> {
let cx = self.cx();
let free_ty = goal.predicate.alias;
let free_alias = goal.predicate.alias;

// Check where clauses
self.add_goals(
GoalSource::Misc,
cx.predicates_of(free_ty.def_id)
.iter_instantiated(cx, free_ty.args)
cx.predicates_of(free_alias.def_id)
.iter_instantiated(cx, free_alias.args)
.map(|pred| goal.with(cx, pred)),
);

let actual = cx.type_of(free_ty.def_id).instantiate(cx, free_ty.args);
self.instantiate_normalizes_to_term(goal, actual.into());
let actual = if free_alias.kind(cx).is_type() {
cx.type_of(free_alias.def_id).instantiate(cx, free_alias.args)
} else {
// FIXME(mgca): once const items are actual aliases defined as equal to type system consts
// this should instead return that.
panic!("normalizing free const aliases in the type system is unsupported");
};

self.instantiate_normalizes_to_term(goal, actual.into());
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ where
D: SolverDelegate<Interner = I>,
I: Interner,
{
pub(super) fn normalize_inherent_associated_type(
pub(super) fn normalize_inherent_associated_term(
&mut self,
goal: Goal<I, ty::NormalizesTo<I>>,
) -> QueryResult<I> {
let cx = self.cx();
let inherent = goal.predicate.alias.expect_ty(cx);
let inherent = goal.predicate.alias;

let impl_def_id = cx.parent(inherent.def_id);
let impl_args = self.fresh_args_for_item(impl_def_id);
Expand Down Expand Up @@ -48,8 +48,13 @@ where
.map(|pred| goal.with(cx, pred)),
);

let normalized = cx.type_of(inherent.def_id).instantiate(cx, inherent_args);
self.instantiate_normalizes_to_term(goal, normalized.into());
let normalized = if inherent.kind(cx).is_type() {
cx.type_of(inherent.def_id).instantiate(cx, inherent_args).into()
} else {
// FIXME(mgca): Properly handle IACs in the type system
panic!("normalizing inherent associated consts in the type system is unsupported");
};
self.instantiate_normalizes_to_term(goal, normalized);
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
}
}
10 changes: 8 additions & 2 deletions compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,13 @@ where
})
})
}
ty::AliasTermKind::InherentTy => self.normalize_inherent_associated_type(goal),
ty::AliasTermKind::InherentTy | ty::AliasTermKind::InherentConst => {
self.normalize_inherent_associated_term(goal)
}
ty::AliasTermKind::OpaqueTy => self.normalize_opaque_type(goal),
ty::AliasTermKind::FreeTy => self.normalize_free_alias(goal),
ty::AliasTermKind::FreeTy | ty::AliasTermKind::FreeConst => {
self.normalize_free_alias(goal)
}
ty::AliasTermKind::UnevaluatedConst => self.normalize_anon_const(goal),
}
}
Expand Down Expand Up @@ -333,6 +337,8 @@ where
cx.type_of(target_item_def_id).map_bound(|ty| ty.into())
}
ty::AliasTermKind::ProjectionConst => {
// FIXME(mgca): once const items are actual aliases defined as equal to type system consts
// this should instead return that.
if cx.features().associated_const_equality() {
panic!("associated const projection is not supported yet")
} else {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_trait_selection/src/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ pub use self::dyn_compatibility::{
pub use self::engine::{ObligationCtxt, TraitEngineExt};
pub use self::fulfill::{FulfillmentContext, OldSolverError, PendingPredicateObligation};
pub use self::normalize::NormalizeExt;
pub use self::project::{normalize_inherent_projection, normalize_projection_ty};
pub use self::project::{normalize_inherent_projection, normalize_projection_term};
pub use self::select::{
EvaluationCache, EvaluationResult, IntercrateAmbiguityCause, OverflowError, SelectionCache,
SelectionContext,
Expand Down
Loading
Loading