Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

make trait-aliases work across crates #57502

Merged
merged 3 commits into from
Jan 19, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/librustc/hir/map/def_collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,10 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
let def_data = match i.node {
ItemKind::Impl(..) => DefPathData::Impl,
ItemKind::Trait(..) => DefPathData::Trait(i.ident.as_interned_str()),
ItemKind::TraitAlias(..) => DefPathData::TraitAlias(i.ident.as_interned_str()),
ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) |
ItemKind::TraitAlias(..) | ItemKind::Existential(..) |
ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) | ItemKind::Ty(..) =>
DefPathData::TypeNs(i.ident.as_interned_str()),
ItemKind::Existential(..) | ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) |
ItemKind::Ty(..) => DefPathData::TypeNs(i.ident.as_interned_str()),
ItemKind::Mod(..) if i.ident == keywords::Invalid.ident() => {
return visit::walk_item(self, i);
}
Expand Down
6 changes: 5 additions & 1 deletion src/librustc/hir/map/definitions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,9 @@ pub enum DefPathData {
/// GlobalMetaData identifies a piece of crate metadata that is global to
/// a whole crate (as opposed to just one item). GlobalMetaData components
/// are only supposed to show up right below the crate root.
GlobalMetaData(InternedString)
GlobalMetaData(InternedString),
/// A trait alias.
TraitAlias(InternedString),
}

#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug,
Expand Down Expand Up @@ -615,6 +617,7 @@ impl DefPathData {
match *self {
TypeNs(name) |
Trait(name) |
TraitAlias(name) |
AssocTypeInTrait(name) |
AssocTypeInImpl(name) |
AssocExistentialInImpl(name) |
Expand Down Expand Up @@ -642,6 +645,7 @@ impl DefPathData {
let s = match *self {
TypeNs(name) |
Trait(name) |
TraitAlias(name) |
AssocTypeInTrait(name) |
AssocTypeInImpl(name) |
AssocExistentialInImpl(name) |
Expand Down
15 changes: 15 additions & 0 deletions src/librustc/hir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ pub use self::PrimTy::*;
pub use self::UnOp::*;
pub use self::UnsafeSource::*;

use errors::FatalError;
use hir::def::Def;
use hir::def_id::{DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX};
use util::nodemap::{NodeMap, FxHashSet};
Expand Down Expand Up @@ -2053,6 +2054,20 @@ pub struct TraitRef {
pub hir_ref_id: HirId,
}

impl TraitRef {
/// Get the `DefId` of the referenced trait. It _must_ actually be a trait or trait alias.
pub fn trait_def_id(&self) -> DefId {
match self.path.def {
Def::Trait(did) => did,
Def::TraitAlias(did) => did,
Def::Err => {
FatalError.raise();
}
_ => unreachable!(),
}
}
}

#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct PolyTraitRef {
/// The `'a` in `<'a> Foo<&'a T>`
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/traits/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2154,7 +2154,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {

let def_id = obligation.predicate.def_id();

if ty::is_trait_alias(self.tcx(), def_id) {
if self.tcx().is_trait_alias(def_id) {
candidates.vec.push(TraitAliasCandidate(def_id.clone()));
}

Expand Down
1 change: 1 addition & 0 deletions src/librustc/ty/item_path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
data @ DefPathData::Misc |
data @ DefPathData::TypeNs(..) |
data @ DefPathData::Trait(..) |
data @ DefPathData::TraitAlias(..) |
data @ DefPathData::AssocTypeInTrait(..) |
data @ DefPathData::AssocTypeInImpl(..) |
data @ DefPathData::AssocExistentialInImpl(..) |
Expand Down
12 changes: 0 additions & 12 deletions src/librustc/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3178,18 +3178,6 @@ pub fn is_impl_trait_defn(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Option<DefI
None
}

/// Returns `true` if `def_id` is a trait alias.
pub fn is_trait_alias(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> bool {
if let Some(node_id) = tcx.hir().as_local_node_id(def_id) {
if let Node::Item(item) = tcx.hir().get(node_id) {
if let hir::ItemKind::TraitAlias(..) = item.node {
return true;
}
}
}
false
}

/// See `ParamEnv` struct definition for details.
fn param_env<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
def_id: DefId)
Expand Down
9 changes: 9 additions & 0 deletions src/librustc/ty/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,15 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
}
}

/// True if `def_id` refers to a trait alias (i.e., `trait Foo = ...;`).
pub fn is_trait_alias(self, def_id: DefId) -> bool {
if let DefPathData::TraitAlias(_) = self.def_key(def_id).disambiguated_data.data {
true
} else {
false
}
}

/// True if this def-id refers to the implicit constructor for
/// a tuple struct like `struct Foo(u32)`.
pub fn is_struct_constructor(self, def_id: DefId) -> bool {
Expand Down
1 change: 1 addition & 0 deletions src/librustc/util/ppaux.rs
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,7 @@ impl PrintContext {
DefPathData::AssocTypeInImpl(_) |
DefPathData::AssocExistentialInImpl(_) |
DefPathData::Trait(_) |
DefPathData::TraitAlias(_) |
DefPathData::Impl |
DefPathData::TypeNs(_) => {
break;
Expand Down
46 changes: 30 additions & 16 deletions src/librustc_metadata/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,7 @@ impl<'tcx> EntryKind<'tcx> {
EntryKind::Mod(_) => Def::Mod(did),
EntryKind::Variant(_) => Def::Variant(did),
EntryKind::Trait(_) => Def::Trait(did),
EntryKind::TraitAlias(_) => Def::TraitAlias(did),
EntryKind::Enum(..) => Def::Enum(did),
EntryKind::MacroDef(_) => Def::Macro(did, MacroKind::Bang),
EntryKind::ForeignType => Def::ForeignTy(did),
Expand Down Expand Up @@ -520,17 +521,26 @@ impl<'a, 'tcx> CrateMetadata {
}

pub fn get_trait_def(&self, item_id: DefIndex, sess: &Session) -> ty::TraitDef {
let data = match self.entry(item_id).kind {
EntryKind::Trait(data) => data.decode((self, sess)),
_ => bug!(),
};

ty::TraitDef::new(self.local_def_id(item_id),
data.unsafety,
data.paren_sugar,
data.has_auto_impl,
data.is_marker,
self.def_path_table.def_path_hash(item_id))
match self.entry(item_id).kind {
EntryKind::Trait(data) => {
let data = data.decode((self, sess));
ty::TraitDef::new(self.local_def_id(item_id),
data.unsafety,
data.paren_sugar,
data.has_auto_impl,
data.is_marker,
self.def_path_table.def_path_hash(item_id))
},
EntryKind::TraitAlias(_) => {
ty::TraitDef::new(self.local_def_id(item_id),
hir::Unsafety::Normal,
false,
false,
false,
self.def_path_table.def_path_hash(item_id))
},
_ => bug!("def-index does not refer to trait or trait alias"),
}
}

fn get_variant(&self,
Expand Down Expand Up @@ -615,10 +625,13 @@ impl<'a, 'tcx> CrateMetadata {
item_id: DefIndex,
tcx: TyCtxt<'a, 'tcx, 'tcx>)
-> ty::GenericPredicates<'tcx> {
match self.entry(item_id).kind {
EntryKind::Trait(data) => data.decode(self).super_predicates.decode((self, tcx)),
_ => bug!(),
}
let super_predicates = match self.entry(item_id).kind {
EntryKind::Trait(data) => data.decode(self).super_predicates,
EntryKind::TraitAlias(data) => data.decode(self).super_predicates,
_ => bug!("def-index does not refer to trait or trait alias"),
};

super_predicates.decode((self, tcx))
}

pub fn get_generics(&self,
Expand Down Expand Up @@ -1014,7 +1027,8 @@ impl<'a, 'tcx> CrateMetadata {
}
def_key.parent.and_then(|parent_index| {
match self.entry(parent_index).kind {
EntryKind::Trait(_) => Some(self.local_def_id(parent_index)),
EntryKind::Trait(_) |
EntryKind::TraitAlias(_) => Some(self.local_def_id(parent_index)),
_ => None,
}
})
Expand Down
17 changes: 13 additions & 4 deletions src/librustc_metadata/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1131,8 +1131,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {

EntryKind::Impl(self.lazy(&data))
}
hir::ItemKind::Trait(..) |
hir::ItemKind::TraitAlias(..) => {
hir::ItemKind::Trait(..) => {
let trait_def = tcx.trait_def(def_id);
let data = TraitData {
unsafety: trait_def.unsafety,
Expand All @@ -1144,6 +1143,13 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {

EntryKind::Trait(self.lazy(&data))
}
hir::ItemKind::TraitAlias(..) => {
let data = TraitAliasData {
super_predicates: self.lazy(&tcx.super_predicates_of(def_id)),
};

EntryKind::TraitAlias(self.lazy(&data))
}
hir::ItemKind::ExternCrate(_) |
hir::ItemKind::Use(..) => bug!("cannot encode info for item {:?}", item),
};
Expand Down Expand Up @@ -1217,6 +1223,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
hir::ItemKind::Impl(..) |
hir::ItemKind::Existential(..) |
hir::ItemKind::Trait(..) => Some(self.encode_generics(def_id)),
hir::ItemKind::TraitAlias(..) => Some(self.encode_generics(def_id)),
_ => None,
},
predicates: match item.node {
Expand All @@ -1229,7 +1236,8 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
hir::ItemKind::Union(..) |
hir::ItemKind::Impl(..) |
hir::ItemKind::Existential(..) |
hir::ItemKind::Trait(..) => Some(self.encode_predicates(def_id)),
hir::ItemKind::Trait(..) |
hir::ItemKind::TraitAlias(..) => Some(self.encode_predicates(def_id)),
_ => None,
},

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

Expand Down
13 changes: 13 additions & 0 deletions src/librustc_metadata/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,7 @@ pub enum EntryKind<'tcx> {
AssociatedType(AssociatedContainer),
AssociatedExistential(AssociatedContainer),
AssociatedConst(AssociatedContainer, ConstQualif, Lazy<RenderedConst>),
TraitAlias(Lazy<TraitAliasData<'tcx>>),
}

impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for EntryKind<'gcx> {
Expand Down Expand Up @@ -370,6 +371,9 @@ impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for EntryKind<'gcx> {
EntryKind::Trait(ref trait_data) => {
trait_data.hash_stable(hcx, hasher);
}
EntryKind::TraitAlias(ref trait_alias_data) => {
trait_alias_data.hash_stable(hcx, hasher);
}
EntryKind::Impl(ref impl_data) => {
impl_data.hash_stable(hcx, hasher);
}
Expand Down Expand Up @@ -474,6 +478,15 @@ impl_stable_hash_for!(struct TraitData<'tcx> {
super_predicates
});

#[derive(RustcEncodable, RustcDecodable)]
pub struct TraitAliasData<'tcx> {
pub super_predicates: Lazy<ty::GenericPredicates<'tcx>>,
}

impl_stable_hash_for!(struct TraitAliasData<'tcx> {
super_predicates
});

#[derive(RustcEncodable, RustcDecodable)]
pub struct ImplData<'tcx> {
pub polarity: hir::ImplPolarity,
Expand Down
3 changes: 3 additions & 0 deletions src/librustc_resolve/build_reduced_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -673,6 +673,9 @@ impl<'a> Resolver<'a> {
}
module.populated.set(true);
}
Def::TraitAlias(..) => {
self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, expansion));
}
Def::Struct(..) | Def::Union(..) => {
self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, expansion));

Expand Down
3 changes: 2 additions & 1 deletion src/librustc_traits/lowering/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,8 @@ crate fn program_clauses_for<'a, 'tcx>(
def_id: DefId,
) -> Clauses<'tcx> {
match tcx.def_key(def_id).disambiguated_data.data {
DefPathData::Trait(_) => program_clauses_for_trait(tcx, def_id),
DefPathData::Trait(_) |
DefPathData::TraitAlias(_) => program_clauses_for_trait(tcx, def_id),
DefPathData::Impl => program_clauses_for_impl(tcx, def_id),
DefPathData::AssocTypeInImpl(..) => program_clauses_for_associated_type_value(tcx, def_id),
DefPathData::AssocTypeInTrait(..) => program_clauses_for_associated_type_def(tcx, def_id),
Expand Down
22 changes: 4 additions & 18 deletions src/librustc_typeck/astconv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//! The main routine here is `ast_ty_to_ty()`; each use is parameterized by an
//! instance of `AstConv`.

use errors::{Applicability, FatalError, DiagnosticId};
use errors::{Applicability, DiagnosticId};
use hir::{self, GenericArg, GenericArgs};
use hir::def::Def;
use hir::def_id::DefId;
Expand Down Expand Up @@ -689,35 +689,21 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
{
self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1);

let trait_def_id = self.trait_def_id(trait_ref);
self.ast_path_to_mono_trait_ref(trait_ref.path.span,
trait_def_id,
trait_ref.trait_def_id(),
self_ty,
trait_ref.path.segments.last().unwrap())
}

/// Get the `DefId` of the given trait ref. It _must_ actually be a trait.
fn trait_def_id(&self, trait_ref: &hir::TraitRef) -> DefId {
let path = &trait_ref.path;
match path.def {
Def::Trait(trait_def_id) => trait_def_id,
Def::TraitAlias(alias_def_id) => alias_def_id,
Def::Err => {
FatalError.raise();
}
_ => unreachable!(),
}
}

/// The given trait ref must actually be a trait.
/// The given trait-ref must actually be a trait.
pub(super) fn instantiate_poly_trait_ref_inner(&self,
trait_ref: &hir::TraitRef,
self_ty: Ty<'tcx>,
poly_projections: &mut Vec<(ty::PolyProjectionPredicate<'tcx>, Span)>,
speculative: bool)
-> (ty::PolyTraitRef<'tcx>, Option<Vec<Span>>)
{
let trait_def_id = self.trait_def_id(trait_ref);
let trait_def_id = trait_ref.trait_def_id();

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

Expand Down
2 changes: 1 addition & 1 deletion src/librustc_typeck/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -706,7 +706,7 @@ fn super_predicates_of<'a, 'tcx>(
// In the case of trait aliases, however, we include all bounds in the where clause,
// so e.g., `trait Foo = where u32: PartialEq<Self>` would include `u32: PartialEq<Self>`
// as one of its "superpredicates".
let is_trait_alias = ty::is_trait_alias(tcx, trait_def_id);
let is_trait_alias = tcx.is_trait_alias(trait_def_id);
let superbounds2 = icx.type_parameter_bounds_in_generics(
generics, item.id, self_param_ty, OnlySelfBounds(!is_trait_alias));

Expand Down
13 changes: 13 additions & 0 deletions src/test/ui/issues/issue-56488.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// run-pass

#![feature(trait_alias)]

mod alpha {
pub trait A {}
pub trait C = A;
}

#[allow(unused_imports)]
use alpha::C;

fn main() {}
Loading