Skip to content

Commit fb35f14

Browse files
author
Alexander Regueiro
committed
Build trait objects from *unexpanded* list of traits & traits aliases.
1 parent 3573acc commit fb35f14

File tree

2 files changed

+35
-24
lines changed

2 files changed

+35
-24
lines changed

src/librustc/traits/util.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -358,8 +358,7 @@ impl<'tcx> TraitAliasExpander<'tcx> {
358358
debug!("expand_trait_aliases: trait_ref={:?}", trait_ref);
359359

360360
// Don't recurse if this bound is not a trait alias.
361-
let is_alias = tcx.is_trait_alias(trait_ref.def_id());
362-
if !is_alias {
361+
if !tcx.is_trait_alias(trait_ref.def_id()) {
363362
return true;
364363
}
365364

src/librustc_typeck/astconv.rs

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1247,8 +1247,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
12471247
// Expand trait aliases recursively and check that only one regular (non-auto) trait
12481248
// is used and no 'maybe' bounds are used.
12491249
let expanded_traits =
1250-
traits::expand_trait_aliases(tcx, bounds.trait_bounds.iter().cloned());
1251-
let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) =
1250+
traits::expand_trait_aliases(tcx, bounds.trait_bounds.iter().cloned())
1251+
// Ensure that trait ref is to self type and not some type param.
1252+
.filter(|info| info.trait_ref().self_ty() == dummy_self);
1253+
let (auto_traits, regular_traits): (Vec<_>, Vec<_>) =
12521254
expanded_traits.partition(|i| tcx.trait_is_auto(i.trait_ref().def_id()));
12531255
if regular_traits.len() > 1 {
12541256
let first_trait = &regular_traits[0];
@@ -1289,7 +1291,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
12891291
let mut associated_types = BTreeSet::default();
12901292

12911293
let regular_traits_refs = bounds.trait_bounds
1292-
.into_iter()
1294+
.iter()
1295+
.cloned()
12931296
.filter(|(trait_ref, _)| !tcx.trait_is_auto(trait_ref.def_id()))
12941297
.map(|(trait_ref, _)| trait_ref);
12951298
for trait_ref in traits::elaborate_trait_refs(tcx, regular_traits_refs) {
@@ -1398,10 +1401,16 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
13981401
err.emit();
13991402
}
14001403

1404+
let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) =
1405+
bounds.trait_bounds
1406+
.into_iter()
1407+
.map(|(trait_ref, _)| trait_ref)
1408+
.partition(|i| tcx.trait_is_auto(i.def_id()));
1409+
14011410
// De-duplicate auto traits so that, e.g., `dyn Trait + Send + Send` is the same as
14021411
// `dyn Trait + Send`.
1403-
auto_traits.sort_by_key(|i| i.trait_ref().def_id());
1404-
auto_traits.dedup_by_key(|i| i.trait_ref().def_id());
1412+
auto_traits.sort_by_key(|i| i.def_id());
1413+
auto_traits.dedup_by_key(|i| i.def_id());
14051414
debug!("regular_traits: {:?}", regular_traits);
14061415
debug!("auto_traits: {:?}", auto_traits);
14071416

@@ -1415,25 +1424,28 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
14151424
};
14161425

14171426
// Erase the `dummy_self` (`trait_object_dummy_self`) used above.
1418-
let existential_trait_refs = regular_traits.iter().map(|i| {
1419-
i.trait_ref().map_bound(|trait_ref| trait_ref_to_existential(trait_ref))
1420-
});
1421-
let existential_projections = bounds.projection_bounds.iter().map(|(bound, _)| {
1422-
bound.map_bound(|b| {
1423-
let trait_ref = trait_ref_to_existential(b.projection_ty.trait_ref(tcx));
1424-
ty::ExistentialProjection {
1425-
ty: b.ty,
1426-
item_def_id: b.projection_ty.item_def_id,
1427-
substs: trait_ref.substs,
1428-
}
1429-
})
1430-
});
1427+
let existential_trait_refs = regular_traits
1428+
.iter()
1429+
.map(|i| i.map_bound(|trait_ref| trait_ref_to_existential(trait_ref)));
1430+
let existential_projections = bounds.projection_bounds
1431+
.iter()
1432+
.map(|(bound, _)| {
1433+
bound.map_bound(|b| {
1434+
let trait_ref = trait_ref_to_existential(b.projection_ty.trait_ref(tcx));
1435+
ty::ExistentialProjection {
1436+
ty: b.ty,
1437+
item_def_id: b.projection_ty.item_def_id,
1438+
substs: trait_ref.substs,
1439+
}
1440+
})
1441+
});
14311442

14321443
// Calling `skip_binder` is okay because the predicates are re-bound.
1433-
let regular_trait_predicates = existential_trait_refs.map(
1434-
|trait_ref| ty::ExistentialPredicate::Trait(*trait_ref.skip_binder()));
1435-
let auto_trait_predicates = auto_traits.into_iter().map(
1436-
|trait_ref| ty::ExistentialPredicate::AutoTrait(trait_ref.trait_ref().def_id()));
1444+
let regular_trait_predicates = existential_trait_refs
1445+
.map(|trait_ref| ty::ExistentialPredicate::Trait(*trait_ref.skip_binder()));
1446+
let auto_trait_predicates = auto_traits
1447+
.into_iter()
1448+
.map(|trait_ref| ty::ExistentialPredicate::AutoTrait(trait_ref.def_id()));
14371449
let mut v =
14381450
regular_trait_predicates
14391451
.chain(auto_trait_predicates)

0 commit comments

Comments
 (0)