Skip to content

Commit 1cb77a2

Browse files
committed
Extract shared helper for registering ConstArgHasType during const projection normalization
1 parent d998320 commit 1cb77a2

3 files changed

Lines changed: 73 additions & 42 deletions

File tree

compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
//! 2. equate the self type, and
66
//! 3. instantiate and register where clauses.
77
8-
use rustc_type_ir::inherent::*;
98
use rustc_type_ir::{self as ty, Interner, Unnormalized};
109

1110
use crate::delegate::SolverDelegate;
@@ -62,15 +61,7 @@ where
6261
.into()
6362
};
6463

65-
if let Some(ct) = normalized.as_const() {
66-
let expected_ty = cx.type_of(inherent.def_id).instantiate(cx, inherent_args);
67-
self.add_goal(
68-
GoalSource::Misc,
69-
goal.with(cx, ty::ClauseKind::ConstArgHasType(ct, expected_ty)),
70-
);
71-
}
72-
73-
self.instantiate_normalizes_to_term(goal, normalized);
64+
self.instantiate_normalizes_to_term_with_type_check(goal, normalized);
7465
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
7566
}
7667
}

compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,27 @@ where
110110
.expect("expected goal term to be fully unconstrained");
111111
}
112112

113+
/// Like `instantiate_normalizes_to_term`, but also registers a
114+
/// `ConstArgHasType` goal when the term is a const. This ensures that
115+
/// the const value's type matches the type of the alias it was
116+
/// normalized from, preventing ICEs from type mismatches.
117+
pub fn instantiate_normalizes_to_term_with_type_check(
118+
&mut self,
119+
goal: Goal<I, NormalizesTo<I>>,
120+
term: I::Term,
121+
) {
122+
if let Some(ct) = term.as_const() {
123+
let cx = self.cx();
124+
let alias = goal.predicate.alias;
125+
let expected_ty = cx.type_of(alias.def_id()).instantiate(cx, alias.args).skip_norm_wip();
126+
self.add_goal(
127+
GoalSource::Misc,
128+
goal.with(cx, ty::ClauseKind::ConstArgHasType(ct, expected_ty)),
129+
);
130+
}
131+
self.instantiate_normalizes_to_term(goal, term);
132+
}
133+
113134
/// Unlike `instantiate_normalizes_to_term` this instantiates the expected term
114135
/// with a rigid alias. Using this is pretty much always wrong.
115136
pub fn structurally_instantiate_normalizes_to_term(
@@ -393,16 +414,10 @@ where
393414
kind => panic!("expected projection, found {kind:?}"),
394415
};
395416

396-
let instantiated_term: I::Term = term.instantiate(cx, target_args);
397-
if let Some(ct) = instantiated_term.as_const() {
398-
let expected_ty = cx.type_of(target_item_def_id).instantiate(cx, target_args);
399-
ecx.add_goal(
400-
GoalSource::Misc,
401-
goal.with(cx, ty::ClauseKind::ConstArgHasType(ct, expected_ty)),
402-
);
403-
}
404-
405-
ecx.instantiate_normalizes_to_term(goal, instantiated_term.skip_norm_wip());
417+
ecx.instantiate_normalizes_to_term_with_type_check(
418+
goal,
419+
term.instantiate(cx, target_args).skip_norm_wip(),
420+
);
406421
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
407422
})
408423
}

compiler/rustc_trait_selection/src/traits/project.rs

Lines changed: 47 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use std::ops::ControlFlow;
55
use rustc_data_structures::sso::SsoHashSet;
66
use rustc_data_structures::stack::ensure_sufficient_stack;
77
use rustc_errors::ErrorGuaranteed;
8+
use rustc_hir::def_id::DefId;
89
use rustc_hir::lang_items::LangItem;
910
use rustc_infer::infer::DefineOpaqueTypes;
1011
use rustc_infer::infer::resolve::OpportunisticRegionResolver;
@@ -484,6 +485,30 @@ fn normalize_to_error<'a, 'tcx>(
484485
Normalized { value: new_value, obligations }
485486
}
486487

488+
/// When normalizing a const alias, register a `ConstArgHasType` obligation
489+
/// to ensure the const value's type matches the declared type.
490+
fn push_const_arg_has_type_obligation<'tcx>(
491+
tcx: TyCtxt<'tcx>,
492+
obligations: &mut PredicateObligations<'tcx>,
493+
cause: &ObligationCause<'tcx>,
494+
depth: usize,
495+
param_env: ty::ParamEnv<'tcx>,
496+
term: Term<'tcx>,
497+
def_id: DefId,
498+
args: ty::GenericArgsRef<'tcx>,
499+
) {
500+
if let Some(ct) = term.as_const() {
501+
let expected_ty = tcx.type_of(def_id).instantiate(tcx, args).skip_norm_wip();
502+
obligations.push(Obligation::with_depth(
503+
tcx,
504+
cause.clone(),
505+
depth,
506+
param_env,
507+
ty::ClauseKind::ConstArgHasType(ct, expected_ty),
508+
));
509+
}
510+
}
511+
487512
/// Confirm and normalize the given inherent projection.
488513
// FIXME(mgca): While this supports constants, it is only used for types by default right now
489514
#[instrument(level = "debug", skip(selcx, param_env, cause, obligations))]
@@ -551,16 +576,16 @@ pub fn normalize_inherent_projection<'a, 'b, 'tcx>(
551576
tcx.const_of_item(alias_term.def_id()).instantiate(tcx, args).skip_norm_wip().into()
552577
};
553578

554-
if let Some(ct) = term.as_const() {
555-
let expected_ty = tcx.type_of(alias_term.def_id).instantiate(tcx, args);
556-
obligations.push(Obligation::with_depth(
557-
tcx,
558-
cause.clone(),
559-
depth + 1,
560-
param_env,
561-
ty::ClauseKind::ConstArgHasType(ct, expected_ty),
562-
));
563-
}
579+
push_const_arg_has_type_obligation(
580+
tcx,
581+
obligations,
582+
&cause,
583+
depth + 1,
584+
param_env,
585+
term,
586+
alias_term.def_id(),
587+
args,
588+
);
564589

565590
let mut term = selcx.infcx.resolve_vars_if_possible(term);
566591
if term.has_aliases() {
@@ -2057,18 +2082,18 @@ fn confirm_impl_candidate<'cx, 'tcx>(
20572082
Progress { term: err, obligations: nested }
20582083
} else {
20592084
assoc_term_own_obligations(selcx, obligation, &mut nested);
2060-
let instantiated_term: Term<'tcx> = term.instantiate(tcx, args);
2061-
if let Some(ct) = instantiated_term.as_const() {
2062-
let expected_ty = tcx.type_of(assoc_term.item.def_id).instantiate(tcx, args);
2063-
nested.push(Obligation::with_depth(
2064-
tcx,
2065-
obligation.cause.clone(),
2066-
obligation.recursion_depth + 1,
2067-
obligation.param_env,
2068-
ty::ClauseKind::ConstArgHasType(ct, expected_ty),
2069-
));
2070-
}
2071-
Progress { term: instantiated_term.skip_norm_wip(), obligations: nested }
2085+
let instantiated_term: Term<'tcx> = term.instantiate(tcx, args).skip_norm_wip();
2086+
push_const_arg_has_type_obligation(
2087+
tcx,
2088+
&mut nested,
2089+
&obligation.cause,
2090+
obligation.recursion_depth + 1,
2091+
obligation.param_env,
2092+
instantiated_term,
2093+
assoc_term.item.def_id,
2094+
args,
2095+
);
2096+
Progress { term: instantiated_term, obligations: nested }
20722097
};
20732098
Ok(Projected::Progress(progress))
20742099
}

0 commit comments

Comments
 (0)