Skip to content

Commit 4409b44

Browse files
committed
Extract shared helper for registering ConstArgHasType during const projection normalization
1 parent 1d1de8b commit 4409b44

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;
@@ -59,15 +58,7 @@ where
5958
cx.const_of_item(inherent.def_id).instantiate(cx, inherent_args).skip_norm_wip().into()
6059
};
6160

62-
if let Some(ct) = normalized.as_const() {
63-
let expected_ty = cx.type_of(inherent.def_id).instantiate(cx, inherent_args);
64-
self.add_goal(
65-
GoalSource::Misc,
66-
goal.with(cx, ty::ClauseKind::ConstArgHasType(ct, expected_ty)),
67-
);
68-
}
69-
70-
self.instantiate_normalizes_to_term(goal, normalized);
61+
self.instantiate_normalizes_to_term_with_type_check(goal, normalized);
7162
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
7263
}
7364
}

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;
@@ -482,6 +483,30 @@ fn normalize_to_error<'a, 'tcx>(
482483
Normalized { value: new_value, obligations }
483484
}
484485

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

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

563588
let mut term = selcx.infcx.resolve_vars_if_possible(term);
564589
if term.has_aliases() {
@@ -2067,18 +2092,18 @@ fn confirm_impl_candidate<'cx, 'tcx>(
20672092
Progress { term: err, obligations: nested }
20682093
} else {
20692094
assoc_term_own_obligations(selcx, obligation, &mut nested);
2070-
let instantiated_term: Term<'tcx> = term.instantiate(tcx, args);
2071-
if let Some(ct) = instantiated_term.as_const() {
2072-
let expected_ty = tcx.type_of(assoc_term.item.def_id).instantiate(tcx, args);
2073-
nested.push(Obligation::with_depth(
2074-
tcx,
2075-
obligation.cause.clone(),
2076-
obligation.recursion_depth + 1,
2077-
obligation.param_env,
2078-
ty::ClauseKind::ConstArgHasType(ct, expected_ty),
2079-
));
2080-
}
2081-
Progress { term: instantiated_term.skip_norm_wip(), obligations: nested }
2095+
let instantiated_term: Term<'tcx> = term.instantiate(tcx, args).skip_norm_wip();
2096+
push_const_arg_has_type_obligation(
2097+
tcx,
2098+
&mut nested,
2099+
&obligation.cause,
2100+
obligation.recursion_depth + 1,
2101+
obligation.param_env,
2102+
instantiated_term,
2103+
assoc_term.item.def_id,
2104+
args,
2105+
);
2106+
Progress { term: instantiated_term, obligations: nested }
20822107
};
20832108
Ok(Projected::Progress(progress))
20842109
}

0 commit comments

Comments
 (0)