self.ty_to_string(rcvr_ty),
candidate.repr(self.tcx()));
- let mut rcvr_substs = candidate.rcvr_substs.clone();
-
- if !self.enforce_object_limitations(candidate) {
- // Here we change `Self` from `Trait` to `err` in the case that
- // this is an illegal object method. This is necessary to prevent
- // the user from getting strange, derivative errors when the method
- // takes an argument/return-type of type `Self` etc.
- rcvr_substs.types.get_mut_slice(SelfSpace)[0] = ty::mk_err();
- }
-
self.enforce_drop_trait_limitations(candidate);
// Determine the values for the generic parameters of the method.
}
}
- fn enforce_object_limitations(&self, candidate: &Candidate) -> bool {
- /*!
- * There are some limitations to calling functions through an
- * object, because (a) the self type is not known
- * (that's the whole point of a trait instance, after all, to
- * obscure the self type) and (b) the call must go through a
- * vtable and hence cannot be monomorphized.
- */
-
- match candidate.origin {
- MethodStatic(..) |
- MethodTypeParam(..) |
- MethodStaticUnboxedClosure(..) => {
- return true; // not a call to a trait instance
- }
- MethodTraitObject(..) => {}
- }
-
- match candidate.method_ty.explicit_self {
- ty::StaticExplicitSelfCategory => { // reason (a) above
- self.tcx().sess.span_err(
- self.span,
- "cannot call a method without a receiver \
- through an object");
- return false;
- }
-
- ty::ByValueExplicitSelfCategory |
- ty::ByReferenceExplicitSelfCategory(..) |
- ty::ByBoxExplicitSelfCategory => {}
- }
-
- // reason (a) above
- let check_for_self_ty = |ty| -> bool {
- if ty::type_has_self(ty) {
- span_err!(self.tcx().sess, self.span, E0038,
- "cannot call a method whose type contains a \
- self-type through an object");
- false
- } else {
- true
- }
- };
- let ref sig = candidate.method_ty.fty.sig;
- for &input_ty in sig.inputs[1..].iter() {
- if !check_for_self_ty(input_ty) {
- return false;
- }
- }
- if let ty::FnConverging(result_type) = sig.output {
- if !check_for_self_ty(result_type) {
- return false;
- }
- }
-
- if candidate.method_ty.generics.has_type_params(subst::FnSpace) {
- // reason (b) above
- span_err!(self.tcx().sess, self.span, E0039,
- "cannot call a generic method through an object");
- return false;
- }
-
- true
- }
-
fn enforce_drop_trait_limitations(&self, candidate: &Candidate) {
// No code can call the finalize method explicitly.
let bad = match candidate.origin {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use middle::subst::{SelfSpace};
+use middle::subst::{SelfSpace, FnSpace};
use middle::traits;
use middle::traits::{SelectionError, OutputTypeParameterMismatch, Overflow, Unimplemented};
use middle::traits::{Obligation, obligation_for_builtin_bound};
// 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);
}
(&ty::ty_rptr(referent_region, ty::mt { ty: referent_ty,
infer::RelateObjectBound(source_expr.span),
target_region,
referent_region);
+
+ check_object_safety(fcx.tcx(), object_trait, source_expr.span);
}
}
}
}
+// TODO comment
+pub fn check_object_safety(tcx: &ty::ctxt, object_trait: &ty::TyTrait, span: Span) {
+ let trait_items = ty::trait_items(tcx, object_trait.def_id);
+ for item in trait_items.iter() {
+ match *item {
+ ty::MethodTraitItem(ref m) => check_object_safety_of_method(tcx, &**m, span),
+ ty::TypeTraitItem(_) => {}
+ }
+ }
+
+ // TODO error messages
+ fn check_object_safety_of_method(tcx: &ty::ctxt, method: &ty::Method, span: Span) {
+ /*!
+ * There are some limitations to calling functions through an
+ * object, because (a) the self type is not known
+ * (that's the whole point of a trait instance, after all, to
+ * obscure the self type) and (b) the call must go through a
+ * vtable and hence cannot be monomorphized.
+ */
+
+ match method.explicit_self {
+ ty::ByValueExplicitSelfCategory => { // reason (a) above
+ tcx.sess.span_err(
+ span,
+ "cannot call a method with a by-value receiver \
+ through a trait object");
+ }
+
+ ty::StaticExplicitSelfCategory |
+ ty::ByReferenceExplicitSelfCategory(..) |
+ ty::ByBoxExplicitSelfCategory => {}
+ }
+
+ // reason (a) above
+ let check_for_self_ty = |ty| {
+ if ty::type_has_self(ty) {
+ span_err!(tcx.sess, span, E0038,
+ "cannot call a method whose type contains a \
+ self-type through an object: {}", ::util::ppaux::ty_to_string(tcx, ty));
+ true
+ } else {
+ false
+ }
+ };
+ let ref sig = method.fty.sig;
+ let mut found_self_ty = false;
+ for &input_ty in sig.inputs.tail().iter() {
+ if check_for_self_ty(input_ty) {
+ found_self_ty = true;
+ break;
+ }
+ }
+ if !found_self_ty {
+ check_for_self_ty(sig.output);
+ }
+
+ if method.generics.has_type_params(FnSpace) {
+ // reason (b) above
+ span_err!(tcx.sess, span, E0039,
+ "cannot call a generic method through an object");
+ }
+ }
+}
+
pub fn register_object_cast_obligations(fcx: &FnCtxt,
span: Span,
object_trait: &ty::TyTrait,