From 5c3d1e5d76fdc6d9f40ab13a6a342e1f7ceb4f17 Mon Sep 17 00:00:00 2001 From: David Wood Date: Thu, 21 Mar 2019 23:38:50 +0100 Subject: Separate variant id and variant constructor id. This commit makes two changes - separating the `NodeId` that identifies an enum variant from the `NodeId` that identifies the variant's constructor; and no longer creating a `NodeId` for `Struct`-style enum variants and structs. Separation of the variant id and variant constructor id will allow the rest of RFC 2008 to be implemented by lowering the visibility of the variant's constructor without lowering the visbility of the variant itself. No longer creating a `NodeId` for `Struct`-style enum variants and structs mostly simplifies logic as previously this `NodeId` wasn't used. There were various cases where the `NodeId` wouldn't be used unless there was an unit or tuple struct or enum variant but not all uses of this `NodeId` had that condition, by removing this `NodeId`, this must be explicitly dealt with. This change mostly applied cleanly, but there were one or two cases in name resolution and one case in type check where the existing logic required a id for `Struct`-style enum variants and structs. --- src/libsyntax/ast.rs | 33 +++++++++++++++++++-------------- src/libsyntax/config.rs | 5 ++--- src/libsyntax/ext/build.rs | 1 + src/libsyntax/mut_visit.rs | 7 ++++--- src/libsyntax/parse/parser.rs | 11 ++++++----- src/libsyntax/print/pprust.rs | 1 + 6 files changed, 33 insertions(+), 25 deletions(-) (limited to 'src/libsyntax') diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 2cbd2dfeb25..c64ffb1232f 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1956,8 +1956,13 @@ pub struct EnumDef { #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Variant_ { + /// Name of the variant. pub ident: Ident, + /// Attributes of the variant. pub attrs: Vec, + /// Id of the variant (not the constructor, see `VariantData::ctor_id()`). + pub id: NodeId, + /// Fields and constructor id of the variant. pub data: VariantData, /// Explicit discriminant, e.g., `Foo = 1`. pub disr_expr: Option, @@ -2117,23 +2122,13 @@ pub struct StructField { pub attrs: Vec, } -/// Fields and Ids of enum variants and structs -/// -/// For enum variants: `NodeId` represents both an Id of the variant itself (relevant for all -/// variant kinds) and an Id of the variant's constructor (not relevant for `Struct`-variants). -/// One shared Id can be successfully used for these two purposes. -/// Id of the whole enum lives in `Item`. -/// -/// For structs: `NodeId` represents an Id of the structure's constructor, so it is not actually -/// used for `Struct`-structs (but still presents). Structures don't have an analogue of "Id of -/// the variant itself" from enum variants. -/// Id of the whole struct lives in `Item`. +/// Fields and constructor ids of enum variants and structs. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum VariantData { /// Struct variant. /// /// E.g., `Bar { .. }` as in `enum Foo { Bar { .. } }`. - Struct(Vec, NodeId, bool), + Struct(Vec, bool), /// Tuple variant. /// /// E.g., `Bar(..)` as in `enum Foo { Bar(..) }`. @@ -2145,17 +2140,23 @@ pub enum VariantData { } impl VariantData { + /// Return the fields of this variant. pub fn fields(&self) -> &[StructField] { match *self { VariantData::Struct(ref fields, ..) | VariantData::Tuple(ref fields, _) => fields, _ => &[], } } - pub fn id(&self) -> NodeId { + + /// Return the `NodeId` of this variant's constructor, if it has one. + pub fn ctor_id(&self) -> Option { match *self { - VariantData::Struct(_, id, _) | VariantData::Tuple(_, id) | VariantData::Unit(id) => id, + VariantData::Struct(..) => None, + VariantData::Tuple(_, id) | VariantData::Unit(id) => Some(id), } } + + /// Does this `VariantData` represent a `Struct`-struct/variant? pub fn is_struct(&self) -> bool { if let VariantData::Struct(..) = *self { true @@ -2163,6 +2164,8 @@ impl VariantData { false } } + + /// Does this `VariantData` represent a tuple struct/variant? pub fn is_tuple(&self) -> bool { if let VariantData::Tuple(..) = *self { true @@ -2170,6 +2173,8 @@ impl VariantData { false } } + + /// Does this `VariantData` represent a unit struct/variant? pub fn is_unit(&self) -> bool { if let VariantData::Unit(..) = *self { true diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index 7159c949513..18173628a26 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -225,10 +225,9 @@ impl<'a> StripUnconfigured<'a> { fn configure_variant_data(&mut self, vdata: &mut ast::VariantData) { match vdata { - ast::VariantData::Struct(fields, _id, _) | - ast::VariantData::Tuple(fields, _id) => + ast::VariantData::Struct(fields, ..) | ast::VariantData::Tuple(fields, _) => fields.flat_map_in_place(|field| self.configure(field)), - ast::VariantData::Unit(_id) => {} + ast::VariantData::Unit(_) => {} } } diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index e95f0589449..614967bdeb4 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -1062,6 +1062,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { respan(span, ast::Variant_ { ident, + id: ast::DUMMY_NODE_ID, attrs: Vec::new(), data: vdata, disr_expr: None, diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index 5bb1d8a4b94..784d0049ac5 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -450,9 +450,10 @@ pub fn noop_visit_foreign_mod(foreign_mod: &mut ForeignMod, vis: } pub fn noop_visit_variant(variant: &mut Variant, vis: &mut T) { - let Spanned { node: Variant_ { ident, attrs, data, disr_expr }, span } = variant; + let Spanned { node: Variant_ { ident, attrs, id, data, disr_expr }, span } = variant; vis.visit_ident(ident); visit_attrs(attrs, vis); + vis.visit_id(id); vis.visit_variant_data(data); visit_opt(disr_expr, |disr_expr| vis.visit_anon_const(disr_expr)); vis.visit_span(span); @@ -765,11 +766,11 @@ pub fn noop_visit_where_predicate(pred: &mut WherePredicate, vis: pub fn noop_visit_variant_data(vdata: &mut VariantData, vis: &mut T) { match vdata { - VariantData::Struct(fields, id, _) | + VariantData::Struct(fields, ..) => visit_vec(fields, |field| vis.visit_struct_field(field)), VariantData::Tuple(fields, id) => { visit_vec(fields, |field| vis.visit_struct_field(field)); vis.visit_id(id); - } + }, VariantData::Unit(id) => vis.visit_id(id), } } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 99260314054..d7a2170342d 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -6844,7 +6844,7 @@ impl<'a> Parser<'a> { } else { // If we see: `struct Foo where T: Copy { ... }` let (fields, recovered) = self.parse_record_struct_body()?; - VariantData::Struct(fields, ast::DUMMY_NODE_ID, recovered) + VariantData::Struct(fields, recovered) } // No `where` so: `struct Foo;` } else if self.eat(&token::Semi) { @@ -6852,7 +6852,7 @@ impl<'a> Parser<'a> { // Record-style struct definition } else if self.token == token::OpenDelim(token::Brace) { let (fields, recovered) = self.parse_record_struct_body()?; - VariantData::Struct(fields, ast::DUMMY_NODE_ID, recovered) + VariantData::Struct(fields, recovered) // Tuple-style struct definition with optional where-clause. } else if self.token == token::OpenDelim(token::Paren) { let body = VariantData::Tuple(self.parse_tuple_struct_body()?, ast::DUMMY_NODE_ID); @@ -6881,10 +6881,10 @@ impl<'a> Parser<'a> { let vdata = if self.token.is_keyword(keywords::Where) { generics.where_clause = self.parse_where_clause()?; let (fields, recovered) = self.parse_record_struct_body()?; - VariantData::Struct(fields, ast::DUMMY_NODE_ID, recovered) + VariantData::Struct(fields, recovered) } else if self.token == token::OpenDelim(token::Brace) { let (fields, recovered) = self.parse_record_struct_body()?; - VariantData::Struct(fields, ast::DUMMY_NODE_ID, recovered) + VariantData::Struct(fields, recovered) } else { let token_str = self.this_token_descr(); let mut err = self.fatal(&format!( @@ -7708,7 +7708,7 @@ impl<'a> Parser<'a> { // Parse a struct variant. all_nullary = false; let (fields, recovered) = self.parse_record_struct_body()?; - struct_def = VariantData::Struct(fields, ast::DUMMY_NODE_ID, recovered); + struct_def = VariantData::Struct(fields, recovered); } else if self.check(&token::OpenDelim(token::Paren)) { all_nullary = false; struct_def = VariantData::Tuple( @@ -7730,6 +7730,7 @@ impl<'a> Parser<'a> { let vr = ast::Variant_ { ident, + id: ast::DUMMY_NODE_ID, attrs: variant_attrs, data: struct_def, disr_expr, diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 07df14ddc72..946fdc0c469 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -3266,6 +3266,7 @@ mod tests { let var = source_map::respan(syntax_pos::DUMMY_SP, ast::Variant_ { ident, attrs: Vec::new(), + id: ast::DUMMY_NODE_ID, // making this up as I go.... ? data: ast::VariantData::Unit(ast::DUMMY_NODE_ID), disr_expr: None, -- cgit 1.4.1-3-g733a5