Skip to content

Commit 710af04

Browse files
committed
Refactor object-safety test to use def-ids only
1 parent 703308d commit 710af04

File tree

5 files changed

+59
-16
lines changed

5 files changed

+59
-16
lines changed

src/librustc/middle/traits/mod.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ pub use self::util::get_vtable_index_of_object_method;
4848
pub use self::util::trait_ref_for_builtin_bound;
4949
pub use self::util::supertraits;
5050
pub use self::util::Supertraits;
51+
pub use self::util::supertrait_def_ids;
52+
pub use self::util::SupertraitDefIds;
5153
pub use self::util::transitive_bounds;
5254
pub use self::util::upcast;
5355

@@ -640,7 +642,7 @@ impl<'tcx> FulfillmentError<'tcx> {
640642
}
641643

642644
impl<'tcx> TraitObligation<'tcx> {
643-
fn self_ty(&self) -> Ty<'tcx> {
644-
self.predicate.0.self_ty()
645+
fn self_ty(&self) -> ty::Binder<Ty<'tcx>> {
646+
ty::Binder(self.predicate.skip_binder().self_ty())
645647
}
646648
}

src/librustc/middle/traits/object_safety.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -53,36 +53,36 @@ pub enum MethodViolationCode {
5353
}
5454

5555
pub fn is_object_safe<'tcx>(tcx: &ty::ctxt<'tcx>,
56-
trait_ref: ty::PolyTraitRef<'tcx>)
56+
trait_def_id: ast::DefId)
5757
-> bool
5858
{
5959
// Because we query yes/no results frequently, we keep a cache:
6060
let cached_result =
61-
tcx.object_safety_cache.borrow().get(&trait_ref.def_id()).cloned();
61+
tcx.object_safety_cache.borrow().get(&trait_def_id).cloned();
6262

6363
let result =
6464
cached_result.unwrap_or_else(|| {
65-
let result = object_safety_violations(tcx, trait_ref.clone()).is_empty();
65+
let result = object_safety_violations(tcx, trait_def_id).is_empty();
6666

6767
// Record just a yes/no result in the cache; this is what is
6868
// queried most frequently. Note that this may overwrite a
6969
// previous result, but always with the same thing.
70-
tcx.object_safety_cache.borrow_mut().insert(trait_ref.def_id(), result);
70+
tcx.object_safety_cache.borrow_mut().insert(trait_def_id, result);
7171

7272
result
7373
});
7474

75-
debug!("is_object_safe({}) = {}", trait_ref.repr(tcx), result);
75+
debug!("is_object_safe({}) = {}", trait_def_id.repr(tcx), result);
7676

7777
result
7878
}
7979

8080
pub fn object_safety_violations<'tcx>(tcx: &ty::ctxt<'tcx>,
81-
sub_trait_ref: ty::PolyTraitRef<'tcx>)
81+
trait_def_id: ast::DefId)
8282
-> Vec<ObjectSafetyViolation<'tcx>>
8383
{
84-
supertraits(tcx, sub_trait_ref)
85-
.flat_map(|tr| object_safety_violations_for_trait(tcx, tr.def_id()).into_iter())
84+
traits::supertrait_def_ids(tcx, trait_def_id)
85+
.flat_map(|def_id| object_safety_violations_for_trait(tcx, def_id).into_iter())
8686
.collect()
8787
}
8888

src/librustc/middle/traits/select.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1237,7 +1237,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
12371237
// self-type from one of the other inputs. Without this check,
12381238
// these cases wind up being considered ambiguous due to a
12391239
// (spurious) ambiguity introduced here.
1240-
if !object_safety::is_object_safe(self.tcx(), obligation.predicate.to_poly_trait_ref()) {
1240+
let predicate_trait_ref = obligation.predicate.to_poly_trait_ref();
1241+
if !object_safety::is_object_safe(self.tcx(), predicate_trait_ref.def_id()) {
12411242
return;
12421243
}
12431244

src/librustc/middle/traits/util.rs

+41
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,47 @@ pub fn transitive_bounds<'cx, 'tcx>(tcx: &'cx ty::ctxt<'tcx>,
209209
elaborate_trait_refs(tcx, bounds).filter_to_traits()
210210
}
211211

212+
///////////////////////////////////////////////////////////////////////////
213+
// Iterator over def-ids of supertraits
214+
215+
pub struct SupertraitDefIds<'cx, 'tcx:'cx> {
216+
tcx: &'cx ty::ctxt<'tcx>,
217+
stack: Vec<ast::DefId>,
218+
visited: FnvHashSet<ast::DefId>,
219+
}
220+
221+
pub fn supertrait_def_ids<'cx, 'tcx>(tcx: &'cx ty::ctxt<'tcx>,
222+
trait_def_id: ast::DefId)
223+
-> SupertraitDefIds<'cx, 'tcx>
224+
{
225+
SupertraitDefIds {
226+
tcx: tcx,
227+
stack: vec![trait_def_id],
228+
visited: Some(trait_def_id).into_iter().collect(),
229+
}
230+
}
231+
232+
impl<'cx, 'tcx> Iterator for SupertraitDefIds<'cx, 'tcx> {
233+
type Item = ast::DefId;
234+
235+
fn next(&mut self) -> Option<ast::DefId> {
236+
let def_id = match self.stack.pop() {
237+
Some(def_id) => def_id,
238+
None => { return None; }
239+
};
240+
241+
let predicates = ty::lookup_super_predicates(self.tcx, def_id);
242+
let visited = &mut self.visited;
243+
self.stack.extend(
244+
predicates.predicates
245+
.iter()
246+
.filter_map(|p| p.to_opt_poly_trait_ref())
247+
.map(|t| t.def_id())
248+
.filter(|&super_def_id| visited.insert(super_def_id)));
249+
Some(def_id)
250+
}
251+
}
252+
212253
///////////////////////////////////////////////////////////////////////////
213254
// Other
214255
///////////////////////////////////////////////////////////////////////////

src/librustc_typeck/check/vtable.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,17 @@ pub fn check_object_safety<'tcx>(tcx: &ty::ctxt<'tcx>,
2828
object_trait: &ty::TyTrait<'tcx>,
2929
span: Span)
3030
{
31-
let object_trait_ref =
32-
object_trait.principal_trait_ref_with_self_ty(tcx, tcx.types.err);
31+
let trait_def_id = object_trait.principal_def_id();
3332

34-
if traits::is_object_safe(tcx, object_trait_ref.clone()) {
33+
if traits::is_object_safe(tcx, trait_def_id) {
3534
return;
3635
}
3736

3837
span_err!(tcx.sess, span, E0038,
3938
"cannot convert to a trait object because trait `{}` is not object-safe",
40-
ty::item_path_str(tcx, object_trait_ref.def_id()));
39+
ty::item_path_str(tcx, trait_def_id));
4140

42-
let violations = traits::object_safety_violations(tcx, object_trait_ref.clone());
41+
let violations = traits::object_safety_violations(tcx, trait_def_id);
4342
for violation in violations {
4443
match violation {
4544
ObjectSafetyViolation::SizedSelf => {

0 commit comments

Comments
 (0)