Skip to content

Commit 607af72

Browse files
Refactor BuiltinBounds to Vec<DefId> on TraitObject.
1 parent 46c7a11 commit 607af72

File tree

10 files changed

+126
-85
lines changed

10 files changed

+126
-85
lines changed

src/librustc/traits/select.rs

Lines changed: 22 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ use ty::{self, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable};
4141
use traits;
4242
use ty::fast_reject;
4343
use ty::relate::TypeRelation;
44+
use middle::lang_items;
4445

4546
use rustc_data_structures::bitvec::BitVector;
4647
use rustc_data_structures::snapshot_vec::{SnapshotVecDelegate, SnapshotVec};
@@ -49,6 +50,7 @@ use std::fmt;
4950
use std::marker::PhantomData;
5051
use std::mem;
5152
use std::rc::Rc;
53+
use std::iter;
5254
use syntax::abi::Abi;
5355
use hir;
5456
use util::nodemap::FxHashMap;
@@ -1516,16 +1518,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
15161518
let self_ty = this.tcx().erase_late_bound_regions(&obligation.self_ty());
15171519
let poly_trait_ref = match self_ty.sty {
15181520
ty::TyTrait(ref data) => {
1519-
match this.tcx().lang_items.to_builtin_kind(obligation.predicate.def_id()) {
1520-
Some(bound @ ty::BoundSend) | Some(bound @ ty::BoundSync) => {
1521-
if data.builtin_bounds.contains(&bound) {
1522-
debug!("assemble_candidates_from_object_ty: matched builtin bound, \
1523-
pushing candidate");
1524-
candidates.vec.push(BuiltinObjectCandidate);
1525-
return;
1526-
}
1527-
}
1528-
_ => {}
1521+
if data.auto_traits().any(|did| did == obligation.predicate.def_id()) {
1522+
debug!("assemble_candidates_from_object_ty: matched builtin bound, \
1523+
pushing candidate");
1524+
candidates.vec.push(BuiltinObjectCandidate);
1525+
return;
15291526
}
15301527

15311528
match data.principal() {
@@ -1616,7 +1613,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
16161613
// #2 (region bounds).
16171614
match (data_a.principal(), data_b.principal()) {
16181615
(Some(ref a), Some(ref b)) => a.def_id() == b.def_id() &&
1619-
data_a.builtin_bounds.is_superset(&data_b.builtin_bounds),
1616+
data_b.auto_traits()
1617+
// All of a's auto traits need to be in b's auto traits.
1618+
.all(|b| data_a.auto_traits().any(|a| a == b)),
16201619
_ => false
16211620
}
16221621
}
@@ -2481,7 +2480,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
24812480
let new_trait = tcx.mk_trait(ty::TraitObject::new(
24822481
data_a.principal(),
24832482
data_b.region_bound,
2484-
data_b.builtin_bounds,
2483+
data_b.auto_traits().collect(),
24852484
data_a.projection_bounds.clone(),
24862485
));
24872486
let origin = TypeOrigin::Misc(obligation.cause.span);
@@ -2504,10 +2503,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
25042503
// T -> Trait.
25052504
(_, &ty::TyTrait(ref data)) => {
25062505
let mut object_dids =
2507-
data.builtin_bounds.iter().flat_map(|bound| {
2508-
tcx.lang_items.from_builtin_kind(bound).ok()
2509-
})
2510-
.chain(data.principal().map(|ref p| p.def_id()));
2506+
data.auto_traits().chain(data.principal().map(|ref p| p.def_id()));
25112507
if let Some(did) = object_dids.find(|did| {
25122508
!tcx.is_object_safe(*did)
25132509
}) {
@@ -2527,19 +2523,21 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
25272523
push(data.principal().unwrap().with_self_ty(tcx, source).to_predicate());
25282524

25292525
// We can only make objects from sized types.
2530-
let mut builtin_bounds = data.builtin_bounds;
2531-
builtin_bounds.insert(ty::BoundSized);
2526+
let trait_refs = data.auto_traits()
2527+
.chain(iter::once(
2528+
tcx.lang_items.require(lang_items::SizedTraitLangItem)
2529+
.unwrap_or_else(|msg| tcx.sess.fatal(&msg[..]))))
2530+
.map(|did| ty::TraitRef {
2531+
def_id: did,
2532+
substs: tcx.mk_substs_trait(source, &[]),
2533+
});
25322534

25332535
// Create additional obligations for all the various builtin
25342536
// bounds attached to the object cast. (In other words, if the
25352537
// object type is Foo+Send, this would create an obligation
25362538
// for the Send check.)
2537-
for bound in &builtin_bounds {
2538-
if let Ok(tr) = tcx.trait_ref_for_builtin_bound(bound, source) {
2539-
push(tr.to_predicate());
2540-
} else {
2541-
return Err(Unimplemented);
2542-
}
2539+
for tr in trait_refs {
2540+
push(tr.to_predicate());
25432541
}
25442542

25452543
// Create obligations for the projection predicates.

src/librustc/ty/relate.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -428,7 +428,11 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
428428
|relation| relation.relate_with_variance(ty::Contravariant,
429429
&a_obj.region_bound,
430430
&b_obj.region_bound))?;
431-
let nb = relation.relate(&a_obj.builtin_bounds, &b_obj.builtin_bounds)?;
431+
let nb = if !a_obj.auto_traits().eq(b_obj.auto_traits()) {
432+
return Err(TypeError::Sorts(expected_found(relation, &a, &b)));
433+
} else {
434+
a_obj.auto_traits().collect()
435+
};
432436
let pb = relation.relate(&a_obj.projection_bounds, &b_obj.projection_bounds)?;
433437
Ok(tcx.mk_trait(ty::TraitObject::new(principal, r, nb, pb)))
434438
}

src/librustc/ty/structural_impls.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::TraitObject<'tcx> {
432432
ty::TraitObject::new(
433433
self.principal().map(|p| p.fold_with(folder)),
434434
self.region_bound.fold_with(folder),
435-
self.builtin_bounds,
435+
self.auto_traits().collect(),
436436
self.projection_bounds.fold_with(folder),
437437
)
438438
}

src/librustc/ty/sty.rs

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -279,25 +279,29 @@ impl<'a, 'gcx, 'acx, 'tcx> ClosureSubsts<'tcx> {
279279
pub struct TraitObject<'tcx> {
280280
principal: Option<PolyExistentialTraitRef<'tcx>>,
281281
pub region_bound: &'tcx ty::Region,
282-
pub builtin_bounds: BuiltinBounds,
282+
auto_traits: Vec<DefId>,
283283
pub projection_bounds: Vec<PolyExistentialProjection<'tcx>>,
284284
}
285285

286286
impl<'tcx> TraitObject<'tcx> {
287287
pub fn new(principal: Option<PolyExistentialTraitRef<'tcx>>, region_bound: &'tcx ty::Region,
288-
builtin_bounds: BuiltinBounds, projection_bounds: Vec<PolyExistentialProjection<'tcx>>)
288+
auto_traits: Vec<DefId>, projection_bounds: Vec<PolyExistentialProjection<'tcx>>)
289289
-> Self {
290290
TraitObject {
291291
principal: principal,
292292
region_bound: region_bound,
293-
builtin_bounds: builtin_bounds,
293+
auto_traits: auto_traits,
294294
projection_bounds: projection_bounds,
295295
}
296296
}
297297

298298
pub fn principal(&self) -> Option<PolyExistentialTraitRef<'tcx>> {
299299
self.principal
300300
}
301+
302+
pub fn auto_traits<'a>(&'a self) -> impl Iterator<Item=DefId> + 'a {
303+
self.auto_traits.iter().cloned()
304+
}
301305
}
302306

303307
/// A complete reference to a trait. These take numerous guises in syntax,
@@ -833,18 +837,22 @@ impl CLike for BuiltinBound {
833837

834838
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
835839
pub fn try_add_builtin_trait(self,
836-
trait_def_id: DefId,
837-
builtin_bounds: &mut EnumSet<BuiltinBound>)
840+
id: DefId,
841+
auto_traits: &mut Vec<DefId>)
838842
-> bool
839843
{
840-
//! Checks whether `trait_ref` refers to one of the builtin
841-
//! traits, like `Send`, and adds the corresponding
842-
//! bound to the set `builtin_bounds` if so. Returns true if `trait_ref`
843-
//! is a builtin trait.
844-
845-
match self.lang_items.to_builtin_kind(trait_def_id) {
846-
Some(bound) => { builtin_bounds.insert(bound); true }
847-
None => false
844+
//! Checks whether `id` refers to one of the builtin
845+
//! traits, like `Send`, and adds it to `auto_traits` if so.
846+
//! Returns true if `idf` refers to a builtin trait.
847+
848+
if Some(id) == self.lang_items.send_trait() ||
849+
Some(id) == self.lang_items.sized_trait() ||
850+
Some(id) == self.lang_items.copy_trait() ||
851+
Some(id) == self.lang_items.sync_trait() {
852+
auto_traits.push(id);
853+
true
854+
} else {
855+
false
848856
}
849857
}
850858
}

src/librustc/ty/util.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -535,7 +535,9 @@ impl<'a, 'gcx, 'tcx, H: Hasher> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tc
535535
if let Some(ref p) = data.principal() {
536536
self.def_id(p.def_id());
537537
}
538-
self.hash(data.builtin_bounds);
538+
for d in data.auto_traits() {
539+
self.def_id(d);
540+
}
539541
}
540542
TyTuple(tys) => {
541543
self.hash(tys.len());

src/librustc/ty/wf.rs

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,6 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
298298
/// is WF. Returns false if `ty0` is an unresolved type variable,
299299
/// in which case we are not able to simplify at all.
300300
fn compute(&mut self, ty0: Ty<'tcx>) -> bool {
301-
let tcx = self.infcx.tcx;
302301
let mut subtys = ty0.walk();
303302
while let Some(ty) = subtys.next() {
304303
match ty.sty {
@@ -391,15 +390,12 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
391390
let cause = self.cause(traits::MiscObligation);
392391

393392
let component_traits =
394-
data.builtin_bounds.iter().flat_map(|bound| {
395-
tcx.lang_items.from_builtin_kind(bound).ok()
396-
})
397-
.chain(data.principal().map(|ref p| p.def_id()));
393+
data.auto_traits().chain(data.principal().map(|ref p| p.def_id()));
398394
self.out.extend(
399-
component_traits.map(|did| { traits::Obligation::new(
395+
component_traits.map(|did| traits::Obligation::new(
400396
cause.clone(),
401397
ty::Predicate::ObjectSafe(did)
402-
)})
398+
))
403399
);
404400
}
405401

@@ -493,7 +489,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
493489
let implicit_bounds =
494490
object_region_bounds(self.infcx.tcx,
495491
data.principal().unwrap(),
496-
data.builtin_bounds);
492+
data.auto_traits());
497493

498494
let explicit_bound = data.region_bound;
499495

@@ -512,18 +508,25 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
512508
/// they declare `trait SomeTrait : 'static`, for example, then
513509
/// `'static` would appear in the list. The hard work is done by
514510
/// `ty::required_region_bounds`, see that for more information.
515-
pub fn object_region_bounds<'a, 'gcx, 'tcx>(
511+
pub fn object_region_bounds<'a, 'gcx, 'tcx, I>(
516512
tcx: TyCtxt<'a, 'gcx, 'tcx>,
517513
principal: ty::PolyExistentialTraitRef<'tcx>,
518-
others: ty::BuiltinBounds)
514+
others: I)
519515
-> Vec<&'tcx ty::Region>
516+
where I: Iterator<Item=DefId>
520517
{
521518
// Since we don't actually *know* the self type for an object,
522519
// this "open(err)" serves as a kind of dummy standin -- basically
523520
// a skolemized type.
524521
let open_ty = tcx.mk_infer(ty::FreshTy(0));
525522

526-
let mut predicates = others.to_predicates(tcx, open_ty);
523+
let mut predicates = others.map(|d| {
524+
let trait_ref = ty::TraitRef {
525+
def_id: d,
526+
substs: tcx.mk_substs_trait(open_ty, &[])
527+
};
528+
trait_ref.to_predicate()
529+
}).collect::<Vec<_>>();
527530
predicates.push(principal.with_self_ty(tcx, open_ty).to_predicate());
528531

529532
tcx.required_region_bounds(open_ty, predicates)

src/librustc/util/ppaux.rs

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -349,13 +349,15 @@ impl<'tcx> fmt::Display for ty::TraitObject<'tcx> {
349349
}).collect();
350350

351351
let tap = ty::Binder(TraitAndProjections(principal, projections));
352-
in_binder(f, tcx, &ty::Binder(""), Some(tap))
353-
})?;
352+
in_binder(f, tcx, &ty::Binder(""), Some(tap))?;
354353

355-
// Builtin bounds.
356-
for bound in &self.builtin_bounds {
357-
write!(f, " + {:?}", bound)?;
358-
}
354+
// Builtin bounds.
355+
for did in self.auto_traits() {
356+
write!(f, " + {}", tcx.item_path_str(did))?;
357+
}
358+
359+
Ok(())
360+
})?;
359361

360362
// FIXME: It'd be nice to compute from context when this bound
361363
// is implied, but that's non-trivial -- we'd perhaps have to
@@ -474,10 +476,14 @@ impl<'tcx> fmt::Debug for ty::TraitObject<'tcx> {
474476
write!(f, "{}", region_str)?;
475477
}
476478

477-
for bound in &self.builtin_bounds {
478-
maybe_continue(f)?;
479-
write!(f, "{:?}", bound)?;
480-
}
479+
ty::tls::with(|tcx| {
480+
for did in self.auto_traits() {
481+
maybe_continue(f)?;
482+
write!(f, " + {}", tcx.item_path_str(did))?;
483+
}
484+
485+
Ok(())
486+
})?;
481487

482488
for projection_bound in &self.projection_bounds {
483489
maybe_continue(f)?;

0 commit comments

Comments
 (0)