Skip to content

Commit e21df4b

Browse files
author
Alexander Regueiro
committed
Handle upcasting to auto traits properly.
1 parent 2ee0694 commit e21df4b

File tree

2 files changed

+42
-26
lines changed

2 files changed

+42
-26
lines changed

src/librustc_codegen_ssa/base.rs

+19-17
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

+23-9
Original file line numberDiff line numberDiff line change
@@ -1865,9 +1865,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
18651865
//
18661866
// We always upcast when we can because of reason 3 (region bounds).
18671867

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

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

29592973
if tcx.features().trait_upcasting {
29602974
// Register obligations for `dyn TraitA1 [TraitA2...]: TraitB1 [TraitB2...]`.
@@ -2975,7 +2989,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
29752989
}
29762990
})
29772991
.map(|predicate|
2978-
predicate_to_obligation(predicate.with_self_ty(tcx, source_ty))
2992+
predicate_to_obligation(predicate.with_self_ty(tcx, source))
29792993
),
29802994
);
29812995
} else {
@@ -2997,7 +3011,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
29973011
// with what our behavior should be there. -nikomatsakis
29983012
let InferOk { obligations, .. } = self.infcx
29993013
.at(&obligation.cause, obligation.param_env)
3000-
.eq(target, source_ty) // FIXME: see above.
3014+
.eq(target, source_with_target_auto_traits) // FIXME: see above.
30013015
.map_err(|_| Unimplemented)?;
30023016
nested.extend(obligations);
30033017
}

0 commit comments

Comments
 (0)