Skip to content

Commit

Permalink
Auto merge of #66197 - Centril:transparent-ast, r=varkor
Browse files Browse the repository at this point in the history
Push `ast::{ItemKind, ImplItemKind}::OpaqueTy` hack down into lowering

We currently have a hack in the form of `ast::{ItemKind, ImplItemKind}::OpaqueTy` which is constructed literally when you write `type Alias = impl Trait;` but not e.g. `type Alias = Vec<impl Trait>;`. Per rust-lang/rfcs#2515, this needs to change to allow `impl Trait` in nested positions.  This PR achieves this change for the syntactic aspect but not the semantic one, which will require changes in lowering and def collection. In the interim, `TyKind::opaque_top_hack` is introduced to avoid knock-on changes in lowering, collection, and resolve. These hacks can then be removed and fixed one by one until the desired semantics are supported.

r? @varkor
  • Loading branch information
bors committed Nov 13, 2019
2 parents 695fe96 + c43e4d1 commit a2ae41c
Show file tree
Hide file tree
Showing 26 changed files with 312 additions and 261 deletions.
1 change: 0 additions & 1 deletion src/librustc/hir/lowering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -452,7 +452,6 @@ impl<'a> LoweringContext<'a> {
| ItemKind::Union(_, ref generics)
| ItemKind::Enum(_, ref generics)
| ItemKind::TyAlias(_, ref generics)
| ItemKind::OpaqueTy(_, ref generics)
| ItemKind::Trait(_, _, ref generics, ..) => {
let def_id = self.lctx.resolver.definitions().local_def_id(item.id);
let count = generics
Expand Down
62 changes: 35 additions & 27 deletions src/librustc/hir/lowering/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -335,20 +335,22 @@ impl LoweringContext<'_> {
ItemKind::Mod(ref m) => hir::ItemKind::Mod(self.lower_mod(m)),
ItemKind::ForeignMod(ref nm) => hir::ItemKind::ForeignMod(self.lower_foreign_mod(nm)),
ItemKind::GlobalAsm(ref ga) => hir::ItemKind::GlobalAsm(self.lower_global_asm(ga)),
ItemKind::TyAlias(ref t, ref generics) => hir::ItemKind::TyAlias(
self.lower_ty(t, ImplTraitContext::disallowed()),
self.lower_generics(generics, ImplTraitContext::disallowed()),
),
ItemKind::OpaqueTy(ref b, ref generics) => hir::ItemKind::OpaqueTy(
hir::OpaqueTy {
generics: self.lower_generics(generics,
ImplTraitContext::OpaqueTy(None)),
bounds: self.lower_param_bounds(b,
ImplTraitContext::OpaqueTy(None)),
impl_trait_fn: None,
origin: hir::OpaqueTyOrigin::TypeAlias,
ItemKind::TyAlias(ref ty, ref generics) => match ty.kind.opaque_top_hack() {
None => {
let ty = self.lower_ty(ty, ImplTraitContext::disallowed());
let generics = self.lower_generics(generics, ImplTraitContext::disallowed());
hir::ItemKind::TyAlias(ty, generics)
},
),
Some(bounds) => {
let ty = hir::OpaqueTy {
generics: self.lower_generics(generics, ImplTraitContext::OpaqueTy(None)),
bounds: self.lower_param_bounds(bounds, ImplTraitContext::OpaqueTy(None)),
impl_trait_fn: None,
origin: hir::OpaqueTyOrigin::TypeAlias,
};
hir::ItemKind::OpaqueTy(ty)
}
}
ItemKind::Enum(ref enum_definition, ref generics) => {
hir::ItemKind::Enum(
hir::EnumDef {
Expand Down Expand Up @@ -914,16 +916,20 @@ impl LoweringContext<'_> {

(generics, hir::ImplItemKind::Method(sig, body_id))
}
ImplItemKind::TyAlias(ref ty) => (
self.lower_generics(&i.generics, ImplTraitContext::disallowed()),
hir::ImplItemKind::TyAlias(self.lower_ty(ty, ImplTraitContext::disallowed())),
),
ImplItemKind::OpaqueTy(ref bounds) => (
self.lower_generics(&i.generics, ImplTraitContext::disallowed()),
hir::ImplItemKind::OpaqueTy(
self.lower_param_bounds(bounds, ImplTraitContext::disallowed()),
),
),
ImplItemKind::TyAlias(ref ty) => {
let generics = self.lower_generics(&i.generics, ImplTraitContext::disallowed());
let kind = match ty.kind.opaque_top_hack() {
None => {
let ty = self.lower_ty(ty, ImplTraitContext::disallowed());
hir::ImplItemKind::TyAlias(ty)
}
Some(bs) => {
let bounds = self.lower_param_bounds(bs, ImplTraitContext::disallowed());
hir::ImplItemKind::OpaqueTy(bounds)
}
};
(generics, kind)
},
ImplItemKind::Macro(..) => bug!("`TyMac` should have been expanded by now"),
};

Expand All @@ -948,11 +954,13 @@ impl LoweringContext<'_> {
span: i.span,
vis: self.lower_visibility(&i.vis, Some(i.id)),
defaultness: self.lower_defaultness(i.defaultness, true /* [1] */),
kind: match i.kind {
kind: match &i.kind {
ImplItemKind::Const(..) => hir::AssocItemKind::Const,
ImplItemKind::TyAlias(..) => hir::AssocItemKind::Type,
ImplItemKind::OpaqueTy(..) => hir::AssocItemKind::OpaqueTy,
ImplItemKind::Method(ref sig, _) => hir::AssocItemKind::Method {
ImplItemKind::TyAlias(ty) => match ty.kind.opaque_top_hack() {
None => hir::AssocItemKind::Type,
Some(_) => hir::AssocItemKind::OpaqueTy,
},
ImplItemKind::Method(sig, _) => hir::AssocItemKind::Method {
has_self: sig.decl.has_self(),
},
ImplItemKind::Macro(..) => unimplemented!(),
Expand Down
5 changes: 2 additions & 3 deletions src/librustc/hir/map/def_collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
}
ItemKind::Mod(..) | ItemKind::Trait(..) | ItemKind::TraitAlias(..) |
ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) |
ItemKind::OpaqueTy(..) | ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) |
ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) |
ItemKind::TyAlias(..) => DefPathData::TypeNs(i.ident.name),
ItemKind::Fn(sig, generics, body) if sig.header.asyncness.node.is_async() => {
return self.visit_async_fn(
Expand Down Expand Up @@ -239,8 +239,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
}
ImplItemKind::Method(..) |
ImplItemKind::Const(..) => DefPathData::ValueNs(ii.ident.name),
ImplItemKind::TyAlias(..) |
ImplItemKind::OpaqueTy(..) => DefPathData::TypeNs(ii.ident.name),
ImplItemKind::TyAlias(..) => DefPathData::TypeNs(ii.ident.name),
ImplItemKind::Macro(..) => return self.visit_macro_invoc(ii.id),
};

Expand Down
61 changes: 13 additions & 48 deletions src/librustc_parse/parser/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use syntax::ast::{self, Abi, DUMMY_NODE_ID, Ident, Attribute, AttrKind, AttrStyl
use syntax::ast::{ItemKind, ImplItem, ImplItemKind, TraitItem, TraitItemKind, UseTree, UseTreeKind};
use syntax::ast::{PathSegment, IsAuto, Constness, IsAsync, Unsafety, Defaultness};
use syntax::ast::{Visibility, VisibilityKind, Mutability, FnHeader, ForeignItem, ForeignItemKind};
use syntax::ast::{Ty, TyKind, Generics, GenericBounds, TraitRef, EnumDef, VariantData, StructField};
use syntax::ast::{Ty, TyKind, Generics, TraitRef, EnumDef, VariantData, StructField};
use syntax::ast::{Mac, MacDelimiter, Block, BindingMode, FnDecl, FnSig, SelfKind, Param};
use syntax::ptr::P;
use syntax::ThinVec;
Expand All @@ -21,15 +21,6 @@ use log::debug;
use std::mem;
use errors::{PResult, Applicability, DiagnosticBuilder, DiagnosticId, StashKey};

/// Whether the type alias or associated type is a concrete type or an opaque type.
#[derive(Debug)]
pub(super) enum AliasKind {
/// Just a new name for the same type.
Weak(P<Ty>),
/// Only trait impls of the type will be usable, not the actual type itself.
OpaqueTy(GenericBounds),
}

pub(super) type ItemInfo = (Ident, ItemKind, Option<Vec<Attribute>>);

impl<'a> Parser<'a> {
Expand Down Expand Up @@ -266,15 +257,11 @@ impl<'a> Parser<'a> {
return self.mk_item_with_info(attrs, lo, vis, info);
}

if let Some(type_) = self.eat_type() {
let (ident, alias, generics) = type_?;
if self.eat_keyword(kw::Type) {
// TYPE ITEM
let item_ = match alias {
AliasKind::Weak(ty) => ItemKind::TyAlias(ty, generics),
AliasKind::OpaqueTy(bounds) => ItemKind::OpaqueTy(bounds, generics),
};
let span = lo.to(self.prev_span);
return Ok(Some(self.mk_item(span, ident, item_, vis, attrs)));
let (ident, ty, generics) = self.parse_type_alias()?;
let kind = ItemKind::TyAlias(ty, generics);
return self.mk_item_with_info(attrs, lo, vis, (ident, kind, None));
}

if self.eat_keyword(kw::Enum) {
Expand Down Expand Up @@ -708,13 +695,9 @@ impl<'a> Parser<'a> {
let lo = self.token.span;
let vis = self.parse_visibility(false)?;
let defaultness = self.parse_defaultness();
let (name, kind, generics) = if let Some(type_) = self.eat_type() {
let (name, alias, generics) = type_?;
let kind = match alias {
AliasKind::Weak(typ) => ast::ImplItemKind::TyAlias(typ),
AliasKind::OpaqueTy(bounds) => ast::ImplItemKind::OpaqueTy(bounds),
};
(name, kind, generics)
let (name, kind, generics) = if self.eat_keyword(kw::Type) {
let (name, ty, generics) = self.parse_type_alias()?;
(name, ast::ImplItemKind::TyAlias(ty), generics)
} else if self.is_const_item() {
self.parse_impl_const()?
} else if let Some(mac) = self.parse_assoc_macro_invoc("impl", Some(&vis), at_end)? {
Expand Down Expand Up @@ -1318,34 +1301,16 @@ impl<'a> Parser<'a> {
})
}

/// Parses `type Foo = Bar;` or returns `None`
/// without modifying the parser state.
fn eat_type(&mut self) -> Option<PResult<'a, (Ident, AliasKind, Generics)>> {
// This parses the grammar:
// Ident ["<"...">"] ["where" ...] ("=" | ":") Ty ";"
if self.eat_keyword(kw::Type) {
Some(self.parse_type_alias())
} else {
None
}
}

/// Parses a type alias or opaque type.
fn parse_type_alias(&mut self) -> PResult<'a, (Ident, AliasKind, Generics)> {
/// Parses the grammar:
/// Ident ["<"...">"] ["where" ...] ("=" | ":") Ty ";"
fn parse_type_alias(&mut self) -> PResult<'a, (Ident, P<Ty>, Generics)> {
let ident = self.parse_ident()?;
let mut tps = self.parse_generics()?;
tps.where_clause = self.parse_where_clause()?;
self.expect(&token::Eq)?;
let alias = if self.check_keyword(kw::Impl) {
self.bump();
let bounds = self.parse_generic_bounds(Some(self.prev_span))?;
AliasKind::OpaqueTy(bounds)
} else {
let ty = self.parse_ty()?;
AliasKind::Weak(ty)
};
let ty = self.parse_ty()?;
self.expect_semi()?;
Ok((ident, alias, tps))
Ok((ident, ty, tps))
}

/// Parses an enum declaration.
Expand Down
10 changes: 1 addition & 9 deletions src/librustc_passes/ast_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use syntax::source_map::Spanned;
use syntax::symbol::{kw, sym};
use syntax::visit::{self, Visitor};
use syntax::{span_err, struct_span_err, walk_list};
use syntax_pos::{Span, MultiSpan};
use syntax_pos::Span;
use errors::{Applicability, FatalError};

struct AstValidator<'a> {
Expand Down Expand Up @@ -584,14 +584,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
"unions cannot have zero fields");
}
}
ItemKind::OpaqueTy(ref bounds, _) => {
if !bounds.iter()
.any(|b| if let GenericBound::Trait(..) = *b { true } else { false }) {
let msp = MultiSpan::from_spans(bounds.iter()
.map(|bound| bound.span()).collect());
self.err_handler().span_err(msp, "at least one trait must be specified");
}
}
_ => {}
}

Expand Down
13 changes: 6 additions & 7 deletions src/librustc_resolve/build_reduced_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -699,13 +699,12 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
}

// These items live in the type namespace.
ItemKind::TyAlias(..) => {
let res = Res::Def(DefKind::TyAlias, self.r.definitions.local_def_id(item.id));
self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion));
}

ItemKind::OpaqueTy(_, _) => {
let res = Res::Def(DefKind::OpaqueTy, self.r.definitions.local_def_id(item.id));
ItemKind::TyAlias(ref ty, _) => {
let def_kind = match ty.kind.opaque_top_hack() {
None => DefKind::TyAlias,
Some(_) => DefKind::OpaqueTy,
};
let res = Res::Def(def_kind, self.r.definitions.local_def_id(item.id));
self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion));
}

Expand Down
13 changes: 0 additions & 13 deletions src/librustc_resolve/late.rs
Original file line number Diff line number Diff line change
Expand Up @@ -730,7 +730,6 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {

match item.kind {
ItemKind::TyAlias(_, ref generics) |
ItemKind::OpaqueTy(_, ref generics) |
ItemKind::Fn(_, ref generics, _) => {
self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes),
|this| visit::walk_item(this, item));
Expand Down Expand Up @@ -1085,18 +1084,6 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {

this.visit_ty(ty);
}
ImplItemKind::OpaqueTy(ref bounds) => {
// If this is a trait impl, ensure the type
// exists in trait
this.check_trait_item(impl_item.ident,
TypeNS,
impl_item.span,
|n, s| TypeNotMemberOfTrait(n, s));

for bound in bounds {
this.visit_param_bound(bound);
}
}
ImplItemKind::Macro(_) =>
panic!("unexpanded macro in resolve!"),
}
Expand Down
38 changes: 0 additions & 38 deletions src/librustc_save_analysis/dump_visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1133,12 +1133,6 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
// trait.
self.visit_ty(ty)
}
ast::ImplItemKind::OpaqueTy(ref bounds) => {
// FIXME: uses of the assoc type should ideally point to this
// 'def' and the name here should be a ref to the def in the
// trait.
self.process_bounds(&bounds);
}
ast::ImplItemKind::Macro(_) => {}
}
}
Expand Down Expand Up @@ -1384,38 +1378,6 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> {
self.visit_ty(&ty);
self.process_generic_params(ty_params, &qualname, item.id);
}
OpaqueTy(ref bounds, ref ty_params) => {
let qualname = format!("::{}",
self.tcx.def_path_str(self.tcx.hir().local_def_id_from_node_id(item.id)));

let value = String::new();
if !self.span.filter_generated(item.ident.span) {
let span = self.span_from_span(item.ident.span);
let id = id_from_node_id(item.id, &self.save_ctxt);
let hir_id = self.tcx.hir().node_to_hir_id(item.id);

self.dumper.dump_def(
&access_from!(self.save_ctxt, item, hir_id),
Def {
kind: DefKind::Type,
id,
span,
name: item.ident.to_string(),
qualname: qualname.clone(),
value,
parent: None,
children: vec![],
decl_id: None,
docs: self.save_ctxt.docs_for_attrs(&item.attrs),
sig: sig::item_signature(item, &self.save_ctxt),
attributes: lower_attributes(item.attrs.clone(), &self.save_ctxt),
},
);
}

self.process_bounds(bounds);
self.process_generic_params(ty_params, &qualname, item.id);
}
Mac(_) => (),
_ => visit::walk_item(self, item),
}
Expand Down
10 changes: 0 additions & 10 deletions src/librustc_save_analysis/sig.rs
Original file line number Diff line number Diff line change
Expand Up @@ -447,16 +447,6 @@ impl Sig for ast::Item {

Ok(merge_sigs(sig.text.clone(), vec![sig, ty]))
}
ast::ItemKind::OpaqueTy(ref bounds, ref generics) => {
let text = "type ".to_owned();
let mut sig = name_and_generics(text, offset, generics, self.id, self.ident, scx)?;

sig.text.push_str(" = impl ");
sig.text.push_str(&pprust::bounds_to_string(bounds));
sig.text.push(';');

Ok(sig)
}
ast::ItemKind::Enum(_, ref generics) => {
let text = "enum ".to_owned();
let mut sig = name_and_generics(text, offset, generics, self.id, self.ident, scx)?;
Expand Down
15 changes: 9 additions & 6 deletions src/libsyntax/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1579,7 +1579,6 @@ pub enum ImplItemKind {
Const(P<Ty>, P<Expr>),
Method(FnSig, P<Block>),
TyAlias(P<Ty>),
OpaqueTy(GenericBounds),
Macro(Mac),
}

Expand Down Expand Up @@ -1816,6 +1815,15 @@ impl TyKind {
false
}
}

/// HACK(type_alias_impl_trait, Centril): A temporary crutch used
/// in lowering to avoid making larger changes there and beyond.
pub fn opaque_top_hack(&self) -> Option<&GenericBounds> {
match self {
Self::ImplTrait(_, bounds) => Some(bounds),
_ => None,
}
}
}

/// Syntax used to declare a trait object.
Expand Down Expand Up @@ -2483,10 +2491,6 @@ pub enum ItemKind {
///
/// E.g., `type Foo = Bar<u8>;`.
TyAlias(P<Ty>, Generics),
/// An opaque `impl Trait` type alias.
///
/// E.g., `type Foo = impl Bar + Boo;`.
OpaqueTy(GenericBounds, Generics),
/// An enum definition (`enum`).
///
/// E.g., `enum Foo<A, B> { C<A>, D<B> }`.
Expand Down Expand Up @@ -2540,7 +2544,6 @@ impl ItemKind {
ItemKind::ForeignMod(..) => "foreign module",
ItemKind::GlobalAsm(..) => "global asm",
ItemKind::TyAlias(..) => "type alias",
ItemKind::OpaqueTy(..) => "opaque type",
ItemKind::Enum(..) => "enum",
ItemKind::Struct(..) => "struct",
ItemKind::Union(..) => "union",
Expand Down
Loading

0 comments on commit a2ae41c

Please sign in to comment.