Skip to content

Commit e317bc9

Browse files
committed
RFC 2027: Disallow coercion to non-object safe trait objects
1 parent 01c5e01 commit e317bc9

File tree

1 file changed

+46
-4
lines changed

1 file changed

+46
-4
lines changed

src/librustc_typeck/check/coercion.rs

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ use rustc::infer::{Coercion, InferResult, InferOk};
5858
use rustc::infer::type_variable::TypeVariableOrigin;
5959
use rustc::traits::{self, ObligationCause, ObligationCauseCode};
6060
use rustc::ty::adjustment::{Adjustment, Adjust, AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
61-
use rustc::ty::{self, TypeAndMut, Ty, ClosureSubsts};
61+
use rustc::ty::{self, TypeAndMut, Ty, ClosureSubsts, Binder, List, ExistentialPredicate};
6262
use rustc::ty::fold::TypeFoldable;
6363
use rustc::ty::error::TypeError;
6464
use rustc::ty::relate::RelateResult;
@@ -555,9 +555,19 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
555555
ty::Predicate::Trait(ref tr) if traits.contains(&tr.def_id()) => {
556556
if unsize_did == tr.def_id() {
557557
let sty = &tr.skip_binder().input_types().nth(1).unwrap().sty;
558-
if let ty::Tuple(..) = sty {
559-
debug!("coerce_unsized: found unsized tuple coercion");
560-
has_unsized_tuple_coercion = true;
558+
match sty {
559+
ty::Tuple(..) => {
560+
debug!("coerce_unsized: found unsized tuple coercion");
561+
has_unsized_tuple_coercion = true;
562+
}
563+
ty::Dynamic(data, _) => {
564+
if self.tcx.features().object_safe_for_dispatch {
565+
self.check_coercion_object_safe(&mut selcx,
566+
tr,
567+
data)?;
568+
}
569+
}
570+
_ => {}
561571
}
562572
}
563573
tr.clone()
@@ -626,6 +636,38 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
626636
Ok(coercion)
627637
}
628638

639+
fn check_coercion_object_safe(&self,
640+
selcx: &mut traits::SelectionContext<'f, 'gcx, 'tcx>,
641+
pred: &ty::PolyTraitPredicate<'tcx>,
642+
data: &Binder<&'tcx List<ExistentialPredicate<'tcx>>>)
643+
-> Result<(), TypeError<'tcx>> {
644+
645+
let source = &pred.skip_binder().self_ty().sty;
646+
match source {
647+
ty::Dynamic(..) => Ok(()),
648+
_ => {
649+
let cause = ObligationCause::misc(self.cause.span, self.body_id);
650+
let component_traits =
651+
data.auto_traits().chain(data.principal_def_id());
652+
for target_def_id in component_traits {
653+
let obj_safe = traits::Obligation::new(
654+
cause.clone(),
655+
self.fcx.param_env,
656+
ty::Predicate::ObjectSafe(target_def_id)
657+
);
658+
match selcx.select(&obj_safe.with(pred.clone())) {
659+
Ok(_) => (),
660+
Err(err) => {
661+
self.report_selection_error(&obj_safe, &err, false);
662+
return Err(TypeError::Mismatch)
663+
}
664+
}
665+
}
666+
Ok(())
667+
}
668+
}
669+
}
670+
629671
fn coerce_from_safe_fn<F, G>(&self,
630672
a: Ty<'tcx>,
631673
fn_ty_a: ty::PolyFnSig<'tcx>,

0 commit comments

Comments
 (0)