Skip to content

Commit 6b61435

Browse files
committed
Auto merge of #56225 - alexreg:type_alias_enum_variants, r=<try>
Implement RFC 2338, "Type alias enum variants" This PR implements [RFC 2338](rust-lang/rfcs#2338), allowing one to write code like the following. ```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 } => {} } } ``` Since `Self` can be considered a type alias in this context, it also enables using `Self::Variant` as both a constructor and pattern. Fixes issues #56199 and #56611. N.B., after discussing the syntax for type arguments on enum variants with @petrochenkov and @eddyb (there are also a few comments on the [tracking issue](#49683)), the consensus seems to be treat the syntax as follows, which ought to be backwards-compatible. ```rust Option::<u8>::None; // OK Option::None::<u8>; // OK, but lint in near future (hard error next edition?) Alias::<u8>::None; // OK Alias::None::<u8>; // Error ``` I do not know if this will need an FCP, but let's start one if so. r? @petrochenkov
2 parents 3499575 + b1a193d commit 6b61435

File tree

87 files changed

+1254
-719
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

87 files changed

+1254
-719
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# `type_alias_enum_variants`
2+
3+
The tracking issue for this feature is: [#49683]
4+
5+
[#49683]: https://github.com/rust-lang/rust/issues/49683
6+
7+
------------------------
8+
9+
The `type_alias_enum_variants` feature enables the use of variants on type
10+
aliases that refer to enums, as both a constructor and a pattern. That is,
11+
it allows for the syntax `EnumAlias::Variant`, which behaves exactly the same
12+
as `Enum::Variant` (assuming that `EnumAlias` is an alias for some enum type
13+
`Enum`).
14+
15+
Note that since `Self` exists as a type alias, this feature also enables the
16+
use of the syntax `Self::Variant` within an impl block for an enum type.
17+
18+
```rust
19+
#![feature(type_alias_enum_variants)]
20+
21+
enum Foo {
22+
Bar(i32),
23+
Baz { i: i32 },
24+
}
25+
26+
type Alias = Foo;
27+
28+
fn main() {
29+
let t = Alias::Bar(0);
30+
let t = Alias::Baz { i: 0 };
31+
match t {
32+
Alias::Bar(_i) => {}
33+
Alias::Baz { i: _i } => {}
34+
}
35+
}
36+
```

src/libproc_macro/bridge/rpc.rs

+15-9
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
//! Serialization for client<->server communication.
11+
//! Serialization for client <-> server communication.
1212
1313
use std::any::Any;
1414
use std::char;
@@ -81,15 +81,18 @@ macro_rules! rpc_encode_decode {
8181
(enum $name:ident $(<$($T:ident),+>)* { $($variant:ident $(($field:ident))*),* $(,)* }) => {
8282
impl<S, $($($T: Encode<S>),+)*> Encode<S> for $name $(<$($T),+>)* {
8383
fn encode(self, w: &mut Writer, s: &mut S) {
84-
// HACK(eddyb) `Tag` enum duplicated between the
84+
// HACK(eddyb): `Tag` enum duplicated between the
8585
// two impls as there's no other place to stash it.
86-
#[repr(u8)] enum Tag { $($variant),* }
8786
#[allow(non_upper_case_globals)]
88-
impl Tag { $(const $variant: u8 = Tag::$variant as u8;)* }
87+
mod tag {
88+
#[repr(u8)] enum Tag { $($variant),* }
89+
90+
$(pub const $variant: u8 = Tag::$variant as u8;)*
91+
}
8992

9093
match self {
9194
$($name::$variant $(($field))* => {
92-
<Tag>::$variant.encode(w, s);
95+
tag::$variant.encode(w, s);
9396
$($field.encode(w, s);)*
9497
})*
9598
}
@@ -100,14 +103,17 @@ macro_rules! rpc_encode_decode {
100103
for $name $(<$($T),+>)*
101104
{
102105
fn decode(r: &mut Reader<'a>, s: &mut S) -> Self {
103-
// HACK(eddyb) `Tag` enum duplicated between the
106+
// HACK(eddyb): `Tag` enum duplicated between the
104107
// two impls as there's no other place to stash it.
105-
#[repr(u8)] enum Tag { $($variant),* }
106108
#[allow(non_upper_case_globals)]
107-
impl Tag { $(const $variant: u8 = Tag::$variant as u8;)* }
109+
mod tag {
110+
#[repr(u8)] enum Tag { $($variant),* }
111+
112+
$(pub const $variant: u8 = Tag::$variant as u8;)*
113+
}
108114

109115
match u8::decode(r, s) {
110-
$(<Tag>::$variant => {
116+
$(tag::$variant => {
111117
$(let $field = DecodeMut::decode(r, s);)*
112118
$name::$variant $(($field))*
113119
})*

src/librustc/hir/intravisit.rs

+7-6
Original file line numberDiff line numberDiff line change
@@ -464,7 +464,7 @@ pub fn walk_trait_ref<'v, V>(visitor: &mut V, trait_ref: &'v TraitRef)
464464

465465
pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
466466
visitor.visit_vis(&item.vis);
467-
visitor.visit_name(item.span, item.name);
467+
visitor.visit_ident(item.ident);
468468
match item.node {
469469
ItemKind::ExternCrate(orig_name) => {
470470
visitor.visit_id(item.id);
@@ -482,7 +482,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
482482
visitor.visit_nested_body(body);
483483
}
484484
ItemKind::Fn(ref declaration, header, ref generics, body_id) => {
485-
visitor.visit_fn(FnKind::ItemFn(item.name,
485+
visitor.visit_fn(FnKind::ItemFn(item.ident.name,
486486
generics,
487487
header,
488488
&item.vis,
@@ -538,7 +538,8 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
538538
ItemKind::Union(ref struct_definition, ref generics) => {
539539
visitor.visit_generics(generics);
540540
visitor.visit_id(item.id);
541-
visitor.visit_variant_data(struct_definition, item.name, generics, item.id, item.span);
541+
visitor.visit_variant_data(struct_definition, item.ident.name, generics, item.id,
542+
item.span);
542543
}
543544
ItemKind::Trait(.., ref generics, ref bounds, ref trait_item_refs) => {
544545
visitor.visit_id(item.id);
@@ -579,9 +580,9 @@ pub fn walk_variant<'v, V: Visitor<'v>>(visitor: &mut V,
579580
variant: &'v Variant,
580581
generics: &'v Generics,
581582
parent_item_id: NodeId) {
582-
visitor.visit_name(variant.span, variant.node.name);
583+
visitor.visit_ident(variant.node.ident);
583584
visitor.visit_variant_data(&variant.node.data,
584-
variant.node.name,
585+
variant.node.ident.name,
585586
generics,
586587
parent_item_id,
587588
variant.span);
@@ -730,7 +731,7 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) {
730731
pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V, foreign_item: &'v ForeignItem) {
731732
visitor.visit_id(foreign_item.id);
732733
visitor.visit_vis(&foreign_item.vis);
733-
visitor.visit_name(foreign_item.span, foreign_item.name);
734+
visitor.visit_ident(foreign_item.ident);
734735

735736
match foreign_item.node {
736737
ForeignItemKind::Fn(ref function_declaration, ref param_names, ref generics) => {

src/librustc/hir/lowering.rs

+27-27
Original file line numberDiff line numberDiff line change
@@ -1370,7 +1370,7 @@ impl<'a> LoweringContext<'a> {
13701370
let exist_ty_item = hir::Item {
13711371
id: exist_ty_id.node_id,
13721372
hir_id: exist_ty_id.hir_id,
1373-
name: keywords::Invalid.name(),
1373+
ident: keywords::Invalid.ident(),
13741374
attrs: Default::default(),
13751375
node: exist_ty_item_kind,
13761376
vis: respan(span.shrink_to_lo(), hir::VisibilityKind::Inherited),
@@ -1573,7 +1573,7 @@ impl<'a> LoweringContext<'a> {
15731573
fn lower_variant(&mut self, v: &Variant) -> hir::Variant {
15741574
Spanned {
15751575
node: hir::VariantKind {
1576-
name: v.node.ident.name,
1576+
ident: v.node.ident,
15771577
attrs: self.lower_attrs(&v.node.attrs),
15781578
data: self.lower_variant_data(&v.node.data),
15791579
disr_expr: v.node.disr_expr.as_ref().map(|e| self.lower_anon_const(e)),
@@ -2748,7 +2748,7 @@ impl<'a> LoweringContext<'a> {
27482748
fn lower_item_kind(
27492749
&mut self,
27502750
id: NodeId,
2751-
name: &mut Name,
2751+
ident: &mut Ident,
27522752
attrs: &hir::HirVec<Attribute>,
27532753
vis: &mut hir::Visibility,
27542754
i: &ItemKind,
@@ -2762,7 +2762,7 @@ impl<'a> LoweringContext<'a> {
27622762
span: use_tree.span,
27632763
};
27642764

2765-
self.lower_use_tree(use_tree, &prefix, id, vis, name, attrs)
2765+
self.lower_use_tree(use_tree, &prefix, id, vis, ident, attrs)
27662766
}
27672767
ItemKind::Static(ref t, m, ref e) => {
27682768
let value = self.lower_body(None, |this| this.lower_expr(e));
@@ -2954,7 +2954,7 @@ impl<'a> LoweringContext<'a> {
29542954
prefix: &Path,
29552955
id: NodeId,
29562956
vis: &mut hir::Visibility,
2957-
name: &mut Name,
2957+
ident: &mut Ident,
29582958
attrs: &hir::HirVec<Attribute>,
29592959
) -> hir::ItemKind {
29602960
debug!("lower_use_tree(tree={:?})", tree);
@@ -2970,28 +2970,28 @@ impl<'a> LoweringContext<'a> {
29702970

29712971
match tree.kind {
29722972
UseTreeKind::Simple(rename, id1, id2) => {
2973-
*name = tree.ident().name;
2973+
*ident = tree.ident();
29742974

2975-
// First apply the prefix to the path
2975+
// First, apply the prefix to the path.
29762976
let mut path = Path {
29772977
segments,
29782978
span: path.span,
29792979
};
29802980

2981-
// Correctly resolve `self` imports
2981+
// Correctly resolve `self` imports.
29822982
if path.segments.len() > 1
29832983
&& path.segments.last().unwrap().ident.name == keywords::SelfLower.name()
29842984
{
29852985
let _ = path.segments.pop();
29862986
if rename.is_none() {
2987-
*name = path.segments.last().unwrap().ident.name;
2987+
*ident = path.segments.last().unwrap().ident;
29882988
}
29892989
}
29902990

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

29972997
// Here, we are looping over namespaces, if they exist for the definition
@@ -3001,7 +3001,7 @@ impl<'a> LoweringContext<'a> {
30013001
// two imports.
30023002
for (def, &new_node_id) in defs.zip([id1, id2].iter()) {
30033003
let vis = vis.clone();
3004-
let name = name.clone();
3004+
let ident = ident.clone();
30053005
let mut path = path.clone();
30063006
for seg in &mut path.segments {
30073007
seg.id = self.sess.next_node_id();
@@ -3042,7 +3042,7 @@ impl<'a> LoweringContext<'a> {
30423042
hir::Item {
30433043
id: new_id.node_id,
30443044
hir_id: new_id.hir_id,
3045-
name: name,
3045+
ident,
30463046
attrs: attrs.clone(),
30473047
node: item,
30483048
vis,
@@ -3068,8 +3068,8 @@ impl<'a> LoweringContext<'a> {
30683068
hir::ItemKind::Use(path, hir::UseKind::Glob)
30693069
}
30703070
UseTreeKind::Nested(ref trees) => {
3071-
// Nested imports are desugared into simple
3072-
// imports. So if we start with
3071+
// Nested imports are desugared into simple imports.
3072+
// So, if we start with
30733073
//
30743074
// ```
30753075
// pub(x) use foo::{a, b};
@@ -3090,14 +3090,14 @@ impl<'a> LoweringContext<'a> {
30903090
// `self.items`. However, the structure of this
30913091
// function also requires us to return one item, and
30923092
// for that we return the `{}` import (called the
3093-
// "`ListStem`").
3093+
// `ListStem`).
30943094

30953095
let prefix = Path {
30963096
segments,
30973097
span: prefix.span.to(path.span),
30983098
};
30993099

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

@@ -3107,10 +3107,10 @@ impl<'a> LoweringContext<'a> {
31073107
} = self.lower_node_id(id);
31083108

31093109
let mut vis = vis.clone();
3110-
let mut name = name.clone();
3110+
let mut ident = ident.clone();
31113111
let mut prefix = prefix.clone();
31123112

3113-
// Give the segments new ids since they are being cloned.
3113+
// Give the segments new node-ids since they are being cloned.
31143114
for seg in &mut prefix.segments {
31153115
seg.id = self.sess.next_node_id();
31163116
}
@@ -3125,7 +3125,7 @@ impl<'a> LoweringContext<'a> {
31253125
&prefix,
31263126
new_id,
31273127
&mut vis,
3128-
&mut name,
3128+
&mut ident,
31293129
attrs);
31303130

31313131
let vis_kind = match vis.node {
@@ -3149,7 +3149,7 @@ impl<'a> LoweringContext<'a> {
31493149
hir::Item {
31503150
id: new_id,
31513151
hir_id: new_hir_id,
3152-
name,
3152+
ident,
31533153
attrs: attrs.clone(),
31543154
node: item,
31553155
vis,
@@ -3176,7 +3176,7 @@ impl<'a> LoweringContext<'a> {
31763176
*vis = respan(prefix.span.shrink_to_lo(), hir::VisibilityKind::Inherited);
31773177
}
31783178
hir::VisibilityKind::Restricted { .. } => {
3179-
// do nothing here, as described in the comment on the match
3179+
// Do nothing here, as described in the comment on the match.
31803180
}
31813181
}
31823182

@@ -3424,15 +3424,15 @@ impl<'a> LoweringContext<'a> {
34243424
}
34253425

34263426
pub fn lower_item(&mut self, i: &Item) -> Option<hir::Item> {
3427-
let mut name = i.ident.name;
3427+
let mut ident = i.ident;
34283428
let mut vis = self.lower_visibility(&i.vis, None);
34293429
let attrs = self.lower_attrs(&i.attrs);
34303430
if let ItemKind::MacroDef(ref def) = i.node {
34313431
if !def.legacy || attr::contains_name(&i.attrs, "macro_export") ||
34323432
attr::contains_name(&i.attrs, "rustc_doc_only_macro") {
34333433
let body = self.lower_token_stream(def.stream());
34343434
self.exported_macros.push(hir::MacroDef {
3435-
name,
3435+
name: ident.name,
34363436
vis,
34373437
attrs,
34383438
id: i.id,
@@ -3444,14 +3444,14 @@ impl<'a> LoweringContext<'a> {
34443444
return None;
34453445
}
34463446

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

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

34513451
Some(hir::Item {
34523452
id: node_id,
34533453
hir_id,
3454-
name,
3454+
ident,
34553455
attrs,
34563456
node,
34573457
vis,
@@ -3464,7 +3464,7 @@ impl<'a> LoweringContext<'a> {
34643464
let def_id = self.resolver.definitions().local_def_id(node_id);
34653465
hir::ForeignItem {
34663466
id: node_id,
3467-
name: i.ident.name,
3467+
ident: i.ident,
34683468
attrs: self.lower_attrs(&i.attrs),
34693469
node: match i.node {
34703470
ForeignItemKind::Fn(ref fdec, ref generics) => {

src/librustc/hir/map/blocks.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ impl<'a> FnLikeNode<'a> {
238238
ast::ItemKind::Fn(ref decl, header, ref generics, block) =>
239239
item_fn(ItemFnParts {
240240
id: i.id,
241-
name: i.name,
241+
name: i.ident.name,
242242
decl: &decl,
243243
body: block,
244244
vis: &i.vis,

0 commit comments

Comments
 (0)