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

Implement RFC 2338, "Type alias enum variants" #56225

Merged
merged 22 commits into from
Dec 29, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
1b150c4
Store `Ident` rather than just `Name` in HIR types `Item` and `Foreig…
alexreg Dec 1, 2018
c77fdbf
Implemented variants on type aliases in both ctor and pattern position.
alexreg Dec 3, 2018
ecacad0
Added tests for feature.
alexreg Dec 3, 2018
767ffce
Made suggestion diagnostics more consistent for enum variant names, r…
alexreg Dec 3, 2018
b9326f7
Fixed tests.
alexreg Dec 6, 2018
58a5756
Fixed more tests.
alexreg Dec 7, 2018
74f2333
Added chapter to Unstable Book.
alexreg Dec 3, 2018
6a2a7ed
Fixed issues raised in first review.
alexreg Dec 6, 2018
edabad6
Work-around for shadowing of variant names with assoc const names in …
alexreg Dec 7, 2018
248dbbd
Added tests for enums & enum aliases with various combinations of gen…
alexreg Dec 13, 2018
66409e0
Fixed issues raised in review.
alexreg Dec 15, 2018
37e7f0a
Expanded tests for enum variants with generic args.
alexreg Dec 15, 2018
65f5058
Removed unnecessary special handling of `VariantCtor` defs in `instan…
alexreg Dec 15, 2018
5a36f9e
Fixed several ICEs.
alexreg Dec 17, 2018
8eb1a9e
Added regression test for using generic parameters on modules.
alexreg Dec 18, 2018
fa07e62
Fixed handling of unit variants of aliased enums in type NS.
alexreg Dec 18, 2018
6a3f96d
Fixed type inference for tuple struct variants.
alexreg Dec 20, 2018
67a30d2
Fixed ICE when type arguments are specified on `Self` type.
alexreg Dec 20, 2018
87532e9
Minor clean-up
alexreg Dec 26, 2018
ab239f3
Minor cosmetic changes
alexreg Dec 26, 2018
5adf8c3
Changed resolution of enum variants to low priority.
alexreg Dec 26, 2018
a4fa7ef
Fixed stderr files for ui tests.
alexreg Dec 29, 2018
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# `type_alias_enum_variants`

The tracking issue for this feature is: [#49683]

[#49683]: https://github.com/rust-lang/rust/issues/49683

------------------------

The `type_alias_enum_variants` feature enables the use of variants on type
aliases that refer to enums, as both a constructor and a pattern. That is,
it allows for the syntax `EnumAlias::Variant`, which behaves exactly the same
as `Enum::Variant` (assuming that `EnumAlias` is an alias for some enum type
`Enum`).

Note that since `Self` exists as a type alias, this feature also enables the
use of the syntax `Self::Variant` within an impl block for an enum type.

```rust
#![feature(type_alias_enum_variants)]

enum Foo {
Bar(i32),
Baz { i: i32 },
}

type Alias = Foo;

fn main() {
let t = Alias::Bar(0);
let t = Alias::Baz { i: 0 };
match t {
Alias::Bar(_i) => {}
Alias::Baz { i: _i } => {}
}
}
```
24 changes: 15 additions & 9 deletions src/libproc_macro/bridge/rpc.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//! Serialization for client<->server communication.
//! Serialization for client-server communication.

use std::any::Any;
use std::char;
Expand Down Expand Up @@ -71,15 +71,18 @@ macro_rules! rpc_encode_decode {
(enum $name:ident $(<$($T:ident),+>)* { $($variant:ident $(($field:ident))*),* $(,)* }) => {
impl<S, $($($T: Encode<S>),+)*> Encode<S> for $name $(<$($T),+>)* {
fn encode(self, w: &mut Writer, s: &mut S) {
// HACK(eddyb) `Tag` enum duplicated between the
// HACK(eddyb): `Tag` enum duplicated between the
// two impls as there's no other place to stash it.
#[repr(u8)] enum Tag { $($variant),* }
#[allow(non_upper_case_globals)]
impl Tag { $(const $variant: u8 = Tag::$variant as u8;)* }
mod tag {
#[repr(u8)] enum Tag { $($variant),* }

$(pub const $variant: u8 = Tag::$variant as u8;)*
}

match self {
$($name::$variant $(($field))* => {
<Tag>::$variant.encode(w, s);
tag::$variant.encode(w, s);
$($field.encode(w, s);)*
})*
}
Expand All @@ -90,14 +93,17 @@ macro_rules! rpc_encode_decode {
for $name $(<$($T),+>)*
{
fn decode(r: &mut Reader<'a>, s: &mut S) -> Self {
// HACK(eddyb) `Tag` enum duplicated between the
// HACK(eddyb): `Tag` enum duplicated between the
// two impls as there's no other place to stash it.
#[repr(u8)] enum Tag { $($variant),* }
#[allow(non_upper_case_globals)]
impl Tag { $(const $variant: u8 = Tag::$variant as u8;)* }
mod tag {
#[repr(u8)] enum Tag { $($variant),* }

$(pub const $variant: u8 = Tag::$variant as u8;)*
}

match u8::decode(r, s) {
$(<Tag>::$variant => {
$(tag::$variant => {
$(let $field = DecodeMut::decode(r, s);)*
$name::$variant $(($field))*
})*
Expand Down
13 changes: 7 additions & 6 deletions src/librustc/hir/intravisit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,7 @@ pub fn walk_trait_ref<'v, V>(visitor: &mut V, trait_ref: &'v TraitRef)

pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
visitor.visit_vis(&item.vis);
visitor.visit_name(item.span, item.name);
visitor.visit_ident(item.ident);
match item.node {
ItemKind::ExternCrate(orig_name) => {
visitor.visit_id(item.id);
Expand All @@ -472,7 +472,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
visitor.visit_nested_body(body);
}
ItemKind::Fn(ref declaration, header, ref generics, body_id) => {
visitor.visit_fn(FnKind::ItemFn(item.name,
visitor.visit_fn(FnKind::ItemFn(item.ident.name,
generics,
header,
&item.vis,
Expand Down Expand Up @@ -528,7 +528,8 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
ItemKind::Union(ref struct_definition, ref generics) => {
visitor.visit_generics(generics);
visitor.visit_id(item.id);
visitor.visit_variant_data(struct_definition, item.name, generics, item.id, item.span);
visitor.visit_variant_data(struct_definition, item.ident.name, generics, item.id,
item.span);
}
ItemKind::Trait(.., ref generics, ref bounds, ref trait_item_refs) => {
visitor.visit_id(item.id);
Expand Down Expand Up @@ -569,9 +570,9 @@ pub fn walk_variant<'v, V: Visitor<'v>>(visitor: &mut V,
variant: &'v Variant,
generics: &'v Generics,
parent_item_id: NodeId) {
visitor.visit_name(variant.span, variant.node.name);
visitor.visit_ident(variant.node.ident);
visitor.visit_variant_data(&variant.node.data,
variant.node.name,
variant.node.ident.name,
generics,
parent_item_id,
variant.span);
Expand Down Expand Up @@ -720,7 +721,7 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) {
pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V, foreign_item: &'v ForeignItem) {
visitor.visit_id(foreign_item.id);
visitor.visit_vis(&foreign_item.vis);
visitor.visit_name(foreign_item.span, foreign_item.name);
visitor.visit_ident(foreign_item.ident);

match foreign_item.node {
ForeignItemKind::Fn(ref function_declaration, ref param_names, ref generics) => {
Expand Down
54 changes: 27 additions & 27 deletions src/librustc/hir/lowering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1360,7 +1360,7 @@ impl<'a> LoweringContext<'a> {
let exist_ty_item = hir::Item {
id: exist_ty_id.node_id,
hir_id: exist_ty_id.hir_id,
name: keywords::Invalid.name(),
ident: keywords::Invalid.ident(),
attrs: Default::default(),
node: exist_ty_item_kind,
vis: respan(span.shrink_to_lo(), hir::VisibilityKind::Inherited),
Expand Down Expand Up @@ -1563,7 +1563,7 @@ impl<'a> LoweringContext<'a> {
fn lower_variant(&mut self, v: &Variant) -> hir::Variant {
Spanned {
node: hir::VariantKind {
name: v.node.ident.name,
ident: v.node.ident,
attrs: self.lower_attrs(&v.node.attrs),
data: self.lower_variant_data(&v.node.data),
disr_expr: v.node.disr_expr.as_ref().map(|e| self.lower_anon_const(e)),
Expand Down Expand Up @@ -2738,7 +2738,7 @@ impl<'a> LoweringContext<'a> {
fn lower_item_kind(
&mut self,
id: NodeId,
name: &mut Name,
ident: &mut Ident,
attrs: &hir::HirVec<Attribute>,
vis: &mut hir::Visibility,
i: &ItemKind,
Expand All @@ -2752,7 +2752,7 @@ impl<'a> LoweringContext<'a> {
span: use_tree.span,
};

self.lower_use_tree(use_tree, &prefix, id, vis, name, attrs)
self.lower_use_tree(use_tree, &prefix, id, vis, ident, attrs)
}
ItemKind::Static(ref t, m, ref e) => {
let value = self.lower_body(None, |this| this.lower_expr(e));
Expand Down Expand Up @@ -2944,7 +2944,7 @@ impl<'a> LoweringContext<'a> {
prefix: &Path,
id: NodeId,
vis: &mut hir::Visibility,
name: &mut Name,
ident: &mut Ident,
attrs: &hir::HirVec<Attribute>,
) -> hir::ItemKind {
debug!("lower_use_tree(tree={:?})", tree);
Expand All @@ -2960,28 +2960,28 @@ impl<'a> LoweringContext<'a> {

match tree.kind {
UseTreeKind::Simple(rename, id1, id2) => {
*name = tree.ident().name;
*ident = tree.ident();

// First apply the prefix to the path
// First, apply the prefix to the path.
let mut path = Path {
segments,
span: path.span,
};

// Correctly resolve `self` imports
// Correctly resolve `self` imports.
if path.segments.len() > 1
&& path.segments.last().unwrap().ident.name == keywords::SelfLower.name()
{
let _ = path.segments.pop();
if rename.is_none() {
*name = path.segments.last().unwrap().ident.name;
*ident = path.segments.last().unwrap().ident;
}
}

let parent_def_index = self.current_hir_id_owner.last().unwrap().0;
let mut defs = self.expect_full_def_from_use(id);
// we want to return *something* from this function, so hang onto the first item
// for later
// We want to return *something* from this function, so hold onto the first item
// for later.
let ret_def = defs.next().unwrap_or(Def::Err);

// Here, we are looping over namespaces, if they exist for the definition
Expand All @@ -2991,7 +2991,7 @@ impl<'a> LoweringContext<'a> {
// two imports.
for (def, &new_node_id) in defs.zip([id1, id2].iter()) {
let vis = vis.clone();
let name = name.clone();
let ident = ident.clone();
let mut path = path.clone();
for seg in &mut path.segments {
seg.id = self.sess.next_node_id();
Expand Down Expand Up @@ -3032,7 +3032,7 @@ impl<'a> LoweringContext<'a> {
hir::Item {
id: new_id.node_id,
hir_id: new_id.hir_id,
name: name,
ident,
attrs: attrs.clone(),
node: item,
vis,
Expand All @@ -3058,8 +3058,8 @@ impl<'a> LoweringContext<'a> {
hir::ItemKind::Use(path, hir::UseKind::Glob)
}
UseTreeKind::Nested(ref trees) => {
// Nested imports are desugared into simple
// imports. So if we start with
// Nested imports are desugared into simple imports.
// So, if we start with
//
// ```
// pub(x) use foo::{a, b};
Expand All @@ -3080,14 +3080,14 @@ impl<'a> LoweringContext<'a> {
// `self.items`. However, the structure of this
// function also requires us to return one item, and
// for that we return the `{}` import (called the
// "`ListStem`").
// `ListStem`).

let prefix = Path {
segments,
span: prefix.span.to(path.span),
};

// Add all the nested PathListItems to the HIR.
// Add all the nested `PathListItem`s to the HIR.
for &(ref use_tree, id) in trees {
self.allocate_hir_id_counter(id, &use_tree);

Expand All @@ -3097,10 +3097,10 @@ impl<'a> LoweringContext<'a> {
} = self.lower_node_id(id);

let mut vis = vis.clone();
let mut name = name.clone();
let mut ident = ident.clone();
let mut prefix = prefix.clone();

// Give the segments new ids since they are being cloned.
// Give the segments new node-ids since they are being cloned.
for seg in &mut prefix.segments {
seg.id = self.sess.next_node_id();
}
Expand All @@ -3115,7 +3115,7 @@ impl<'a> LoweringContext<'a> {
&prefix,
new_id,
&mut vis,
&mut name,
&mut ident,
attrs);

let vis_kind = match vis.node {
Expand All @@ -3139,7 +3139,7 @@ impl<'a> LoweringContext<'a> {
hir::Item {
id: new_id,
hir_id: new_hir_id,
name,
ident,
attrs: attrs.clone(),
node: item,
vis,
Expand All @@ -3166,7 +3166,7 @@ impl<'a> LoweringContext<'a> {
*vis = respan(prefix.span.shrink_to_lo(), hir::VisibilityKind::Inherited);
}
hir::VisibilityKind::Restricted { .. } => {
// do nothing here, as described in the comment on the match
// Do nothing here, as described in the comment on the match.
}
}

Expand Down Expand Up @@ -3414,15 +3414,15 @@ impl<'a> LoweringContext<'a> {
}

pub fn lower_item(&mut self, i: &Item) -> Option<hir::Item> {
let mut name = i.ident.name;
let mut ident = i.ident;
let mut vis = self.lower_visibility(&i.vis, None);
let attrs = self.lower_attrs(&i.attrs);
if let ItemKind::MacroDef(ref def) = i.node {
if !def.legacy || attr::contains_name(&i.attrs, "macro_export") ||
attr::contains_name(&i.attrs, "rustc_doc_only_macro") {
let body = self.lower_token_stream(def.stream());
self.exported_macros.push(hir::MacroDef {
name,
name: ident.name,
vis,
attrs,
id: i.id,
Expand All @@ -3434,14 +3434,14 @@ impl<'a> LoweringContext<'a> {
return None;
}

let node = self.lower_item_kind(i.id, &mut name, &attrs, &mut vis, &i.node);
let node = self.lower_item_kind(i.id, &mut ident, &attrs, &mut vis, &i.node);

let LoweredNodeId { node_id, hir_id } = self.lower_node_id(i.id);

Some(hir::Item {
id: node_id,
hir_id,
name,
ident,
attrs,
node,
vis,
Expand All @@ -3454,7 +3454,7 @@ impl<'a> LoweringContext<'a> {
let def_id = self.resolver.definitions().local_def_id(node_id);
hir::ForeignItem {
id: node_id,
name: i.ident.name,
ident: i.ident,
attrs: self.lower_attrs(&i.attrs),
node: match i.node {
ForeignItemKind::Fn(ref fdec, ref generics) => {
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/hir/map/blocks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ impl<'a> FnLikeNode<'a> {
ast::ItemKind::Fn(ref decl, header, ref generics, block) =>
item_fn(ItemFnParts {
id: i.id,
name: i.name,
name: i.ident.name,
decl: &decl,
body: block,
vis: &i.vis,
Expand Down
Loading