diff options
| author | Niko Matsakis <niko@alum.mit.edu> | 2015-03-26 15:51:11 -0400 |
|---|---|---|
| committer | Niko Matsakis <niko@alum.mit.edu> | 2015-03-26 17:52:39 -0400 |
| commit | 710af0498d086f66de5f2f5fe47b6e16650f8d86 (patch) | |
| tree | 709e71c7fcbd6a29f9a6d5fecb165c128c627a2d | |
| parent | 703308db4a130191db4000dfbbfc92936c604b52 (diff) | |
| download | rust-710af0498d086f66de5f2f5fe47b6e16650f8d86.tar.gz rust-710af0498d086f66de5f2f5fe47b6e16650f8d86.zip | |
Refactor object-safety test to use def-ids only
| -rw-r--r-- | src/librustc/middle/traits/mod.rs | 6 | ||||
| -rw-r--r-- | src/librustc/middle/traits/object_safety.rs | 16 | ||||
| -rw-r--r-- | src/librustc/middle/traits/select.rs | 3 | ||||
| -rw-r--r-- | src/librustc/middle/traits/util.rs | 41 | ||||
| -rw-r--r-- | src/librustc_typeck/check/vtable.rs | 9 |
5 files changed, 59 insertions, 16 deletions
diff --git a/src/librustc/middle/traits/mod.rs b/src/librustc/middle/traits/mod.rs index 24b201c960f..ffc11efe7c7 100644 --- a/src/librustc/middle/traits/mod.rs +++ b/src/librustc/middle/traits/mod.rs @@ -48,6 +48,8 @@ pub use self::util::get_vtable_index_of_object_method; pub use self::util::trait_ref_for_builtin_bound; pub use self::util::supertraits; pub use self::util::Supertraits; +pub use self::util::supertrait_def_ids; +pub use self::util::SupertraitDefIds; pub use self::util::transitive_bounds; pub use self::util::upcast; @@ -640,7 +642,7 @@ impl<'tcx> FulfillmentError<'tcx> { } impl<'tcx> TraitObligation<'tcx> { - fn self_ty(&self) -> Ty<'tcx> { - self.predicate.0.self_ty() + fn self_ty(&self) -> ty::Binder<Ty<'tcx>> { + ty::Binder(self.predicate.skip_binder().self_ty()) } } diff --git a/src/librustc/middle/traits/object_safety.rs b/src/librustc/middle/traits/object_safety.rs index 881487a2dad..9dccadc932b 100644 --- a/src/librustc/middle/traits/object_safety.rs +++ b/src/librustc/middle/traits/object_safety.rs @@ -53,36 +53,36 @@ pub enum MethodViolationCode { } pub fn is_object_safe<'tcx>(tcx: &ty::ctxt<'tcx>, - trait_ref: ty::PolyTraitRef<'tcx>) + trait_def_id: ast::DefId) -> bool { // Because we query yes/no results frequently, we keep a cache: let cached_result = - tcx.object_safety_cache.borrow().get(&trait_ref.def_id()).cloned(); + tcx.object_safety_cache.borrow().get(&trait_def_id).cloned(); let result = cached_result.unwrap_or_else(|| { - let result = object_safety_violations(tcx, trait_ref.clone()).is_empty(); + let result = object_safety_violations(tcx, trait_def_id).is_empty(); // Record just a yes/no result in the cache; this is what is // queried most frequently. Note that this may overwrite a // previous result, but always with the same thing. - tcx.object_safety_cache.borrow_mut().insert(trait_ref.def_id(), result); + tcx.object_safety_cache.borrow_mut().insert(trait_def_id, result); result }); - debug!("is_object_safe({}) = {}", trait_ref.repr(tcx), result); + debug!("is_object_safe({}) = {}", trait_def_id.repr(tcx), result); result } pub fn object_safety_violations<'tcx>(tcx: &ty::ctxt<'tcx>, - sub_trait_ref: ty::PolyTraitRef<'tcx>) + trait_def_id: ast::DefId) -> Vec<ObjectSafetyViolation<'tcx>> { - supertraits(tcx, sub_trait_ref) - .flat_map(|tr| object_safety_violations_for_trait(tcx, tr.def_id()).into_iter()) + traits::supertrait_def_ids(tcx, trait_def_id) + .flat_map(|def_id| object_safety_violations_for_trait(tcx, def_id).into_iter()) .collect() } diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index 6121a441992..7e89534026f 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -1237,7 +1237,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // 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()) { + let predicate_trait_ref = obligation.predicate.to_poly_trait_ref(); + if !object_safety::is_object_safe(self.tcx(), predicate_trait_ref.def_id()) { return; } diff --git a/src/librustc/middle/traits/util.rs b/src/librustc/middle/traits/util.rs index 965aaf12044..06b687bd92b 100644 --- a/src/librustc/middle/traits/util.rs +++ b/src/librustc/middle/traits/util.rs @@ -210,6 +210,47 @@ pub fn transitive_bounds<'cx, 'tcx>(tcx: &'cx ty::ctxt<'tcx>, } /////////////////////////////////////////////////////////////////////////// +// Iterator over def-ids of supertraits + +pub struct SupertraitDefIds<'cx, 'tcx:'cx> { + tcx: &'cx ty::ctxt<'tcx>, + stack: Vec<ast::DefId>, + visited: FnvHashSet<ast::DefId>, +} + +pub fn supertrait_def_ids<'cx, 'tcx>(tcx: &'cx ty::ctxt<'tcx>, + trait_def_id: ast::DefId) + -> SupertraitDefIds<'cx, 'tcx> +{ + SupertraitDefIds { + tcx: tcx, + stack: vec![trait_def_id], + visited: Some(trait_def_id).into_iter().collect(), + } +} + +impl<'cx, 'tcx> Iterator for SupertraitDefIds<'cx, 'tcx> { + type Item = ast::DefId; + + fn next(&mut self) -> Option<ast::DefId> { + let def_id = match self.stack.pop() { + Some(def_id) => def_id, + None => { return None; } + }; + + let predicates = ty::lookup_super_predicates(self.tcx, def_id); + let visited = &mut self.visited; + self.stack.extend( + predicates.predicates + .iter() + .filter_map(|p| p.to_opt_poly_trait_ref()) + .map(|t| t.def_id()) + .filter(|&super_def_id| visited.insert(super_def_id))); + Some(def_id) + } +} + +/////////////////////////////////////////////////////////////////////////// // Other /////////////////////////////////////////////////////////////////////////// diff --git a/src/librustc_typeck/check/vtable.rs b/src/librustc_typeck/check/vtable.rs index 2858dc9b569..67461ff561b 100644 --- a/src/librustc_typeck/check/vtable.rs +++ b/src/librustc_typeck/check/vtable.rs @@ -28,18 +28,17 @@ pub fn check_object_safety<'tcx>(tcx: &ty::ctxt<'tcx>, object_trait: &ty::TyTrait<'tcx>, span: Span) { - let object_trait_ref = - object_trait.principal_trait_ref_with_self_ty(tcx, tcx.types.err); + let trait_def_id = object_trait.principal_def_id(); - if traits::is_object_safe(tcx, object_trait_ref.clone()) { + if traits::is_object_safe(tcx, trait_def_id) { return; } span_err!(tcx.sess, span, E0038, "cannot convert to a trait object because trait `{}` is not object-safe", - ty::item_path_str(tcx, object_trait_ref.def_id())); + ty::item_path_str(tcx, trait_def_id)); - let violations = traits::object_safety_violations(tcx, object_trait_ref.clone()); + let violations = traits::object_safety_violations(tcx, trait_def_id); for violation in violations { match violation { ObjectSafetyViolation::SizedSelf => { |
