self.register_unsize_obligations(span, &**u)
}
ty::UnsizeVtable(ref ty_trait, self_ty) => {
- vtable::check_object_safety(self.tcx(), ty_trait, span);
-
+ vtable::check_object_safety(self.tcx(), &ty_trait.principal, span);
// If the type is `Foo+'a`, ensures that the type
// being cast to `Foo+'a` implements `Foo`:
vtable::register_object_cast_obligations(self,
// Ensure that if ~T is cast to ~Trait, then T : Trait
push_cast_obligation(fcx, cast_expr, object_trait, referent_ty);
- check_object_safety(fcx.tcx(), object_trait, source_expr.span);
+ check_object_safety(fcx.tcx(), &object_trait.principal, source_expr.span);
}
(&ty::ty_rptr(referent_region, ty::mt { ty: referent_ty,
target_region,
referent_region);
- check_object_safety(fcx.tcx(), object_trait, source_expr.span);
+ check_object_safety(fcx.tcx(), &object_trait.principal, source_expr.span);
}
}
// self by value, has no type parameters and does not use the `Self` type, except
// in self position.
pub fn check_object_safety<'tcx>(tcx: &ty::ctxt<'tcx>,
- object_trait: &ty::TyTrait<'tcx>,
+ object_trait: &ty::TraitRef<'tcx>,
+ span: Span) {
+
+ let mut object = object_trait.clone();
+ if object.substs.types.len(SelfSpace) == 0 {
+ object.substs.types.push(SelfSpace, ty::mk_err());
+ }
+
+ let object = Rc::new(object);
+ for tr in traits::supertraits(tcx, object) {
+ check_object_safety_inner(tcx, &*tr, span);
+ }
+}
+
+fn check_object_safety_inner<'tcx>(tcx: &ty::ctxt<'tcx>,
+ object_trait: &ty::TraitRef<'tcx>,
span: Span) {
// Skip the fn_once lang item trait since only the compiler should call
// `call_once` which is the method which takes self by value. What could go
// wrong?
match tcx.lang_items.fn_once_trait() {
- Some(def_id) if def_id == object_trait.principal.def_id => return,
+ Some(def_id) if def_id == object_trait.def_id => return,
_ => {}
}
- let trait_items = ty::trait_items(tcx, object_trait.principal.def_id);
+ let trait_items = ty::trait_items(tcx, object_trait.def_id);
let mut errors = Vec::new();
for item in trait_items.iter() {
let mut errors = errors.iter().flat_map(|x| x.iter()).peekable();
if errors.peek().is_some() {
- let trait_name = ty::item_path_str(tcx, object_trait.principal.def_id);
+ let trait_name = ty::item_path_str(tcx, object_trait.def_id);
span_err!(tcx.sess, span, E0038,
"cannot convert to a trait object because trait `{}` is not object-safe",
trait_name);
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub trait Foo for Sized? { fn foo<T>(&self, ext_thing: &T); }
+pub trait Bar for Sized?: Foo { }
+impl<T: Foo> Bar for T { }
+
+pub struct Thing;
+impl Foo for Thing {
+ fn foo<T>(&self, _: &T) {}
+}
+
+#[inline(never)] fn foo(b: &Bar) { b.foo(&0u) }
+
+fn main() {
+ let mut thing = Thing;
+ let test: &Bar = &mut thing; //~ ERROR cannot convert to a trait object because trait `Foo`
+ foo(test);
+}