Skip to content

Commit 518648d

Browse files
Structurally normalize in selection
1 parent da1d099 commit 518648d

File tree

2 files changed

+64
-17
lines changed

2 files changed

+64
-17
lines changed

compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs

+46-17
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,23 @@ use rustc_hir::def_id::DefId;
44
use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk};
55
use rustc_infer::traits::util::supertraits;
66
use rustc_infer::traits::{
7-
Obligation, PolyTraitObligation, PredicateObligation, Selection, SelectionResult,
7+
Obligation, PolyTraitObligation, PredicateObligation, Selection, SelectionResult, TraitEngine,
88
};
99
use rustc_middle::traits::solve::{CanonicalInput, Certainty, Goal};
1010
use rustc_middle::traits::{
1111
ImplSource, ImplSourceObjectData, ImplSourceTraitUpcastingData, ImplSourceUserDefinedData,
1212
ObligationCause, SelectionError,
1313
};
14-
use rustc_middle::ty::{self, TyCtxt};
14+
use rustc_middle::ty::{self, Ty, TyCtxt};
1515
use rustc_span::DUMMY_SP;
1616

1717
use crate::solve::assembly::{BuiltinImplSource, Candidate, CandidateSource};
1818
use crate::solve::eval_ctxt::{EvalCtxt, GenerateProofTree};
1919
use crate::solve::inspect::ProofTreeBuilder;
2020
use crate::solve::search_graph::OverflowHandler;
2121
use crate::traits::vtable::{count_own_vtable_entries, prepare_vtable_segments, VtblSegment};
22+
use crate::traits::StructurallyNormalizeExt;
23+
use crate::traits::TraitEngineExt;
2224

2325
pub trait InferCtxtSelectExt<'tcx> {
2426
fn select_in_new_trait_solver(
@@ -220,25 +222,33 @@ fn rematch_object<'tcx>(
220222
goal: Goal<'tcx, ty::TraitPredicate<'tcx>>,
221223
mut nested: Vec<PredicateObligation<'tcx>>,
222224
) -> SelectionResult<'tcx, Selection<'tcx>> {
223-
let self_ty = goal.predicate.self_ty();
224-
let ty::Dynamic(data, _, source_kind) = *self_ty.kind()
225+
let a_ty = structurally_normalize(goal.predicate.self_ty(), infcx, goal.param_env, &mut nested);
226+
let ty::Dynamic(data, _, source_kind) = *a_ty.kind()
225227
else {
226228
bug!()
227229
};
228-
let source_trait_ref = data.principal().unwrap().with_self_ty(infcx.tcx, self_ty);
229-
230-
let (is_upcasting, target_trait_ref_unnormalized) = if Some(goal.predicate.def_id())
231-
== infcx.tcx.lang_items().unsize_trait()
232-
{
233-
assert_eq!(source_kind, ty::Dyn, "cannot upcast dyn*");
234-
if let ty::Dynamic(data, _, ty::Dyn) = goal.predicate.trait_ref.substs.type_at(1).kind() {
235-
(true, data.principal().unwrap().with_self_ty(infcx.tcx, self_ty))
230+
let source_trait_ref = data.principal().unwrap().with_self_ty(infcx.tcx, a_ty);
231+
232+
let (is_upcasting, target_trait_ref_unnormalized) =
233+
if Some(goal.predicate.def_id()) == infcx.tcx.lang_items().unsize_trait() {
234+
assert_eq!(source_kind, ty::Dyn, "cannot upcast dyn*");
235+
let b_ty = structurally_normalize(
236+
goal.predicate.trait_ref.substs.type_at(1),
237+
infcx,
238+
goal.param_env,
239+
&mut nested,
240+
);
241+
if let ty::Dynamic(data, _, ty::Dyn) = *b_ty.kind() {
242+
// FIXME: We also need to ensure that the source lifetime outlives the
243+
// target lifetime. This doesn't matter for codegen, though, and only
244+
// *really* matters if the goal's certainty is ambiguous.
245+
(true, data.principal().unwrap().with_self_ty(infcx.tcx, a_ty))
246+
} else {
247+
bug!()
248+
}
236249
} else {
237-
bug!()
238-
}
239-
} else {
240-
(false, ty::Binder::dummy(goal.predicate.trait_ref))
241-
};
250+
(false, ty::Binder::dummy(goal.predicate.trait_ref))
251+
};
242252

243253
let mut target_trait_ref = None;
244254
for candidate_trait_ref in supertraits(infcx.tcx, source_trait_ref) {
@@ -305,3 +315,22 @@ fn rematch_object<'tcx>(
305315
ImplSource::Object(ImplSourceObjectData { vtable_base, nested })
306316
}))
307317
}
318+
319+
fn structurally_normalize<'tcx>(
320+
ty: Ty<'tcx>,
321+
infcx: &InferCtxt<'tcx>,
322+
param_env: ty::ParamEnv<'tcx>,
323+
nested: &mut Vec<PredicateObligation<'tcx>>,
324+
) -> Ty<'tcx> {
325+
if matches!(ty.kind(), ty::Alias(..)) {
326+
let mut engine = <dyn TraitEngine<'tcx>>::new(infcx);
327+
let normalized_ty = infcx
328+
.at(&ObligationCause::dummy(), param_env)
329+
.structurally_normalize(ty, &mut *engine)
330+
.expect("normalization shouldn't fail if we got to here");
331+
nested.extend(engine.pending_obligations());
332+
normalized_ty
333+
} else {
334+
ty
335+
}
336+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// check-pass
2+
// compile-flags: -Ztrait-solver=next
3+
4+
pub trait A {}
5+
pub trait B: A {}
6+
7+
pub trait Mirror {
8+
type Assoc: ?Sized;
9+
}
10+
impl<T: ?Sized> Mirror for T {
11+
type Assoc = T;
12+
}
13+
14+
pub fn foo<'a>(x: &'a <dyn B + 'static as Mirror>::Assoc) -> &'a (dyn A + 'static) {
15+
x
16+
}
17+
18+
fn main() {}

0 commit comments

Comments
 (0)