diff options
Diffstat (limited to 'compiler/rustc_ast')
-rw-r--r-- | compiler/rustc_ast/Cargo.toml | 2 | ||||
-rw-r--r-- | compiler/rustc_ast/src/ast.rs | 419 | ||||
-rw-r--r-- | compiler/rustc_ast/src/attr/mod.rs | 313 | ||||
-rw-r--r-- | compiler/rustc_ast/src/lib.rs | 1 | ||||
-rw-r--r-- | compiler/rustc_ast/src/mut_visit.rs | 91 | ||||
-rw-r--r-- | compiler/rustc_ast/src/token.rs | 88 | ||||
-rw-r--r-- | compiler/rustc_ast/src/tokenstream.rs | 28 | ||||
-rw-r--r-- | compiler/rustc_ast/src/util/case.rs | 6 | ||||
-rw-r--r-- | compiler/rustc_ast/src/util/classify.rs | 5 | ||||
-rw-r--r-- | compiler/rustc_ast/src/util/comments.rs | 4 | ||||
-rw-r--r-- | compiler/rustc_ast/src/util/literal.rs | 88 | ||||
-rw-r--r-- | compiler/rustc_ast/src/util/parser.rs | 28 | ||||
-rw-r--r-- | compiler/rustc_ast/src/util/unicode.rs | 2 | ||||
-rw-r--r-- | compiler/rustc_ast/src/visit.rs | 293 |
14 files changed, 700 insertions, 668 deletions
diff --git a/compiler/rustc_ast/Cargo.toml b/compiler/rustc_ast/Cargo.toml index fcbf96818..9253b7e68 100644 --- a/compiler/rustc_ast/Cargo.toml +++ b/compiler/rustc_ast/Cargo.toml @@ -14,5 +14,5 @@ rustc_macros = { path = "../rustc_macros" } rustc_serialize = { path = "../rustc_serialize" } rustc_span = { path = "../rustc_span" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } -thin-vec = "0.2.8" +thin-vec = "0.2.9" tracing = "0.1" diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 4ef43735a..4d80f904a 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -13,7 +13,7 @@ //! - [`FnDecl`], [`FnHeader`] and [`Param`]: Metadata associated with a function declaration. //! - [`Generics`], [`GenericParam`], [`WhereClause`]: Metadata associated with generic parameters. //! - [`EnumDef`] and [`Variant`]: Enum declaration. -//! - [`Lit`] and [`LitKind`]: Literal expressions. +//! - [`MetaItemLit`] and [`LitKind`]: Literal expressions. //! - [`MacroDef`], [`MacStmtStyle`], [`MacCall`], [`MacDelimiter`]: Macro definition and invocation. //! - [`Attribute`]: Metadata associated with item. //! - [`UnOp`], [`BinOp`], and [`BinOpKind`]: Unary and binary operators. @@ -36,7 +36,7 @@ use rustc_span::{Span, DUMMY_SP}; use std::convert::TryFrom; use std::fmt; use std::mem; -use thin_vec::ThinVec; +use thin_vec::{thin_vec, ThinVec}; /// A "Label" is an identifier of some point in sources, /// e.g. in the following code: @@ -90,7 +90,7 @@ pub struct Path { pub span: Span, /// The segments in the path: the things separated by `::`. /// Global paths begin with `kw::PathRoot`. - pub segments: Vec<PathSegment>, + pub segments: ThinVec<PathSegment>, pub tokens: Option<LazyAttrTokenStream>, } @@ -111,10 +111,10 @@ impl<CTX: rustc_span::HashStableContext> HashStable<CTX> for Path { } impl Path { - // Convert a span and an identifier to the corresponding - // one-segment path. + /// Convert a span and an identifier to the corresponding + /// one-segment path. pub fn from_ident(ident: Ident) -> Path { - Path { segments: vec![PathSegment::from_ident(ident)], span: ident.span, tokens: None } + Path { segments: thin_vec![PathSegment::from_ident(ident)], span: ident.span, tokens: None } } pub fn is_global(&self) -> bool { @@ -175,9 +175,9 @@ impl GenericArgs { } pub fn span(&self) -> Span { - match *self { - AngleBracketed(ref data) => data.span, - Parenthesized(ref data) => data.span, + match self { + AngleBracketed(data) => data.span, + Parenthesized(data) => data.span, } } } @@ -312,8 +312,8 @@ pub enum GenericBound { impl GenericBound { pub fn span(&self) -> Span { match self { - GenericBound::Trait(ref t, ..) => t.span, - GenericBound::Outlives(ref l) => l.ident.span, + GenericBound::Trait(t, ..) => t.span, + GenericBound::Outlives(l) => l.ident.span, } } } @@ -392,15 +392,7 @@ pub struct Generics { impl Default for Generics { /// Creates an instance of `Generics`. fn default() -> Generics { - Generics { - params: Vec::new(), - where_clause: WhereClause { - has_where_token: false, - predicates: Vec::new(), - span: DUMMY_SP, - }, - span: DUMMY_SP, - } + Generics { params: Vec::new(), where_clause: Default::default(), span: DUMMY_SP } } } @@ -415,6 +407,12 @@ pub struct WhereClause { pub span: Span, } +impl Default for WhereClause { + fn default() -> WhereClause { + WhereClause { has_where_token: false, predicates: Vec::new(), span: DUMMY_SP } + } +} + /// A single predicate in a where-clause. #[derive(Clone, Encodable, Decodable, Debug)] pub enum WherePredicate { @@ -481,20 +479,10 @@ pub struct Crate { pub is_placeholder: bool, } -/// Possible values inside of compile-time attribute lists. -/// -/// E.g., the '..' in `#[name(..)]`. -#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)] -pub enum NestedMetaItem { - /// A full MetaItem, for recursive meta items. - MetaItem(MetaItem), - /// A literal. - /// - /// E.g., `"foo"`, `64`, `true`. - Literal(Lit), -} - -/// A spanned compile-time attribute item. +/// A semantic representation of a meta item. A meta item is a slightly +/// restricted form of an attribute -- it can only contain expressions in +/// certain leaf positions, rather than arbitrary token streams -- that is used +/// for most built-in attributes. /// /// E.g., `#[test]`, `#[derive(..)]`, `#[rustfmt::skip]` or `#[feature = "foo"]`. #[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)] @@ -504,23 +492,37 @@ pub struct MetaItem { pub span: Span, } -/// A compile-time attribute item. -/// -/// E.g., `#[test]`, `#[derive(..)]` or `#[feature = "foo"]`. +/// The meta item kind, containing the data after the initial path. #[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)] pub enum MetaItemKind { /// Word meta item. /// - /// E.g., `test` as in `#[test]`. + /// E.g., `#[test]`, which lacks any arguments after `test`. Word, + /// List meta item. /// - /// E.g., `derive(..)` as in `#[derive(..)]`. + /// E.g., `#[derive(..)]`, where the field represents the `..`. List(Vec<NestedMetaItem>), + /// Name value meta item. /// - /// E.g., `feature = "foo"` as in `#[feature = "foo"]`. - NameValue(Lit), + /// E.g., `#[feature = "foo"]`, where the field represents the `"foo"`. + NameValue(MetaItemLit), +} + +/// Values inside meta item lists. +/// +/// E.g., each of `Clone`, `Copy` in `#[derive(Clone, Copy)]`. +#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)] +pub enum NestedMetaItem { + /// A full MetaItem, for recursive meta items. + MetaItem(MetaItem), + + /// A literal. + /// + /// E.g., `"foo"`, `64`, `true`. + Lit(MetaItemLit), } /// A block (`{ .. }`). @@ -720,10 +722,10 @@ pub enum PatKind { /// A struct or struct variant pattern (e.g., `Variant {x, y, ..}`). /// The `bool` is `true` in the presence of a `..`. - Struct(Option<QSelf>, Path, Vec<PatField>, /* recovered */ bool), + Struct(Option<P<QSelf>>, Path, Vec<PatField>, /* recovered */ bool), /// A tuple struct/variant pattern (`Variant(x, y, .., z)`). - TupleStruct(Option<QSelf>, Path, Vec<P<Pat>>), + TupleStruct(Option<P<QSelf>>, Path, Vec<P<Pat>>), /// An or-pattern `A | B | C`. /// Invariant: `pats.len() >= 2`. @@ -733,7 +735,7 @@ pub enum PatKind { /// Unqualified path patterns `A::B::C` can legally refer to variants, structs, constants /// or associated constants. Qualified path patterns `<A>::B::C`/`<A as Trait>::B::C` can /// only legally refer to associated constants. - Path(Option<QSelf>, Path), + Path(Option<P<QSelf>>, Path), /// A tuple pattern (`(a, b)`). Tuple(Vec<P<Pat>>), @@ -777,8 +779,9 @@ pub enum PatKind { #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)] #[derive(HashStable_Generic, Encodable, Decodable)] pub enum Mutability { - Mut, + // N.B. Order is deliberate, so that Not < Mut Not, + Mut, } impl Mutability { @@ -789,12 +792,39 @@ impl Mutability { } } - pub fn prefix_str(&self) -> &'static str { + /// Returns `""` (empty string) or `"mut "` depending on the mutability. + pub fn prefix_str(self) -> &'static str { match self { Mutability::Mut => "mut ", Mutability::Not => "", } } + + /// Returns `"&"` or `"&mut "` depending on the mutability. + pub fn ref_prefix_str(self) -> &'static str { + match self { + Mutability::Not => "&", + Mutability::Mut => "&mut ", + } + } + + /// Returns `""` (empty string) or `"mutably "` depending on the mutability. + pub fn mutably_str(self) -> &'static str { + match self { + Mutability::Not => "", + Mutability::Mut => "mutably ", + } + } + + /// Return `true` if self is mutable + pub fn is_mut(self) -> bool { + matches!(self, Self::Mut) + } + + /// Return `true` if self is **not** mutable + pub fn is_not(self) -> bool { + matches!(self, Self::Not) + } } /// The kind of borrow in an `AddrOf` expression, @@ -1117,23 +1147,23 @@ impl Expr { /// If this is not the case, name resolution does not resolve `N` when using /// `min_const_generics` as more complex expressions are not supported. pub fn is_potential_trivial_const_param(&self) -> bool { - let this = if let ExprKind::Block(ref block, None) = self.kind { - if block.stmts.len() == 1 { - if let StmtKind::Expr(ref expr) = block.stmts[0].kind { expr } else { self } - } else { - self - } + let this = if let ExprKind::Block(block, None) = &self.kind + && block.stmts.len() == 1 + && let StmtKind::Expr(expr) = &block.stmts[0].kind + { + expr } else { self }; - if let ExprKind::Path(None, ref path) = this.kind { - if path.segments.len() == 1 && path.segments[0].args.is_none() { - return true; - } + if let ExprKind::Path(None, path) = &this.kind + && path.segments.len() == 1 + && path.segments[0].args.is_none() + { + true + } else { + false } - - false } pub fn to_bound(&self) -> Option<GenericBound> { @@ -1149,7 +1179,7 @@ impl Expr { pub fn peel_parens(&self) -> &Expr { let mut expr = self; while let ExprKind::Paren(inner) = &expr.kind { - expr = &inner; + expr = inner; } expr } @@ -1208,7 +1238,7 @@ impl Expr { ExprKind::Tup(_) => ExprPrecedence::Tup, ExprKind::Binary(op, ..) => ExprPrecedence::Binary(op.node), ExprKind::Unary(..) => ExprPrecedence::Unary, - ExprKind::Lit(_) => ExprPrecedence::Lit, + ExprKind::Lit(_) | ExprKind::IncludedBytes(..) => ExprPrecedence::Lit, ExprKind::Type(..) | ExprKind::Cast(..) => ExprPrecedence::Cast, ExprKind::Let(..) => ExprPrecedence::Let, ExprKind::If(..) => ExprPrecedence::If, @@ -1257,7 +1287,7 @@ impl Expr { ) } - // To a first-order approximation, is this a pattern + /// To a first-order approximation, is this a pattern? pub fn is_approximately_pattern(&self) -> bool { match &self.peel_parens().kind { ExprKind::Box(_) @@ -1274,6 +1304,20 @@ impl Expr { } } +#[derive(Clone, Encodable, Decodable, Debug)] +pub struct Closure { + pub binder: ClosureBinder, + pub capture_clause: CaptureBy, + pub asyncness: Async, + pub movability: Movability, + pub fn_decl: P<FnDecl>, + pub body: P<Expr>, + /// The span of the declaration block: 'move |...| -> ...' + pub fn_decl_span: Span, + /// The span of the argument block `|...|` + pub fn_arg_span: Span, +} + /// Limit types of a range (inclusive or exclusive) #[derive(Copy, Clone, PartialEq, Encodable, Decodable, Debug)] pub enum RangeLimits { @@ -1283,6 +1327,20 @@ pub enum RangeLimits { Closed, } +/// A method call (e.g. `x.foo::<Bar, Baz>(a, b, c)`). +#[derive(Clone, Encodable, Decodable, Debug)] +pub struct MethodCall { + /// The method name and its generic arguments, e.g. `foo::<Bar, Baz>`. + pub seg: PathSegment, + /// The receiver, e.g. `x`. + pub receiver: P<Expr>, + /// The arguments, e.g. `a, b, c`. + pub args: Vec<P<Expr>>, + /// The span of the function, without the dot and receiver e.g. `foo::<Bar, + /// Baz>(a, b, c)`. + pub span: Span, +} + #[derive(Clone, Encodable, Decodable, Debug)] pub enum StructRest { /// `..x`. @@ -1295,7 +1353,7 @@ pub enum StructRest { #[derive(Clone, Encodable, Decodable, Debug)] pub struct StructExpr { - pub qself: Option<QSelf>, + pub qself: Option<P<QSelf>>, pub path: Path, pub fields: Vec<ExprField>, pub rest: StructRest, @@ -1316,17 +1374,8 @@ pub enum ExprKind { /// This also represents calling the constructor of /// tuple-like ADTs such as tuple structs and enum variants. Call(P<Expr>, Vec<P<Expr>>), - /// A method call (`x.foo::<'static, Bar, Baz>(a, b, c, d)`) - /// - /// The `PathSegment` represents the method name and its generic arguments - /// (within the angle brackets). - /// The standalone `Expr` is the receiver expression. - /// The vector of `Expr` is the arguments. - /// `x.foo::<Bar, Baz>(a, b, c, d)` is represented as - /// `ExprKind::MethodCall(PathSegment { foo, [Bar, Baz] }, x, [a, b, c, d])`. - /// This `Span` is the span of the function, without the dot and receiver - /// (e.g. `foo(a, b)` in `x.foo(a, b)` - MethodCall(PathSegment, P<Expr>, Vec<P<Expr>>, Span), + /// A method call (e.g. `x.foo::<Bar, Baz>(a, b, c)`). + MethodCall(Box<MethodCall>), /// A tuple (e.g., `(a, b, c, d)`). Tup(Vec<P<Expr>>), /// A binary operation (e.g., `a + b`, `a * b`). @@ -1334,7 +1383,7 @@ pub enum ExprKind { /// A unary operation (e.g., `!x`, `*x`). Unary(UnOp, P<Expr>), /// A literal (e.g., `1`, `"foo"`). - Lit(Lit), + Lit(token::Lit), /// A cast (e.g., `foo as f64`). Cast(P<Expr>, P<Ty>), /// A type ascription (e.g., `42: usize`). @@ -1361,13 +1410,11 @@ pub enum ExprKind { /// Conditionless loop (can be exited with `break`, `continue`, or `return`). /// /// `'label: loop { block }` - Loop(P<Block>, Option<Label>), + Loop(P<Block>, Option<Label>, Span), /// A `match` block. Match(P<Expr>, Vec<Arm>), /// A closure (e.g., `move |a, b, c| a + b + c`). - /// - /// The final span is the span of the argument block `|...|`. - Closure(ClosureBinder, CaptureBy, Async, Movability, P<FnDecl>, P<Expr>, Span), + Closure(Box<Closure>), /// A block (`'label: { ... }`). Block(P<Block>, Option<Label>), /// An async block (`async move { ... }`). @@ -1405,7 +1452,7 @@ pub enum ExprKind { /// parameters (e.g., `foo::bar::<baz>`). /// /// Optionally "qualified" (e.g., `<Vec<T> as SomeTrait>::SomeType`). - Path(Option<QSelf>, Path), + Path(Option<P<QSelf>>, Path), /// A referencing operation (`&a`, `&mut a`, `&raw const a` or `&raw mut a`). AddrOf(BorrowKind, Mutability, P<Expr>), @@ -1446,6 +1493,12 @@ pub enum ExprKind { /// with an optional value to be returned. Yeet(Option<P<Expr>>), + /// Bytes included via `include_bytes!` + /// Added for optimization purposes to avoid the need to escape + /// large binary blobs - should always behave like [`ExprKind::Lit`] + /// with a `ByteStr` literal. + IncludedBytes(Lrc<[u8]>), + /// Placeholder for an expression that wasn't syntactically well formed in some way. Err, } @@ -1525,55 +1578,48 @@ pub enum ClosureBinder { #[derive(Clone, Encodable, Decodable, Debug)] pub struct MacCall { pub path: Path, - pub args: P<MacArgs>, + pub args: P<DelimArgs>, pub prior_type_ascription: Option<(Span, bool)>, } impl MacCall { pub fn span(&self) -> Span { - self.path.span.to(self.args.span().unwrap_or(self.path.span)) + self.path.span.to(self.args.dspan.entire()) } } -/// Arguments passed to an attribute or a function-like macro. +/// Arguments passed to an attribute macro. #[derive(Clone, Encodable, Decodable, Debug)] -pub enum MacArgs { - /// No arguments - `#[attr]`. +pub enum AttrArgs { + /// No arguments: `#[attr]`. Empty, - /// Delimited arguments - `#[attr()/[]/{}]` or `mac!()/[]/{}`. - Delimited(DelimSpan, MacDelimiter, TokenStream), - /// Arguments of a key-value attribute - `#[attr = "value"]`. + /// Delimited arguments: `#[attr()/[]/{}]`. + Delimited(DelimArgs), + /// Arguments of a key-value attribute: `#[attr = "value"]`. Eq( /// Span of the `=` token. Span, /// The "value". - MacArgsEq, + AttrArgsEq, ), } -// The RHS of a `MacArgs::Eq` starts out as an expression. Once macro expansion -// is completed, all cases end up either as a literal, which is the form used -// after lowering to HIR, or as an error. +// The RHS of an `AttrArgs::Eq` starts out as an expression. Once macro +// expansion is completed, all cases end up either as a meta item literal, +// which is the form used after lowering to HIR, or as an error. #[derive(Clone, Encodable, Decodable, Debug)] -pub enum MacArgsEq { +pub enum AttrArgsEq { Ast(P<Expr>), - Hir(Lit), + Hir(MetaItemLit), } -impl MacArgs { - pub fn delim(&self) -> Option<Delimiter> { - match self { - MacArgs::Delimited(_, delim, _) => Some(delim.to_token()), - MacArgs::Empty | MacArgs::Eq(..) => None, - } - } - +impl AttrArgs { pub fn span(&self) -> Option<Span> { match self { - MacArgs::Empty => None, - MacArgs::Delimited(dspan, ..) => Some(dspan.entire()), - MacArgs::Eq(eq_span, MacArgsEq::Ast(expr)) => Some(eq_span.to(expr.span)), - MacArgs::Eq(_, MacArgsEq::Hir(lit)) => { + AttrArgs::Empty => None, + AttrArgs::Delimited(args) => Some(args.dspan.entire()), + AttrArgs::Eq(eq_span, AttrArgsEq::Ast(expr)) => Some(eq_span.to(expr.span)), + AttrArgs::Eq(_, AttrArgsEq::Hir(lit)) => { unreachable!("in literal form when getting span: {:?}", lit); } } @@ -1583,39 +1629,29 @@ impl MacArgs { /// Proc macros see these tokens, for example. pub fn inner_tokens(&self) -> TokenStream { match self { - MacArgs::Empty => TokenStream::default(), - MacArgs::Delimited(.., tokens) => tokens.clone(), - MacArgs::Eq(_, MacArgsEq::Ast(expr)) => TokenStream::from_ast(expr), - MacArgs::Eq(_, MacArgsEq::Hir(lit)) => { + AttrArgs::Empty => TokenStream::default(), + AttrArgs::Delimited(args) => args.tokens.clone(), + AttrArgs::Eq(_, AttrArgsEq::Ast(expr)) => TokenStream::from_ast(expr), + AttrArgs::Eq(_, AttrArgsEq::Hir(lit)) => { unreachable!("in literal form when getting inner tokens: {:?}", lit) } } } - - /// Whether a macro with these arguments needs a semicolon - /// when used as a standalone item or statement. - pub fn need_semicolon(&self) -> bool { - !matches!(self, MacArgs::Delimited(_, MacDelimiter::Brace, _)) - } } -impl<CTX> HashStable<CTX> for MacArgs +impl<CTX> HashStable<CTX> for AttrArgs where CTX: crate::HashStableContext, { fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(ctx, hasher); match self { - MacArgs::Empty => {} - MacArgs::Delimited(dspan, delim, tokens) => { - dspan.hash_stable(ctx, hasher); - delim.hash_stable(ctx, hasher); - tokens.hash_stable(ctx, hasher); - } - MacArgs::Eq(_eq_span, MacArgsEq::Ast(expr)) => { + AttrArgs::Empty => {} + AttrArgs::Delimited(args) => args.hash_stable(ctx, hasher), + AttrArgs::Eq(_eq_span, AttrArgsEq::Ast(expr)) => { unreachable!("hash_stable {:?}", expr); } - MacArgs::Eq(eq_span, MacArgsEq::Hir(lit)) => { + AttrArgs::Eq(eq_span, AttrArgsEq::Hir(lit)) => { eq_span.hash_stable(ctx, hasher); lit.hash_stable(ctx, hasher); } @@ -1623,6 +1659,34 @@ where } } +/// Delimited arguments, as used in `#[attr()/[]/{}]` or `mac!()/[]/{}`. +#[derive(Clone, Encodable, Decodable, Debug)] +pub struct DelimArgs { + pub dspan: DelimSpan, + pub delim: MacDelimiter, + pub tokens: TokenStream, +} + +impl DelimArgs { + /// Whether a macro with these arguments needs a semicolon + /// when used as a standalone item or statement. + pub fn need_semicolon(&self) -> bool { + !matches!(self, DelimArgs { delim: MacDelimiter::Brace, .. }) + } +} + +impl<CTX> HashStable<CTX> for DelimArgs +where + CTX: crate::HashStableContext, +{ + fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { + let DelimArgs { dspan, delim, tokens } = self; + dspan.hash_stable(ctx, hasher); + delim.hash_stable(ctx, hasher); + tokens.hash_stable(ctx, hasher); + } +} + #[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, HashStable_Generic)] pub enum MacDelimiter { Parenthesis, @@ -1652,7 +1716,7 @@ impl MacDelimiter { /// Represents a macro definition. #[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)] pub struct MacroDef { - pub body: P<MacArgs>, + pub body: P<DelimArgs>, /// `true` if macro was defined with `macro_rules`. pub macro_rules: bool, } @@ -1668,19 +1732,18 @@ pub enum StrStyle { Raw(u8), } -/// An AST literal. +/// A literal in a meta item. #[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)] -pub struct Lit { +pub struct MetaItemLit { /// The original literal token as written in source code. pub token_lit: token::Lit, /// The "semantic" representation of the literal lowered from the original tokens. /// Strings are unescaped, hexadecimal forms are eliminated, etc. - /// FIXME: Remove this and only create the semantic representation during lowering to HIR. pub kind: LitKind, pub span: Span, } -/// Same as `Lit`, but restricted to string literals. +/// Similar to `MetaItemLit`, but restricted to string literals. #[derive(Clone, Copy, Encodable, Decodable, Debug)] pub struct StrLit { /// The original literal token as written in source code. @@ -1689,21 +1752,16 @@ pub struct StrLit { pub suffix: Option<Symbol>, pub span: Span, /// The unescaped "semantic" representation of the literal lowered from the original token. - /// FIXME: Remove this and only create the semantic representation during lowering to HIR. pub symbol_unescaped: Symbol, } impl StrLit { - pub fn as_lit(&self) -> Lit { + pub fn as_token_lit(&self) -> token::Lit { let token_kind = match self.style { StrStyle::Cooked => token::Str, StrStyle::Raw(n) => token::StrRaw(n), }; - Lit { - token_lit: token::Lit::new(token_kind, self.symbol, self.suffix), - span: self.span, - kind: LitKind::Str(self.symbol_unescaped, self.style), - } + token::Lit::new(token_kind, self.symbol, self.suffix) } } @@ -1729,9 +1787,12 @@ pub enum LitFloatType { Unsuffixed, } -/// Literal kind. +/// This type is used within both `ast::MetaItemLit` and `hir::Lit`. /// -/// E.g., `"foo"`, `42`, `12.34`, or `bool`. +/// Note that the entire literal (including the suffix) is considered when +/// deciding the `LitKind`. This means that float literals like `1f32` are +/// classified by this type as `Float`. This is different to `token::LitKind` +/// which does *not* consider the suffix. #[derive(Clone, Encodable, Decodable, Debug, Hash, Eq, PartialEq, HashStable_Generic)] pub enum LitKind { /// A string literal (`"foo"`). The symbol is unescaped, and so may differ @@ -1745,10 +1806,11 @@ pub enum LitKind { Char(char), /// An integer literal (`1`). Int(u128, LitIntType), - /// A float literal (`1f64` or `1E10f64`). Stored as a symbol rather than - /// `f64` so that `LitKind` can impl `Eq` and `Hash`. + /// A float literal (`1.0`, `1f64` or `1E10f64`). The pre-suffix part is + /// stored as a symbol rather than `f64` so that `LitKind` can impl `Eq` + /// and `Hash`. Float(Symbol, LitFloatType), - /// A boolean literal. + /// A boolean literal (`true`, `false`). Bool(bool), /// Placeholder for a literal that wasn't well-formed in some way. Err, @@ -1967,7 +2029,7 @@ impl Ty { pub fn peel_refs(&self) -> &Self { let mut final_ty = self; while let TyKind::Rptr(_, MutTy { ty, .. }) = &final_ty.kind { - final_ty = &ty; + final_ty = ty; } final_ty } @@ -2004,7 +2066,7 @@ pub enum TyKind { /// "qualified", e.g., `<Vec<T> as SomeTrait>::SomeType`. /// /// Type parameters are stored in the `Path` itself. - Path(Option<QSelf>, Path), + Path(Option<P<QSelf>>, Path), /// A trait object type `Bound1 + Bound2 + Bound3` /// where `Bound` is a trait or a lifetime. TraitObject(GenericBounds, TraitObjectSyntax), @@ -2136,7 +2198,7 @@ impl InlineAsmTemplatePiece { #[derive(Clone, Encodable, Decodable, Debug)] pub struct InlineAsmSym { pub id: NodeId, - pub qself: Option<QSelf>, + pub qself: Option<P<QSelf>>, pub path: Path, } @@ -2376,9 +2438,9 @@ pub enum FnRetTy { impl FnRetTy { pub fn span(&self) -> Span { - match *self { - FnRetTy::Default(span) => span, - FnRetTy::Ty(ref ty) => ty.span, + match self { + &FnRetTy::Default(span) => span, + FnRetTy::Ty(ty) => ty.span, } } } @@ -2457,10 +2519,7 @@ pub struct Variant { #[derive(Clone, Encodable, Decodable, Debug)] pub enum UseTreeKind { /// `use prefix` or `use prefix as rename` - /// - /// The extra `NodeId`s are for HIR lowering, when additional statements are created for each - /// namespace. - Simple(Option<Ident>, NodeId, NodeId), + Simple(Option<Ident>), /// `use prefix::{...}` Nested(Vec<(UseTree, NodeId)>), /// `use prefix::*` @@ -2479,8 +2538,8 @@ pub struct UseTree { impl UseTree { pub fn ident(&self) -> Ident { match self.kind { - UseTreeKind::Simple(Some(rename), ..) => rename, - UseTreeKind::Simple(None, ..) => { + UseTreeKind::Simple(Some(rename)) => rename, + UseTreeKind::Simple(None) => { self.prefix.segments.last().expect("empty prefix in a simple import").ident } _ => panic!("`UseTree::ident` can only be used on a simple import"), @@ -2514,17 +2573,10 @@ impl<D: Decoder> Decodable<D> for AttrId { } } -#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)] -pub struct AttrItem { - pub path: Path, - pub args: MacArgs, - pub tokens: Option<LazyAttrTokenStream>, -} - /// A list of attributes. pub type AttrVec = ThinVec<Attribute>; -/// Metadata associated with an item. +/// A syntax-level representation of an attribute. #[derive(Clone, Encodable, Decodable, Debug)] pub struct Attribute { pub kind: AttrKind, @@ -2536,12 +2588,6 @@ pub struct Attribute { } #[derive(Clone, Encodable, Decodable, Debug)] -pub struct NormalAttr { - pub item: AttrItem, - pub tokens: Option<LazyAttrTokenStream>, -} - -#[derive(Clone, Encodable, Decodable, Debug)] pub enum AttrKind { /// A normal attribute. Normal(P<NormalAttr>), @@ -2552,6 +2598,19 @@ pub enum AttrKind { DocComment(CommentKind, Symbol), } +#[derive(Clone, Encodable, Decodable, Debug)] +pub struct NormalAttr { + pub item: AttrItem, + pub tokens: Option<LazyAttrTokenStream>, +} + +#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)] +pub struct AttrItem { + pub path: Path, + pub args: AttrArgs, + pub tokens: Option<LazyAttrTokenStream>, +} + /// `TraitRef`s appear in impls. /// /// Resolution maps each `TraitRef`'s `ref_id` to its defining trait; that's all @@ -2640,14 +2699,14 @@ pub enum VariantData { impl VariantData { /// Return the fields of this variant. pub fn fields(&self) -> &[FieldDef] { - match *self { - VariantData::Struct(ref fields, ..) | VariantData::Tuple(ref fields, _) => fields, + match self { + VariantData::Struct(fields, ..) | VariantData::Tuple(fields, _) => fields, _ => &[], } } /// Return the `NodeId` of this variant's constructor, if it has one. - pub fn ctor_id(&self) -> Option<NodeId> { + pub fn ctor_node_id(&self) -> Option<NodeId> { match *self { VariantData::Struct(..) => None, VariantData::Tuple(_, id) | VariantData::Unit(id) => Some(id), @@ -3029,28 +3088,28 @@ mod size_asserts { static_assert_size!(AssocItemKind, 32); static_assert_size!(Attribute, 32); static_assert_size!(Block, 48); - static_assert_size!(Expr, 104); - static_assert_size!(ExprKind, 72); + static_assert_size!(Expr, 72); + static_assert_size!(ExprKind, 40); static_assert_size!(Fn, 184); static_assert_size!(ForeignItem, 96); static_assert_size!(ForeignItemKind, 24); static_assert_size!(GenericArg, 24); - static_assert_size!(GenericBound, 88); + static_assert_size!(GenericBound, 72); static_assert_size!(Generics, 72); - static_assert_size!(Impl, 200); + static_assert_size!(Impl, 184); static_assert_size!(Item, 184); static_assert_size!(ItemKind, 112); - static_assert_size!(Lit, 48); static_assert_size!(LitKind, 24); static_assert_size!(Local, 72); + static_assert_size!(MetaItemLit, 48); static_assert_size!(Param, 40); - static_assert_size!(Pat, 120); - static_assert_size!(Path, 40); + static_assert_size!(Pat, 88); + static_assert_size!(Path, 24); static_assert_size!(PathSegment, 24); - static_assert_size!(PatKind, 96); + static_assert_size!(PatKind, 64); static_assert_size!(Stmt, 32); static_assert_size!(StmtKind, 16); - static_assert_size!(Ty, 96); - static_assert_size!(TyKind, 72); + static_assert_size!(Ty, 64); + static_assert_size!(TyKind, 40); // tidy-alphabetical-end } diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index 990f4f8f1..057cc26b5 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs @@ -1,35 +1,33 @@ //! Functions dealing with attributes and meta items. use crate::ast; -use crate::ast::{AttrId, AttrItem, AttrKind, AttrStyle, Attribute}; -use crate::ast::{Lit, LitKind}; -use crate::ast::{MacArgs, MacArgsEq, MacDelimiter, MetaItem, MetaItemKind, NestedMetaItem}; -use crate::ast::{Path, PathSegment}; +use crate::ast::{AttrArgs, AttrArgsEq, AttrId, AttrItem, AttrKind, AttrStyle, AttrVec, Attribute}; +use crate::ast::{DelimArgs, Expr, ExprKind, LitKind, MetaItemLit}; +use crate::ast::{MacDelimiter, MetaItem, MetaItemKind, NestedMetaItem, NormalAttr}; +use crate::ast::{Path, PathSegment, StrStyle, DUMMY_NODE_ID}; use crate::ptr::P; use crate::token::{self, CommentKind, Delimiter, Token}; use crate::tokenstream::{DelimSpan, Spacing, TokenTree}; use crate::tokenstream::{LazyAttrTokenStream, TokenStream}; use crate::util::comments; - use rustc_data_structures::sync::WorkerLocal; use rustc_index::bit_set::GrowableBitSet; -use rustc_span::source_map::BytePos; use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_span::Span; - use std::cell::Cell; use std::iter; #[cfg(debug_assertions)] use std::ops::BitXor; #[cfg(debug_assertions)] use std::sync::atomic::{AtomicU32, Ordering}; +use thin_vec::thin_vec; pub struct MarkedAttrs(GrowableBitSet<AttrId>); impl MarkedAttrs { - // We have no idea how many attributes there will be, so just - // initiate the vectors with 0 bits. We'll grow them as necessary. pub fn new() -> Self { + // We have no idea how many attributes there will be, so just + // initiate the vectors with 0 bits. We'll grow them as necessary. MarkedAttrs(GrowableBitSet::new_empty()) } @@ -45,16 +43,16 @@ impl MarkedAttrs { impl NestedMetaItem { /// Returns the `MetaItem` if `self` is a `NestedMetaItem::MetaItem`. pub fn meta_item(&self) -> Option<&MetaItem> { - match *self { - NestedMetaItem::MetaItem(ref item) => Some(item), + match self { + NestedMetaItem::MetaItem(item) => Some(item), _ => None, } } - /// Returns the `Lit` if `self` is a `NestedMetaItem::Literal`s. - pub fn literal(&self) -> Option<&Lit> { - match *self { - NestedMetaItem::Literal(ref lit) => Some(lit), + /// Returns the `MetaItemLit` if `self` is a `NestedMetaItem::Literal`s. + pub fn lit(&self) -> Option<&MetaItemLit> { + match self { + NestedMetaItem::Lit(lit) => Some(lit), _ => None, } } @@ -79,12 +77,12 @@ impl NestedMetaItem { } /// Returns a name and single literal value tuple of the `MetaItem`. - pub fn name_value_literal(&self) -> Option<(Symbol, &Lit)> { + pub fn name_value_literal(&self) -> Option<(Symbol, &MetaItemLit)> { self.meta_item().and_then(|meta_item| { meta_item.meta_item_list().and_then(|meta_item_list| { if meta_item_list.len() == 1 && let Some(ident) = meta_item.ident() - && let Some(lit) = meta_item_list[0].literal() + && let Some(lit) = meta_item_list[0].lit() { return Some((ident.name, lit)); } @@ -117,18 +115,18 @@ impl NestedMetaItem { impl Attribute { #[inline] pub fn has_name(&self, name: Symbol) -> bool { - match self.kind { - AttrKind::Normal(ref normal) => normal.item.path == name, + match &self.kind { + AttrKind::Normal(normal) => normal.item.path == name, AttrKind::DocComment(..) => false, } } /// For a single-segment attribute, returns its name; otherwise, returns `None`. pub fn ident(&self) -> Option<Ident> { - match self.kind { - AttrKind::Normal(ref normal) => { - if normal.item.path.segments.len() == 1 { - Some(normal.item.path.segments[0].ident) + match &self.kind { + AttrKind::Normal(normal) => { + if let [ident] = &*normal.item.path.segments { + Some(ident.ident) } else { None } @@ -141,17 +139,15 @@ impl Attribute { } pub fn value_str(&self) -> Option<Symbol> { - match self.kind { - AttrKind::Normal(ref normal) => { - normal.item.meta_kind().and_then(|kind| kind.value_str()) - } + match &self.kind { + AttrKind::Normal(normal) => normal.item.meta_kind().and_then(|kind| kind.value_str()), AttrKind::DocComment(..) => None, } } pub fn meta_item_list(&self) -> Option<Vec<NestedMetaItem>> { - match self.kind { - AttrKind::Normal(ref normal) => match normal.item.meta_kind() { + match &self.kind { + AttrKind::Normal(normal) => match normal.item.meta_kind() { Some(MetaItemKind::List(list)) => Some(list), _ => None, }, @@ -161,7 +157,7 @@ impl Attribute { pub fn is_word(&self) -> bool { if let AttrKind::Normal(normal) = &self.kind { - matches!(normal.item.args, MacArgs::Empty) + matches!(normal.item.args, AttrArgs::Empty) } else { false } @@ -177,10 +173,12 @@ impl MetaItem { self.ident().unwrap_or_else(Ident::empty).name } - // Example: - // #[attribute(name = "value")] - // ^^^^^^^^^^^^^^ - pub fn name_value_literal(&self) -> Option<&Lit> { + /// ```text + /// Example: + /// #[attribute(name = "value")] + /// ^^^^^^^^^^^^^^ + /// ``` + pub fn name_value_literal(&self) -> Option<&MetaItemLit> { match &self.kind { MetaItemKind::NameValue(v) => Some(v), _ => None, @@ -192,8 +190,8 @@ impl MetaItem { } pub fn meta_item_list(&self) -> Option<&[NestedMetaItem]> { - match self.kind { - MetaItemKind::List(ref l) => Some(&l[..]), + match &self.kind { + MetaItemKind::List(l) => Some(&**l), _ => None, } } @@ -224,15 +222,11 @@ impl AttrItem { } pub fn meta(&self, span: Span) -> Option<MetaItem> { - Some(MetaItem { - path: self.path.clone(), - kind: MetaItemKind::from_mac_args(&self.args)?, - span, - }) + Some(MetaItem { path: self.path.clone(), kind: self.meta_kind()?, span }) } pub fn meta_kind(&self) -> Option<MetaItemKind> { - MetaItemKind::from_mac_args(&self.args) + MetaItemKind::from_attr_args(&self.args) } } @@ -269,9 +263,9 @@ impl Attribute { /// * `#[doc = "doc"]` returns `Some("doc")`. /// * `#[doc(...)]` returns `None`. pub fn doc_str(&self) -> Option<Symbol> { - match self.kind { - AttrKind::DocComment(.., data) => Some(data), - AttrKind::Normal(ref normal) if normal.item.path == sym::doc => { + match &self.kind { + AttrKind::DocComment(.., data) => Some(*data), + AttrKind::Normal(normal) if normal.item.path == sym::doc => { normal.item.meta_kind().and_then(|kind| kind.value_str()) } _ => None, @@ -283,8 +277,8 @@ impl Attribute { } pub fn get_normal_item(&self) -> &AttrItem { - match self.kind { - AttrKind::Normal(ref normal) => &normal.item, + match &self.kind { + AttrKind::Normal(normal) => &normal.item, AttrKind::DocComment(..) => panic!("unexpected doc comment"), } } @@ -298,28 +292,28 @@ impl Attribute { /// Extracts the MetaItem from inside this Attribute. pub fn meta(&self) -> Option<MetaItem> { - match self.kind { - AttrKind::Normal(ref normal) => normal.item.meta(self.span), + match &self.kind { + AttrKind::Normal(normal) => normal.item.meta(self.span), AttrKind::DocComment(..) => None, } } pub fn meta_kind(&self) -> Option<MetaItemKind> { - match self.kind { - AttrKind::Normal(ref normal) => normal.item.meta_kind(), + match &self.kind { + AttrKind::Normal(normal) => normal.item.meta_kind(), AttrKind::DocComment(..) => None, } } pub fn tokens(&self) -> TokenStream { - match self.kind { - AttrKind::Normal(ref normal) => normal + match &self.kind { + AttrKind::Normal(normal) => normal .tokens .as_ref() .unwrap_or_else(|| panic!("attribute is missing tokens: {:?}", self)) .to_attr_token_stream() .to_tokenstream(), - AttrKind::DocComment(comment_kind, data) => TokenStream::new(vec![TokenTree::Token( + &AttrKind::DocComment(comment_kind, data) => TokenStream::new(vec![TokenTree::Token( Token::new(token::DocComment(comment_kind, self.style, data), self.span), Spacing::Alone, )]), @@ -330,26 +324,13 @@ impl Attribute { /* Constructors */ pub fn mk_name_value_item_str(ident: Ident, str: Symbol, str_span: Span) -> MetaItem { - let lit_kind = LitKind::Str(str, ast::StrStyle::Cooked); - mk_name_value_item(ident, lit_kind, str_span) + mk_name_value_item(ident, LitKind::Str(str, ast::StrStyle::Cooked), str_span) } -pub fn mk_name_value_item(ident: Ident, lit_kind: LitKind, lit_span: Span) -> MetaItem { - let lit = Lit::from_lit_kind(lit_kind, lit_span); +pub fn mk_name_value_item(ident: Ident, kind: LitKind, lit_span: Span) -> MetaItem { + let lit = MetaItemLit { token_lit: kind.to_token_lit(), kind, span: lit_span }; let span = ident.span.to(lit_span); - MetaItem { path: Path::from_ident(ident), span, kind: MetaItemKind::NameValue(lit) } -} - -pub fn mk_list_item(ident: Ident, items: Vec<NestedMetaItem>) -> MetaItem { - MetaItem { path: Path::from_ident(ident), span: ident.span, kind: MetaItemKind::List(items) } -} - -pub fn mk_word_item(ident: Ident) -> MetaItem { - MetaItem { path: Path::from_ident(ident), span: ident.span, kind: MetaItemKind::Word } -} - -pub fn mk_nested_word_item(ident: Ident) -> NestedMetaItem { - NestedMetaItem::MetaItem(mk_word_item(ident)) + MetaItem { path: Path::from_ident(ident), kind: MetaItemKind::NameValue(lit), span } } pub struct AttrIdGenerator(WorkerLocal<Cell<u32>>); @@ -393,7 +374,7 @@ pub fn mk_attr( g: &AttrIdGenerator, style: AttrStyle, path: Path, - args: MacArgs, + args: AttrArgs, span: Span, ) -> Attribute { mk_attr_from_item(g, AttrItem { path, args, tokens: None }, None, style, span) @@ -407,21 +388,58 @@ pub fn mk_attr_from_item( span: Span, ) -> Attribute { Attribute { - kind: AttrKind::Normal(P(ast::NormalAttr { item, tokens })), + kind: AttrKind::Normal(P(NormalAttr { item, tokens })), id: g.mk_attr_id(), style, span, } } -/// Returns an inner attribute with the given value and span. -pub fn mk_attr_inner(g: &AttrIdGenerator, item: MetaItem) -> Attribute { - mk_attr(g, AttrStyle::Inner, item.path, item.kind.mac_args(item.span), item.span) +pub fn mk_attr_word(g: &AttrIdGenerator, style: AttrStyle, name: Symbol, span: Span) -> Attribute { + let path = Path::from_ident(Ident::new(name, span)); + let args = AttrArgs::Empty; + mk_attr(g, style, path, args, span) +} + +pub fn mk_attr_name_value_str( + g: &AttrIdGenerator, + style: AttrStyle, + name: Symbol, + val: Symbol, + span: Span, +) -> Attribute { + let lit = LitKind::Str(val, StrStyle::Cooked).to_token_lit(); + let expr = P(Expr { + id: DUMMY_NODE_ID, + kind: ExprKind::Lit(lit), + span, + attrs: AttrVec::new(), + tokens: None, + }); + let path = Path::from_ident(Ident::new(name, span)); + let args = AttrArgs::Eq(span, AttrArgsEq::Ast(expr)); + mk_attr(g, style, path, args, span) } -/// Returns an outer attribute with the given value and span. -pub fn mk_attr_outer(g: &AttrIdGenerator, item: MetaItem) -> Attribute { - mk_attr(g, AttrStyle::Outer, item.path, item.kind.mac_args(item.span), item.span) +pub fn mk_attr_nested_word( + g: &AttrIdGenerator, + style: AttrStyle, + outer: Symbol, + inner: Symbol, + span: Span, +) -> Attribute { + let inner_tokens = TokenStream::new(vec![TokenTree::Token( + Token::from_ast_ident(Ident::new(inner, span)), + Spacing::Alone, + )]); + let outer_ident = Ident::new(outer, span); + let path = Path::from_ident(outer_ident); + let attr_args = AttrArgs::Delimited(DelimArgs { + dspan: DelimSpan::from_single(span), + delim: MacDelimiter::Parenthesis, + tokens: inner_tokens, + }); + mk_attr(g, style, path, attr_args, span) } pub fn mk_doc_comment( @@ -439,23 +457,6 @@ pub fn list_contains_name(items: &[NestedMetaItem], name: Symbol) -> bool { } impl MetaItem { - fn token_trees(&self) -> Vec<TokenTree> { - let mut idents = vec![]; - let mut last_pos = BytePos(0_u32); - for (i, segment) in self.path.segments.iter().enumerate() { - let is_first = i == 0; - if !is_first { - let mod_sep_span = - Span::new(last_pos, segment.ident.span.lo(), segment.ident.span.ctxt(), None); - idents.push(TokenTree::token_alone(token::ModSep, mod_sep_span)); - } - idents.push(TokenTree::Token(Token::from_ast_ident(segment.ident), Spacing::Alone)); - last_pos = segment.ident.span.hi(); - } - idents.extend(self.kind.token_trees(self.span)); - idents - } - fn from_tokens<I>(tokens: &mut iter::Peekable<I>) -> Option<MetaItem> where I: Iterator<Item = TokenTree>, @@ -471,12 +472,12 @@ impl MetaItem { tokens.peek() { tokens.next(); - vec![PathSegment::from_ident(Ident::new(name, span))] + thin_vec![PathSegment::from_ident(Ident::new(name, span))] } else { break 'arm Path::from_ident(Ident::new(name, span)); } } else { - vec![PathSegment::path_root(span)] + thin_vec![PathSegment::path_root(span)] }; loop { if let Some(TokenTree::Token(Token { kind: token::Ident(name, _), span }, _)) = @@ -497,17 +498,17 @@ impl MetaItem { let span = span.with_hi(segments.last().unwrap().ident.span.hi()); Path { span, segments, tokens: None } } - Some(TokenTree::Token(Token { kind: token::Interpolated(nt), .. }, _)) => match *nt { - token::Nonterminal::NtMeta(ref item) => return item.meta(item.path.span), - token::Nonterminal::NtPath(ref path) => (**path).clone(), + Some(TokenTree::Token(Token { kind: token::Interpolated(nt), .. }, _)) => match &*nt { + token::Nonterminal::NtMeta(item) => return item.meta(item.path.span), + token::Nonterminal::NtPath(path) => (**path).clone(), _ => return None, }, _ => return None, }; let list_closing_paren_pos = tokens.peek().map(|tt| tt.span().hi()); let kind = MetaItemKind::from_tokens(tokens)?; - let hi = match kind { - MetaItemKind::NameValue(ref lit) => lit.span.hi(), + let hi = match &kind { + MetaItemKind::NameValue(lit) => lit.span.hi(), MetaItemKind::List(..) => list_closing_paren_pos.unwrap_or(path.span.hi()), _ => path.span.hi(), }; @@ -519,70 +520,14 @@ impl MetaItem { impl MetaItemKind { pub fn value_str(&self) -> Option<Symbol> { match self { - MetaItemKind::NameValue(ref v) => match v.kind { - LitKind::Str(ref s, _) => Some(*s), + MetaItemKind::NameValue(v) => match v.kind { + LitKind::Str(s, _) => Some(s), _ => None, }, _ => None, } } - pub fn mac_args(&self, span: Span) -> MacArgs { - match self { - MetaItemKind::Word => MacArgs::Empty, - MetaItemKind::NameValue(lit) => { - let expr = P(ast::Expr { - id: ast::DUMMY_NODE_ID, - kind: ast::ExprKind::Lit(lit.clone()), - span: lit.span, - attrs: ast::AttrVec::new(), - tokens: None, - }); - MacArgs::Eq(span, MacArgsEq::Ast(expr)) - } - MetaItemKind::List(list) => { - let mut tts = Vec::new(); - for (i, item) in list.iter().enumerate() { - if i > 0 { - tts.push(TokenTree::token_alone(token::Comma, span)); - } - tts.extend(item.token_trees()) - } - MacArgs::Delimited( - DelimSpan::from_single(span), - MacDelimiter::Parenthesis, - TokenStream::new(tts), - ) - } - } - } - - fn token_trees(&self, span: Span) -> Vec<TokenTree> { - match *self { - MetaItemKind::Word => vec![], - MetaItemKind::NameValue(ref lit) => { - vec![ - TokenTree::token_alone(token::Eq, span), - TokenTree::Token(lit.to_token(), Spacing::Alone), - ] - } - MetaItemKind::List(ref list) => { - let mut tokens = Vec::new(); - for (i, item) in list.iter().enumerate() { - if i > 0 { - tokens.push(TokenTree::token_alone(token::Comma, span)); - } - tokens.extend(item.token_trees()) - } - vec![TokenTree::Delimited( - DelimSpan::from_single(span), - Delimiter::Parenthesis, - TokenStream::new(tokens), - )] - } - } - } - fn list_from_tokens(tokens: TokenStream) -> Option<MetaItemKind> { let mut tokens = tokens.into_trees().peekable(); let mut result = Vec::new(); @@ -605,24 +550,31 @@ impl MetaItemKind { MetaItemKind::name_value_from_tokens(&mut inner_tokens.into_trees()) } Some(TokenTree::Token(token, _)) => { - Lit::from_token(&token).ok().map(MetaItemKind::NameValue) + MetaItemLit::from_token(&token).map(MetaItemKind::NameValue) } _ => None, } } - fn from_mac_args(args: &MacArgs) -> Option<MetaItemKind> { + fn from_attr_args(args: &AttrArgs) -> Option<MetaItemKind> { match args { - MacArgs::Empty => Some(MetaItemKind::Word), - MacArgs::Delimited(_, MacDelimiter::Parenthesis, tokens) => { - MetaItemKind::list_from_tokens(tokens.clone()) - } - MacArgs::Delimited(..) => None, - MacArgs::Eq(_, MacArgsEq::Ast(expr)) => match &expr.kind { - ast::ExprKind::Lit(lit) => Some(MetaItemKind::NameValue(lit.clone())), + AttrArgs::Empty => Some(MetaItemKind::Word), + AttrArgs::Delimited(DelimArgs { + dspan: _, + delim: MacDelimiter::Parenthesis, + tokens, + }) => MetaItemKind::list_from_tokens(tokens.clone()), + AttrArgs::Delimited(..) => None, + AttrArgs::Eq(_, AttrArgsEq::Ast(expr)) => match expr.kind { + ExprKind::Lit(token_lit) => { + // Turn failures to `None`, we'll get parse errors elsewhere. + MetaItemLit::from_token_lit(token_lit, expr.span) + .ok() + .map(|lit| MetaItemKind::NameValue(lit)) + } _ => None, }, - MacArgs::Eq(_, MacArgsEq::Hir(lit)) => Some(MetaItemKind::NameValue(lit.clone())), + AttrArgs::Eq(_, AttrArgsEq::Hir(lit)) => Some(MetaItemKind::NameValue(lit.clone())), } } @@ -647,18 +599,9 @@ impl MetaItemKind { impl NestedMetaItem { pub fn span(&self) -> Span { - match *self { - NestedMetaItem::MetaItem(ref item) => item.span, - NestedMetaItem::Literal(ref lit) => lit.span, - } - } - - fn token_trees(&self) -> Vec<TokenTree> { - match *self { - NestedMetaItem::MetaItem(ref item) => item.token_trees(), - NestedMetaItem::Literal(ref lit) => { - vec![TokenTree::Token(lit.to_token(), Spacing::Alone)] - } + match self { + NestedMetaItem::MetaItem(item) => item.span, + NestedMetaItem::Lit(lit) => lit.span, } } @@ -668,10 +611,10 @@ impl NestedMetaItem { { match tokens.peek() { Some(TokenTree::Token(token, _)) - if let Ok(lit) = Lit::from_token(token) => + if let Some(lit) = MetaItemLit::from_token(token) => { tokens.next(); - return Some(NestedMetaItem::Literal(lit)); + return Some(NestedMetaItem::Lit(lit)); } Some(TokenTree::Delimited(_, Delimiter::Invisible, inner_tokens)) => { let inner_tokens = inner_tokens.clone(); diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs index eeb7e56e2..9c1dfeb1a 100644 --- a/compiler/rustc_ast/src/lib.rs +++ b/compiler/rustc_ast/src/lib.rs @@ -29,6 +29,7 @@ extern crate rustc_macros; extern crate tracing; pub mod util { + pub mod case; pub mod classify; pub mod comments; pub mod literal; diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index b970e57e0..a45ee6067 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -194,7 +194,7 @@ pub trait MutVisitor: Sized { noop_visit_path(p, self); } - fn visit_qself(&mut self, qs: &mut Option<QSelf>) { + fn visit_qself(&mut self, qs: &mut Option<P<QSelf>>) { noop_visit_qself(qs, self); } @@ -367,23 +367,27 @@ pub fn visit_fn_sig<T: MutVisitor>(FnSig { header, decl, span }: &mut FnSig, vis } // No `noop_` prefix because there isn't a corresponding method in `MutVisitor`. -pub fn visit_mac_args<T: MutVisitor>(args: &mut MacArgs, vis: &mut T) { +pub fn visit_attr_args<T: MutVisitor>(args: &mut AttrArgs, vis: &mut T) { match args { - MacArgs::Empty => {} - MacArgs::Delimited(dspan, _delim, tokens) => { - visit_delim_span(dspan, vis); - visit_tts(tokens, vis); - } - MacArgs::Eq(eq_span, MacArgsEq::Ast(expr)) => { + AttrArgs::Empty => {} + AttrArgs::Delimited(args) => visit_delim_args(args, vis), + AttrArgs::Eq(eq_span, AttrArgsEq::Ast(expr)) => { vis.visit_span(eq_span); vis.visit_expr(expr); } - MacArgs::Eq(_, MacArgsEq::Hir(lit)) => { + AttrArgs::Eq(_, AttrArgsEq::Hir(lit)) => { unreachable!("in literal form when visiting mac args eq: {:?}", lit) } } } +// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`. +pub fn visit_delim_args<T: MutVisitor>(args: &mut DelimArgs, vis: &mut T) { + let DelimArgs { dspan, delim: _, tokens } = args; + visit_delim_span(dspan, vis); + visit_tts(tokens, vis); +} + pub fn visit_delim_span<T: MutVisitor>(dspan: &mut DelimSpan, vis: &mut T) { vis.visit_span(&mut dspan.open); vis.visit_span(&mut dspan.close); @@ -406,11 +410,7 @@ pub fn noop_visit_use_tree<T: MutVisitor>(use_tree: &mut UseTree, vis: &mut T) { let UseTree { prefix, kind, span } = use_tree; vis.visit_path(prefix); match kind { - UseTreeKind::Simple(rename, id1, id2) => { - visit_opt(rename, |rename| vis.visit_ident(rename)); - vis.visit_id(id1); - vis.visit_id(id2); - } + UseTreeKind::Simple(rename) => visit_opt(rename, |rename| vis.visit_ident(rename)), UseTreeKind::Nested(items) => { for (tree, id) in items { vis.visit_use_tree(tree); @@ -439,15 +439,15 @@ pub fn noop_visit_constraint<T: MutVisitor>( ) { vis.visit_id(id); vis.visit_ident(ident); - if let Some(ref mut gen_args) = gen_args { + if let Some(gen_args) = gen_args { vis.visit_generic_args(gen_args); } match kind { - AssocConstraintKind::Equality { ref mut term } => match term { + AssocConstraintKind::Equality { term } => match term { Term::Ty(ty) => vis.visit_ty(ty), Term::Const(c) => vis.visit_anon_const(c), }, - AssocConstraintKind::Bound { ref mut bounds } => visit_bounds(bounds, vis), + AssocConstraintKind::Bound { bounds } => visit_bounds(bounds, vis), } vis.visit_span(span); } @@ -529,8 +529,9 @@ pub fn noop_visit_path<T: MutVisitor>(Path { segments, span, tokens }: &mut Path visit_lazy_tts(tokens, vis); } -pub fn noop_visit_qself<T: MutVisitor>(qself: &mut Option<QSelf>, vis: &mut T) { - visit_opt(qself, |QSelf { ty, path_span, position: _ }| { +pub fn noop_visit_qself<T: MutVisitor>(qself: &mut Option<P<QSelf>>, vis: &mut T) { + visit_opt(qself, |qself| { + let QSelf { ty, path_span, position: _ } = &mut **qself; vis.visit_ty(ty); vis.visit_span(path_span); }) @@ -600,7 +601,7 @@ pub fn noop_visit_attribute<T: MutVisitor>(attr: &mut Attribute, vis: &mut T) { let NormalAttr { item: AttrItem { path, args, tokens }, tokens: attr_tokens } = &mut **normal; vis.visit_path(path); - visit_mac_args(args, vis); + visit_attr_args(args, vis); visit_lazy_tts(tokens, vis); visit_lazy_tts(attr_tokens, vis); } @@ -612,18 +613,18 @@ pub fn noop_visit_attribute<T: MutVisitor>(attr: &mut Attribute, vis: &mut T) { pub fn noop_visit_mac<T: MutVisitor>(mac: &mut MacCall, vis: &mut T) { let MacCall { path, args, prior_type_ascription: _ } = mac; vis.visit_path(path); - visit_mac_args(args, vis); + visit_delim_args(args, vis); } pub fn noop_visit_macro_def<T: MutVisitor>(macro_def: &mut MacroDef, vis: &mut T) { let MacroDef { body, macro_rules: _ } = macro_def; - visit_mac_args(body, vis); + visit_delim_args(body, vis); } pub fn noop_visit_meta_list_item<T: MutVisitor>(li: &mut NestedMetaItem, vis: &mut T) { match li { NestedMetaItem::MetaItem(mi) => vis.visit_meta_item(mi), - NestedMetaItem::Literal(_lit) => {} + NestedMetaItem::Lit(_lit) => {} } } @@ -720,10 +721,10 @@ pub fn visit_lazy_tts<T: MutVisitor>(lazy_tts: &mut Option<LazyAttrTokenStream>, visit_lazy_tts_opt_mut(lazy_tts.as_mut(), vis); } +/// Applies ident visitor if it's an ident; applies other visits to interpolated nodes. +/// In practice the ident part is not actually used by specific visitors right now, +/// but there's a test below checking that it works. // No `noop_` prefix because there isn't a corresponding method in `MutVisitor`. -// Applies ident visitor if it's an ident; applies other visits to interpolated nodes. -// In practice the ident part is not actually used by specific visitors right now, -// but there's a test below checking that it works. pub fn visit_token<T: MutVisitor>(t: &mut Token, vis: &mut T) { let Token { kind, span } = t; match kind { @@ -735,8 +736,7 @@ pub fn visit_token<T: MutVisitor>(t: &mut Token, vis: &mut T) { return; // Avoid visiting the span for the second time. } token::Interpolated(nt) => { - let mut nt = Lrc::make_mut(nt); - visit_nonterminal(&mut nt, vis); + visit_nonterminal(Lrc::make_mut(nt), vis); } _ => {} } @@ -791,7 +791,7 @@ pub fn visit_nonterminal<T: MutVisitor>(nt: &mut token::Nonterminal, vis: &mut T token::NtMeta(item) => { let AttrItem { path, args, tokens } = item.deref_mut(); vis.visit_path(path); - visit_mac_args(args, vis); + visit_attr_args(args, vis); visit_lazy_tts(tokens, vis); } token::NtPath(path) => vis.visit_path(path), @@ -879,7 +879,7 @@ pub fn noop_flat_map_generic_param<T: MutVisitor>( let GenericParam { id, ident, attrs, bounds, kind, colon_span, is_placeholder: _ } = &mut param; vis.visit_id(id); vis.visit_ident(ident); - if let Some(ref mut colon_span) = colon_span { + if let Some(colon_span) = colon_span { vis.visit_span(colon_span); } visit_attrs(attrs, vis); @@ -1303,12 +1303,17 @@ pub fn noop_visit_expr<T: MutVisitor>( vis.visit_expr(f); visit_exprs(args, vis); } - ExprKind::MethodCall(PathSegment { ident, id, args }, receiver, exprs, span) => { + ExprKind::MethodCall(box MethodCall { + seg: PathSegment { ident, id, args: seg_args }, + receiver, + args: call_args, + span, + }) => { vis.visit_ident(ident); vis.visit_id(id); - visit_opt(args, |args| vis.visit_generic_args(args)); + visit_opt(seg_args, |args| vis.visit_generic_args(args)); vis.visit_method_receiver_expr(receiver); - visit_exprs(exprs, vis); + visit_exprs(call_args, vis); vis.visit_span(span); } ExprKind::Binary(_binop, lhs, rhs) => { @@ -1345,20 +1350,30 @@ pub fn noop_visit_expr<T: MutVisitor>( vis.visit_block(body); visit_opt(label, |label| vis.visit_label(label)); } - ExprKind::Loop(body, label) => { + ExprKind::Loop(body, label, span) => { vis.visit_block(body); visit_opt(label, |label| vis.visit_label(label)); + vis.visit_span(span); } ExprKind::Match(expr, arms) => { vis.visit_expr(expr); arms.flat_map_in_place(|arm| vis.flat_map_arm(arm)); } - ExprKind::Closure(binder, _capture_by, asyncness, _movability, decl, body, span) => { + ExprKind::Closure(box Closure { + binder, + capture_clause: _, + asyncness, + movability: _, + fn_decl, + body, + fn_decl_span, + fn_arg_span: _, + }) => { vis.visit_closure_binder(binder); vis.visit_asyncness(asyncness); - vis.visit_fn_decl(decl); + vis.visit_fn_decl(fn_decl); vis.visit_expr(body); - vis.visit_span(span); + vis.visit_span(fn_decl_span); } ExprKind::Block(blk, label) => { vis.visit_block(blk); @@ -1428,7 +1443,7 @@ pub fn noop_visit_expr<T: MutVisitor>( } ExprKind::Try(expr) => vis.visit_expr(expr), ExprKind::TryBlock(body) => vis.visit_block(body), - ExprKind::Lit(_) | ExprKind::Err => {} + ExprKind::Lit(_) | ExprKind::IncludedBytes(..) | ExprKind::Err => {} } vis.visit_id(id); vis.visit_span(span); diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 83b10d906..c0cc4e79a 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -5,6 +5,7 @@ pub use TokenKind::*; use crate::ast; use crate::ptr::P; +use crate::util::case::Case; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::Lrc; @@ -58,13 +59,17 @@ pub enum Delimiter { Invisible, } +// Note that the suffix is *not* considered when deciding the `LitKind` in this +// type. This means that float literals like `1f32` are classified by this type +// as `Int`. Only upon conversion to `ast::LitKind` will such a literal be +// given the `Float` kind. #[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)] pub enum LitKind { Bool, // AST only, must never appear in a `Token` Byte, Char, - Integer, - Float, + Integer, // e.g. `1`, `1u8`, `1f32` + Float, // e.g. `1.`, `1.0`, `1e3f32` Str, StrRaw(u8), // raw string delimited by `n` hash symbols ByteStr, @@ -80,6 +85,42 @@ pub struct Lit { pub suffix: Option<Symbol>, } +impl Lit { + pub fn new(kind: LitKind, symbol: Symbol, suffix: Option<Symbol>) -> Lit { + Lit { kind, symbol, suffix } + } + + /// Returns `true` if this is semantically a float literal. This includes + /// ones like `1f32` that have an `Integer` kind but a float suffix. + pub fn is_semantic_float(&self) -> bool { + match self.kind { + LitKind::Float => true, + LitKind::Integer => match self.suffix { + Some(sym) => sym == sym::f32 || sym == sym::f64, + None => false, + }, + _ => false, + } + } + + /// Keep this in sync with `Token::can_begin_literal_or_bool` excluding unary negation. + pub fn from_token(token: &Token) -> Option<Lit> { + match token.uninterpolate().kind { + Ident(name, false) if name.is_bool_lit() => { + Some(Lit::new(Bool, name, None)) + } + Literal(token_lit) => Some(token_lit), + Interpolated(ref nt) + if let NtExpr(expr) | NtLiteral(expr) = &**nt + && let ast::ExprKind::Lit(token_lit) = expr.kind => + { + Some(token_lit.clone()) + } + _ => None, + } + } +} + impl fmt::Display for Lit { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let Lit { kind, symbol, suffix } = *self; @@ -138,12 +179,6 @@ impl LitKind { } } -impl Lit { - pub fn new(kind: LitKind, symbol: Symbol, suffix: Option<Symbol>) -> Lit { - Lit { kind, symbol, suffix } - } -} - pub fn ident_can_begin_expr(name: Symbol, span: Span, is_raw: bool) -> bool { let ident_token = Token::new(Ident(name, is_raw), span); @@ -267,9 +302,9 @@ impl TokenKind { Literal(Lit::new(kind, symbol, suffix)) } - // An approximation to proc-macro-style single-character operators used by rustc parser. - // If the operator token can be broken into two tokens, the first of which is single-character, - // then this function performs that operation, otherwise it returns `None`. + /// An approximation to proc-macro-style single-character operators used by rustc parser. + /// If the operator token can be broken into two tokens, the first of which is single-character, + /// then this function performs that operation, otherwise it returns `None`. pub fn break_two_token_op(&self) -> Option<(TokenKind, TokenKind)> { Some(match *self { Le => (Lt, Eq), @@ -503,10 +538,10 @@ impl Token { } } - // A convenience function for matching on identifiers during parsing. - // Turns interpolated identifier (`$i: ident`) or lifetime (`$l: lifetime`) token - // into the regular identifier or lifetime token it refers to, - // otherwise returns the original token. + /// A convenience function for matching on identifiers during parsing. + /// Turns interpolated identifier (`$i: ident`) or lifetime (`$l: lifetime`) token + /// into the regular identifier or lifetime token it refers to, + /// otherwise returns the original token. pub fn uninterpolate(&self) -> Cow<'_, Token> { match &self.kind { Interpolated(nt) => match **nt { @@ -566,9 +601,10 @@ impl Token { /// Returns `true` if the token is an interpolated path. fn is_path(&self) -> bool { - if let Interpolated(ref nt) = self.kind && let NtPath(..) = **nt { + if let Interpolated(nt) = &self.kind && let NtPath(..) = **nt { return true; } + false } @@ -576,7 +612,7 @@ impl Token { /// That is, is this a pre-parsed expression dropped into the token stream /// (which happens while parsing the result of macro expansion)? pub fn is_whole_expr(&self) -> bool { - if let Interpolated(ref nt) = self.kind + if let Interpolated(nt) = &self.kind && let NtExpr(_) | NtLiteral(_) | NtPath(_) | NtBlock(_) = **nt { return true; @@ -585,11 +621,12 @@ impl Token { false } - // Is the token an interpolated block (`$b:block`)? + /// Is the token an interpolated block (`$b:block`)? pub fn is_whole_block(&self) -> bool { - if let Interpolated(ref nt) = self.kind && let NtBlock(..) = **nt { + if let Interpolated(nt) = &self.kind && let NtBlock(..) = **nt { return true; } + false } @@ -615,12 +652,21 @@ impl Token { self.is_non_raw_ident_where(|id| id.name == kw) } + /// Returns `true` if the token is a given keyword, `kw` or if `case` is `Insensitive` and this token is an identifier equal to `kw` ignoring the case. + pub fn is_keyword_case(&self, kw: Symbol, case: Case) -> bool { + self.is_keyword(kw) + || (case == Case::Insensitive + && self.is_non_raw_ident_where(|id| { + id.name.as_str().to_lowercase() == kw.as_str().to_lowercase() + })) + } + pub fn is_path_segment_keyword(&self) -> bool { self.is_non_raw_ident_where(Ident::is_path_segment_keyword) } - // Returns true for reserved identifiers used internally for elided lifetimes, - // unnamed method parameters, crate root module, error recovery etc. + /// Returns true for reserved identifiers used internally for elided lifetimes, + /// unnamed method parameters, crate root module, error recovery etc. pub fn is_special_ident(&self) -> bool { self.is_non_raw_ident_where(Ident::is_special) } diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs index 015f5c1ee..482c30295 100644 --- a/compiler/rustc_ast/src/tokenstream.rs +++ b/compiler/rustc_ast/src/tokenstream.rs @@ -64,7 +64,7 @@ impl TokenTree { match (self, other) { (TokenTree::Token(token, _), TokenTree::Token(token2, _)) => token.kind == token2.kind, (TokenTree::Delimited(_, delim, tts), TokenTree::Delimited(_, delim2, tts2)) => { - delim == delim2 && tts.eq_unspanned(&tts2) + delim == delim2 && tts.eq_unspanned(tts2) } _ => false, } @@ -86,12 +86,12 @@ impl TokenTree { } } - // Create a `TokenTree::Token` with alone spacing. + /// Create a `TokenTree::Token` with alone spacing. pub fn token_alone(kind: TokenKind, span: Span) -> TokenTree { TokenTree::Token(Token::new(kind, span), Spacing::Alone) } - // Create a `TokenTree::Token` with joint spacing. + /// Create a `TokenTree::Token` with joint spacing. pub fn token_joint(kind: TokenKind, span: Span) -> TokenTree { TokenTree::Token(Token::new(kind, span), Spacing::Joint) } @@ -402,7 +402,7 @@ impl TokenStream { let mut t1 = self.trees(); let mut t2 = other.trees(); for (t1, t2) in iter::zip(&mut t1, &mut t2) { - if !t1.eq_unspanned(&t2) { + if !t1.eq_unspanned(t2) { return false; } } @@ -413,17 +413,17 @@ impl TokenStream { TokenStream(Lrc::new(self.0.iter().enumerate().map(|(i, tree)| f(i, tree)).collect())) } - // Create a token stream containing a single token with alone spacing. + /// Create a token stream containing a single token with alone spacing. pub fn token_alone(kind: TokenKind, span: Span) -> TokenStream { TokenStream::new(vec![TokenTree::token_alone(kind, span)]) } - // Create a token stream containing a single token with joint spacing. + /// Create a token stream containing a single token with joint spacing. pub fn token_joint(kind: TokenKind, span: Span) -> TokenStream { TokenStream::new(vec![TokenTree::token_joint(kind, span)]) } - // Create a token stream containing a single `Delimited`. + /// Create a token stream containing a single `Delimited`. pub fn delimited(span: DelimSpan, delim: Delimiter, tts: TokenStream) -> TokenStream { TokenStream::new(vec![TokenTree::Delimited(span, delim, tts)]) } @@ -475,7 +475,7 @@ impl TokenStream { token::Interpolated(nt) => TokenTree::Delimited( DelimSpan::from_single(token.span), Delimiter::Invisible, - TokenStream::from_nonterminal_ast(&nt).flattened(), + TokenStream::from_nonterminal_ast(nt).flattened(), ), _ => TokenTree::Token(token.clone(), spacing), } @@ -511,7 +511,7 @@ impl TokenStream { fn try_glue_to_last(vec: &mut Vec<TokenTree>, tt: &TokenTree) -> bool { if let Some(TokenTree::Token(last_tok, Spacing::Joint)) = vec.last() && let TokenTree::Token(tok, spacing) = tt - && let Some(glued_tok) = last_tok.glue(&tok) + && let Some(glued_tok) = last_tok.glue(tok) { // ...then overwrite the last token tree in `vec` with the // glued token, and skip the first token tree from `stream`. @@ -522,8 +522,8 @@ impl TokenStream { } } - // Push `tt` onto the end of the stream, possibly gluing it to the last - // token. Uses `make_mut` to maximize efficiency. + /// Push `tt` onto the end of the stream, possibly gluing it to the last + /// token. Uses `make_mut` to maximize efficiency. pub fn push_tree(&mut self, tt: TokenTree) { let vec_mut = Lrc::make_mut(&mut self.0); @@ -534,9 +534,9 @@ impl TokenStream { } } - // Push `stream` onto the end of the stream, possibly gluing the first - // token tree to the last token. (No other token trees will be glued.) - // Uses `make_mut` to maximize efficiency. + /// Push `stream` onto the end of the stream, possibly gluing the first + /// token tree to the last token. (No other token trees will be glued.) + /// Uses `make_mut` to maximize efficiency. pub fn push_stream(&mut self, stream: TokenStream) { let vec_mut = Lrc::make_mut(&mut self.0); diff --git a/compiler/rustc_ast/src/util/case.rs b/compiler/rustc_ast/src/util/case.rs new file mode 100644 index 000000000..1afd7dea7 --- /dev/null +++ b/compiler/rustc_ast/src/util/case.rs @@ -0,0 +1,6 @@ +/// Whatever to ignore case (`fn` vs `Fn` vs `FN`) or not. Used for recovering. +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub enum Case { + Sensitive, + Insensitive, +} diff --git a/compiler/rustc_ast/src/util/classify.rs b/compiler/rustc_ast/src/util/classify.rs index 6ea3db6d3..cdc244c12 100644 --- a/compiler/rustc_ast/src/util/classify.rs +++ b/compiler/rustc_ast/src/util/classify.rs @@ -21,6 +21,7 @@ pub fn expr_requires_semi_to_be_stmt(e: &ast::Expr) -> bool { | ast::ExprKind::Loop(..) | ast::ExprKind::ForLoop(..) | ast::ExprKind::TryBlock(..) + | ast::ExprKind::ConstBlock(..) ) } @@ -36,7 +37,6 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<&ast::Expr> { | Binary(_, _, e) | Box(e) | Break(_, Some(e)) - | Closure(.., e, _) | Let(_, e, _) | Range(_, Some(e), _) | Ret(Some(e)) @@ -44,6 +44,9 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<&ast::Expr> { | Yield(Some(e)) => { expr = e; } + Closure(closure) => { + expr = &closure.body; + } Async(..) | Block(..) | ForLoop(..) | If(..) | Loop(..) | Match(..) | Struct(..) | TryBlock(..) | While(..) => break Some(expr), _ => break None, diff --git a/compiler/rustc_ast/src/util/comments.rs b/compiler/rustc_ast/src/util/comments.rs index c96474ccb..35454c3a6 100644 --- a/compiler/rustc_ast/src/util/comments.rs +++ b/compiler/rustc_ast/src/util/comments.rs @@ -110,7 +110,7 @@ pub fn beautify_doc_string(data: Symbol, kind: CommentKind) -> Symbol { } else { &mut lines }; - if let Some(horizontal) = get_horizontal_trim(&lines, kind) { + if let Some(horizontal) = get_horizontal_trim(lines, kind) { changes = true; // remove a "[ \t]*\*" block from each line, if possible for line in lines.iter_mut() { @@ -147,7 +147,7 @@ fn all_whitespace(s: &str, col: CharPos) -> Option<usize> { fn trim_whitespace_prefix(s: &str, col: CharPos) -> &str { let len = s.len(); - match all_whitespace(&s, col) { + match all_whitespace(s, col) { Some(col) => { if col < len { &s[col..] diff --git a/compiler/rustc_ast/src/util/literal.rs b/compiler/rustc_ast/src/util/literal.rs index 536b38560..f6f186b51 100644 --- a/compiler/rustc_ast/src/util/literal.rs +++ b/compiler/rustc_ast/src/util/literal.rs @@ -1,17 +1,14 @@ //! Code related to parsing literals. -use crate::ast::{self, Lit, LitKind}; +use crate::ast::{self, LitKind, MetaItemLit}; use crate::token::{self, Token}; - -use rustc_lexer::unescape::{unescape_byte, unescape_char}; -use rustc_lexer::unescape::{unescape_byte_literal, unescape_literal, Mode}; +use rustc_lexer::unescape::{byte_from_char, unescape_byte, unescape_char, unescape_literal, Mode}; use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::Span; - use std::ascii; +#[derive(Debug)] pub enum LitError { - NotLiteral, LexerError, InvalidSuffix, InvalidIntSuffix, @@ -55,14 +52,14 @@ impl LitKind { // new symbol because the string in the LitKind is different to the // string in the token. let s = symbol.as_str(); - let symbol = if s.contains(&['\\', '\r']) { + let symbol = if s.contains(['\\', '\r']) { let mut buf = String::with_capacity(s.len()); let mut error = Ok(()); // Force-inlining here is aggressive but the closure is // called on every char in the string, so it can be // hot in programs with many long strings. unescape_literal( - &s, + s, Mode::Str, &mut #[inline(always)] |_, unescaped_char| match unescaped_char { @@ -88,7 +85,7 @@ impl LitKind { if s.contains('\r') { let mut buf = String::with_capacity(s.len()); let mut error = Ok(()); - unescape_literal(&s, Mode::RawStr, &mut |_, unescaped_char| { + unescape_literal(s, Mode::RawStr, &mut |_, unescaped_char| { match unescaped_char { Ok(c) => buf.push(c), Err(err) => { @@ -109,13 +106,11 @@ impl LitKind { let s = symbol.as_str(); let mut buf = Vec::with_capacity(s.len()); let mut error = Ok(()); - unescape_byte_literal(&s, Mode::ByteStr, &mut |_, unescaped_byte| { - match unescaped_byte { - Ok(c) => buf.push(c), - Err(err) => { - if err.is_fatal() { - error = Err(LitError::LexerError); - } + unescape_literal(s, Mode::ByteStr, &mut |_, c| match c { + Ok(c) => buf.push(byte_from_char(c)), + Err(err) => { + if err.is_fatal() { + error = Err(LitError::LexerError); } } }); @@ -127,13 +122,11 @@ impl LitKind { let bytes = if s.contains('\r') { let mut buf = Vec::with_capacity(s.len()); let mut error = Ok(()); - unescape_byte_literal(&s, Mode::RawByteStr, &mut |_, unescaped_byte| { - match unescaped_byte { - Ok(c) => buf.push(c), - Err(err) => { - if err.is_fatal() { - error = Err(LitError::LexerError); - } + unescape_literal(s, Mode::RawByteStr, &mut |_, c| match c { + Ok(c) => buf.push(byte_from_char(c)), + Err(err) => { + if err.is_fatal() { + error = Err(LitError::LexerError); } } }); @@ -202,49 +195,16 @@ impl LitKind { } } -impl Lit { - /// Converts literal token into an AST literal. - pub fn from_token_lit(token_lit: token::Lit, span: Span) -> Result<Lit, LitError> { - Ok(Lit { token_lit, kind: LitKind::from_token_lit(token_lit)?, span }) - } - - /// Converts arbitrary token into an AST literal. - /// - /// Keep this in sync with `Token::can_begin_literal_or_bool` excluding unary negation. - pub fn from_token(token: &Token) -> Result<Lit, LitError> { - let lit = match token.uninterpolate().kind { - token::Ident(name, false) if name.is_bool_lit() => { - token::Lit::new(token::Bool, name, None) - } - token::Literal(lit) => lit, - token::Interpolated(ref nt) => { - if let token::NtExpr(expr) | token::NtLiteral(expr) = &**nt - && let ast::ExprKind::Lit(lit) = &expr.kind - { - return Ok(lit.clone()); - } - return Err(LitError::NotLiteral); - } - _ => return Err(LitError::NotLiteral), - }; - - Lit::from_token_lit(lit, token.span) - } - - /// Attempts to recover an AST literal from semantic literal. - /// This function is used when the original token doesn't exist (e.g. the literal is created - /// by an AST-based macro) or unavailable (e.g. from HIR pretty-printing). - pub fn from_lit_kind(kind: LitKind, span: Span) -> Lit { - Lit { token_lit: kind.to_token_lit(), kind, span } +impl MetaItemLit { + /// Converts token literal into a meta item literal. + pub fn from_token_lit(token_lit: token::Lit, span: Span) -> Result<MetaItemLit, LitError> { + Ok(MetaItemLit { token_lit, kind: LitKind::from_token_lit(token_lit)?, span }) } - /// Losslessly convert an AST literal into a token. - pub fn to_token(&self) -> Token { - let kind = match self.token_lit.kind { - token::Bool => token::Ident(self.token_lit.symbol, false), - _ => token::Literal(self.token_lit), - }; - Token::new(kind, self.span) + /// Converts an arbitrary token into meta item literal. + pub fn from_token(token: &Token) -> Option<MetaItemLit> { + token::Lit::from_token(token) + .and_then(|token_lit| MetaItemLit::from_token_lit(token_lit, token.span).ok()) } } diff --git a/compiler/rustc_ast/src/util/parser.rs b/compiler/rustc_ast/src/util/parser.rs index b40ad6f70..819f1884a 100644 --- a/compiler/rustc_ast/src/util/parser.rs +++ b/compiler/rustc_ast/src/util/parser.rs @@ -377,28 +377,28 @@ pub fn needs_par_as_let_scrutinee(order: i8) -> bool { /// parens or other delimiters, e.g., `X { y: 1 }`, `X { y: 1 }.method()`, `foo == X { y: 1 }` and /// `X { y: 1 } == foo` all do, but `(X { y: 1 }) == foo` does not. pub fn contains_exterior_struct_lit(value: &ast::Expr) -> bool { - match value.kind { + match &value.kind { ast::ExprKind::Struct(..) => true, - ast::ExprKind::Assign(ref lhs, ref rhs, _) - | ast::ExprKind::AssignOp(_, ref lhs, ref rhs) - | ast::ExprKind::Binary(_, ref lhs, ref rhs) => { + ast::ExprKind::Assign(lhs, rhs, _) + | ast::ExprKind::AssignOp(_, lhs, rhs) + | ast::ExprKind::Binary(_, lhs, rhs) => { // X { y: 1 } + X { y: 2 } - contains_exterior_struct_lit(&lhs) || contains_exterior_struct_lit(&rhs) + contains_exterior_struct_lit(lhs) || contains_exterior_struct_lit(rhs) } - ast::ExprKind::Await(ref x) - | ast::ExprKind::Unary(_, ref x) - | ast::ExprKind::Cast(ref x, _) - | ast::ExprKind::Type(ref x, _) - | ast::ExprKind::Field(ref x, _) - | ast::ExprKind::Index(ref x, _) => { + ast::ExprKind::Await(x) + | ast::ExprKind::Unary(_, x) + | ast::ExprKind::Cast(x, _) + | ast::ExprKind::Type(x, _) + | ast::ExprKind::Field(x, _) + | ast::ExprKind::Index(x, _) => { // &X { y: 1 }, X { y: 1 }.y - contains_exterior_struct_lit(&x) + contains_exterior_struct_lit(x) } - ast::ExprKind::MethodCall(_, ref receiver, _, _) => { + ast::ExprKind::MethodCall(box ast::MethodCall { receiver, .. }) => { // X { y: 1 }.bar(...) - contains_exterior_struct_lit(&receiver) + contains_exterior_struct_lit(receiver) } _ => false, diff --git a/compiler/rustc_ast/src/util/unicode.rs b/compiler/rustc_ast/src/util/unicode.rs index f009f7b30..0eae791b2 100644 --- a/compiler/rustc_ast/src/util/unicode.rs +++ b/compiler/rustc_ast/src/util/unicode.rs @@ -17,7 +17,7 @@ pub fn contains_text_flow_control_chars(s: &str) -> bool { // U+2069 - E2 81 A9 let mut bytes = s.as_bytes(); loop { - match core::slice::memchr::memchr(0xE2, &bytes) { + match core::slice::memchr::memchr(0xE2, bytes) { Some(idx) => { // bytes are valid UTF-8 -> E2 must be followed by two bytes let ch = &bytes[idx..idx + 3]; diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 6f56c1ef0..991eb489f 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -251,7 +251,7 @@ pub trait Visitor<'ast>: Sized { macro_rules! walk_list { ($visitor: expr, $method: ident, $list: expr $(, $($extra_args: expr),* )?) => { { - #[cfg_attr(not(bootstrap), allow(for_loops_over_fallibles))] + #[allow(for_loops_over_fallibles)] for elem in $list { $visitor.$method(elem $(, $($extra_args,)* )?) } @@ -299,74 +299,68 @@ pub fn walk_trait_ref<'a, V: Visitor<'a>>(visitor: &mut V, trait_ref: &'a TraitR pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) { visitor.visit_vis(&item.vis); visitor.visit_ident(item.ident); - match item.kind { + match &item.kind { ItemKind::ExternCrate(_) => {} - ItemKind::Use(ref use_tree) => visitor.visit_use_tree(use_tree, item.id, false), - ItemKind::Static(ref typ, _, ref expr) | ItemKind::Const(_, ref typ, ref expr) => { + ItemKind::Use(use_tree) => visitor.visit_use_tree(use_tree, item.id, false), + ItemKind::Static(typ, _, expr) | ItemKind::Const(_, typ, expr) => { visitor.visit_ty(typ); walk_list!(visitor, visit_expr, expr); } - ItemKind::Fn(box Fn { defaultness: _, ref generics, ref sig, ref body }) => { + ItemKind::Fn(box Fn { defaultness: _, generics, sig, body }) => { let kind = FnKind::Fn(FnCtxt::Free, item.ident, sig, &item.vis, generics, body.as_deref()); visitor.visit_fn(kind, item.span, item.id) } - ItemKind::Mod(_unsafety, ref mod_kind) => match mod_kind { + ItemKind::Mod(_unsafety, mod_kind) => match mod_kind { ModKind::Loaded(items, _inline, _inner_span) => { walk_list!(visitor, visit_item, items) } ModKind::Unloaded => {} }, - ItemKind::ForeignMod(ref foreign_module) => { + ItemKind::ForeignMod(foreign_module) => { walk_list!(visitor, visit_foreign_item, &foreign_module.items); } - ItemKind::GlobalAsm(ref asm) => visitor.visit_inline_asm(asm), - ItemKind::TyAlias(box TyAlias { ref generics, ref bounds, ref ty, .. }) => { + ItemKind::GlobalAsm(asm) => visitor.visit_inline_asm(asm), + ItemKind::TyAlias(box TyAlias { generics, bounds, ty, .. }) => { visitor.visit_generics(generics); walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound); walk_list!(visitor, visit_ty, ty); } - ItemKind::Enum(ref enum_definition, ref generics) => { + ItemKind::Enum(enum_definition, generics) => { visitor.visit_generics(generics); visitor.visit_enum_def(enum_definition) } ItemKind::Impl(box Impl { defaultness: _, unsafety: _, - ref generics, + generics, constness: _, polarity: _, - ref of_trait, - ref self_ty, - ref items, + of_trait, + self_ty, + items, }) => { visitor.visit_generics(generics); walk_list!(visitor, visit_trait_ref, of_trait); visitor.visit_ty(self_ty); walk_list!(visitor, visit_assoc_item, items, AssocCtxt::Impl); } - ItemKind::Struct(ref struct_definition, ref generics) - | ItemKind::Union(ref struct_definition, ref generics) => { + ItemKind::Struct(struct_definition, generics) + | ItemKind::Union(struct_definition, generics) => { visitor.visit_generics(generics); visitor.visit_variant_data(struct_definition); } - ItemKind::Trait(box Trait { - unsafety: _, - is_auto: _, - ref generics, - ref bounds, - ref items, - }) => { + ItemKind::Trait(box Trait { unsafety: _, is_auto: _, generics, bounds, items }) => { visitor.visit_generics(generics); walk_list!(visitor, visit_param_bound, bounds, BoundKind::SuperTraits); walk_list!(visitor, visit_assoc_item, items, AssocCtxt::Trait); } - ItemKind::TraitAlias(ref generics, ref bounds) => { + ItemKind::TraitAlias(generics, bounds) => { visitor.visit_generics(generics); walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound); } - ItemKind::MacCall(ref mac) => visitor.visit_mac_call(mac), - ItemKind::MacroDef(ref ts) => visitor.visit_mac_def(ts, item.id), + ItemKind::MacCall(mac) => visitor.visit_mac_call(mac), + ItemKind::MacroDef(ts) => visitor.visit_mac_def(ts, item.id), } walk_list!(visitor, visit_attribute, &item.attrs); } @@ -399,39 +393,39 @@ pub fn walk_pat_field<'a, V: Visitor<'a>>(visitor: &mut V, fp: &'a PatField) { } pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) { - match typ.kind { - TyKind::Slice(ref ty) | TyKind::Paren(ref ty) => visitor.visit_ty(ty), - TyKind::Ptr(ref mutable_type) => visitor.visit_ty(&mutable_type.ty), - TyKind::Rptr(ref opt_lifetime, ref mutable_type) => { + match &typ.kind { + TyKind::Slice(ty) | TyKind::Paren(ty) => visitor.visit_ty(ty), + TyKind::Ptr(mutable_type) => visitor.visit_ty(&mutable_type.ty), + TyKind::Rptr(opt_lifetime, mutable_type) => { walk_list!(visitor, visit_lifetime, opt_lifetime, LifetimeCtxt::Rptr); visitor.visit_ty(&mutable_type.ty) } - TyKind::Tup(ref tuple_element_types) => { + TyKind::Tup(tuple_element_types) => { walk_list!(visitor, visit_ty, tuple_element_types); } - TyKind::BareFn(ref function_declaration) => { + TyKind::BareFn(function_declaration) => { walk_list!(visitor, visit_generic_param, &function_declaration.generic_params); walk_fn_decl(visitor, &function_declaration.decl); } - TyKind::Path(ref maybe_qself, ref path) => { - if let Some(ref qself) = *maybe_qself { + TyKind::Path(maybe_qself, path) => { + if let Some(qself) = maybe_qself { visitor.visit_ty(&qself.ty); } visitor.visit_path(path, typ.id); } - TyKind::Array(ref ty, ref length) => { + TyKind::Array(ty, length) => { visitor.visit_ty(ty); visitor.visit_anon_const(length) } - TyKind::TraitObject(ref bounds, ..) => { + TyKind::TraitObject(bounds, ..) => { walk_list!(visitor, visit_param_bound, bounds, BoundKind::TraitObject); } - TyKind::ImplTrait(_, ref bounds) => { + TyKind::ImplTrait(_, bounds) => { walk_list!(visitor, visit_param_bound, bounds, BoundKind::Impl); } - TyKind::Typeof(ref expression) => visitor.visit_anon_const(expression), + TyKind::Typeof(expression) => visitor.visit_anon_const(expression), TyKind::Infer | TyKind::ImplicitSelf | TyKind::Err => {} - TyKind::MacCall(ref mac) => visitor.visit_mac_call(mac), + TyKind::MacCall(mac) => visitor.visit_mac_call(mac), TyKind::Never | TyKind::CVarArgs => {} } } @@ -444,15 +438,15 @@ pub fn walk_path<'a, V: Visitor<'a>>(visitor: &mut V, path: &'a Path) { pub fn walk_use_tree<'a, V: Visitor<'a>>(visitor: &mut V, use_tree: &'a UseTree, id: NodeId) { visitor.visit_path(&use_tree.prefix, id); - match use_tree.kind { - UseTreeKind::Simple(rename, ..) => { + match &use_tree.kind { + UseTreeKind::Simple(rename) => { // The extra IDs are handled during HIR lowering. - if let Some(rename) = rename { + if let &Some(rename) = rename { visitor.visit_ident(rename); } } UseTreeKind::Glob => {} - UseTreeKind::Nested(ref use_trees) => { + UseTreeKind::Nested(use_trees) => { for &(ref nested_tree, nested_id) in use_trees { visitor.visit_use_tree(nested_tree, nested_id, true); } @@ -462,7 +456,7 @@ pub fn walk_use_tree<'a, V: Visitor<'a>>(visitor: &mut V, use_tree: &'a UseTree, pub fn walk_path_segment<'a, V: Visitor<'a>>(visitor: &mut V, segment: &'a PathSegment) { visitor.visit_ident(segment.ident); - if let Some(ref args) = segment.args { + if let Some(args) = &segment.args { visitor.visit_generic_args(args); } } @@ -471,8 +465,8 @@ pub fn walk_generic_args<'a, V>(visitor: &mut V, generic_args: &'a GenericArgs) where V: Visitor<'a>, { - match *generic_args { - GenericArgs::AngleBracketed(ref data) => { + match generic_args { + GenericArgs::AngleBracketed(data) => { for arg in &data.args { match arg { AngleBracketedArg::Arg(a) => visitor.visit_generic_arg(a), @@ -480,7 +474,7 @@ where } } } - GenericArgs::Parenthesized(ref data) => { + GenericArgs::Parenthesized(data) => { walk_list!(visitor, visit_ty, &data.inputs); walk_fn_ret_ty(visitor, &data.output); } @@ -500,64 +494,64 @@ where pub fn walk_assoc_constraint<'a, V: Visitor<'a>>(visitor: &mut V, constraint: &'a AssocConstraint) { visitor.visit_ident(constraint.ident); - if let Some(ref gen_args) = constraint.gen_args { + if let Some(gen_args) = &constraint.gen_args { visitor.visit_generic_args(gen_args); } - match constraint.kind { - AssocConstraintKind::Equality { ref term } => match term { + match &constraint.kind { + AssocConstraintKind::Equality { term } => match term { Term::Ty(ty) => visitor.visit_ty(ty), Term::Const(c) => visitor.visit_anon_const(c), }, - AssocConstraintKind::Bound { ref bounds } => { + AssocConstraintKind::Bound { bounds } => { walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound); } } } pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) { - match pattern.kind { - PatKind::TupleStruct(ref opt_qself, ref path, ref elems) => { - if let Some(ref qself) = *opt_qself { + match &pattern.kind { + PatKind::TupleStruct(opt_qself, path, elems) => { + if let Some(qself) = opt_qself { visitor.visit_ty(&qself.ty); } visitor.visit_path(path, pattern.id); walk_list!(visitor, visit_pat, elems); } - PatKind::Path(ref opt_qself, ref path) => { - if let Some(ref qself) = *opt_qself { + PatKind::Path(opt_qself, path) => { + if let Some(qself) = opt_qself { visitor.visit_ty(&qself.ty); } visitor.visit_path(path, pattern.id) } - PatKind::Struct(ref opt_qself, ref path, ref fields, _) => { - if let Some(ref qself) = *opt_qself { + PatKind::Struct(opt_qself, path, fields, _) => { + if let Some(qself) = opt_qself { visitor.visit_ty(&qself.ty); } visitor.visit_path(path, pattern.id); walk_list!(visitor, visit_pat_field, fields); } - PatKind::Box(ref subpattern) - | PatKind::Ref(ref subpattern, _) - | PatKind::Paren(ref subpattern) => visitor.visit_pat(subpattern), - PatKind::Ident(_, ident, ref optional_subpattern) => { - visitor.visit_ident(ident); + PatKind::Box(subpattern) | PatKind::Ref(subpattern, _) | PatKind::Paren(subpattern) => { + visitor.visit_pat(subpattern) + } + PatKind::Ident(_, ident, optional_subpattern) => { + visitor.visit_ident(*ident); walk_list!(visitor, visit_pat, optional_subpattern); } - PatKind::Lit(ref expression) => visitor.visit_expr(expression), - PatKind::Range(ref lower_bound, ref upper_bound, _) => { + PatKind::Lit(expression) => visitor.visit_expr(expression), + PatKind::Range(lower_bound, upper_bound, _) => { walk_list!(visitor, visit_expr, lower_bound); walk_list!(visitor, visit_expr, upper_bound); } PatKind::Wild | PatKind::Rest => {} - PatKind::Tuple(ref elems) | PatKind::Slice(ref elems) | PatKind::Or(ref elems) => { + PatKind::Tuple(elems) | PatKind::Slice(elems) | PatKind::Or(elems) => { walk_list!(visitor, visit_pat, elems); } - PatKind::MacCall(ref mac) => visitor.visit_mac_call(mac), + PatKind::MacCall(mac) => visitor.visit_mac_call(mac), } } pub fn walk_foreign_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a ForeignItem) { - let Item { id, span, ident, ref vis, ref attrs, ref kind, tokens: _ } = *item; + let &Item { id, span, ident, ref vis, ref attrs, ref kind, tokens: _ } = item; visitor.visit_vis(vis); visitor.visit_ident(ident); walk_list!(visitor, visit_attribute, attrs); @@ -566,7 +560,7 @@ pub fn walk_foreign_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a ForeignI visitor.visit_ty(ty); walk_list!(visitor, visit_expr, expr); } - ForeignItemKind::Fn(box Fn { defaultness: _, ref generics, ref sig, ref body }) => { + ForeignItemKind::Fn(box Fn { defaultness: _, generics, sig, body }) => { let kind = FnKind::Fn(FnCtxt::Foreign, ident, sig, vis, generics, body.as_deref()); visitor.visit_fn(kind, span, id); } @@ -582,11 +576,9 @@ pub fn walk_foreign_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a ForeignI } pub fn walk_param_bound<'a, V: Visitor<'a>>(visitor: &mut V, bound: &'a GenericBound) { - match *bound { - GenericBound::Trait(ref typ, ref _modifier) => visitor.visit_poly_trait_ref(typ), - GenericBound::Outlives(ref lifetime) => { - visitor.visit_lifetime(lifetime, LifetimeCtxt::Bound) - } + match bound { + GenericBound::Trait(typ, _modifier) => visitor.visit_poly_trait_ref(typ), + GenericBound::Outlives(lifetime) => visitor.visit_lifetime(lifetime, LifetimeCtxt::Bound), } } @@ -594,10 +586,10 @@ pub fn walk_generic_param<'a, V: Visitor<'a>>(visitor: &mut V, param: &'a Generi visitor.visit_ident(param.ident); walk_list!(visitor, visit_attribute, param.attrs.iter()); walk_list!(visitor, visit_param_bound, ¶m.bounds, BoundKind::Bound); - match param.kind { + match ¶m.kind { GenericParamKind::Lifetime => (), - GenericParamKind::Type { ref default } => walk_list!(visitor, visit_ty, default), - GenericParamKind::Const { ref ty, ref default, .. } => { + GenericParamKind::Type { default } => walk_list!(visitor, visit_ty, default), + GenericParamKind::Const { ty, default, .. } => { visitor.visit_ty(ty); if let Some(default) = default { visitor.visit_anon_const(default); @@ -621,24 +613,22 @@ pub fn walk_closure_binder<'a, V: Visitor<'a>>(visitor: &mut V, binder: &'a Clos } pub fn walk_where_predicate<'a, V: Visitor<'a>>(visitor: &mut V, predicate: &'a WherePredicate) { - match *predicate { + match predicate { WherePredicate::BoundPredicate(WhereBoundPredicate { - ref bounded_ty, - ref bounds, - ref bound_generic_params, + bounded_ty, + bounds, + bound_generic_params, .. }) => { visitor.visit_ty(bounded_ty); walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound); walk_list!(visitor, visit_generic_param, bound_generic_params); } - WherePredicate::RegionPredicate(WhereRegionPredicate { - ref lifetime, ref bounds, .. - }) => { + WherePredicate::RegionPredicate(WhereRegionPredicate { lifetime, bounds, .. }) => { visitor.visit_lifetime(lifetime, LifetimeCtxt::Bound); walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound); } - WherePredicate::EqPredicate(WhereEqPredicate { ref lhs_ty, ref rhs_ty, .. }) => { + WherePredicate::EqPredicate(WhereEqPredicate { lhs_ty, rhs_ty, .. }) => { visitor.visit_ty(lhs_ty); visitor.visit_ty(rhs_ty); } @@ -646,7 +636,7 @@ pub fn walk_where_predicate<'a, V: Visitor<'a>>(visitor: &mut V, predicate: &'a } pub fn walk_fn_ret_ty<'a, V: Visitor<'a>>(visitor: &mut V, ret_ty: &'a FnRetTy) { - if let FnRetTy::Ty(ref output_ty) = *ret_ty { + if let FnRetTy::Ty(output_ty) = ret_ty { visitor.visit_ty(output_ty) } } @@ -675,7 +665,7 @@ pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>) { } pub fn walk_assoc_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem, ctxt: AssocCtxt) { - let Item { id, span, ident, ref vis, ref attrs, ref kind, tokens: _ } = *item; + let &Item { id, span, ident, ref vis, ref attrs, ref kind, tokens: _ } = item; visitor.visit_vis(vis); visitor.visit_ident(ident); walk_list!(visitor, visit_attribute, attrs); @@ -684,7 +674,7 @@ pub fn walk_assoc_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem, visitor.visit_ty(ty); walk_list!(visitor, visit_expr, expr); } - AssocItemKind::Fn(box Fn { defaultness: _, ref generics, ref sig, ref body }) => { + AssocItemKind::Fn(box Fn { defaultness: _, generics, sig, body }) => { let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), ident, sig, vis, generics, body.as_deref()); visitor.visit_fn(kind, span, id); } @@ -717,13 +707,13 @@ pub fn walk_block<'a, V: Visitor<'a>>(visitor: &mut V, block: &'a Block) { } pub fn walk_stmt<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Stmt) { - match statement.kind { - StmtKind::Local(ref local) => visitor.visit_local(local), - StmtKind::Item(ref item) => visitor.visit_item(item), - StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => visitor.visit_expr(expr), + match &statement.kind { + StmtKind::Local(local) => visitor.visit_local(local), + StmtKind::Item(item) => visitor.visit_item(item), + StmtKind::Expr(expr) | StmtKind::Semi(expr) => visitor.visit_expr(expr), StmtKind::Empty => {} - StmtKind::MacCall(ref mac) => { - let MacCallStmt { ref mac, style: _, ref attrs, tokens: _ } = **mac; + StmtKind::MacCall(mac) => { + let MacCallStmt { mac, attrs, style: _, tokens: _ } = &**mac; visitor.visit_mac_call(mac); for attr in attrs.iter() { visitor.visit_attribute(attr); @@ -760,7 +750,7 @@ pub fn walk_inline_asm<'a, V: Visitor<'a>>(visitor: &mut V, asm: &'a InlineAsm) } pub fn walk_inline_asm_sym<'a, V: Visitor<'a>>(visitor: &mut V, sym: &'a InlineAsmSym) { - if let Some(ref qself) = sym.qself { + if let Some(qself) = &sym.qself { visitor.visit_ty(&qself.ty); } visitor.visit_path(&sym.path, sym.id); @@ -769,18 +759,18 @@ pub fn walk_inline_asm_sym<'a, V: Visitor<'a>>(visitor: &mut V, sym: &'a InlineA pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) { walk_list!(visitor, visit_attribute, expression.attrs.iter()); - match expression.kind { - ExprKind::Box(ref subexpression) => visitor.visit_expr(subexpression), - ExprKind::Array(ref subexpressions) => { + match &expression.kind { + ExprKind::Box(subexpression) => visitor.visit_expr(subexpression), + ExprKind::Array(subexpressions) => { walk_list!(visitor, visit_expr, subexpressions); } - ExprKind::ConstBlock(ref anon_const) => visitor.visit_anon_const(anon_const), - ExprKind::Repeat(ref element, ref count) => { + ExprKind::ConstBlock(anon_const) => visitor.visit_anon_const(anon_const), + ExprKind::Repeat(element, count) => { visitor.visit_expr(element); visitor.visit_anon_const(count) } - ExprKind::Struct(ref se) => { - if let Some(ref qself) = se.qself { + ExprKind::Struct(se) => { + if let Some(qself) = &se.qself { visitor.visit_ty(&qself.ty); } visitor.visit_path(&se.path, expression.id); @@ -791,117 +781,126 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) { StructRest::None => {} } } - ExprKind::Tup(ref subexpressions) => { + ExprKind::Tup(subexpressions) => { walk_list!(visitor, visit_expr, subexpressions); } - ExprKind::Call(ref callee_expression, ref arguments) => { + ExprKind::Call(callee_expression, arguments) => { visitor.visit_expr(callee_expression); walk_list!(visitor, visit_expr, arguments); } - ExprKind::MethodCall(ref segment, ref receiver, ref arguments, _span) => { - visitor.visit_path_segment(segment); + ExprKind::MethodCall(box MethodCall { seg, receiver, args, span: _ }) => { + visitor.visit_path_segment(seg); visitor.visit_expr(receiver); - walk_list!(visitor, visit_expr, arguments); + walk_list!(visitor, visit_expr, args); } - ExprKind::Binary(_, ref left_expression, ref right_expression) => { + ExprKind::Binary(_, left_expression, right_expression) => { visitor.visit_expr(left_expression); visitor.visit_expr(right_expression) } - ExprKind::AddrOf(_, _, ref subexpression) | ExprKind::Unary(_, ref subexpression) => { + ExprKind::AddrOf(_, _, subexpression) | ExprKind::Unary(_, subexpression) => { visitor.visit_expr(subexpression) } - ExprKind::Cast(ref subexpression, ref typ) | ExprKind::Type(ref subexpression, ref typ) => { + ExprKind::Cast(subexpression, typ) | ExprKind::Type(subexpression, typ) => { visitor.visit_expr(subexpression); visitor.visit_ty(typ) } - ExprKind::Let(ref pat, ref expr, _) => { + ExprKind::Let(pat, expr, _) => { visitor.visit_pat(pat); visitor.visit_expr(expr); } - ExprKind::If(ref head_expression, ref if_block, ref optional_else) => { + ExprKind::If(head_expression, if_block, optional_else) => { visitor.visit_expr(head_expression); visitor.visit_block(if_block); walk_list!(visitor, visit_expr, optional_else); } - ExprKind::While(ref subexpression, ref block, ref opt_label) => { + ExprKind::While(subexpression, block, opt_label) => { walk_list!(visitor, visit_label, opt_label); visitor.visit_expr(subexpression); visitor.visit_block(block); } - ExprKind::ForLoop(ref pattern, ref subexpression, ref block, ref opt_label) => { + ExprKind::ForLoop(pattern, subexpression, block, opt_label) => { walk_list!(visitor, visit_label, opt_label); visitor.visit_pat(pattern); visitor.visit_expr(subexpression); visitor.visit_block(block); } - ExprKind::Loop(ref block, ref opt_label) => { + ExprKind::Loop(block, opt_label, _) => { walk_list!(visitor, visit_label, opt_label); visitor.visit_block(block); } - ExprKind::Match(ref subexpression, ref arms) => { + ExprKind::Match(subexpression, arms) => { visitor.visit_expr(subexpression); walk_list!(visitor, visit_arm, arms); } - ExprKind::Closure(ref binder, _, _, _, ref decl, ref body, _decl_span) => { - visitor.visit_fn(FnKind::Closure(binder, decl, body), expression.span, expression.id) + ExprKind::Closure(box Closure { + binder, + capture_clause: _, + asyncness: _, + movability: _, + fn_decl, + body, + fn_decl_span: _, + fn_arg_span: _, + }) => { + visitor.visit_fn(FnKind::Closure(binder, fn_decl, body), expression.span, expression.id) } - ExprKind::Block(ref block, ref opt_label) => { + ExprKind::Block(block, opt_label) => { walk_list!(visitor, visit_label, opt_label); visitor.visit_block(block); } - ExprKind::Async(_, _, ref body) => { + ExprKind::Async(_, _, body) => { visitor.visit_block(body); } - ExprKind::Await(ref expr) => visitor.visit_expr(expr), - ExprKind::Assign(ref lhs, ref rhs, _) => { + ExprKind::Await(expr) => visitor.visit_expr(expr), + ExprKind::Assign(lhs, rhs, _) => { visitor.visit_expr(lhs); visitor.visit_expr(rhs); } - ExprKind::AssignOp(_, ref left_expression, ref right_expression) => { + ExprKind::AssignOp(_, left_expression, right_expression) => { visitor.visit_expr(left_expression); visitor.visit_expr(right_expression); } - ExprKind::Field(ref subexpression, ident) => { + ExprKind::Field(subexpression, ident) => { visitor.visit_expr(subexpression); - visitor.visit_ident(ident); + visitor.visit_ident(*ident); } - ExprKind::Index(ref main_expression, ref index_expression) => { + ExprKind::Index(main_expression, index_expression) => { visitor.visit_expr(main_expression); visitor.visit_expr(index_expression) } - ExprKind::Range(ref start, ref end, _) => { + ExprKind::Range(start, end, _) => { walk_list!(visitor, visit_expr, start); walk_list!(visitor, visit_expr, end); } ExprKind::Underscore => {} - ExprKind::Path(ref maybe_qself, ref path) => { - if let Some(ref qself) = *maybe_qself { + ExprKind::Path(maybe_qself, path) => { + if let Some(qself) = maybe_qself { visitor.visit_ty(&qself.ty); } visitor.visit_path(path, expression.id) } - ExprKind::Break(ref opt_label, ref opt_expr) => { + ExprKind::Break(opt_label, opt_expr) => { walk_list!(visitor, visit_label, opt_label); walk_list!(visitor, visit_expr, opt_expr); } - ExprKind::Continue(ref opt_label) => { + ExprKind::Continue(opt_label) => { walk_list!(visitor, visit_label, opt_label); } - ExprKind::Ret(ref optional_expression) => { + ExprKind::Ret(optional_expression) => { walk_list!(visitor, visit_expr, optional_expression); } - ExprKind::Yeet(ref optional_expression) => { + ExprKind::Yeet(optional_expression) => { walk_list!(visitor, visit_expr, optional_expression); } - ExprKind::MacCall(ref mac) => visitor.visit_mac_call(mac), - ExprKind::Paren(ref subexpression) => visitor.visit_expr(subexpression), - ExprKind::InlineAsm(ref asm) => visitor.visit_inline_asm(asm), - ExprKind::Yield(ref optional_expression) => { + ExprKind::MacCall(mac) => visitor.visit_mac_call(mac), + ExprKind::Paren(subexpression) => visitor.visit_expr(subexpression), + ExprKind::InlineAsm(asm) => visitor.visit_inline_asm(asm), + ExprKind::Yield(optional_expression) => { walk_list!(visitor, visit_expr, optional_expression); } - ExprKind::Try(ref subexpression) => visitor.visit_expr(subexpression), - ExprKind::TryBlock(ref body) => visitor.visit_block(body), - ExprKind::Lit(_) | ExprKind::Err => {} + ExprKind::Try(subexpression) => visitor.visit_expr(subexpression), + ExprKind::TryBlock(body) => visitor.visit_block(body), + ExprKind::Lit(_) | ExprKind::IncludedBytes(..) | ExprKind::Err => {} } visitor.visit_expr_post(expression) @@ -927,18 +926,18 @@ pub fn walk_vis<'a, V: Visitor<'a>>(visitor: &mut V, vis: &'a Visibility) { } pub fn walk_attribute<'a, V: Visitor<'a>>(visitor: &mut V, attr: &'a Attribute) { - match attr.kind { - AttrKind::Normal(ref normal) => walk_mac_args(visitor, &normal.item.args), + match &attr.kind { + AttrKind::Normal(normal) => walk_attr_args(visitor, &normal.item.args), AttrKind::DocComment(..) => {} } } -pub fn walk_mac_args<'a, V: Visitor<'a>>(visitor: &mut V, args: &'a MacArgs) { +pub fn walk_attr_args<'a, V: Visitor<'a>>(visitor: &mut V, args: &'a AttrArgs) { match args { - MacArgs::Empty => {} - MacArgs::Delimited(_dspan, _delim, _tokens) => {} - MacArgs::Eq(_eq_span, MacArgsEq::Ast(expr)) => visitor.visit_expr(expr), - MacArgs::Eq(_, MacArgsEq::Hir(lit)) => { + AttrArgs::Empty => {} + AttrArgs::Delimited(_) => {} + AttrArgs::Eq(_eq_span, AttrArgsEq::Ast(expr)) => visitor.visit_expr(expr), + AttrArgs::Eq(_, AttrArgsEq::Hir(lit)) => { unreachable!("in literal form when walking mac args eq: {:?}", lit) } } |