diff options
| author | bors <bors@rust-lang.org> | 2018-05-20 22:37:06 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2018-05-20 22:37:06 +0000 |
| commit | 538fea57573ab8143e6c7a4f64ff1c2c03febd93 (patch) | |
| tree | 207259a55a86a638a71a84ee5c1e55f765731037 /src/libsyntax | |
| parent | a1d4a9503e236b9f49cbdb23d00893201c117b2a (diff) | |
| parent | 26aad254875464ff352a4e18d16f668b5bd9b7cb (diff) | |
| download | rust-538fea57573ab8143e6c7a4f64ff1c2c03febd93.tar.gz rust-538fea57573ab8143e6c7a4f64ff1c2c03febd93.zip | |
Auto merge of #50851 - eddyb:the-only-constant, r=nikomatsakis
rustc: introduce {ast,hir}::AnonConst to consolidate so-called "embedded constants".
Previously, constants in array lengths and enum variant discriminants were "merely an expression", and had no separate ID for, e.g. type-checking or const-eval, instead reusing the expression's.
That complicated code working with bodies, because such constants were the only special case where the "owner" of the body wasn't the HIR parent, but rather the same node as the body itself.
Also, if the body happened to be a closure, we had no way to allocate a `DefId` for both the constant *and* the closure, leading to *several* bugs (mostly ICEs where type errors were expected).
This PR rectifies the situation by adding another (`{ast,hir}::AnonConst`) node around every such constant. Also, const generics are expected to rely on the new `AnonConst` nodes, as well (cc @varkor).
* fixes #48838
* fixes #50600
* fixes #50688
* fixes #50689
* obsoletes #50623
r? @nikomatsakis
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ast.rs | 24 | ||||
| -rw-r--r-- | src/libsyntax/diagnostics/plugin.rs | 5 | ||||
| -rw-r--r-- | src/libsyntax/fold.rs | 22 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 24 | ||||
| -rw-r--r-- | src/libsyntax/print/pprust.rs | 12 | ||||
| -rw-r--r-- | src/libsyntax/visit.rs | 15 |
6 files changed, 73 insertions, 29 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 1817726d6a1..0ce9763ded8 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -920,6 +920,18 @@ pub enum UnsafeSource { UserProvided, } +/// A constant (expression) that's not an item or associated item, +/// but needs its own `DefId` for type-checking, const-eval, etc. +/// These are usually found nested inside types (e.g. array lengths) +/// or expressions (e.g. repeat counts), and also used to define +/// explicit discriminant values for enum variants. +#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] +pub struct AnonConst { + pub id: NodeId, + pub value: P<Expr>, +} + + /// An expression #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash,)] pub struct Expr { @@ -1168,9 +1180,9 @@ pub enum ExprKind { /// An array literal constructed from one repeated element. /// - /// For example, `[1; 5]`. The first expression is the element - /// to be repeated; the second is the number of times to repeat it. - Repeat(P<Expr>, P<Expr>), + /// For example, `[1; 5]`. The expression is the element to be + /// repeated; the constant is the number of times to repeat it. + Repeat(P<Expr>, AnonConst), /// No-op: used solely so we can pretty-print faithfully Paren(P<Expr>), @@ -1565,7 +1577,7 @@ pub enum TyKind { /// A variable-length slice (`[T]`) Slice(P<Ty>), /// A fixed length array (`[T; n]`) - Array(P<Ty>, P<Expr>), + Array(P<Ty>, AnonConst), /// A raw pointer (`*const T` or `*mut T`) Ptr(MutTy), /// A reference (`&'a T` or `&'a mut T`) @@ -1590,7 +1602,7 @@ pub enum TyKind { /// No-op; kept solely so that we can pretty-print faithfully Paren(P<Ty>), /// Unused for now - Typeof(P<Expr>), + Typeof(AnonConst), /// TyKind::Infer means the type should be inferred instead of it having been /// specified. This can appear anywhere in a type. Infer, @@ -1856,7 +1868,7 @@ pub struct Variant_ { pub attrs: Vec<Attribute>, pub data: VariantData, /// Explicit discriminant, e.g. `Foo = 1` - pub disr_expr: Option<P<Expr>>, + pub disr_expr: Option<AnonConst>, } pub type Variant = Spanned<Variant_>; diff --git a/src/libsyntax/diagnostics/plugin.rs b/src/libsyntax/diagnostics/plugin.rs index aecf32ab6af..6c3117b963f 100644 --- a/src/libsyntax/diagnostics/plugin.rs +++ b/src/libsyntax/diagnostics/plugin.rs @@ -207,7 +207,10 @@ pub fn expand_build_diagnostic_array<'cx>(ecx: &'cx mut ExtCtxt, span, ast::TyKind::Tup(vec![ty_str.clone(), ty_str]) ), - ecx.expr_usize(span, count), + ast::AnonConst { + id: ast::DUMMY_NODE_ID, + value: ecx.expr_usize(span, count), + }, ), ); diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 29cc208c06b..28fb95f165f 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -112,6 +112,10 @@ pub trait Folder : Sized { noop_fold_pat(p, self) } + fn fold_anon_const(&mut self, c: AnonConst) -> AnonConst { + noop_fold_anon_const(c, self) + } + fn fold_expr(&mut self, e: P<Expr>) -> P<Expr> { e.map(|e| noop_fold_expr(e, self)) } @@ -394,11 +398,11 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> { }); TyKind::Path(qself, fld.fold_path(path)) } - TyKind::Array(ty, e) => { - TyKind::Array(fld.fold_ty(ty), fld.fold_expr(e)) + TyKind::Array(ty, length) => { + TyKind::Array(fld.fold_ty(ty), fld.fold_anon_const(length)) } TyKind::Typeof(expr) => { - TyKind::Typeof(fld.fold_expr(expr)) + TyKind::Typeof(fld.fold_anon_const(expr)) } TyKind::TraitObject(bounds, syntax) => { TyKind::TraitObject(bounds.move_map(|b| fld.fold_ty_param_bound(b)), syntax) @@ -433,7 +437,7 @@ pub fn noop_fold_variant<T: Folder>(v: Variant, fld: &mut T) -> Variant { ident: fld.fold_ident(v.node.ident), attrs: fold_attrs(v.node.attrs, fld), data: fld.fold_variant_data(v.node.data), - disr_expr: v.node.disr_expr.map(|e| fld.fold_expr(e)), + disr_expr: v.node.disr_expr.map(|e| fld.fold_anon_const(e)), }, span: fld.new_span(v.span), } @@ -1170,6 +1174,14 @@ pub fn noop_fold_range_end<T: Folder>(end: RangeEnd, _folder: &mut T) -> RangeEn end } +pub fn noop_fold_anon_const<T: Folder>(constant: AnonConst, folder: &mut T) -> AnonConst { + let AnonConst {id, value} = constant; + AnonConst { + id: folder.new_id(id), + value: folder.fold_expr(value), + } +} + pub fn noop_fold_expr<T: Folder>(Expr {id, node, span, attrs}: Expr, folder: &mut T) -> Expr { Expr { node: match node { @@ -1180,7 +1192,7 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span, attrs}: Expr, folder: &mu ExprKind::Array(folder.fold_exprs(exprs)) } ExprKind::Repeat(expr, count) => { - ExprKind::Repeat(folder.fold_expr(expr), folder.fold_expr(count)) + ExprKind::Repeat(folder.fold_expr(expr), folder.fold_anon_const(count)) } ExprKind::Tup(exprs) => ExprKind::Tup(folder.fold_exprs(exprs)), ExprKind::Call(f, args) => { diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 3e9869494f9..729ad491fd5 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -12,7 +12,7 @@ use rustc_target::spec::abi::{self, Abi}; use ast::{AngleBracketedParameterData, ParenthesizedParameterData, AttrStyle, BareFnTy}; use ast::{RegionTyParamBound, TraitTyParamBound, TraitBoundModifier}; use ast::Unsafety; -use ast::{Mod, Arg, Arm, Attribute, BindingMode, TraitItemKind}; +use ast::{Mod, AnonConst, Arg, Arm, Attribute, BindingMode, TraitItemKind}; use ast::Block; use ast::{BlockCheckMode, CaptureBy, Movability}; use ast::{Constness, Crate}; @@ -1544,7 +1544,10 @@ impl<'a> Parser<'a> { // Parse optional `; EXPR` in `[TYPE; EXPR]` let t = match self.maybe_parse_fixed_length_of_vec()? { None => TyKind::Slice(t), - Some(suffix) => TyKind::Array(t, suffix), + Some(length) => TyKind::Array(t, AnonConst { + id: ast::DUMMY_NODE_ID, + value: length, + }), }; self.expect(&token::CloseDelim(token::Bracket))?; t @@ -1556,7 +1559,10 @@ impl<'a> Parser<'a> { // `typeof(EXPR)` // In order to not be ambiguous, the type must be surrounded by parens. self.expect(&token::OpenDelim(token::Paren))?; - let e = self.parse_expr()?; + let e = AnonConst { + id: ast::DUMMY_NODE_ID, + value: self.parse_expr()?, + }; self.expect(&token::CloseDelim(token::Paren))?; TyKind::Typeof(e) } else if self.eat_keyword(keywords::Underscore) { @@ -2265,7 +2271,10 @@ impl<'a> Parser<'a> { if self.check(&token::Semi) { // Repeating array syntax: [ 0; 512 ] self.bump(); - let count = self.parse_expr()?; + let count = AnonConst { + id: ast::DUMMY_NODE_ID, + value: self.parse_expr()?, + }; self.expect(&token::CloseDelim(token::Bracket))?; ex = ExprKind::Repeat(first_expr, count); } else if self.check(&token::Comma) { @@ -6354,8 +6363,11 @@ impl<'a> Parser<'a> { struct_def = VariantData::Tuple(self.parse_tuple_struct_body()?, ast::DUMMY_NODE_ID); } else if self.eat(&token::Eq) { - disr_expr = Some(self.parse_expr()?); - any_disr = disr_expr.as_ref().map(|expr| expr.span); + disr_expr = Some(AnonConst { + id: ast::DUMMY_NODE_ID, + value: self.parse_expr()?, + }); + any_disr = disr_expr.as_ref().map(|c| c.value.span); struct_def = VariantData::Unit(ast::DUMMY_NODE_ID); } else { struct_def = VariantData::Unit(ast::DUMMY_NODE_ID); diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 17f83a09c77..be3408ce565 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1076,16 +1076,16 @@ impl<'a> State<'a> { ast::TyKind::ImplTrait(ref bounds) => { self.print_bounds("impl", &bounds[..])?; } - ast::TyKind::Array(ref ty, ref v) => { + ast::TyKind::Array(ref ty, ref length) => { self.s.word("[")?; self.print_type(ty)?; self.s.word("; ")?; - self.print_expr(v)?; + self.print_expr(&length.value)?; self.s.word("]")?; } ast::TyKind::Typeof(ref e) => { self.s.word("typeof(")?; - self.print_expr(e)?; + self.print_expr(&e.value)?; self.s.word(")")?; } ast::TyKind::Infer => { @@ -1552,7 +1552,7 @@ impl<'a> State<'a> { Some(ref d) => { self.s.space()?; self.word_space("=")?; - self.print_expr(d) + self.print_expr(&d.value) } _ => Ok(()) } @@ -1905,14 +1905,14 @@ impl<'a> State<'a> { fn print_expr_repeat(&mut self, element: &ast::Expr, - count: &ast::Expr, + count: &ast::AnonConst, attrs: &[Attribute]) -> io::Result<()> { self.ibox(INDENT_UNIT)?; self.s.word("[")?; self.print_inner_attributes_inline(attrs)?; self.print_expr(element)?; self.word_space(";")?; - self.print_expr(count)?; + self.print_expr(&count.value)?; self.s.word("]")?; self.end() } diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 2013e838c05..b6eb649daa2 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -69,6 +69,7 @@ pub trait Visitor<'ast>: Sized { fn visit_stmt(&mut self, s: &'ast Stmt) { walk_stmt(self, s) } fn visit_arm(&mut self, a: &'ast Arm) { walk_arm(self, a) } fn visit_pat(&mut self, p: &'ast Pat) { walk_pat(self, p) } + fn visit_anon_const(&mut self, c: &'ast AnonConst) { walk_anon_const(self, c) } fn visit_expr(&mut self, ex: &'ast Expr) { walk_expr(self, ex) } fn visit_expr_post(&mut self, _ex: &'ast Expr) { } fn visit_ty(&mut self, t: &'ast Ty) { walk_ty(self, t) } @@ -296,7 +297,7 @@ pub fn walk_variant<'a, V>(visitor: &mut V, visitor.visit_ident(variant.node.ident); visitor.visit_variant_data(&variant.node.data, variant.node.ident, generics, item_id, variant.span); - walk_list!(visitor, visit_expr, &variant.node.disr_expr); + walk_list!(visitor, visit_anon_const, &variant.node.disr_expr); walk_list!(visitor, visit_attribute, &variant.node.attrs); } @@ -326,16 +327,16 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) { } visitor.visit_path(path, typ.id); } - TyKind::Array(ref ty, ref expression) => { + TyKind::Array(ref ty, ref length) => { visitor.visit_ty(ty); - visitor.visit_expr(expression) + visitor.visit_anon_const(length) } TyKind::TraitObject(ref bounds, ..) | TyKind::ImplTrait(ref bounds) => { walk_list!(visitor, visit_ty_param_bound, bounds); } TyKind::Typeof(ref expression) => { - visitor.visit_expr(expression) + visitor.visit_anon_const(expression) } TyKind::Infer | TyKind::ImplicitSelf | TyKind::Err => {} TyKind::Mac(ref mac) => { @@ -647,6 +648,10 @@ pub fn walk_mac<'a, V: Visitor<'a>>(_: &mut V, _: &Mac) { // Empty! } +pub fn walk_anon_const<'a, V: Visitor<'a>>(visitor: &mut V, constant: &'a AnonConst) { + visitor.visit_expr(&constant.value); +} + pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) { for attr in expression.attrs.iter() { visitor.visit_attribute(attr); @@ -660,7 +665,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) { } ExprKind::Repeat(ref element, ref count) => { visitor.visit_expr(element); - visitor.visit_expr(count) + visitor.visit_anon_const(count) } ExprKind::Struct(ref path, ref fields, ref optional_base) => { visitor.visit_path(path, expression.id); |
