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

trait alias infrastructure #45047

Merged
merged 11 commits into from
Dec 14, 2017
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
5 changes: 4 additions & 1 deletion src/librustc/hir/def.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ pub enum Def {
Trait(DefId),
TyAlias(DefId),
TyForeign(DefId),
TraitAlias(DefId),
AssociatedTy(DefId),
PrimTy(hir::PrimTy),
TyParam(DefId),
Expand Down Expand Up @@ -155,7 +156,8 @@ impl Def {
pub fn def_id(&self) -> DefId {
match *self {
Def::Fn(id) | Def::Mod(id) | Def::Static(id, _) |
Def::Variant(id) | Def::VariantCtor(id, ..) | Def::Enum(id) | Def::TyAlias(id) |
Def::Variant(id) | Def::VariantCtor(id, ..) | Def::Enum(id) |
Def::TyAlias(id) | Def::TraitAlias(id) |
Def::AssociatedTy(id) | Def::TyParam(id) | Def::Struct(id) | Def::StructCtor(id, ..) |
Def::Union(id) | Def::Trait(id) | Def::Method(id) | Def::Const(id) |
Def::AssociatedConst(id) | Def::Macro(id, ..) |
Expand Down Expand Up @@ -186,6 +188,7 @@ impl Def {
Def::VariantCtor(.., CtorKind::Fictive) => "struct variant",
Def::Enum(..) => "enum",
Def::TyAlias(..) => "type alias",
Def::TraitAlias(..) => "trait alias",
Def::AssociatedTy(..) => "associated type",
Def::Struct(..) => "struct",
Def::StructCtor(.., CtorKind::Fn) => "tuple struct",
Expand Down
5 changes: 5 additions & 0 deletions src/librustc/hir/intravisit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,11 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
walk_list!(visitor, visit_ty_param_bound, bounds);
walk_list!(visitor, visit_trait_item_ref, trait_item_refs);
}
ItemTraitAlias(ref generics, ref bounds) => {
visitor.visit_id(item.id);
visitor.visit_generics(generics);
walk_list!(visitor, visit_ty_param_bound, bounds);
}
}
walk_list!(visitor, visit_attribute, &item.attrs);
}
Expand Down
6 changes: 4 additions & 2 deletions src/librustc/hir/lowering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1924,9 +1924,11 @@ impl<'a> LoweringContext<'a> {
bounds,
items)
}
ItemKind::MacroDef(..) | ItemKind::Mac(..) => {
panic!("Shouldn't still be around")
ItemKind::TraitAlias(ref generics, ref bounds) => {
hir::ItemTraitAlias(self.lower_generics(generics),
self.lower_bounds(bounds, ImplTraitContext::Disallowed))
}
ItemKind::MacroDef(..) | ItemKind::Mac(..) => panic!("Shouldn't still be around"),
}

// [1] `defaultness.has_value()` is never called for an `impl`, always `true` in order to
Expand Down
3 changes: 2 additions & 1 deletion src/librustc/hir/map/def_collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,8 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
let def_data = match i.node {
ItemKind::AutoImpl(..) | ItemKind::Impl(..) =>
DefPathData::Impl,
ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) | ItemKind::Trait(..) |
ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) |
ItemKind::Trait(..) | ItemKind::TraitAlias(..) |
ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) | ItemKind::Ty(..) =>
DefPathData::TypeNs(i.ident.name.as_str()),
ItemKind::Mod(..) if i.ident == keywords::Invalid.ident() => {
Expand Down
1 change: 1 addition & 0 deletions src/librustc/hir/map/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1185,6 +1185,7 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
ItemStruct(..) => "struct",
ItemUnion(..) => "union",
ItemTrait(..) => "trait",
ItemTraitAlias(..) => "trait alias",
ItemImpl(..) => "impl",
ItemAutoImpl(..) => "default impl",
};
Expand Down
3 changes: 3 additions & 0 deletions src/librustc/hir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1888,6 +1888,8 @@ pub enum Item_ {
ItemUnion(VariantData, Generics),
/// Represents a Trait Declaration
ItemTrait(IsAuto, Unsafety, Generics, TyParamBounds, HirVec<TraitItemRef>),
/// Represents a Trait Alias Declaration
ItemTraitAlias(Generics, TyParamBounds),

/// Auto trait implementations
///
Expand Down Expand Up @@ -1919,6 +1921,7 @@ impl Item_ {
ItemStruct(..) => "struct",
ItemUnion(..) => "union",
ItemTrait(..) => "trait",
ItemTraitAlias(..) => "trait alias",
ItemImpl(..) |
ItemAutoImpl(..) => "item",
}
Expand Down
21 changes: 21 additions & 0 deletions src/librustc/hir/print.rs
Original file line number Diff line number Diff line change
Expand Up @@ -747,6 +747,27 @@ impl<'a> State<'a> {
}
self.bclose(item.span)?;
}
hir::ItemTraitAlias(ref generics, ref bounds) => {
self.head("")?;
self.print_visibility(&item.vis)?;
self.word_nbsp("trait")?;
self.print_name(item.name)?;
self.print_generics(generics)?;
let mut real_bounds = Vec::with_capacity(bounds.len());
// FIXME(durka) this seems to be some quite outdated syntax
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, you used to have to say trait Foo for ?Sized, but now that's the default (and you have to write trait Foo: Sized)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would assume that TraitBoundModifier::Maybe in this context is illegal, right? i.e., trait Foo = ?Sized is kind of nonsense.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed.

for b in bounds.iter() {
if let TraitTyParamBound(ref ptr, hir::TraitBoundModifier::Maybe) = *b {
self.s.space()?;
self.word_space("for ?")?;
self.print_trait_ref(&ptr.trait_ref)?;
} else {
real_bounds.push(b.clone());
}
}
self.print_bounds(" = ", &real_bounds[..])?;
self.print_where_clause(&generics.where_clause)?;
self.s.word(";")?;
}
}
self.ann.post(self, NodeItem(item))
}
Expand Down
2 changes: 2 additions & 0 deletions src/librustc/ich/impls_hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -848,6 +848,7 @@ impl_stable_hash_for!(enum hir::Item_ {
ItemStruct(variant_data, generics),
ItemUnion(variant_data, generics),
ItemTrait(is_auto, unsafety, generics, bounds, item_refs),
ItemTraitAlias(generics, bounds),
ItemAutoImpl(unsafety, trait_ref),
ItemImpl(unsafety, impl_polarity, impl_defaultness, generics, trait_ref, ty, impl_item_refs)
});
Expand Down Expand Up @@ -1004,6 +1005,7 @@ impl_stable_hash_for!(enum hir::def::Def {
Variant(def_id),
Trait(def_id),
TyAlias(def_id),
TraitAlias(def_id),
AssociatedTy(def_id),
PrimTy(prim_ty),
TyParam(def_id),
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/reachable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
hir::ItemExternCrate(_) | hir::ItemUse(..) |
hir::ItemTy(..) | hir::ItemStatic(..) |
hir::ItemMod(..) | hir::ItemForeignMod(..) |
hir::ItemImpl(..) | hir::ItemTrait(..) |
hir::ItemImpl(..) | hir::ItemTrait(..) | hir::ItemTraitAlias(..) |
hir::ItemStruct(..) | hir::ItemEnum(..) |
hir::ItemUnion(..) | hir::ItemAutoImpl(..) |
hir::ItemGlobalAsm(..) => {}
Expand Down
1 change: 1 addition & 0 deletions src/librustc/middle/resolve_lifetime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
| hir::ItemStruct(_, ref generics)
| hir::ItemUnion(_, ref generics)
| hir::ItemTrait(_, _, ref generics, ..)
| hir::ItemTraitAlias(ref generics, ..)
| hir::ItemImpl(_, _, _, ref generics, ..) => {
// These kinds of items have only early bound lifetime parameters.
let mut index = if let hir::ItemTrait(..) = item.node {
Expand Down
1 change: 1 addition & 0 deletions src/librustc/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2577,6 +2577,7 @@ fn associated_item_def_ids<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
.map(|id| tcx.hir.local_def_id(id.node_id))
.collect()
}
hir::ItemTraitAlias(..) => vec![],
_ => span_bug!(item.span, "associated_item_def_ids: not impl or trait")
};
Rc::new(vec)
Expand Down
1 change: 1 addition & 0 deletions src/librustc_driver/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> {
hir::ItemStruct(..) |
hir::ItemUnion(..) |
hir::ItemTrait(..) |
hir::ItemTraitAlias(..) |
hir::ItemImpl(..) |
hir::ItemAutoImpl(..) => None,

Expand Down
4 changes: 3 additions & 1 deletion src/librustc_metadata/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -979,6 +979,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
EntryKind::Trait(self.lazy(&data))
}
hir::ItemExternCrate(_) |
hir::ItemTraitAlias(..) |
hir::ItemUse(..) => bug!("cannot encode info for item {:?}", item),
};

Expand Down Expand Up @@ -1526,7 +1527,8 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
hir::ItemExternCrate(..) |
hir::ItemUse(..) |
hir::ItemAutoImpl(..) |
hir::ItemTy(..) => {
hir::ItemTy(..) |
hir::ItemTraitAlias(..) => {
// no sub-item recording needed in these cases
}
hir::ItemEnum(..) => {
Expand Down
14 changes: 14 additions & 0 deletions src/librustc_passes/ast_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,20 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
}
}
}
ItemKind::TraitAlias(Generics { ref ty_params, .. }, ..) => {
for &TyParam { ref bounds, ref default, span, .. } in ty_params {
if !bounds.is_empty() {
self.err_handler().span_err(span,
"type parameters on the left side of a \
trait alias cannot be bounded");
}
if !default.is_none() {
self.err_handler().span_err(span,
"type parameters on the left side of a \
trait alias cannot have defaults");
}
}
}
ItemKind::Mod(_) => {
// Ensure that `path` attributes on modules are recorded as used (c.f. #35584).
attr::first_attr_value_str_by_name(&item.attrs, "path");
Expand Down
13 changes: 11 additions & 2 deletions src/librustc_privacy/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,8 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> {
// Other `pub` items inherit levels from parents
hir::ItemConst(..) | hir::ItemEnum(..) | hir::ItemExternCrate(..) |
hir::ItemGlobalAsm(..) | hir::ItemFn(..) | hir::ItemMod(..) |
hir::ItemStatic(..) | hir::ItemStruct(..) | hir::ItemTrait(..) |
hir::ItemStatic(..) | hir::ItemStruct(..) |
hir::ItemTrait(..) | hir::ItemTraitAlias(..) |
hir::ItemTy(..) | hir::ItemUnion(..) | hir::ItemUse(..) => {
if item.vis == hir::Public { self.prev_level } else { None }
}
Expand Down Expand Up @@ -212,7 +213,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> {
}
}
hir::ItemUse(..) | hir::ItemStatic(..) | hir::ItemConst(..) |
hir::ItemGlobalAsm(..) | hir::ItemTy(..) | hir::ItemMod(..) |
hir::ItemGlobalAsm(..) | hir::ItemTy(..) | hir::ItemMod(..) | hir::ItemTraitAlias(..) |
hir::ItemFn(..) | hir::ItemExternCrate(..) | hir::ItemAutoImpl(..) => {}
}

Expand Down Expand Up @@ -252,6 +253,11 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> {
}
}
}
hir::ItemTraitAlias(..) => {
if item_level.is_some() {
self.reach(item.id).generics().predicates();
}
}
// Visit everything except for private impl items
hir::ItemImpl(.., ref trait_ref, _, ref impl_item_refs) => {
if item_level.is_some() {
Expand Down Expand Up @@ -1498,6 +1504,9 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx>
}
}
}
hir::ItemTraitAlias(..) => {
self.check(item.id, item_visibility).generics().predicates();
}
hir::ItemEnum(ref def, _) => {
self.check(item.id, item_visibility).generics().predicates();

Expand Down
6 changes: 6 additions & 0 deletions src/librustc_resolve/build_reduced_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,11 @@ impl<'a> Resolver<'a> {
}
}

ItemKind::TraitAlias(..) => {
let def = Def::TraitAlias(self.definitions.local_def_id(item.id));
self.define(parent, ident, TypeNS, (def, vis, sp, expansion));
}

// These items live in both the type and value namespaces.
ItemKind::Struct(ref struct_def, _) => {
// Define a name in the type namespace.
Expand Down Expand Up @@ -411,6 +416,7 @@ impl<'a> Resolver<'a> {
self.define(parent, ident, TypeNS, (module, vis, sp, expansion));
self.current_module = module;
}

ItemKind::MacroDef(..) | ItemKind::Mac(_) => unreachable!(),
}
}
Expand Down
44 changes: 33 additions & 11 deletions src/librustc_resolve/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -390,12 +390,18 @@ impl PatternSource {
}
}

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
enum AliasPossibility {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll be the first to admit this is a bad name.

No,
Maybe,
}

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
enum PathSource<'a> {
// Type paths `Path`.
Type,
// Trait paths in bounds or impls.
Trait,
Trait(AliasPossibility),
// Expression paths `path`, with optional parent context.
Expr(Option<&'a Expr>),
// Paths in path patterns `Path`.
Expand All @@ -415,7 +421,7 @@ enum PathSource<'a> {
impl<'a> PathSource<'a> {
fn namespace(self) -> Namespace {
match self {
PathSource::Type | PathSource::Trait | PathSource::Struct |
PathSource::Type | PathSource::Trait(_) | PathSource::Struct |
PathSource::Visibility | PathSource::ImportPrefix => TypeNS,
PathSource::Expr(..) | PathSource::Pat | PathSource::TupleStruct => ValueNS,
PathSource::TraitItem(ns) => ns,
Expand All @@ -427,23 +433,23 @@ impl<'a> PathSource<'a> {
PathSource::Visibility | PathSource::ImportPrefix => true,
PathSource::Type | PathSource::Expr(..) | PathSource::Pat |
PathSource::Struct | PathSource::TupleStruct |
PathSource::Trait | PathSource::TraitItem(..) => false,
PathSource::Trait(_) | PathSource::TraitItem(..) => false,
}
}

fn defer_to_typeck(self) -> bool {
match self {
PathSource::Type | PathSource::Expr(..) | PathSource::Pat |
PathSource::Struct | PathSource::TupleStruct => true,
PathSource::Trait | PathSource::TraitItem(..) |
PathSource::Trait(_) | PathSource::TraitItem(..) |
PathSource::Visibility | PathSource::ImportPrefix => false,
}
}

fn descr_expected(self) -> &'static str {
match self {
PathSource::Type => "type",
PathSource::Trait => "trait",
PathSource::Trait(_) => "trait",
PathSource::Pat => "unit struct/variant or constant",
PathSource::Struct => "struct, variant or union type",
PathSource::TupleStruct => "tuple struct/variant",
Expand Down Expand Up @@ -472,10 +478,15 @@ impl<'a> PathSource<'a> {
Def::TyForeign(..) => true,
_ => false,
},
PathSource::Trait => match def {
PathSource::Trait(AliasPossibility::No) => match def {
Def::Trait(..) => true,
_ => false,
},
PathSource::Trait(AliasPossibility::Maybe) => match def {
Def::Trait(..) => true,
Def::TraitAlias(..) => true,
_ => false,
},
PathSource::Expr(..) => match def {
Def::StructCtor(_, CtorKind::Const) | Def::StructCtor(_, CtorKind::Fn) |
Def::VariantCtor(_, CtorKind::Const) | Def::VariantCtor(_, CtorKind::Fn) |
Expand Down Expand Up @@ -530,8 +541,8 @@ impl<'a> PathSource<'a> {
__diagnostic_used!(E0577);
__diagnostic_used!(E0578);
match (self, has_unexpected_resolution) {
(PathSource::Trait, true) => "E0404",
(PathSource::Trait, false) => "E0405",
(PathSource::Trait(_), true) => "E0404",
(PathSource::Trait(_), false) => "E0405",
(PathSource::Type, true) => "E0573",
(PathSource::Type, false) => "E0412",
(PathSource::Struct, true) => "E0574",
Expand Down Expand Up @@ -693,7 +704,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
tref: &'tcx ast::PolyTraitRef,
m: &'tcx ast::TraitBoundModifier) {
self.smart_resolve_path(tref.trait_ref.ref_id, None,
&tref.trait_ref.path, PathSource::Trait);
&tref.trait_ref.path, PathSource::Trait(AliasPossibility::Maybe));
visit::walk_poly_trait_ref(self, tref, m);
}
fn visit_variant(&mut self,
Expand Down Expand Up @@ -1935,6 +1946,17 @@ impl<'a> Resolver<'a> {
});
}

ItemKind::TraitAlias(ref generics, ref bounds) => {
// Create a new rib for the trait-wide type parameters.
self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind), |this| {
let local_def_id = this.definitions.local_def_id(item.id);
this.with_self_rib(Def::SelfTy(Some(local_def_id), None), |this| {
this.visit_generics(generics);
walk_list!(this, visit_ty_param_bound, bounds);
});
});
}

ItemKind::Mod(_) | ItemKind::ForeignMod(_) => {
self.with_scope(item.id, |this| {
visit::walk_item(this, item);
Expand Down Expand Up @@ -2083,7 +2105,7 @@ impl<'a> Resolver<'a> {
&path,
trait_ref.path.span,
trait_ref.path.segments.last().unwrap().span,
PathSource::Trait)
PathSource::Trait(AliasPossibility::No))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function with_optional_trait_ref is only invoked when resolving a trait impl or auto trait impl. But there's no documentation so I don't know whether that's intended or not. If not, it's the wrong place to make this distinction.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I guess this was tacitly endorsed, so I'll add comments in a future commit.

.base_def();
if def != Def::Err {
new_id = Some(def.def_id());
Expand Down Expand Up @@ -2635,7 +2657,7 @@ impl<'a> Resolver<'a> {
err.span_label(span, format!("did you mean `{}!(...)`?", path_str));
return (err, candidates);
}
(Def::TyAlias(..), PathSource::Trait) => {
(Def::TyAlias(..), PathSource::Trait(_)) => {
err.span_label(span, "type aliases cannot be used for traits");
return (err, candidates);
}
Expand Down
Loading