Skip to content

Commit

Permalink
Rollup merge of rust-lang#57502 - nikomatsakis:fix-trait-alias-1b, r=…
Browse files Browse the repository at this point in the history
…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.
  • Loading branch information
Centril authored Jan 19, 2019
2 parents 349c9ee + b411994 commit 5272be5
Show file tree
Hide file tree
Showing 21 changed files with 223 additions and 57 deletions.
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 @@ -2055,6 +2056,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 @@ -2198,7 +2198,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 @@ -3170,18 +3170,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 @@ -1128,8 +1128,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 @@ -1141,6 +1140,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 @@ -1214,6 +1220,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 @@ -1226,7 +1233,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 @@ -1236,7 +1244,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 @@ -690,35 +690,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 @@ -715,7 +715,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

0 comments on commit 5272be5

Please sign in to comment.