Skip to content

Commit cd6dec3

Browse files
committed
IAT: Proper WF computation
1 parent 61e1eda commit cd6dec3

File tree

2 files changed

+99
-54
lines changed

2 files changed

+99
-54
lines changed

compiler/rustc_trait_selection/src/traits/project.rs

+43-23
Original file line numberDiff line numberDiff line change
@@ -1274,29 +1274,14 @@ pub fn normalize_inherent_projection<'a, 'b, 'tcx>(
12741274
});
12751275
}
12761276

1277-
let impl_def_id = tcx.parent(alias_ty.def_id);
1278-
let impl_substs = selcx.infcx.fresh_substs_for_item(cause.span, impl_def_id);
1279-
1280-
let impl_ty = tcx.type_of(impl_def_id).subst(tcx, impl_substs);
1281-
let impl_ty =
1282-
normalize_with_depth_to(selcx, param_env, cause.clone(), depth + 1, impl_ty, obligations);
1283-
1284-
// Infer the generic parameters of the impl by unifying the
1285-
// impl type with the self type of the projection.
1286-
let self_ty = alias_ty.self_ty();
1287-
match selcx.infcx.at(&cause, param_env).eq(DefineOpaqueTypes::No, impl_ty, self_ty) {
1288-
Ok(mut ok) => obligations.append(&mut ok.obligations),
1289-
Err(_) => {
1290-
tcx.sess.delay_span_bug(
1291-
cause.span,
1292-
format!(
1293-
"{self_ty:?} was a subtype of {impl_ty:?} during selection but now it is not"
1294-
),
1295-
);
1296-
}
1297-
}
1298-
1299-
let substs = alias_ty.rebase_substs_onto_impl(impl_substs, tcx);
1277+
let substs = compute_inherent_assoc_ty_substs(
1278+
selcx,
1279+
param_env,
1280+
alias_ty,
1281+
cause.clone(),
1282+
depth,
1283+
obligations,
1284+
);
13001285

13011286
// Register the obligations arising from the impl and from the associated type itself.
13021287
let predicates = tcx.predicates_of(alias_ty.def_id).instantiate(tcx, substs);
@@ -1343,6 +1328,41 @@ pub fn normalize_inherent_projection<'a, 'b, 'tcx>(
13431328
ty
13441329
}
13451330

1331+
pub fn compute_inherent_assoc_ty_substs<'a, 'b, 'tcx>(
1332+
selcx: &'a mut SelectionContext<'b, 'tcx>,
1333+
param_env: ty::ParamEnv<'tcx>,
1334+
alias_ty: ty::AliasTy<'tcx>,
1335+
cause: ObligationCause<'tcx>,
1336+
depth: usize,
1337+
obligations: &mut Vec<PredicateObligation<'tcx>>,
1338+
) -> ty::SubstsRef<'tcx> {
1339+
let tcx = selcx.tcx();
1340+
1341+
let impl_def_id = tcx.parent(alias_ty.def_id);
1342+
let impl_substs = selcx.infcx.fresh_substs_for_item(cause.span, impl_def_id);
1343+
1344+
let impl_ty = tcx.type_of(impl_def_id).subst(tcx, impl_substs);
1345+
let impl_ty =
1346+
normalize_with_depth_to(selcx, param_env, cause.clone(), depth + 1, impl_ty, obligations);
1347+
1348+
// Infer the generic parameters of the impl by unifying the
1349+
// impl type with the self type of the projection.
1350+
let self_ty = alias_ty.self_ty();
1351+
match selcx.infcx.at(&cause, param_env).eq(DefineOpaqueTypes::No, impl_ty, self_ty) {
1352+
Ok(mut ok) => obligations.append(&mut ok.obligations),
1353+
Err(_) => {
1354+
tcx.sess.delay_span_bug(
1355+
cause.span,
1356+
format!(
1357+
"{self_ty:?} was a subtype of {impl_ty:?} during selection but now it is not"
1358+
),
1359+
);
1360+
}
1361+
}
1362+
1363+
alias_ty.rebase_substs_onto_impl(impl_substs, tcx)
1364+
}
1365+
13461366
enum Projected<'tcx> {
13471367
Progress(Progress<'tcx>),
13481368
NoProgress(ty::Term<'tcx>),

compiler/rustc_trait_selection/src/traits/wf.rs

+56-31
Original file line numberDiff line numberDiff line change
@@ -58,15 +58,8 @@ pub fn obligations<'tcx>(
5858
GenericArgKind::Lifetime(..) => return Some(Vec::new()),
5959
};
6060

61-
let mut wf = WfPredicates {
62-
tcx: infcx.tcx,
63-
param_env,
64-
body_id,
65-
span,
66-
out: vec![],
67-
recursion_depth,
68-
item: None,
69-
};
61+
let mut wf =
62+
WfPredicates { infcx, param_env, body_id, span, out: vec![], recursion_depth, item: None };
7063
wf.compute(arg);
7164
debug!("wf::obligations({:?}, body_id={:?}) = {:?}", arg, body_id, wf.out);
7265

@@ -91,7 +84,7 @@ pub fn unnormalized_obligations<'tcx>(
9184
debug_assert_eq!(arg, infcx.resolve_vars_if_possible(arg));
9285

9386
let mut wf = WfPredicates {
94-
tcx: infcx.tcx,
87+
infcx,
9588
param_env,
9689
body_id: CRATE_DEF_ID,
9790
span: DUMMY_SP,
@@ -116,7 +109,7 @@ pub fn trait_obligations<'tcx>(
116109
item: &'tcx hir::Item<'tcx>,
117110
) -> Vec<traits::PredicateObligation<'tcx>> {
118111
let mut wf = WfPredicates {
119-
tcx: infcx.tcx,
112+
infcx,
120113
param_env,
121114
body_id,
122115
span,
@@ -138,7 +131,7 @@ pub fn predicate_obligations<'tcx>(
138131
span: Span,
139132
) -> Vec<traits::PredicateObligation<'tcx>> {
140133
let mut wf = WfPredicates {
141-
tcx: infcx.tcx,
134+
infcx,
142135
param_env,
143136
body_id,
144137
span,
@@ -190,8 +183,8 @@ pub fn predicate_obligations<'tcx>(
190183
wf.normalize(infcx)
191184
}
192185

193-
struct WfPredicates<'tcx> {
194-
tcx: TyCtxt<'tcx>,
186+
struct WfPredicates<'a, 'tcx> {
187+
infcx: &'a InferCtxt<'tcx>,
195188
param_env: ty::ParamEnv<'tcx>,
196189
body_id: LocalDefId,
197190
span: Span,
@@ -290,9 +283,9 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>(
290283
}
291284
}
292285

293-
impl<'tcx> WfPredicates<'tcx> {
286+
impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
294287
fn tcx(&self) -> TyCtxt<'tcx> {
295-
self.tcx
288+
self.infcx.tcx
296289
}
297290

298291
fn cause(&self, code: traits::ObligationCauseCode<'tcx>) -> traits::ObligationCause<'tcx> {
@@ -325,7 +318,7 @@ impl<'tcx> WfPredicates<'tcx> {
325318

326319
/// Pushes the obligations required for `trait_ref` to be WF into `self.out`.
327320
fn compute_trait_pred(&mut self, trait_pred: &ty::TraitPredicate<'tcx>, elaborate: Elaborate) {
328-
let tcx = self.tcx;
321+
let tcx = self.tcx();
329322
let trait_ref = &trait_pred.trait_ref;
330323

331324
// Negative trait predicates don't require supertraits to hold, just
@@ -369,7 +362,6 @@ impl<'tcx> WfPredicates<'tcx> {
369362
self.out.extend(obligations);
370363
}
371364

372-
let tcx = self.tcx();
373365
self.out.extend(
374366
trait_ref
375367
.substs
@@ -436,13 +428,45 @@ impl<'tcx> WfPredicates<'tcx> {
436428
let obligations = self.nominal_obligations_without_const(data.def_id, data.substs);
437429
self.out.extend(obligations);
438430

431+
self.compute_projection_substs(data.substs);
432+
}
433+
434+
fn compute_inherent_projection(&mut self, data: ty::AliasTy<'tcx>) {
435+
// An inherent projection is well-formed if
436+
//
437+
// (a) its predicates hold (*)
438+
// (b) its substs are wf
439+
//
440+
// (*) The predicates of an inherent associated type include the
441+
// predicates of the impl that it's contained in.
442+
443+
if !data.self_ty().has_escaping_bound_vars() {
444+
// FIXME(inherent_associated_types): Should this happen inside of a snapshot?
445+
// FIXME(inherent_associated_types): This is incompatible with the new solver and lazy norm!
446+
let substs = traits::project::compute_inherent_assoc_ty_substs(
447+
&mut traits::SelectionContext::new(self.infcx),
448+
self.param_env,
449+
data,
450+
self.cause(traits::WellFormed(None)),
451+
self.recursion_depth,
452+
&mut self.out,
453+
);
454+
// Inherent projection types do not require const predicates.
455+
let obligations = self.nominal_obligations_without_const(data.def_id, substs);
456+
self.out.extend(obligations);
457+
}
458+
459+
self.compute_projection_substs(data.substs);
460+
}
461+
462+
fn compute_projection_substs(&mut self, substs: SubstsRef<'tcx>) {
439463
let tcx = self.tcx();
440464
let cause = self.cause(traits::WellFormed(None));
441465
let param_env = self.param_env;
442466
let depth = self.recursion_depth;
443467

444468
self.out.extend(
445-
data.substs
469+
substs
446470
.iter()
447471
.filter(|arg| {
448472
matches!(arg.unpack(), GenericArgKind::Type(..) | GenericArgKind::Const(..))
@@ -464,9 +488,9 @@ impl<'tcx> WfPredicates<'tcx> {
464488
if !subty.has_escaping_bound_vars() {
465489
let cause = self.cause(cause);
466490
let trait_ref =
467-
ty::TraitRef::from_lang_item(self.tcx, LangItem::Sized, cause.span, [subty]);
491+
ty::TraitRef::from_lang_item(self.tcx(), LangItem::Sized, cause.span, [subty]);
468492
self.out.push(traits::Obligation::with_depth(
469-
self.tcx,
493+
self.tcx(),
470494
cause,
471495
self.recursion_depth,
472496
self.param_env,
@@ -605,8 +629,9 @@ impl<'tcx> WfPredicates<'tcx> {
605629
walker.skip_current_subtree(); // Subtree handled by compute_projection.
606630
self.compute_projection(data);
607631
}
608-
ty::Alias(ty::Inherent, _) => {
609-
// WF if their substs are WF.
632+
ty::Alias(ty::Inherent, data) => {
633+
walker.skip_current_subtree(); // Subtree handled by compute_inherent_projection.
634+
self.compute_inherent_projection(data);
610635
}
611636

612637
ty::Adt(def, substs) => {
@@ -700,7 +725,7 @@ impl<'tcx> WfPredicates<'tcx> {
700725
// All of the requirements on type parameters
701726
// have already been checked for `impl Trait` in
702727
// return position. We do need to check type-alias-impl-trait though.
703-
if self.tcx.is_type_alias_impl_trait(def_id) {
728+
if self.tcx().is_type_alias_impl_trait(def_id) {
704729
let obligations = self.nominal_obligations(def_id, substs);
705730
self.out.extend(obligations);
706731
}
@@ -770,15 +795,15 @@ impl<'tcx> WfPredicates<'tcx> {
770795
substs: SubstsRef<'tcx>,
771796
remap_constness: bool,
772797
) -> Vec<traits::PredicateObligation<'tcx>> {
773-
let predicates = self.tcx.predicates_of(def_id);
798+
let predicates = self.tcx().predicates_of(def_id);
774799
let mut origins = vec![def_id; predicates.predicates.len()];
775800
let mut head = predicates;
776801
while let Some(parent) = head.parent {
777-
head = self.tcx.predicates_of(parent);
802+
head = self.tcx().predicates_of(parent);
778803
origins.extend(iter::repeat(parent).take(head.predicates.len()));
779804
}
780805

781-
let predicates = predicates.instantiate(self.tcx, substs);
806+
let predicates = predicates.instantiate(self.tcx(), substs);
782807
trace!("{:#?}", predicates);
783808
debug_assert_eq!(predicates.predicates.len(), origins.len());
784809

@@ -791,10 +816,10 @@ impl<'tcx> WfPredicates<'tcx> {
791816
};
792817
let cause = self.cause(code);
793818
if remap_constness {
794-
pred = pred.without_const(self.tcx);
819+
pred = pred.without_const(self.tcx());
795820
}
796821
traits::Obligation::with_depth(
797-
self.tcx,
822+
self.tcx(),
798823
cause,
799824
self.recursion_depth,
800825
self.param_env,
@@ -859,7 +884,7 @@ impl<'tcx> WfPredicates<'tcx> {
859884
// Note: in fact we only permit builtin traits, not `Bar<'d>`, I
860885
// am looking forward to the future here.
861886
if !data.has_escaping_bound_vars() && !region.has_escaping_bound_vars() {
862-
let implicit_bounds = object_region_bounds(self.tcx, data);
887+
let implicit_bounds = object_region_bounds(self.tcx(), data);
863888

864889
let explicit_bound = region;
865890

@@ -869,7 +894,7 @@ impl<'tcx> WfPredicates<'tcx> {
869894
let outlives =
870895
ty::Binder::dummy(ty::OutlivesPredicate(explicit_bound, implicit_bound));
871896
self.out.push(traits::Obligation::with_depth(
872-
self.tcx,
897+
self.tcx(),
873898
cause,
874899
self.recursion_depth,
875900
self.param_env,

0 commit comments

Comments
 (0)