]> git.lizzy.rs Git - rust.git/commitdiff
Ensure that, for every trait `Foo`, the predicate `Foo : Foo` holds.
authorNiko Matsakis <niko@alum.mit.edu>
Tue, 23 Dec 2014 10:26:34 +0000 (05:26 -0500)
committerNiko Matsakis <niko@alum.mit.edu>
Fri, 2 Jan 2015 17:09:38 +0000 (12:09 -0500)
src/libcore/fmt/mod.rs
src/librustc/middle/traits/mod.rs
src/librustc/middle/traits/project.rs
src/librustc/middle/traits/select.rs
src/librustc/middle/traits/util.rs
src/librustc/middle/ty_fold.rs
src/librustc_trans/trans/meth.rs
src/librustc_typeck/check/vtable.rs

index 43f0d72eeba9219a5fa80daa36f60035afa2f8af..c0f8eb59fce861250abc84f8973def3d37479fed 100644 (file)
@@ -605,9 +605,6 @@ fn fmt(&self, f: &mut Formatter) -> Result { (**self).fmt(f) }
 impl<'a, Sized? T: Show> Show for &'a mut T {
     fn fmt(&self, f: &mut Formatter) -> Result { (**self).fmt(f) }
 }
-impl<'a> Show for &'a (Show+'a) {
-    fn fmt(&self, f: &mut Formatter) -> Result { (*self).fmt(f) }
-}
 
 impl Show for bool {
     fn fmt(&self, f: &mut Formatter) -> Result {
index d7d16556acdc476816eb44a4a92347a77aa94682..41028292da8f7100950b9baa4c1d0708a9bdd935 100644 (file)
@@ -217,6 +217,9 @@ pub enum Vtable<'tcx, N> {
     /// for some type parameter.
     VtableParam,
 
+    /// Virtual calls through an object
+    VtableObject(VtableObjectData<'tcx>),
+
     /// Successful resolution for a builtin trait.
     VtableBuiltin(VtableBuiltinData<N>),
 
@@ -252,6 +255,13 @@ pub struct VtableBuiltinData<N> {
     pub nested: subst::VecPerParamSpace<N>
 }
 
+/// A vtable for some object-safe trait `Foo` automatically derived
+/// for the object type `Foo`.
+#[deriving(PartialEq,Eq,Clone)]
+pub struct VtableObjectData<'tcx> {
+    pub object_ty: Ty<'tcx>,
+}
+
 /// True if neither the trait nor self type is local. Note that `impl_def_id` must refer to an impl
 /// of a trait, not an inherent impl.
 pub fn is_orphan_impl(tcx: &ty::ctxt,
@@ -372,6 +382,7 @@ pub fn iter_nested(&self) -> Iter<N> {
             VtableFnPointer(..) => (&[]).iter(),
             VtableUnboxedClosure(..) => (&[]).iter(),
             VtableParam => (&[]).iter(),
+            VtableObject(_) => (&[]).iter(),
             VtableBuiltin(ref i) => i.iter_nested(),
         }
     }
@@ -382,6 +393,7 @@ pub fn map_nested<M, F>(&self, op: F) -> Vtable<'tcx, M> where F: FnMut(&N) -> M
             VtableFnPointer(ref sig) => VtableFnPointer((*sig).clone()),
             VtableUnboxedClosure(d, ref s) => VtableUnboxedClosure(d, s.clone()),
             VtableParam => VtableParam,
+            VtableObject(ref p) => VtableObject(p.clone()),
             VtableBuiltin(ref b) => VtableBuiltin(b.map_nested(op)),
         }
     }
@@ -394,6 +406,7 @@ pub fn map_move_nested<M, F>(self, op: F) -> Vtable<'tcx, M> where
             VtableFnPointer(sig) => VtableFnPointer(sig),
             VtableUnboxedClosure(d, s) => VtableUnboxedClosure(d, s),
             VtableParam => VtableParam,
+            VtableObject(p) => VtableObject(p),
             VtableBuiltin(no) => VtableBuiltin(no.map_move_nested(op)),
         }
     }
index c84f31bf6c3bcad624c7c94a5f1aa1a58dab54b0..0544e32b62c6a7846bf165011c35886a67cdf448 100644 (file)
@@ -377,20 +377,14 @@ fn project_type<'cx,'tcx>(
         ambiguous: false,
     };
 
-    assemble_candidates_from_object_type(selcx,
-                                         obligation,
-                                         &mut candidates);
-
-    if candidates.vec.is_empty() {
-        assemble_candidates_from_param_env(selcx,
-                                           obligation,
-                                           &mut candidates);
-
-        if let Err(e) = assemble_candidates_from_impls(selcx,
-                                                       obligation,
-                                                       &mut candidates) {
-            return Err(ProjectionTyError::TraitSelectionError(e));
-        }
+    assemble_candidates_from_param_env(selcx,
+                                       obligation,
+                                       &mut candidates);
+
+    if let Err(e) = assemble_candidates_from_impls(selcx,
+                                                   obligation,
+                                                   &mut candidates) {
+        return Err(ProjectionTyError::TraitSelectionError(e));
     }
 
     debug!("{} candidates, ambiguous={}",
@@ -467,18 +461,22 @@ fn assemble_candidates_from_predicates<'cx,'tcx>(
 fn assemble_candidates_from_object_type<'cx,'tcx>(
     selcx: &mut SelectionContext<'cx,'tcx>,
     obligation:  &ProjectionTyObligation<'tcx>,
-    candidate_set: &mut ProjectionTyCandidateSet<'tcx>)
+    candidate_set: &mut ProjectionTyCandidateSet<'tcx>,
+    object_ty: Ty<'tcx>)
 {
     let infcx = selcx.infcx();
-    let trait_ref = infcx.resolve_type_vars_if_possible(&obligation.predicate.trait_ref);
-    debug!("assemble_candidates_from_object_type(trait_ref={})",
-           trait_ref.repr(infcx.tcx));
-    let self_ty = trait_ref.self_ty();
-    let data = match self_ty.sty {
+    debug!("assemble_candidates_from_object_type(object_ty={})",
+           object_ty.repr(infcx.tcx));
+    let data = match object_ty.sty {
         ty::ty_trait(ref data) => data,
-        _ => { return; }
+        _ => {
+            selcx.tcx().sess.span_bug(
+                obligation.cause.span,
+                format!("assemble_candidates_from_object_type called with non-object: {}",
+                        object_ty.repr(selcx.tcx()))[]);
+        }
     };
-    let projection_bounds = data.projection_bounds_with_self_ty(selcx.tcx(), self_ty);
+    let projection_bounds = data.projection_bounds_with_self_ty(selcx.tcx(), object_ty);
     let env_predicates = projection_bounds.iter()
                                           .map(|p| p.as_predicate())
                                           .collect();
@@ -515,6 +513,10 @@ fn assemble_candidates_from_impls<'cx,'tcx>(
             candidate_set.vec.push(
                 ProjectionTyCandidate::Impl(data));
         }
+        super::VtableObject(data) => {
+            assemble_candidates_from_object_type(
+                selcx, obligation, candidate_set, data.object_ty);
+        }
         super::VtableParam(..) => {
             // This case tell us nothing about the value of an
             // associated type. Consider:
index f9dced088f8c124b7d2ba2daa71576e4ee2cdb82..6a69c878a762fde1e72f16399d26938900802efa 100644 (file)
 use super::{SelectionError, Unimplemented, Overflow, OutputTypeParameterMismatch};
 use super::{Selection};
 use super::{SelectionResult};
-use super::{VtableBuiltin, VtableImpl, VtableParam, VtableUnboxedClosure, VtableFnPointer};
-use super::{VtableImplData, VtableBuiltinData};
+use super::{VtableBuiltin, VtableImpl, VtableParam, VtableUnboxedClosure,
+            VtableFnPointer, VtableObject};
+use super::{VtableImplData, VtableObjectData, VtableBuiltinData};
+use super::object_safety;
 use super::{util};
 
 use middle::fast_reject;
@@ -147,6 +149,8 @@ enum SelectionCandidate<'tcx> {
     /// types generated for a fn pointer type (e.g., `fn(int)->int`)
     FnPointerCandidate,
 
+    ObjectCandidate,
+
     ErrorCandidate,
 }
 
@@ -717,6 +721,7 @@ fn assemble_candidates<'o>(&mut self,
                 try!(self.assemble_unboxed_closure_candidates(obligation, &mut candidates));
                 try!(self.assemble_fn_pointer_candidates(obligation, &mut candidates));
                 try!(self.assemble_candidates_from_impls(obligation, &mut candidates.vec));
+                self.assemble_candidates_from_object_ty(obligation, &mut candidates);
             }
         }
 
@@ -878,7 +883,7 @@ fn assemble_candidates_from_caller_bounds(&mut self,
         let matching_bounds =
             all_bounds.filter(
                 |bound| self.infcx.probe(
-                    |_| self.match_where_clause(obligation, bound.clone())).is_ok());
+                    |_| self.match_poly_trait_ref(obligation, bound.clone())).is_ok());
 
         let param_candidates =
             matching_bounds.map(|bound| ParamCandidate(bound));
@@ -945,7 +950,7 @@ fn assemble_fn_pointer_candidates(&mut self,
 
         let self_ty = self.infcx.shallow_resolve(obligation.self_ty());
         match self_ty.sty {
-            ty::ty_infer(..) => {
+            ty::ty_infer(ty::TyVar(_)) => {
                 candidates.ambiguous = true; // could wind up being a fn() type
             }
 
@@ -991,6 +996,67 @@ fn assemble_candidates_from_impls(&mut self,
         Ok(())
     }
 
+    /// Search for impls that might apply to `obligation`.
+    fn assemble_candidates_from_object_ty(&mut self,
+                                          obligation: &TraitObligation<'tcx>,
+                                          candidates: &mut SelectionCandidateSet<'tcx>)
+    {
+        let self_ty = self.infcx.shallow_resolve(obligation.self_ty());
+
+        debug!("assemble_candidates_from_object_ty(self_ty={})",
+               self_ty.repr(self.tcx()));
+
+        // Object-safety candidates are only applicable to object-safe
+        // traits. Including this check is useful because it helps
+        // inference in cases of traits like `BorrowFrom`, which are
+        // not object-safe, and which rely on being able to infer the
+        // self-type from one of the other inputs. Without this check,
+        // these cases wind up being considered ambiguous due to a
+        // (spurious) ambiguity introduced here.
+        if !object_safety::is_object_safe(self.tcx(), obligation.predicate.to_poly_trait_ref()) {
+            return;
+        }
+
+        let poly_trait_ref = match self_ty.sty {
+            ty::ty_trait(ref data) => {
+                data.principal_trait_ref_with_self_ty(self.tcx(), self_ty)
+            }
+            ty::ty_infer(ty::TyVar(_)) => {
+                debug!("assemble_candidates_from_object_ty: ambiguous");
+                candidates.ambiguous = true; // could wind up being an object type
+                return;
+            }
+            _ => {
+                return;
+            }
+        };
+
+        debug!("assemble_candidates_from_object_ty: poly_trait_ref={}",
+               poly_trait_ref.repr(self.tcx()));
+
+        // see whether the object trait can be upcast to the trait we are looking for
+        let obligation_def_id = obligation.predicate.def_id();
+        let upcast_trait_ref = match util::upcast(self.tcx(), poly_trait_ref, obligation_def_id) {
+            Some(r) => r,
+            None => { return; }
+        };
+
+        debug!("assemble_candidates_from_object_ty: upcast_trait_ref={}",
+               upcast_trait_ref.repr(self.tcx()));
+
+        // check whether the upcast version of the trait-ref matches what we are looking for
+        match
+            self.infcx.probe(
+                |_| self.match_poly_trait_ref(obligation, upcast_trait_ref.clone()))
+        {
+            Ok(()) => {
+                debug!("assemble_candidates_from_object_ty: matched, pushing candidate");
+                candidates.vec.push(ObjectCandidate);
+            }
+            Err(()) => { }
+        }
+    }
+
     ///////////////////////////////////////////////////////////////////////////
     // WINNOW
     //
@@ -1544,6 +1610,11 @@ fn confirm_candidate(&mut self,
                 Ok(VtableUnboxedClosure(closure_def_id, substs))
             }
 
+            ObjectCandidate => {
+                let data = self.confirm_object_candidate(obligation);
+                Ok(VtableObject(data))
+            }
+
             FnPointerCandidate => {
                 let fn_type =
                     try!(self.confirm_fn_pointer_candidate(obligation));
@@ -1727,6 +1798,48 @@ fn vtable_impl(&mut self,
                          nested: impl_predicates }
     }
 
+    fn confirm_object_candidate(&mut self,
+                                obligation: &TraitObligation<'tcx>)
+                                -> VtableObjectData<'tcx>
+    {
+        debug!("confirm_object_candidate({})",
+               obligation.repr(self.tcx()));
+
+        let self_ty = self.infcx.shallow_resolve(obligation.self_ty());
+        let poly_trait_ref = match self_ty.sty {
+            ty::ty_trait(ref data) => {
+                data.principal_trait_ref_with_self_ty(self.tcx(), self_ty)
+            }
+            _ => {
+                self.tcx().sess.span_bug(obligation.cause.span,
+                                         "object candidate with non-object");
+            }
+        };
+
+        let obligation_def_id = obligation.predicate.def_id();
+        let upcast_trait_ref = match util::upcast(self.tcx(),
+                                                  poly_trait_ref.clone(),
+                                                  obligation_def_id) {
+            Some(r) => r,
+            None => {
+                self.tcx().sess.span_bug(obligation.cause.span,
+                                         format!("unable to upcast from {} to {}",
+                                                 poly_trait_ref.repr(self.tcx()),
+                                                 obligation_def_id.repr(self.tcx())).as_slice());
+            }
+        };
+
+        match self.match_poly_trait_ref(obligation, upcast_trait_ref) {
+            Ok(()) => { }
+            Err(()) => {
+                self.tcx().sess.span_bug(obligation.cause.span,
+                                         "failed to match trait refs");
+            }
+        }
+
+        VtableObjectData { object_ty: self_ty }
+    }
+
     fn confirm_fn_pointer_candidate(&mut self,
                                     obligation: &TraitObligation<'tcx>)
                                     -> Result<ty::Ty<'tcx>,SelectionError<'tcx>>
@@ -1962,12 +2075,12 @@ fn fast_reject_trait_refs(&mut self,
             })
     }
 
-    fn match_where_clause(&mut self,
-                          obligation: &TraitObligation<'tcx>,
-                          where_clause_trait_ref: ty::PolyTraitRef<'tcx>)
-                        -> Result<(),()>
+    fn match_poly_trait_ref(&mut self,
+                            obligation: &TraitObligation<'tcx>,
+                            where_clause_trait_ref: ty::PolyTraitRef<'tcx>)
+                            -> Result<(),()>
     {
-        debug!("match_where_clause: obligation={} where_clause_trait_ref={}",
+        debug!("match_poly_trait_ref: obligation={} where_clause_trait_ref={}",
                obligation.repr(self.tcx()),
                where_clause_trait_ref.repr(self.tcx()));
 
@@ -2161,6 +2274,9 @@ fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
             ImplCandidate(a) => format!("ImplCandidate({})", a.repr(tcx)),
             ProjectionCandidate => format!("ProjectionCandidate"),
             FnPointerCandidate => format!("FnPointerCandidate"),
+            ObjectCandidate => {
+                format!("ObjectCandidate")
+            }
             UnboxedClosureCandidate(c, ref s) => {
                 format!("UnboxedClosureCandidate({},{})", c, s.repr(tcx))
             }
index 541fa4dbbf716782fdee4508dff0120c21a76ecc..41a59d6a5d84679b63d9a3c056bb9463a457bb87 100644 (file)
@@ -238,6 +238,12 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
+impl<'tcx> fmt::Show for super::VtableObjectData<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "VtableObject(...)")
+    }
+}
+
 /// See `super::obligations_for_generics`
 pub fn predicates_for_generics<'tcx>(tcx: &ty::ctxt<'tcx>,
                                      cause: ObligationCause<'tcx>,
@@ -366,6 +372,10 @@ fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
                 format!("VtableFnPointer({})",
                         d.repr(tcx)),
 
+            super::VtableObject(ref d) =>
+                format!("VtableObject({})",
+                        d.repr(tcx)),
+
             super::VtableParam =>
                 format!("VtableParam"),
 
@@ -391,6 +401,13 @@ fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
     }
 }
 
+impl<'tcx> Repr<'tcx> for super::VtableObjectData<'tcx> {
+    fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
+        format!("VtableObject(object_ty={})",
+                self.object_ty.repr(tcx))
+    }
+}
+
 impl<'tcx> Repr<'tcx> for super::SelectionError<'tcx> {
     fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
         match *self {
index 7b13bea7d79c7093fec3a9eeece7b4c77f9762ab..abbf530529bb2fd41959cb259c4dc90e5a04db15 100644 (file)
@@ -503,6 +503,15 @@ fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::Vtable<'tcx,
             }
             traits::VtableParam => traits::VtableParam,
             traits::VtableBuiltin(ref d) => traits::VtableBuiltin(d.fold_with(folder)),
+            traits::VtableObject(ref d) => traits::VtableObject(d.fold_with(folder)),
+        }
+    }
+}
+
+impl<'tcx> TypeFoldable<'tcx> for traits::VtableObjectData<'tcx> {
+    fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::VtableObjectData<'tcx> {
+        traits::VtableObjectData {
+            object_ty: self.object_ty.fold_with(folder)
         }
     }
 }
index 9535ffaec0e6a182b9b925387ac4ac4dd68bccc9..99624f1b1e7d8197a36e4a12e91a161a35c9c621 100644 (file)
@@ -8,12 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
+use arena::TypedArena;
 use back::abi;
-use llvm;
-use llvm::ValueRef;
+use back::link;
+use llvm::{mod, ValueRef, get_param};
 use metadata::csearch;
-use middle::subst::{Substs};
+use middle::subst::{Subst, Substs};
 use middle::subst::VecPerParamSpace;
 use middle::subst;
 use middle::traits;
@@ -370,6 +370,10 @@ fn trans_monomorphized_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             let llfn = trans_fn_pointer_shim(bcx.ccx(), fn_ty);
             Callee { bcx: bcx, data: Fn(llfn) }
         }
+        traits::VtableObject(ref data) => {
+            let llfn = trans_object_shim(bcx.ccx(), data.object_ty, trait_id, n_method);
+            Callee { bcx: bcx, data: Fn(llfn) }
+        }
         traits::VtableBuiltin(..) |
         traits::VtableParam(..) => {
             bcx.sess().bug(
@@ -503,6 +507,137 @@ pub fn trans_trait_callee_from_llval<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     };
 }
 
+/// Generate a shim function that allows an object type like `SomeTrait` to
+/// implement the type `SomeTrait`. Imagine a trait definition:
+///
+///    trait SomeTrait { fn get(&self) -> int; ... }
+///
+/// And a generic bit of code:
+///
+///    fn foo<T:SomeTrait>(t: &T) {
+///        let x = SomeTrait::get;
+///        x(t)
+///    }
+///
+/// What is the value of `x` when `foo` is invoked with `T=SomeTrait`?
+/// The answer is that it it is a shim function generate by this
+/// routine:
+///
+///    fn shim(t: &SomeTrait) -> int {
+///        // ... call t.get() virtually ...
+///    }
+///
+/// In fact, all virtual calls can be thought of as normal trait calls
+/// that go through this shim function.
+pub fn trans_object_shim<'a, 'tcx>(
+    ccx: &'a CrateContext<'a, 'tcx>,
+    object_ty: Ty<'tcx>,
+    trait_id: ast::DefId,
+    method_offset_in_trait: uint)
+    -> ValueRef
+{
+    let _icx = push_ctxt("trans_object_shim");
+    let tcx = ccx.tcx();
+
+    debug!("trans_object_shim(object_ty={}, trait_id={}, n_method={})",
+           object_ty.repr(tcx),
+           trait_id.repr(tcx),
+           method_offset_in_trait);
+
+    let object_trait_ref =
+        match object_ty.sty {
+            ty::ty_trait(ref data) => {
+                data.principal_trait_ref_with_self_ty(tcx, object_ty)
+            }
+            _ => {
+                tcx.sess.bug(format!("trans_object_shim() called on non-object: {}",
+                                     object_ty.repr(tcx)).as_slice());
+            }
+        };
+
+    // Upcast to the trait in question and extract out the substitutions.
+    let upcast_trait_ref = traits::upcast(ccx.tcx(), object_trait_ref.clone(), trait_id).unwrap();
+    let object_substs = upcast_trait_ref.substs().clone().erase_regions();
+    debug!("trans_object_shim: object_substs={}", object_substs.repr(tcx));
+
+    // Lookup the type of this method as deeclared in the trait and apply substitutions.
+    let method_ty = match ty::trait_item(tcx, trait_id, method_offset_in_trait) {
+        ty::MethodTraitItem(method) => method,
+        ty::TypeTraitItem(_) => {
+            tcx.sess.bug("can't create a method shim for an associated type")
+        }
+    };
+    let fty = method_ty.fty.subst(tcx, &object_substs);
+    let fty = tcx.mk_bare_fn(fty);
+    debug!("trans_object_shim: fty={}", fty.repr(tcx));
+
+    //
+    let method_bare_fn_ty =
+        ty::mk_bare_fn(tcx, None, fty);
+    let function_name =
+        link::mangle_internal_name_by_type_and_seq(ccx, method_bare_fn_ty, "object_shim");
+    let llfn =
+        decl_internal_rust_fn(ccx, method_bare_fn_ty, function_name.as_slice());
+
+    //
+    let block_arena = TypedArena::new();
+    let empty_substs = Substs::trans_empty();
+    let fcx = new_fn_ctxt(ccx,
+                          llfn,
+                          ast::DUMMY_NODE_ID,
+                          false,
+                          fty.sig.0.output,
+                          &empty_substs,
+                          None,
+                          &block_arena);
+    let mut bcx = init_function(&fcx, false, fty.sig.0.output);
+
+    // the first argument (`self`) will be a trait object
+    let llobject = get_param(fcx.llfn, fcx.arg_pos(0) as u32);
+
+    debug!("trans_object_shim: llobject={}",
+           bcx.val_to_string(llobject));
+
+    // the remaining arguments will be, well, whatever they are
+    let llargs: Vec<_> =
+        fty.sig.0.inputs[1..].iter()
+        .enumerate()
+        .map(|(i, _)| {
+            let llarg = get_param(fcx.llfn, fcx.arg_pos(i+1) as u32);
+            debug!("trans_object_shim: input #{} == {}",
+                   i, bcx.val_to_string(llarg));
+            llarg
+        })
+        .collect();
+    assert!(!fcx.needs_ret_allocas);
+
+    let dest =
+        fcx.llretslotptr.get().map(
+            |_| expr::SaveIn(fcx.get_ret_slot(bcx, fty.sig.0.output, "ret_slot")));
+
+    let method_offset_in_vtable =
+        traits::get_vtable_index_of_object_method(bcx.tcx(),
+                                                  object_trait_ref.clone(),
+                                                  trait_id,
+                                                  method_offset_in_trait);
+    debug!("trans_object_shim: method_offset_in_vtable={}",
+           method_offset_in_vtable);
+
+    bcx = trans_call_inner(bcx,
+                           None,
+                           method_bare_fn_ty,
+                           |bcx, _| trans_trait_callee_from_llval(bcx,
+                                                                  method_bare_fn_ty,
+                                                                  method_offset_in_vtable,
+                                                                  llobject),
+                           ArgVals(llargs.as_slice()),
+                           dest).bcx;
+
+    finish_fn(&fcx, bcx, fty.sig.0.output);
+
+    llfn
+}
+
 /// Creates a returns a dynamic vtable for the given type and vtable origin.
 /// This is used only for objects.
 ///
@@ -560,6 +695,14 @@ pub fn get_vtable<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 let llfn = vec![trans_fn_pointer_shim(bcx.ccx(), bare_fn_ty)];
                 llfn.into_iter()
             }
+            traits::VtableObject(ref data) => {
+                // this would imply that the Self type being erased is
+                // an object type; this cannot happen because we
+                // cannot cast an unsized type into a trait object
+                bcx.sess().bug(
+                    format!("cannot get vtable for an object type: {}",
+                            data.repr(bcx.tcx())).as_slice());
+            }
             traits::VtableParam => {
                 bcx.sess().bug(
                     format!("resolved vtable for {} to bad vtable {} in trans",
index 65f8ee4990861a224c71ed44780f60a6f6f03f5a..1ef6c1140321846dc53f24970f355a5f0c57af51 100644 (file)
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 use check::{FnCtxt, structurally_resolved_type};
-use middle::subst::{FnSpace, SelfSpace};
 use middle::traits::{mod, ObjectSafetyViolation, MethodViolationCode};
 use middle::traits::{Obligation, ObligationCause};
 use middle::traits::report_fulfillment_errors;