Skip to content

Commit 2702404

Browse files
author
Alexander Regueiro
committed
Handle upcasting to auto traits properly.
1 parent 550167d commit 2702404

File tree

2 files changed

+42
-26
lines changed

2 files changed

+42
-26
lines changed

src/librustc_codegen_ssa/base.rs

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -161,25 +161,27 @@ pub fn unsized_info<'tcx, 'a, Bx: BuilderMethods<'a, 'tcx>>(
161161
// Trait upcast
162162

163163
let source_ptr = old_info.expect("unsized_info: missing old info for trait upcast");
164-
let target_trait_ref = target_data.principal()
165-
.expect("target trait object of upcast does not have principal");
166-
167-
let trait_ref = target_trait_ref.with_self_ty(tcx, source);
168-
let vtable = tcx.codegen_fulfill_obligation((ty::ParamEnv::reveal_all(), trait_ref));
169-
let offset = match vtable {
170-
Vtable::VtableObject(ref data) => data.vtable_base,
171-
// HACK(alexreg): dubious solution to ICE in `manual-self-impl-for-unsafe-obj` test.
172-
Vtable::VtableImpl(_) => 0,
173-
_ => bug!("unsized_info: unexpected vtable kind {:?}", vtable),
174-
};
164+
let target_ptr = if let Some(target_trait_ref) = target_data.principal() {
165+
let trait_ref = target_trait_ref.with_self_ty(tcx, source);
166+
let vtable = tcx.codegen_fulfill_obligation((ty::ParamEnv::reveal_all(), trait_ref));
167+
let offset = match vtable {
168+
Vtable::VtableObject(ref data) => data.vtable_base,
169+
// HACK(alexreg): slightly dubious solution to ICE in
170+
// `manual-self-impl-for-unsafe-obj` test.
171+
Vtable::VtableImpl(_) => 0,
172+
_ => bug!("unsized_info: unexpected vtable kind {:?}", vtable),
173+
};
175174

176-
let vtable_layout = bx.cx().layout_of(tcx.mk_mut_ptr(source));
177-
let source_ptr = bx.pointercast(
178-
source_ptr,
179-
bx.cx().scalar_pair_element_backend_type(vtable_layout, 1, true),
180-
);
175+
let vtable_layout = bx.cx().layout_of(tcx.mk_mut_ptr(source));
176+
let source_ptr = bx.pointercast(
177+
source_ptr,
178+
bx.cx().scalar_pair_element_backend_type(vtable_layout, 1, true),
179+
);
181180

182-
let target_ptr = bx.struct_gep(source_ptr, offset as u64);
181+
bx.struct_gep(source_ptr, offset as u64)
182+
} else {
183+
source_ptr
184+
};
183185

184186
let vtable_layout = bx.cx().layout_of(tcx.mk_mut_ptr(target));
185187
bx.pointercast(

src/librustc_trait_selection/traits/select.rs

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1864,9 +1864,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
18641864
//
18651865
// We always upcast when we can because of reason 3 (region bounds).
18661866

1867-
// All of a's auto traits need to be in b's auto traits.
1868-
data_b.auto_traits()
1869-
.all(|b| data_a.auto_traits().any(|a| a == b))
1867+
if self.tcx().features().trait_upcasting {
1868+
true
1869+
} else {
1870+
// Just allow upcast kinds 2 and 3 from above.
1871+
data_a.principal_def_id() == data_b.principal_def_id() &&
1872+
data_b.auto_traits()
1873+
// All of a's auto traits need to be in b's auto traits.
1874+
.all(|b| data_a.auto_traits().any(|a| a == b))
1875+
}
18701876
}
18711877

18721878
// `T` -> `Trait`
@@ -2948,12 +2954,20 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
29482954
let iter = data_a
29492955
.principal()
29502956
.map(ty::ExistentialPredicate::Trait)
2951-
.into_iter()
2952-
.chain(data_a.projection_bounds().map(ty::ExistentialPredicate::Projection))
2953-
.chain(data_b.auto_traits().map(ty::ExistentialPredicate::AutoTrait));
2957+
.into_iter().chain(
2958+
data_a
2959+
.projection_bounds()
2960+
.map(|x| ty::ExistentialPredicate::Projection(x)),
2961+
)
2962+
.chain(
2963+
data_b
2964+
.auto_traits()
2965+
.map(ty::ExistentialPredicate::AutoTrait),
2966+
);
29542967
tcx.mk_existential_predicates(iter)
29552968
});
2956-
let source_ty = tcx.mk_dynamic(existential_predicates, region_b);
2969+
let source_with_target_auto_traits =
2970+
tcx.mk_dynamic(existential_predicates, region_b);
29572971

29582972
if tcx.features().trait_upcasting {
29592973
// Register obligations for `dyn TraitA1 [TraitA2...]: TraitB1 [TraitB2...]`.
@@ -2974,7 +2988,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
29742988
}
29752989
})
29762990
.map(|predicate|
2977-
predicate_to_obligation(predicate.with_self_ty(tcx, source_ty))
2991+
predicate_to_obligation(predicate.with_self_ty(tcx, source))
29782992
),
29792993
);
29802994
} else {
@@ -2996,7 +3010,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
29963010
// with what our behavior should be there. -nikomatsakis
29973011
let InferOk { obligations, .. } = self.infcx
29983012
.at(&obligation.cause, obligation.param_env)
2999-
.eq(target, source_ty) // FIXME: see above.
3013+
.eq(target, source_with_target_auto_traits) // FIXME: see above.
30003014
.map_err(|_| Unimplemented)?;
30013015
nested.extend(obligations);
30023016
}

0 commit comments

Comments
 (0)