Skip to content

Commit 5272be5

Browse files
authored
Rollup merge of rust-lang#57502 - nikomatsakis:fix-trait-alias-1b, r=nikomatsakis
make trait-aliases work across crates This is rebase of a small part of @alexreg's PR rust-lang#55994. It focuses just on the changes that integrate trait aliases properly into crate metadata, excluding the stylistic edits and the trait objects. The stylistic edits I also rebased and can open a separate PR. The trait object stuff I found challenging and decided it basically needed to be reimplemented. For now I've excluded it. Since this is really @alexreg's work (I really just rebased) I am going to make it r=me once it is working. Fixes rust-lang#56488. Fixes rust-lang#57023.
2 parents 349c9ee + b411994 commit 5272be5

21 files changed

+223
-57
lines changed

src/librustc/hir/map/def_collector.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -120,10 +120,10 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
120120
let def_data = match i.node {
121121
ItemKind::Impl(..) => DefPathData::Impl,
122122
ItemKind::Trait(..) => DefPathData::Trait(i.ident.as_interned_str()),
123+
ItemKind::TraitAlias(..) => DefPathData::TraitAlias(i.ident.as_interned_str()),
123124
ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) |
124-
ItemKind::TraitAlias(..) | ItemKind::Existential(..) |
125-
ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) | ItemKind::Ty(..) =>
126-
DefPathData::TypeNs(i.ident.as_interned_str()),
125+
ItemKind::Existential(..) | ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) |
126+
ItemKind::Ty(..) => DefPathData::TypeNs(i.ident.as_interned_str()),
127127
ItemKind::Mod(..) if i.ident == keywords::Invalid.ident() => {
128128
return visit::walk_item(self, i);
129129
}

src/librustc/hir/map/definitions.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,9 @@ pub enum DefPathData {
373373
/// GlobalMetaData identifies a piece of crate metadata that is global to
374374
/// a whole crate (as opposed to just one item). GlobalMetaData components
375375
/// are only supposed to show up right below the crate root.
376-
GlobalMetaData(InternedString)
376+
GlobalMetaData(InternedString),
377+
/// A trait alias.
378+
TraitAlias(InternedString),
377379
}
378380

379381
#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug,
@@ -615,6 +617,7 @@ impl DefPathData {
615617
match *self {
616618
TypeNs(name) |
617619
Trait(name) |
620+
TraitAlias(name) |
618621
AssocTypeInTrait(name) |
619622
AssocTypeInImpl(name) |
620623
AssocExistentialInImpl(name) |
@@ -642,6 +645,7 @@ impl DefPathData {
642645
let s = match *self {
643646
TypeNs(name) |
644647
Trait(name) |
648+
TraitAlias(name) |
645649
AssocTypeInTrait(name) |
646650
AssocTypeInImpl(name) |
647651
AssocExistentialInImpl(name) |

src/librustc/hir/mod.rs

+15
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ pub use self::PrimTy::*;
1010
pub use self::UnOp::*;
1111
pub use self::UnsafeSource::*;
1212

13+
use errors::FatalError;
1314
use hir::def::Def;
1415
use hir::def_id::{DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX};
1516
use util::nodemap::{NodeMap, FxHashSet};
@@ -2055,6 +2056,20 @@ pub struct TraitRef {
20552056
pub hir_ref_id: HirId,
20562057
}
20572058

2059+
impl TraitRef {
2060+
/// Get the `DefId` of the referenced trait. It _must_ actually be a trait or trait alias.
2061+
pub fn trait_def_id(&self) -> DefId {
2062+
match self.path.def {
2063+
Def::Trait(did) => did,
2064+
Def::TraitAlias(did) => did,
2065+
Def::Err => {
2066+
FatalError.raise();
2067+
}
2068+
_ => unreachable!(),
2069+
}
2070+
}
2071+
}
2072+
20582073
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
20592074
pub struct PolyTraitRef {
20602075
/// The `'a` in `<'a> Foo<&'a T>`

src/librustc/traits/select.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2198,7 +2198,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
21982198

21992199
let def_id = obligation.predicate.def_id();
22002200

2201-
if ty::is_trait_alias(self.tcx(), def_id) {
2201+
if self.tcx().is_trait_alias(def_id) {
22022202
candidates.vec.push(TraitAliasCandidate(def_id.clone()));
22032203
}
22042204

src/librustc/ty/item_path.rs

+1
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
311311
data @ DefPathData::Misc |
312312
data @ DefPathData::TypeNs(..) |
313313
data @ DefPathData::Trait(..) |
314+
data @ DefPathData::TraitAlias(..) |
314315
data @ DefPathData::AssocTypeInTrait(..) |
315316
data @ DefPathData::AssocTypeInImpl(..) |
316317
data @ DefPathData::AssocExistentialInImpl(..) |

src/librustc/ty/mod.rs

-12
Original file line numberDiff line numberDiff line change
@@ -3170,18 +3170,6 @@ pub fn is_impl_trait_defn(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Option<DefI
31703170
None
31713171
}
31723172

3173-
/// Returns `true` if `def_id` is a trait alias.
3174-
pub fn is_trait_alias(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> bool {
3175-
if let Some(node_id) = tcx.hir().as_local_node_id(def_id) {
3176-
if let Node::Item(item) = tcx.hir().get(node_id) {
3177-
if let hir::ItemKind::TraitAlias(..) = item.node {
3178-
return true;
3179-
}
3180-
}
3181-
}
3182-
false
3183-
}
3184-
31853173
/// See `ParamEnv` struct definition for details.
31863174
fn param_env<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
31873175
def_id: DefId)

src/librustc/ty/util.rs

+9
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,15 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
526526
}
527527
}
528528

529+
/// True if `def_id` refers to a trait alias (i.e., `trait Foo = ...;`).
530+
pub fn is_trait_alias(self, def_id: DefId) -> bool {
531+
if let DefPathData::TraitAlias(_) = self.def_key(def_id).disambiguated_data.data {
532+
true
533+
} else {
534+
false
535+
}
536+
}
537+
529538
/// True if this def-id refers to the implicit constructor for
530539
/// a tuple struct like `struct Foo(u32)`.
531540
pub fn is_struct_constructor(self, def_id: DefId) -> bool {

src/librustc/util/ppaux.rs

+1
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,7 @@ impl PrintContext {
409409
DefPathData::AssocTypeInImpl(_) |
410410
DefPathData::AssocExistentialInImpl(_) |
411411
DefPathData::Trait(_) |
412+
DefPathData::TraitAlias(_) |
412413
DefPathData::Impl |
413414
DefPathData::TypeNs(_) => {
414415
break;

src/librustc_metadata/decoder.rs

+30-16
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,7 @@ impl<'tcx> EntryKind<'tcx> {
418418
EntryKind::Mod(_) => Def::Mod(did),
419419
EntryKind::Variant(_) => Def::Variant(did),
420420
EntryKind::Trait(_) => Def::Trait(did),
421+
EntryKind::TraitAlias(_) => Def::TraitAlias(did),
421422
EntryKind::Enum(..) => Def::Enum(did),
422423
EntryKind::MacroDef(_) => Def::Macro(did, MacroKind::Bang),
423424
EntryKind::ForeignType => Def::ForeignTy(did),
@@ -520,17 +521,26 @@ impl<'a, 'tcx> CrateMetadata {
520521
}
521522

522523
pub fn get_trait_def(&self, item_id: DefIndex, sess: &Session) -> ty::TraitDef {
523-
let data = match self.entry(item_id).kind {
524-
EntryKind::Trait(data) => data.decode((self, sess)),
525-
_ => bug!(),
526-
};
527-
528-
ty::TraitDef::new(self.local_def_id(item_id),
529-
data.unsafety,
530-
data.paren_sugar,
531-
data.has_auto_impl,
532-
data.is_marker,
533-
self.def_path_table.def_path_hash(item_id))
524+
match self.entry(item_id).kind {
525+
EntryKind::Trait(data) => {
526+
let data = data.decode((self, sess));
527+
ty::TraitDef::new(self.local_def_id(item_id),
528+
data.unsafety,
529+
data.paren_sugar,
530+
data.has_auto_impl,
531+
data.is_marker,
532+
self.def_path_table.def_path_hash(item_id))
533+
},
534+
EntryKind::TraitAlias(_) => {
535+
ty::TraitDef::new(self.local_def_id(item_id),
536+
hir::Unsafety::Normal,
537+
false,
538+
false,
539+
false,
540+
self.def_path_table.def_path_hash(item_id))
541+
},
542+
_ => bug!("def-index does not refer to trait or trait alias"),
543+
}
534544
}
535545

536546
fn get_variant(&self,
@@ -615,10 +625,13 @@ impl<'a, 'tcx> CrateMetadata {
615625
item_id: DefIndex,
616626
tcx: TyCtxt<'a, 'tcx, 'tcx>)
617627
-> ty::GenericPredicates<'tcx> {
618-
match self.entry(item_id).kind {
619-
EntryKind::Trait(data) => data.decode(self).super_predicates.decode((self, tcx)),
620-
_ => bug!(),
621-
}
628+
let super_predicates = match self.entry(item_id).kind {
629+
EntryKind::Trait(data) => data.decode(self).super_predicates,
630+
EntryKind::TraitAlias(data) => data.decode(self).super_predicates,
631+
_ => bug!("def-index does not refer to trait or trait alias"),
632+
};
633+
634+
super_predicates.decode((self, tcx))
622635
}
623636

624637
pub fn get_generics(&self,
@@ -1014,7 +1027,8 @@ impl<'a, 'tcx> CrateMetadata {
10141027
}
10151028
def_key.parent.and_then(|parent_index| {
10161029
match self.entry(parent_index).kind {
1017-
EntryKind::Trait(_) => Some(self.local_def_id(parent_index)),
1030+
EntryKind::Trait(_) |
1031+
EntryKind::TraitAlias(_) => Some(self.local_def_id(parent_index)),
10181032
_ => None,
10191033
}
10201034
})

src/librustc_metadata/encoder.rs

+13-4
Original file line numberDiff line numberDiff line change
@@ -1128,8 +1128,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
11281128

11291129
EntryKind::Impl(self.lazy(&data))
11301130
}
1131-
hir::ItemKind::Trait(..) |
1132-
hir::ItemKind::TraitAlias(..) => {
1131+
hir::ItemKind::Trait(..) => {
11331132
let trait_def = tcx.trait_def(def_id);
11341133
let data = TraitData {
11351134
unsafety: trait_def.unsafety,
@@ -1141,6 +1140,13 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
11411140

11421141
EntryKind::Trait(self.lazy(&data))
11431142
}
1143+
hir::ItemKind::TraitAlias(..) => {
1144+
let data = TraitAliasData {
1145+
super_predicates: self.lazy(&tcx.super_predicates_of(def_id)),
1146+
};
1147+
1148+
EntryKind::TraitAlias(self.lazy(&data))
1149+
}
11441150
hir::ItemKind::ExternCrate(_) |
11451151
hir::ItemKind::Use(..) => bug!("cannot encode info for item {:?}", item),
11461152
};
@@ -1214,6 +1220,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
12141220
hir::ItemKind::Impl(..) |
12151221
hir::ItemKind::Existential(..) |
12161222
hir::ItemKind::Trait(..) => Some(self.encode_generics(def_id)),
1223+
hir::ItemKind::TraitAlias(..) => Some(self.encode_generics(def_id)),
12171224
_ => None,
12181225
},
12191226
predicates: match item.node {
@@ -1226,7 +1233,8 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
12261233
hir::ItemKind::Union(..) |
12271234
hir::ItemKind::Impl(..) |
12281235
hir::ItemKind::Existential(..) |
1229-
hir::ItemKind::Trait(..) => Some(self.encode_predicates(def_id)),
1236+
hir::ItemKind::Trait(..) |
1237+
hir::ItemKind::TraitAlias(..) => Some(self.encode_predicates(def_id)),
12301238
_ => None,
12311239
},
12321240

@@ -1236,7 +1244,8 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
12361244
// hack. (No reason not to expand it in the future if
12371245
// necessary.)
12381246
predicates_defined_on: match item.node {
1239-
hir::ItemKind::Trait(..) => Some(self.encode_predicates_defined_on(def_id)),
1247+
hir::ItemKind::Trait(..) |
1248+
hir::ItemKind::TraitAlias(..) => Some(self.encode_predicates_defined_on(def_id)),
12401249
_ => None, // not *wrong* for other kinds of items, but not needed
12411250
},
12421251

src/librustc_metadata/schema.rs

+13
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,7 @@ pub enum EntryKind<'tcx> {
316316
AssociatedType(AssociatedContainer),
317317
AssociatedExistential(AssociatedContainer),
318318
AssociatedConst(AssociatedContainer, ConstQualif, Lazy<RenderedConst>),
319+
TraitAlias(Lazy<TraitAliasData<'tcx>>),
319320
}
320321

321322
impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for EntryKind<'gcx> {
@@ -370,6 +371,9 @@ impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for EntryKind<'gcx> {
370371
EntryKind::Trait(ref trait_data) => {
371372
trait_data.hash_stable(hcx, hasher);
372373
}
374+
EntryKind::TraitAlias(ref trait_alias_data) => {
375+
trait_alias_data.hash_stable(hcx, hasher);
376+
}
373377
EntryKind::Impl(ref impl_data) => {
374378
impl_data.hash_stable(hcx, hasher);
375379
}
@@ -474,6 +478,15 @@ impl_stable_hash_for!(struct TraitData<'tcx> {
474478
super_predicates
475479
});
476480

481+
#[derive(RustcEncodable, RustcDecodable)]
482+
pub struct TraitAliasData<'tcx> {
483+
pub super_predicates: Lazy<ty::GenericPredicates<'tcx>>,
484+
}
485+
486+
impl_stable_hash_for!(struct TraitAliasData<'tcx> {
487+
super_predicates
488+
});
489+
477490
#[derive(RustcEncodable, RustcDecodable)]
478491
pub struct ImplData<'tcx> {
479492
pub polarity: hir::ImplPolarity,

src/librustc_resolve/build_reduced_graph.rs

+3
Original file line numberDiff line numberDiff line change
@@ -673,6 +673,9 @@ impl<'a> Resolver<'a> {
673673
}
674674
module.populated.set(true);
675675
}
676+
Def::TraitAlias(..) => {
677+
self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, expansion));
678+
}
676679
Def::Struct(..) | Def::Union(..) => {
677680
self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, expansion));
678681

src/librustc_traits/lowering/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,8 @@ crate fn program_clauses_for<'a, 'tcx>(
158158
def_id: DefId,
159159
) -> Clauses<'tcx> {
160160
match tcx.def_key(def_id).disambiguated_data.data {
161-
DefPathData::Trait(_) => program_clauses_for_trait(tcx, def_id),
161+
DefPathData::Trait(_) |
162+
DefPathData::TraitAlias(_) => program_clauses_for_trait(tcx, def_id),
162163
DefPathData::Impl => program_clauses_for_impl(tcx, def_id),
163164
DefPathData::AssocTypeInImpl(..) => program_clauses_for_associated_type_value(tcx, def_id),
164165
DefPathData::AssocTypeInTrait(..) => program_clauses_for_associated_type_def(tcx, def_id),

src/librustc_typeck/astconv.rs

+4-18
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//! The main routine here is `ast_ty_to_ty()`; each use is parameterized by an
33
//! instance of `AstConv`.
44
5-
use errors::{Applicability, FatalError, DiagnosticId};
5+
use errors::{Applicability, DiagnosticId};
66
use hir::{self, GenericArg, GenericArgs};
77
use hir::def::Def;
88
use hir::def_id::DefId;
@@ -690,35 +690,21 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
690690
{
691691
self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1);
692692

693-
let trait_def_id = self.trait_def_id(trait_ref);
694693
self.ast_path_to_mono_trait_ref(trait_ref.path.span,
695-
trait_def_id,
694+
trait_ref.trait_def_id(),
696695
self_ty,
697696
trait_ref.path.segments.last().unwrap())
698697
}
699698

700-
/// Get the `DefId` of the given trait ref. It _must_ actually be a trait.
701-
fn trait_def_id(&self, trait_ref: &hir::TraitRef) -> DefId {
702-
let path = &trait_ref.path;
703-
match path.def {
704-
Def::Trait(trait_def_id) => trait_def_id,
705-
Def::TraitAlias(alias_def_id) => alias_def_id,
706-
Def::Err => {
707-
FatalError.raise();
708-
}
709-
_ => unreachable!(),
710-
}
711-
}
712-
713-
/// The given trait ref must actually be a trait.
699+
/// The given trait-ref must actually be a trait.
714700
pub(super) fn instantiate_poly_trait_ref_inner(&self,
715701
trait_ref: &hir::TraitRef,
716702
self_ty: Ty<'tcx>,
717703
poly_projections: &mut Vec<(ty::PolyProjectionPredicate<'tcx>, Span)>,
718704
speculative: bool)
719705
-> (ty::PolyTraitRef<'tcx>, Option<Vec<Span>>)
720706
{
721-
let trait_def_id = self.trait_def_id(trait_ref);
707+
let trait_def_id = trait_ref.trait_def_id();
722708

723709
debug!("instantiate_poly_trait_ref({:?}, def_id={:?})", trait_ref, trait_def_id);
724710

src/librustc_typeck/collect.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -715,7 +715,7 @@ fn super_predicates_of<'a, 'tcx>(
715715
// In the case of trait aliases, however, we include all bounds in the where clause,
716716
// so e.g., `trait Foo = where u32: PartialEq<Self>` would include `u32: PartialEq<Self>`
717717
// as one of its "superpredicates".
718-
let is_trait_alias = ty::is_trait_alias(tcx, trait_def_id);
718+
let is_trait_alias = tcx.is_trait_alias(trait_def_id);
719719
let superbounds2 = icx.type_parameter_bounds_in_generics(
720720
generics, item.id, self_param_ty, OnlySelfBounds(!is_trait_alias));
721721

src/test/ui/issues/issue-56488.rs

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// run-pass
2+
3+
#![feature(trait_alias)]
4+
5+
mod alpha {
6+
pub trait A {}
7+
pub trait C = A;
8+
}
9+
10+
#[allow(unused_imports)]
11+
use alpha::C;
12+
13+
fn main() {}

0 commit comments

Comments
 (0)