summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_ast/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_ast/src')
-rw-r--r--compiler/rustc_ast/src/ast.rs266
-rw-r--r--compiler/rustc_ast/src/ast_traits.rs90
-rw-r--r--compiler/rustc_ast/src/attr/mod.rs153
-rw-r--r--compiler/rustc_ast/src/lib.rs8
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs77
-rw-r--r--compiler/rustc_ast/src/node_id.rs2
-rw-r--r--compiler/rustc_ast/src/token.rs49
-rw-r--r--compiler/rustc_ast/src/tokenstream.rs127
-rw-r--r--compiler/rustc_ast/src/util/literal.rs32
-rw-r--r--compiler/rustc_ast/src/util/parser.rs68
-rw-r--r--compiler/rustc_ast/src/visit.rs66
11 files changed, 497 insertions, 441 deletions
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 870a7c0be..d86db8f8b 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -24,22 +24,19 @@ pub use UnsafeSource::*;
use crate::ptr::P;
use crate::token::{self, CommentKind, Delimiter};
-use crate::tokenstream::{DelimSpan, LazyTokenStream, TokenStream};
-
+use crate::tokenstream::{DelimSpan, LazyAttrTokenStream, TokenStream};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_data_structures::sync::Lrc;
-use rustc_data_structures::thin_vec::ThinVec;
use rustc_macros::HashStable_Generic;
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use rustc_span::source_map::{respan, Spanned};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{Span, DUMMY_SP};
-
-use std::cmp::Ordering;
use std::convert::TryFrom;
use std::fmt;
use std::mem;
+use thin_vec::ThinVec;
/// A "Label" is an identifier of some point in sources,
/// e.g. in the following code:
@@ -94,7 +91,7 @@ pub struct Path {
/// The segments in the path: the things separated by `::`.
/// Global paths begin with `kw::PathRoot`.
pub segments: Vec<PathSegment>,
- pub tokens: Option<LazyTokenStream>,
+ pub tokens: Option<LazyAttrTokenStream>,
}
impl PartialEq<Symbol> for Path {
@@ -326,46 +323,17 @@ pub type GenericBounds = Vec<GenericBound>;
/// Specifies the enforced ordering for generic parameters. In the future,
/// if we wanted to relax this order, we could override `PartialEq` and
/// `PartialOrd`, to allow the kinds to be unordered.
-#[derive(Hash, Clone, Copy)]
+#[derive(Hash, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum ParamKindOrd {
Lifetime,
- Type,
- Const,
- // `Infer` is not actually constructed directly from the AST, but is implicitly constructed
- // during HIR lowering, and `ParamKindOrd` will implicitly order inferred variables last.
- Infer,
-}
-
-impl Ord for ParamKindOrd {
- fn cmp(&self, other: &Self) -> Ordering {
- use ParamKindOrd::*;
- let to_int = |v| match v {
- Lifetime => 0,
- Infer | Type | Const => 1,
- };
-
- to_int(*self).cmp(&to_int(*other))
- }
-}
-impl PartialOrd for ParamKindOrd {
- fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
- Some(self.cmp(other))
- }
+ TypeOrConst,
}
-impl PartialEq for ParamKindOrd {
- fn eq(&self, other: &Self) -> bool {
- self.cmp(other) == Ordering::Equal
- }
-}
-impl Eq for ParamKindOrd {}
impl fmt::Display for ParamKindOrd {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ParamKindOrd::Lifetime => "lifetime".fmt(f),
- ParamKindOrd::Type => "type".fmt(f),
- ParamKindOrd::Const { .. } => "const".fmt(f),
- ParamKindOrd::Infer => "infer".fmt(f),
+ ParamKindOrd::TypeOrConst => "type and const".fmt(f),
}
}
}
@@ -497,7 +465,6 @@ pub struct WhereRegionPredicate {
/// E.g., `T = int`.
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct WhereEqPredicate {
- pub id: NodeId,
pub span: Span,
pub lhs_ty: P<Ty>,
pub rhs_ty: P<Ty>,
@@ -505,7 +472,7 @@ pub struct WhereEqPredicate {
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct Crate {
- pub attrs: Vec<Attribute>,
+ pub attrs: AttrVec,
pub items: Vec<P<Item>>,
pub spans: ModSpans,
/// Must be equal to `CRATE_NODE_ID` after the crate root is expanded, but may hold
@@ -567,7 +534,7 @@ pub struct Block {
/// Distinguishes between `unsafe { ... }` and `{ ... }`.
pub rules: BlockCheckMode,
pub span: Span,
- pub tokens: Option<LazyTokenStream>,
+ pub tokens: Option<LazyAttrTokenStream>,
/// The following *isn't* a parse error, but will cause multiple errors in following stages.
/// ```compile_fail
/// let x = {
@@ -586,7 +553,7 @@ pub struct Pat {
pub id: NodeId,
pub kind: PatKind,
pub span: Span,
- pub tokens: Option<LazyTokenStream>,
+ pub tokens: Option<LazyAttrTokenStream>,
}
impl Pat {
@@ -597,7 +564,7 @@ impl Pat {
// In a type expression `_` is an inference variable.
PatKind::Wild => TyKind::Infer,
// An IDENT pattern with no binding mode would be valid as path to a type. E.g. `u32`.
- PatKind::Ident(BindingMode::ByValue(Mutability::Not), ident, None) => {
+ PatKind::Ident(BindingAnnotation::NONE, ident, None) => {
TyKind::Path(None, Path::from_ident(*ident))
}
PatKind::Path(qself, path) => TyKind::Path(qself.clone(), path.clone()),
@@ -684,10 +651,43 @@ pub struct PatField {
pub is_placeholder: bool,
}
-#[derive(Clone, PartialEq, Encodable, Decodable, Debug, Copy)]
-pub enum BindingMode {
- ByRef(Mutability),
- ByValue(Mutability),
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+#[derive(Encodable, Decodable, HashStable_Generic)]
+pub enum ByRef {
+ Yes,
+ No,
+}
+
+impl From<bool> for ByRef {
+ fn from(b: bool) -> ByRef {
+ match b {
+ false => ByRef::No,
+ true => ByRef::Yes,
+ }
+ }
+}
+
+/// Explicit binding annotations given in the HIR for a binding. Note
+/// that this is not the final binding *mode* that we infer after type
+/// inference.
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+#[derive(Encodable, Decodable, HashStable_Generic)]
+pub struct BindingAnnotation(pub ByRef, pub Mutability);
+
+impl BindingAnnotation {
+ pub const NONE: Self = Self(ByRef::No, Mutability::Not);
+ pub const REF: Self = Self(ByRef::Yes, Mutability::Not);
+ pub const MUT: Self = Self(ByRef::No, Mutability::Mut);
+ pub const REF_MUT: Self = Self(ByRef::Yes, Mutability::Mut);
+
+ pub fn prefix_str(self) -> &'static str {
+ match self {
+ Self::NONE => "",
+ Self::REF => "ref ",
+ Self::MUT => "mut ",
+ Self::REF_MUT => "ref mut ",
+ }
+ }
}
#[derive(Clone, Encodable, Decodable, Debug)]
@@ -716,7 +716,7 @@ pub enum PatKind {
/// or a unit struct/variant pattern, or a const pattern (in the last two cases the third
/// field must be `None`). Disambiguation cannot be done with parser alone, so it happens
/// during name resolution.
- Ident(BindingMode, Ident, Option<P<Pat>>),
+ Ident(BindingAnnotation, Ident, Option<P<Pat>>),
/// A struct or struct variant pattern (e.g., `Variant {x, y, ..}`).
/// The `bool` is `true` in the presence of a `..`.
@@ -771,7 +771,7 @@ pub enum PatKind {
Paren(P<Pat>),
/// A macro pattern; pre-expansion.
- MacCall(MacCall),
+ MacCall(P<MacCall>),
}
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)]
@@ -937,8 +937,8 @@ impl Stmt {
/// a trailing semicolon.
///
/// This only modifies the parsed AST struct, not the attached
- /// `LazyTokenStream`. The parser is responsible for calling
- /// `CreateTokenStream::add_trailing_semi` when there is actually
+ /// `LazyAttrTokenStream`. The parser is responsible for calling
+ /// `ToAttrTokenStream::add_trailing_semi` when there is actually
/// a semicolon in the tokenstream.
pub fn add_trailing_semicolon(mut self) -> Self {
self.kind = match self.kind {
@@ -981,10 +981,10 @@ pub enum StmtKind {
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct MacCallStmt {
- pub mac: MacCall,
+ pub mac: P<MacCall>,
pub style: MacStmtStyle,
pub attrs: AttrVec,
- pub tokens: Option<LazyTokenStream>,
+ pub tokens: Option<LazyAttrTokenStream>,
}
#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug)]
@@ -1009,7 +1009,7 @@ pub struct Local {
pub kind: LocalKind,
pub span: Span,
pub attrs: AttrVec,
- pub tokens: Option<LazyTokenStream>,
+ pub tokens: Option<LazyAttrTokenStream>,
}
#[derive(Clone, Encodable, Decodable, Debug)]
@@ -1108,7 +1108,7 @@ pub struct Expr {
pub kind: ExprKind,
pub span: Span,
pub attrs: AttrVec,
- pub tokens: Option<LazyTokenStream>,
+ pub tokens: Option<LazyAttrTokenStream>,
}
impl Expr {
@@ -1269,7 +1269,7 @@ impl Expr {
id: DUMMY_NODE_ID,
kind: ExprKind::Err,
span: DUMMY_SP,
- attrs: ThinVec::new(),
+ attrs: AttrVec::new(),
tokens: None,
},
)
@@ -1439,7 +1439,7 @@ pub enum ExprKind {
InlineAsm(P<InlineAsm>),
/// A macro invocation; pre-expansion.
- MacCall(MacCall),
+ MacCall(P<MacCall>),
/// A struct literal expression.
///
@@ -1691,7 +1691,7 @@ pub enum StrStyle {
#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
pub struct Lit {
/// The original literal token as written in source code.
- pub token: token::Lit,
+ 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.
@@ -1719,7 +1719,7 @@ impl StrLit {
StrStyle::Raw(n) => token::StrRaw(n),
};
Lit {
- token: token::Lit::new(token_kind, self.symbol, self.suffix),
+ token_lit: token::Lit::new(token_kind, self.symbol, self.suffix),
span: self.span,
kind: LitKind::Str(self.symbol_unescaped, self.style),
}
@@ -1753,7 +1753,8 @@ pub enum LitFloatType {
/// E.g., `"foo"`, `42`, `12.34`, or `bool`.
#[derive(Clone, Encodable, Decodable, Debug, Hash, Eq, PartialEq, HashStable_Generic)]
pub enum LitKind {
- /// A string literal (`"foo"`).
+ /// A string literal (`"foo"`). The symbol is unescaped, and so may differ
+ /// from the original token's symbol.
Str(Symbol, StrStyle),
/// A byte string (`b"foo"`).
ByteStr(Lrc<[u8]>),
@@ -1763,12 +1764,13 @@ pub enum LitKind {
Char(char),
/// An integer literal (`1`).
Int(u128, LitIntType),
- /// A float literal (`1f64` or `1E10f64`).
+ /// A float literal (`1f64` or `1E10f64`). Stored as a symbol rather than
+ /// `f64` so that `LitKind` can impl `Eq` and `Hash`.
Float(Symbol, LitFloatType),
/// A boolean literal.
Bool(bool),
/// Placeholder for a literal that wasn't well-formed in some way.
- Err(Symbol),
+ Err,
}
impl LitKind {
@@ -1807,7 +1809,7 @@ impl LitKind {
| LitKind::Int(_, LitIntType::Unsuffixed)
| LitKind::Float(_, LitFloatType::Unsuffixed)
| LitKind::Bool(..)
- | LitKind::Err(..) => false,
+ | LitKind::Err => false,
}
}
}
@@ -1966,7 +1968,7 @@ pub struct Ty {
pub id: NodeId,
pub kind: TyKind,
pub span: Span,
- pub tokens: Option<LazyTokenStream>,
+ pub tokens: Option<LazyAttrTokenStream>,
}
impl Clone for Ty {
@@ -2042,7 +2044,7 @@ pub enum TyKind {
/// Inferred type of a `self` or `&self` argument in a method.
ImplicitSelf,
/// A macro in the type position.
- MacCall(MacCall),
+ MacCall(P<MacCall>),
/// Placeholder for a kind that has failed to be defined.
Err,
/// Placeholder for a `va_list`.
@@ -2059,8 +2061,11 @@ impl TyKind {
}
pub fn is_simple_path(&self) -> Option<Symbol> {
- if let TyKind::Path(None, Path { segments, .. }) = &self && segments.len() == 1 {
- Some(segments[0].ident.name)
+ if let TyKind::Path(None, Path { segments, .. }) = &self
+ && let [segment] = &segments[..]
+ && segment.args.is_none()
+ {
+ Some(segment.ident.name)
} else {
None
}
@@ -2071,6 +2076,7 @@ impl TyKind {
#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
pub enum TraitObjectSyntax {
Dyn,
+ DynStar,
None,
}
@@ -2086,15 +2092,15 @@ pub enum InlineAsmRegOrRegClass {
bitflags::bitflags! {
#[derive(Encodable, Decodable, HashStable_Generic)]
pub struct InlineAsmOptions: u16 {
- const PURE = 1 << 0;
- const NOMEM = 1 << 1;
- const READONLY = 1 << 2;
+ const PURE = 1 << 0;
+ const NOMEM = 1 << 1;
+ const READONLY = 1 << 2;
const PRESERVES_FLAGS = 1 << 3;
- const NORETURN = 1 << 4;
- const NOSTACK = 1 << 5;
- const ATT_SYNTAX = 1 << 6;
- const RAW = 1 << 7;
- const MAY_UNWIND = 1 << 8;
+ const NORETURN = 1 << 4;
+ const NOSTACK = 1 << 5;
+ const ATT_SYNTAX = 1 << 6;
+ const RAW = 1 << 7;
+ const MAY_UNWIND = 1 << 8;
}
}
@@ -2230,7 +2236,7 @@ pub type ExplicitSelf = Spanned<SelfKind>;
impl Param {
/// Attempts to cast parameter to `ExplicitSelf`.
pub fn to_self(&self) -> Option<ExplicitSelf> {
- if let PatKind::Ident(BindingMode::ByValue(mutbl), ident, _) = self.pat.kind {
+ if let PatKind::Ident(BindingAnnotation(ByRef::No, mutbl), ident, _) = self.pat.kind {
if ident.name == kw::SelfLower {
return match self.ty.kind {
TyKind::ImplicitSelf => Some(respan(self.pat.span, SelfKind::Value(mutbl))),
@@ -2260,11 +2266,24 @@ impl Param {
pub fn from_self(attrs: AttrVec, eself: ExplicitSelf, eself_ident: Ident) -> Param {
let span = eself.span.to(eself_ident.span);
let infer_ty = P(Ty { id: DUMMY_NODE_ID, kind: TyKind::ImplicitSelf, span, tokens: None });
- let param = |mutbl, ty| Param {
+ let (mutbl, ty) = match eself.node {
+ SelfKind::Explicit(ty, mutbl) => (mutbl, ty),
+ SelfKind::Value(mutbl) => (mutbl, infer_ty),
+ SelfKind::Region(lt, mutbl) => (
+ Mutability::Not,
+ P(Ty {
+ id: DUMMY_NODE_ID,
+ kind: TyKind::Rptr(lt, MutTy { ty: infer_ty, mutbl }),
+ span,
+ tokens: None,
+ }),
+ ),
+ };
+ Param {
attrs,
pat: P(Pat {
id: DUMMY_NODE_ID,
- kind: PatKind::Ident(BindingMode::ByValue(mutbl), eself_ident, None),
+ kind: PatKind::Ident(BindingAnnotation(ByRef::No, mutbl), eself_ident, None),
span,
tokens: None,
}),
@@ -2272,19 +2291,6 @@ impl Param {
ty,
id: DUMMY_NODE_ID,
is_placeholder: false,
- };
- match eself.node {
- SelfKind::Explicit(ty, mutbl) => param(mutbl, ty),
- SelfKind::Value(mutbl) => param(mutbl, infer_ty),
- SelfKind::Region(lt, mutbl) => param(
- Mutability::Not,
- P(Ty {
- id: DUMMY_NODE_ID,
- kind: TyKind::Rptr(lt, MutTy { ty: infer_ty, mutbl }),
- span,
- tokens: None,
- }),
- ),
}
}
}
@@ -2336,9 +2342,9 @@ impl Async {
}
/// In this case this is an `async` return, the `NodeId` for the generated `impl Trait` item.
- pub fn opt_return_id(self) -> Option<NodeId> {
+ pub fn opt_return_id(self) -> Option<(NodeId, Span)> {
match self {
- Async::Yes { return_impl_trait_id, .. } => Some(return_impl_trait_id),
+ Async::Yes { return_impl_trait_id, span, .. } => Some((return_impl_trait_id, span)),
Async::No => None,
}
}
@@ -2522,8 +2528,8 @@ impl<S: Encoder> Encodable<S> for AttrId {
}
impl<D: Decoder> Decodable<D> for AttrId {
- fn decode(_: &mut D) -> AttrId {
- crate::attr::mk_attr_id()
+ default fn decode(_: &mut D) -> AttrId {
+ panic!("cannot decode `AttrId` with `{}`", std::any::type_name::<D>());
}
}
@@ -2531,7 +2537,7 @@ impl<D: Decoder> Decodable<D> for AttrId {
pub struct AttrItem {
pub path: Path,
pub args: MacArgs,
- pub tokens: Option<LazyTokenStream>,
+ pub tokens: Option<LazyAttrTokenStream>,
}
/// A list of attributes.
@@ -2549,9 +2555,15 @@ 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(AttrItem, Option<LazyTokenStream>),
+ Normal(P<NormalAttr>),
/// A doc comment (e.g. `/// ...`, `//! ...`, `/** ... */`, `/*! ... */`).
/// Doc attributes (e.g. `#[doc="..."]`) are represented with the `Normal`
@@ -2596,13 +2608,13 @@ impl PolyTraitRef {
pub struct Visibility {
pub kind: VisibilityKind,
pub span: Span,
- pub tokens: Option<LazyTokenStream>,
+ pub tokens: Option<LazyAttrTokenStream>,
}
#[derive(Clone, Encodable, Decodable, Debug)]
pub enum VisibilityKind {
Public,
- Restricted { path: P<Path>, id: NodeId },
+ Restricted { path: P<Path>, id: NodeId, shorthand: bool },
Inherited,
}
@@ -2665,7 +2677,7 @@ impl VariantData {
/// An item definition.
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct Item<K = ItemKind> {
- pub attrs: Vec<Attribute>,
+ pub attrs: AttrVec,
pub id: NodeId,
pub span: Span,
pub vis: Visibility,
@@ -2682,7 +2694,7 @@ pub struct Item<K = ItemKind> {
///
/// Note that the tokens here do not include the outer attributes, but will
/// include inner attributes.
- pub tokens: Option<LazyTokenStream>,
+ pub tokens: Option<LazyAttrTokenStream>,
}
impl Item {
@@ -2873,7 +2885,7 @@ pub enum ItemKind {
/// A macro invocation.
///
/// E.g., `foo!(..)`.
- MacCall(MacCall),
+ MacCall(P<MacCall>),
/// A macro definition.
MacroDef(MacroDef),
@@ -2947,7 +2959,7 @@ pub enum AssocItemKind {
/// An associated type.
TyAlias(Box<TyAlias>),
/// A macro expanding to associated items.
- MacCall(MacCall),
+ MacCall(P<MacCall>),
}
impl AssocItemKind {
@@ -2996,7 +3008,7 @@ pub enum ForeignItemKind {
/// An foreign type.
TyAlias(Box<TyAlias>),
/// A macro expanding to foreign items.
- MacCall(MacCall),
+ MacCall(P<MacCall>),
}
impl From<ForeignItemKind> for ItemKind {
@@ -3030,22 +3042,34 @@ pub type ForeignItem = Item<ForeignItemKind>;
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
mod size_asserts {
use super::*;
+ use rustc_data_structures::static_assert_size;
// These are in alphabetical order, which is easy to maintain.
- rustc_data_structures::static_assert_size!(AssocItemKind, 72);
- rustc_data_structures::static_assert_size!(Attribute, 152);
- rustc_data_structures::static_assert_size!(Block, 48);
- rustc_data_structures::static_assert_size!(Expr, 104);
- rustc_data_structures::static_assert_size!(Fn, 192);
- rustc_data_structures::static_assert_size!(ForeignItemKind, 72);
- rustc_data_structures::static_assert_size!(GenericBound, 88);
- rustc_data_structures::static_assert_size!(Generics, 72);
- rustc_data_structures::static_assert_size!(Impl, 200);
- rustc_data_structures::static_assert_size!(Item, 200);
- rustc_data_structures::static_assert_size!(ItemKind, 112);
- rustc_data_structures::static_assert_size!(Lit, 48);
- rustc_data_structures::static_assert_size!(Pat, 120);
- rustc_data_structures::static_assert_size!(Path, 40);
- rustc_data_structures::static_assert_size!(PathSegment, 24);
- rustc_data_structures::static_assert_size!(Stmt, 32);
- rustc_data_structures::static_assert_size!(Ty, 96);
+ static_assert_size!(AssocItem, 104);
+ 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);
+ #[cfg(not(bootstrap))]
+ 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!(Generics, 72);
+ static_assert_size!(Impl, 200);
+ 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!(Param, 40);
+ static_assert_size!(Pat, 120);
+ static_assert_size!(PatKind, 96);
+ static_assert_size!(Path, 40);
+ static_assert_size!(PathSegment, 24);
+ static_assert_size!(Stmt, 32);
+ static_assert_size!(StmtKind, 16);
+ static_assert_size!(Ty, 96);
+ static_assert_size!(TyKind, 72);
}
diff --git a/compiler/rustc_ast/src/ast_traits.rs b/compiler/rustc_ast/src/ast_traits.rs
index 5c30a75a1..1b31be07f 100644
--- a/compiler/rustc_ast/src/ast_traits.rs
+++ b/compiler/rustc_ast/src/ast_traits.rs
@@ -4,7 +4,7 @@
use crate::ptr::P;
use crate::token::Nonterminal;
-use crate::tokenstream::LazyTokenStream;
+use crate::tokenstream::LazyAttrTokenStream;
use crate::{Arm, Crate, ExprField, FieldDef, GenericParam, Param, PatField, Variant};
use crate::{AssocItem, Expr, ForeignItem, Item, NodeId};
use crate::{AttrItem, AttrKind, Block, Pat, Path, Ty, Visibility};
@@ -124,18 +124,18 @@ impl HasSpan for AttrItem {
/// A trait for AST nodes having (or not having) collected tokens.
pub trait HasTokens {
- fn tokens(&self) -> Option<&LazyTokenStream>;
- fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>>;
+ fn tokens(&self) -> Option<&LazyAttrTokenStream>;
+ fn tokens_mut(&mut self) -> Option<&mut Option<LazyAttrTokenStream>>;
}
macro_rules! impl_has_tokens {
($($T:ty),+ $(,)?) => {
$(
impl HasTokens for $T {
- fn tokens(&self) -> Option<&LazyTokenStream> {
+ fn tokens(&self) -> Option<&LazyAttrTokenStream> {
self.tokens.as_ref()
}
- fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> {
+ fn tokens_mut(&mut self) -> Option<&mut Option<LazyAttrTokenStream>> {
Some(&mut self.tokens)
}
}
@@ -147,10 +147,10 @@ macro_rules! impl_has_tokens_none {
($($T:ty),+ $(,)?) => {
$(
impl HasTokens for $T {
- fn tokens(&self) -> Option<&LazyTokenStream> {
+ fn tokens(&self) -> Option<&LazyAttrTokenStream> {
None
}
- fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> {
+ fn tokens_mut(&mut self) -> Option<&mut Option<LazyAttrTokenStream>> {
None
}
}
@@ -162,25 +162,25 @@ impl_has_tokens!(AssocItem, AttrItem, Block, Expr, ForeignItem, Item, Pat, Path,
impl_has_tokens_none!(Arm, ExprField, FieldDef, GenericParam, Param, PatField, Variant);
impl<T: AstDeref<Target: HasTokens>> HasTokens for T {
- fn tokens(&self) -> Option<&LazyTokenStream> {
+ fn tokens(&self) -> Option<&LazyAttrTokenStream> {
self.ast_deref().tokens()
}
- fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> {
+ fn tokens_mut(&mut self) -> Option<&mut Option<LazyAttrTokenStream>> {
self.ast_deref_mut().tokens_mut()
}
}
impl<T: HasTokens> HasTokens for Option<T> {
- fn tokens(&self) -> Option<&LazyTokenStream> {
+ fn tokens(&self) -> Option<&LazyAttrTokenStream> {
self.as_ref().and_then(|inner| inner.tokens())
}
- fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> {
+ fn tokens_mut(&mut self) -> Option<&mut Option<LazyAttrTokenStream>> {
self.as_mut().and_then(|inner| inner.tokens_mut())
}
}
impl HasTokens for StmtKind {
- fn tokens(&self) -> Option<&LazyTokenStream> {
+ fn tokens(&self) -> Option<&LazyAttrTokenStream> {
match self {
StmtKind::Local(local) => local.tokens.as_ref(),
StmtKind::Item(item) => item.tokens(),
@@ -189,7 +189,7 @@ impl HasTokens for StmtKind {
StmtKind::MacCall(mac) => mac.tokens.as_ref(),
}
}
- fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> {
+ fn tokens_mut(&mut self) -> Option<&mut Option<LazyAttrTokenStream>> {
match self {
StmtKind::Local(local) => Some(&mut local.tokens),
StmtKind::Item(item) => item.tokens_mut(),
@@ -201,26 +201,26 @@ impl HasTokens for StmtKind {
}
impl HasTokens for Stmt {
- fn tokens(&self) -> Option<&LazyTokenStream> {
+ fn tokens(&self) -> Option<&LazyAttrTokenStream> {
self.kind.tokens()
}
- fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> {
+ fn tokens_mut(&mut self) -> Option<&mut Option<LazyAttrTokenStream>> {
self.kind.tokens_mut()
}
}
impl HasTokens for Attribute {
- fn tokens(&self) -> Option<&LazyTokenStream> {
+ fn tokens(&self) -> Option<&LazyAttrTokenStream> {
match &self.kind {
- AttrKind::Normal(_, tokens) => tokens.as_ref(),
+ AttrKind::Normal(normal) => normal.tokens.as_ref(),
kind @ AttrKind::DocComment(..) => {
panic!("Called tokens on doc comment attr {:?}", kind)
}
}
}
- fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> {
+ fn tokens_mut(&mut self) -> Option<&mut Option<LazyAttrTokenStream>> {
Some(match &mut self.kind {
- AttrKind::Normal(_, tokens) => tokens,
+ AttrKind::Normal(normal) => &mut normal.tokens,
kind @ AttrKind::DocComment(..) => {
panic!("Called tokens_mut on doc comment attr {:?}", kind)
}
@@ -229,7 +229,7 @@ impl HasTokens for Attribute {
}
impl HasTokens for Nonterminal {
- fn tokens(&self) -> Option<&LazyTokenStream> {
+ fn tokens(&self) -> Option<&LazyAttrTokenStream> {
match self {
Nonterminal::NtItem(item) => item.tokens(),
Nonterminal::NtStmt(stmt) => stmt.tokens(),
@@ -243,7 +243,7 @@ impl HasTokens for Nonterminal {
Nonterminal::NtIdent(..) | Nonterminal::NtLifetime(..) => None,
}
}
- fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> {
+ fn tokens_mut(&mut self) -> Option<&mut Option<LazyAttrTokenStream>> {
match self {
Nonterminal::NtItem(item) => item.tokens_mut(),
Nonterminal::NtStmt(stmt) => stmt.tokens_mut(),
@@ -270,7 +270,7 @@ pub trait HasAttrs {
/// during token collection.
const SUPPORTS_CUSTOM_INNER_ATTRS: bool;
fn attrs(&self) -> &[Attribute];
- fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>));
+ fn visit_attrs(&mut self, f: impl FnOnce(&mut AttrVec));
}
macro_rules! impl_has_attrs {
@@ -279,12 +279,13 @@ macro_rules! impl_has_attrs {
impl HasAttrs for $T {
const SUPPORTS_CUSTOM_INNER_ATTRS: bool = $inner;
+ #[inline]
fn attrs(&self) -> &[Attribute] {
&self.attrs
}
- fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) {
- VecOrAttrVec::visit(&mut self.attrs, f)
+ fn visit_attrs(&mut self, f: impl FnOnce(&mut AttrVec)) {
+ f(&mut self.attrs)
}
}
)+
@@ -299,7 +300,7 @@ macro_rules! impl_has_attrs_none {
fn attrs(&self) -> &[Attribute] {
&[]
}
- fn visit_attrs(&mut self, _f: impl FnOnce(&mut Vec<Attribute>)) {}
+ fn visit_attrs(&mut self, _f: impl FnOnce(&mut AttrVec)) {}
}
)+
};
@@ -330,7 +331,7 @@ impl<T: AstDeref<Target: HasAttrs>> HasAttrs for T {
fn attrs(&self) -> &[Attribute] {
self.ast_deref().attrs()
}
- fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) {
+ fn visit_attrs(&mut self, f: impl FnOnce(&mut AttrVec)) {
self.ast_deref_mut().visit_attrs(f)
}
}
@@ -340,7 +341,7 @@ impl<T: HasAttrs> HasAttrs for Option<T> {
fn attrs(&self) -> &[Attribute] {
self.as_ref().map(|inner| inner.attrs()).unwrap_or(&[])
}
- fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) {
+ fn visit_attrs(&mut self, f: impl FnOnce(&mut AttrVec)) {
if let Some(inner) = self.as_mut() {
inner.visit_attrs(f);
}
@@ -362,13 +363,13 @@ impl HasAttrs for StmtKind {
}
}
- fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) {
+ fn visit_attrs(&mut self, f: impl FnOnce(&mut AttrVec)) {
match self {
- StmtKind::Local(local) => visit_attrvec(&mut local.attrs, f),
+ StmtKind::Local(local) => f(&mut local.attrs),
StmtKind::Expr(expr) | StmtKind::Semi(expr) => expr.visit_attrs(f),
StmtKind::Item(item) => item.visit_attrs(f),
StmtKind::Empty => {}
- StmtKind::MacCall(mac) => visit_attrvec(&mut mac.attrs, f),
+ StmtKind::MacCall(mac) => f(&mut mac.attrs),
}
}
}
@@ -378,38 +379,11 @@ impl HasAttrs for Stmt {
fn attrs(&self) -> &[Attribute] {
self.kind.attrs()
}
- fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) {
+ fn visit_attrs(&mut self, f: impl FnOnce(&mut AttrVec)) {
self.kind.visit_attrs(f);
}
}
-/// Helper trait for the impls above. Abstracts over
-/// the two types of attribute fields that AST nodes
-/// may have (`Vec<Attribute>` or `AttrVec`).
-trait VecOrAttrVec {
- fn visit(&mut self, f: impl FnOnce(&mut Vec<Attribute>));
-}
-
-impl VecOrAttrVec for Vec<Attribute> {
- fn visit(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) {
- f(self)
- }
-}
-
-impl VecOrAttrVec for AttrVec {
- fn visit(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) {
- visit_attrvec(self, f)
- }
-}
-
-fn visit_attrvec(attrs: &mut AttrVec, f: impl FnOnce(&mut Vec<Attribute>)) {
- crate::mut_visit::visit_clobber(attrs, |attrs| {
- let mut vec = attrs.into();
- f(&mut vec);
- vec.into()
- });
-}
-
/// A newtype around an AST node that implements the traits above if the node implements them.
pub struct AstNodeWrapper<Wrapped, Tag> {
pub wrapped: Wrapped,
diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs
index 86af7769d..990f4f8f1 100644
--- a/compiler/rustc_ast/src/attr/mod.rs
+++ b/compiler/rustc_ast/src/attr/mod.rs
@@ -7,18 +7,22 @@ use crate::ast::{MacArgs, MacArgsEq, MacDelimiter, MetaItem, MetaItemKind, Neste
use crate::ast::{Path, PathSegment};
use crate::ptr::P;
use crate::token::{self, CommentKind, Delimiter, Token};
-use crate::tokenstream::{AttrAnnotatedTokenStream, AttrAnnotatedTokenTree};
use crate::tokenstream::{DelimSpan, Spacing, TokenTree};
-use crate::tokenstream::{LazyTokenStream, TokenStream};
+use crate::tokenstream::{LazyAttrTokenStream, TokenStream};
use crate::util::comments;
-use rustc_data_structures::thin_vec::ThinVec;
+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};
pub struct MarkedAttrs(GrowableBitSet<AttrId>);
@@ -114,7 +118,7 @@ impl Attribute {
#[inline]
pub fn has_name(&self, name: Symbol) -> bool {
match self.kind {
- AttrKind::Normal(ref item, _) => item.path == name,
+ AttrKind::Normal(ref normal) => normal.item.path == name,
AttrKind::DocComment(..) => false,
}
}
@@ -122,9 +126,9 @@ impl Attribute {
/// For a single-segment attribute, returns its name; otherwise, returns `None`.
pub fn ident(&self) -> Option<Ident> {
match self.kind {
- AttrKind::Normal(ref item, _) => {
- if item.path.segments.len() == 1 {
- Some(item.path.segments[0].ident)
+ AttrKind::Normal(ref normal) => {
+ if normal.item.path.segments.len() == 1 {
+ Some(normal.item.path.segments[0].ident)
} else {
None
}
@@ -138,14 +142,16 @@ impl Attribute {
pub fn value_str(&self) -> Option<Symbol> {
match self.kind {
- AttrKind::Normal(ref item, _) => item.meta_kind().and_then(|kind| kind.value_str()),
+ AttrKind::Normal(ref 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 item, _) => match item.meta_kind() {
+ AttrKind::Normal(ref normal) => match normal.item.meta_kind() {
Some(MetaItemKind::List(list)) => Some(list),
_ => None,
},
@@ -154,8 +160,8 @@ impl Attribute {
}
pub fn is_word(&self) -> bool {
- if let AttrKind::Normal(item, _) = &self.kind {
- matches!(item.args, MacArgs::Empty)
+ if let AttrKind::Normal(normal) = &self.kind {
+ matches!(normal.item.args, MacArgs::Empty)
} else {
false
}
@@ -182,13 +188,7 @@ impl MetaItem {
}
pub fn value_str(&self) -> Option<Symbol> {
- match self.kind {
- MetaItemKind::NameValue(ref v) => match v.kind {
- LitKind::Str(ref s, _) => Some(*s),
- _ => None,
- },
- _ => None,
- }
+ self.kind.value_str()
}
pub fn meta_item_list(&self) -> Option<&[NestedMetaItem]> {
@@ -237,6 +237,9 @@ impl AttrItem {
}
impl Attribute {
+ /// Returns `true` if it is a sugared doc comment (`///` or `//!` for example).
+ /// So `#[doc = "doc"]` (which is a doc comment) and `#[doc(...)]` (which is not
+ /// a doc comment) will return `false`.
pub fn is_doc_comment(&self) -> bool {
match self.kind {
AttrKind::Normal(..) => false,
@@ -244,10 +247,16 @@ impl Attribute {
}
}
+ /// Returns the documentation and its kind if this is a doc comment or a sugared doc comment.
+ /// * `///doc` returns `Some(("doc", CommentKind::Line))`.
+ /// * `/** doc */` returns `Some(("doc", CommentKind::Block))`.
+ /// * `#[doc = "doc"]` returns `Some(("doc", CommentKind::Line))`.
+ /// * `#[doc(...)]` returns `None`.
pub fn doc_str_and_comment_kind(&self) -> Option<(Symbol, CommentKind)> {
match self.kind {
AttrKind::DocComment(kind, data) => Some((data, kind)),
- AttrKind::Normal(ref item, _) if item.path == sym::doc => item
+ AttrKind::Normal(ref normal) if normal.item.path == sym::doc => normal
+ .item
.meta_kind()
.and_then(|kind| kind.value_str())
.map(|data| (data, CommentKind::Line)),
@@ -255,11 +264,15 @@ impl Attribute {
}
}
+ /// Returns the documentation if this is a doc comment or a sugared doc comment.
+ /// * `///doc` returns `Some("doc")`.
+ /// * `#[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 item, _) if item.path == sym::doc => {
- item.meta_kind().and_then(|kind| kind.value_str())
+ AttrKind::Normal(ref normal) if normal.item.path == sym::doc => {
+ normal.item.meta_kind().and_then(|kind| kind.value_str())
}
_ => None,
}
@@ -271,14 +284,14 @@ impl Attribute {
pub fn get_normal_item(&self) -> &AttrItem {
match self.kind {
- AttrKind::Normal(ref item, _) => item,
+ AttrKind::Normal(ref normal) => &normal.item,
AttrKind::DocComment(..) => panic!("unexpected doc comment"),
}
}
pub fn unwrap_normal_item(self) -> AttrItem {
match self.kind {
- AttrKind::Normal(item, _) => item,
+ AttrKind::Normal(normal) => normal.into_inner().item,
AttrKind::DocComment(..) => panic!("unexpected doc comment"),
}
}
@@ -286,31 +299,30 @@ impl Attribute {
/// Extracts the MetaItem from inside this Attribute.
pub fn meta(&self) -> Option<MetaItem> {
match self.kind {
- AttrKind::Normal(ref item, _) => item.meta(self.span),
+ AttrKind::Normal(ref normal) => normal.item.meta(self.span),
AttrKind::DocComment(..) => None,
}
}
pub fn meta_kind(&self) -> Option<MetaItemKind> {
match self.kind {
- AttrKind::Normal(ref item, _) => item.meta_kind(),
+ AttrKind::Normal(ref normal) => normal.item.meta_kind(),
AttrKind::DocComment(..) => None,
}
}
- pub fn tokens(&self) -> AttrAnnotatedTokenStream {
+ pub fn tokens(&self) -> TokenStream {
match self.kind {
- AttrKind::Normal(_, ref tokens) => tokens
+ AttrKind::Normal(ref normal) => normal
+ .tokens
.as_ref()
.unwrap_or_else(|| panic!("attribute is missing tokens: {:?}", self))
- .create_token_stream(),
- AttrKind::DocComment(comment_kind, data) => AttrAnnotatedTokenStream::from((
- AttrAnnotatedTokenTree::Token(Token::new(
- token::DocComment(comment_kind, self.style, data),
- self.span,
- )),
+ .to_attr_token_stream()
+ .to_tokenstream(),
+ AttrKind::DocComment(comment_kind, data) => TokenStream::new(vec![TokenTree::Token(
+ Token::new(token::DocComment(comment_kind, self.style, data), self.span),
Spacing::Alone,
- )),
+ )]),
}
}
}
@@ -340,47 +352,86 @@ pub fn mk_nested_word_item(ident: Ident) -> NestedMetaItem {
NestedMetaItem::MetaItem(mk_word_item(ident))
}
-pub(crate) fn mk_attr_id() -> AttrId {
- use std::sync::atomic::AtomicU32;
- use std::sync::atomic::Ordering;
+pub struct AttrIdGenerator(WorkerLocal<Cell<u32>>);
- static NEXT_ATTR_ID: AtomicU32 = AtomicU32::new(0);
+#[cfg(debug_assertions)]
+static MAX_ATTR_ID: AtomicU32 = AtomicU32::new(u32::MAX);
- let id = NEXT_ATTR_ID.fetch_add(1, Ordering::SeqCst);
- assert!(id != u32::MAX);
- AttrId::from_u32(id)
+impl AttrIdGenerator {
+ pub fn new() -> Self {
+ // We use `(index as u32).reverse_bits()` to initialize the
+ // starting value of AttrId in each worker thread.
+ // The `index` is the index of the worker thread.
+ // This ensures that the AttrId generated in each thread is unique.
+ AttrIdGenerator(WorkerLocal::new(|index| {
+ let index: u32 = index.try_into().unwrap();
+
+ #[cfg(debug_assertions)]
+ {
+ let max_id = ((index + 1).next_power_of_two() - 1).bitxor(u32::MAX).reverse_bits();
+ MAX_ATTR_ID.fetch_min(max_id, Ordering::Release);
+ }
+
+ Cell::new(index.reverse_bits())
+ }))
+ }
+
+ pub fn mk_attr_id(&self) -> AttrId {
+ let id = self.0.get();
+
+ // Ensure the assigned attr_id does not overlap the bits
+ // representing the number of threads.
+ #[cfg(debug_assertions)]
+ assert!(id <= MAX_ATTR_ID.load(Ordering::Acquire));
+
+ self.0.set(id + 1);
+ AttrId::from_u32(id)
+ }
}
-pub fn mk_attr(style: AttrStyle, path: Path, args: MacArgs, span: Span) -> Attribute {
- mk_attr_from_item(AttrItem { path, args, tokens: None }, None, style, span)
+pub fn mk_attr(
+ g: &AttrIdGenerator,
+ style: AttrStyle,
+ path: Path,
+ args: MacArgs,
+ span: Span,
+) -> Attribute {
+ mk_attr_from_item(g, AttrItem { path, args, tokens: None }, None, style, span)
}
pub fn mk_attr_from_item(
+ g: &AttrIdGenerator,
item: AttrItem,
- tokens: Option<LazyTokenStream>,
+ tokens: Option<LazyAttrTokenStream>,
style: AttrStyle,
span: Span,
) -> Attribute {
- Attribute { kind: AttrKind::Normal(item, tokens), id: mk_attr_id(), style, span }
+ Attribute {
+ kind: AttrKind::Normal(P(ast::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(item: MetaItem) -> Attribute {
- mk_attr(AttrStyle::Inner, item.path, item.kind.mac_args(item.span), item.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)
}
/// Returns an outer attribute with the given value and span.
-pub fn mk_attr_outer(item: MetaItem) -> Attribute {
- mk_attr(AttrStyle::Outer, item.path, item.kind.mac_args(item.span), item.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_doc_comment(
+ g: &AttrIdGenerator,
comment_kind: CommentKind,
style: AttrStyle,
data: Symbol,
span: Span,
) -> Attribute {
- Attribute { kind: AttrKind::DocComment(comment_kind, data), id: mk_attr_id(), style, span }
+ Attribute { kind: AttrKind::DocComment(comment_kind, data), id: g.mk_attr_id(), style, span }
}
pub fn list_contains_name(items: &[NestedMetaItem], name: Symbol) -> bool {
@@ -484,7 +535,7 @@ impl MetaItemKind {
id: ast::DUMMY_NODE_ID,
kind: ast::ExprKind::Lit(lit.clone()),
span: lit.span,
- attrs: ThinVec::new(),
+ attrs: ast::AttrVec::new(),
tokens: None,
});
MacArgs::Eq(span, MacArgsEq::Ast(expr))
diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs
index 4b94ec0d6..bd7a85b07 100644
--- a/compiler/rustc_ast/src/lib.rs
+++ b/compiler/rustc_ast/src/lib.rs
@@ -13,17 +13,23 @@
#![feature(const_default_impls)]
#![feature(const_trait_impl)]
#![feature(if_let_guard)]
-#![feature(label_break_value)]
+#![cfg_attr(bootstrap, feature(label_break_value))]
#![feature(let_chains)]
+#![cfg_attr(bootstrap, feature(let_else))]
#![feature(min_specialization)]
#![feature(negative_impls)]
#![feature(slice_internals)]
#![feature(stmt_expr_attributes)]
#![recursion_limit = "256"]
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
#[macro_use]
extern crate rustc_macros;
+#[macro_use]
+extern crate tracing;
+
pub mod util {
pub mod classify;
pub mod comments;
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 01bd498b3..9fd0b63c4 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -14,7 +14,6 @@ use crate::tokenstream::*;
use rustc_data_structures::map_in_place::MapInPlace;
use rustc_data_structures::sync::Lrc;
-use rustc_data_structures::thin_vec::ThinVec;
use rustc_span::source_map::Spanned;
use rustc_span::symbol::Ident;
use rustc_span::Span;
@@ -338,12 +337,7 @@ where
}
// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
-pub fn visit_attrs<T: MutVisitor>(attrs: &mut Vec<Attribute>, vis: &mut T) {
- visit_vec(attrs, |attr| vis.visit_attribute(attr));
-}
-
-// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
-pub fn visit_thin_attrs<T: MutVisitor>(attrs: &mut AttrVec, vis: &mut T) {
+pub fn visit_attrs<T: MutVisitor>(attrs: &mut AttrVec, vis: &mut T) {
for attr in attrs.iter_mut() {
vis.visit_attribute(attr);
}
@@ -398,7 +392,7 @@ pub fn noop_flat_map_pat_field<T: MutVisitor>(
vis.visit_ident(ident);
vis.visit_pat(pat);
vis.visit_span(span);
- visit_thin_attrs(attrs, vis);
+ visit_attrs(attrs, vis);
smallvec![fp]
}
@@ -424,7 +418,7 @@ pub fn noop_visit_use_tree<T: MutVisitor>(use_tree: &mut UseTree, vis: &mut T) {
pub fn noop_flat_map_arm<T: MutVisitor>(mut arm: Arm, vis: &mut T) -> SmallVec<[Arm; 1]> {
let Arm { attrs, pat, guard, body, span, id, is_placeholder: _ } = &mut arm;
- visit_thin_attrs(attrs, vis);
+ visit_attrs(attrs, vis);
vis.visit_id(id);
vis.visit_pat(pat);
visit_opt(guard, |guard| vis.visit_expr(guard));
@@ -507,7 +501,7 @@ pub fn noop_flat_map_variant<T: MutVisitor>(
let Variant { ident, vis, attrs, id, data, disr_expr, span, is_placeholder: _ } = &mut variant;
visitor.visit_ident(ident);
visitor.visit_vis(vis);
- visit_thin_attrs(attrs, visitor);
+ visit_attrs(attrs, visitor);
visitor.visit_id(id);
visitor.visit_variant_data(data);
visit_opt(disr_expr, |disr_expr| visitor.visit_anon_const(disr_expr));
@@ -589,14 +583,16 @@ pub fn noop_visit_local<T: MutVisitor>(local: &mut P<Local>, vis: &mut T) {
}
}
vis.visit_span(span);
- visit_thin_attrs(attrs, vis);
+ visit_attrs(attrs, vis);
visit_lazy_tts(tokens, vis);
}
pub fn noop_visit_attribute<T: MutVisitor>(attr: &mut Attribute, vis: &mut T) {
let Attribute { kind, id: _, style: _, span } = attr;
match kind {
- AttrKind::Normal(AttrItem { path, args, tokens }, attr_tokens) => {
+ AttrKind::Normal(normal) => {
+ let NormalAttr { item: AttrItem { path, args, tokens }, tokens: attr_tokens } =
+ &mut **normal;
vis.visit_path(path);
visit_mac_args(args, vis);
visit_lazy_tts(tokens, vis);
@@ -638,7 +634,7 @@ pub fn noop_visit_meta_item<T: MutVisitor>(mi: &mut MetaItem, vis: &mut T) {
pub fn noop_flat_map_param<T: MutVisitor>(mut param: Param, vis: &mut T) -> SmallVec<[Param; 1]> {
let Param { attrs, id, pat, span, ty, is_placeholder: _ } = &mut param;
vis.visit_id(id);
- visit_thin_attrs(attrs, vis);
+ visit_attrs(attrs, vis);
vis.visit_pat(pat);
vis.visit_span(span);
vis.visit_ty(ty);
@@ -646,21 +642,21 @@ pub fn noop_flat_map_param<T: MutVisitor>(mut param: Param, vis: &mut T) -> Smal
}
// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
-pub fn visit_attr_annotated_tt<T: MutVisitor>(tt: &mut AttrAnnotatedTokenTree, vis: &mut T) {
+pub fn visit_attr_tt<T: MutVisitor>(tt: &mut AttrTokenTree, vis: &mut T) {
match tt {
- AttrAnnotatedTokenTree::Token(token) => {
+ AttrTokenTree::Token(token, _) => {
visit_token(token, vis);
}
- AttrAnnotatedTokenTree::Delimited(DelimSpan { open, close }, _delim, tts) => {
+ AttrTokenTree::Delimited(DelimSpan { open, close }, _delim, tts) => {
vis.visit_span(open);
vis.visit_span(close);
- visit_attr_annotated_tts(tts, vis);
+ visit_attr_tts(tts, vis);
}
- AttrAnnotatedTokenTree::Attributes(data) => {
+ AttrTokenTree::Attributes(data) => {
for attr in &mut *data.attrs {
match &mut attr.kind {
- AttrKind::Normal(_, attr_tokens) => {
- visit_lazy_tts(attr_tokens, vis);
+ AttrKind::Normal(normal) => {
+ visit_lazy_tts(&mut normal.tokens, vis);
}
AttrKind::DocComment(..) => {
vis.visit_span(&mut attr.span);
@@ -694,27 +690,27 @@ pub fn visit_tts<T: MutVisitor>(TokenStream(tts): &mut TokenStream, vis: &mut T)
}
}
-pub fn visit_attr_annotated_tts<T: MutVisitor>(
- AttrAnnotatedTokenStream(tts): &mut AttrAnnotatedTokenStream,
- vis: &mut T,
-) {
+pub fn visit_attr_tts<T: MutVisitor>(AttrTokenStream(tts): &mut AttrTokenStream, vis: &mut T) {
if T::VISIT_TOKENS && !tts.is_empty() {
let tts = Lrc::make_mut(tts);
- visit_vec(tts, |(tree, _is_joint)| visit_attr_annotated_tt(tree, vis));
+ visit_vec(tts, |tree| visit_attr_tt(tree, vis));
}
}
-pub fn visit_lazy_tts_opt_mut<T: MutVisitor>(lazy_tts: Option<&mut LazyTokenStream>, vis: &mut T) {
+pub fn visit_lazy_tts_opt_mut<T: MutVisitor>(
+ lazy_tts: Option<&mut LazyAttrTokenStream>,
+ vis: &mut T,
+) {
if T::VISIT_TOKENS {
if let Some(lazy_tts) = lazy_tts {
- let mut tts = lazy_tts.create_token_stream();
- visit_attr_annotated_tts(&mut tts, vis);
- *lazy_tts = LazyTokenStream::new(tts);
+ let mut tts = lazy_tts.to_attr_token_stream();
+ visit_attr_tts(&mut tts, vis);
+ *lazy_tts = LazyAttrTokenStream::new(tts);
}
}
}
-pub fn visit_lazy_tts<T: MutVisitor>(lazy_tts: &mut Option<LazyTokenStream>, vis: &mut T) {
+pub fn visit_lazy_tts<T: MutVisitor>(lazy_tts: &mut Option<LazyAttrTokenStream>, vis: &mut T) {
visit_lazy_tts_opt_mut(lazy_tts.as_mut(), vis);
}
@@ -880,7 +876,7 @@ pub fn noop_flat_map_generic_param<T: MutVisitor>(
if let Some(ref mut colon_span) = colon_span {
vis.visit_span(colon_span);
}
- visit_thin_attrs(attrs, vis);
+ visit_attrs(attrs, vis);
visit_vec(bounds, |bound| noop_visit_param_bound(bound, vis));
match kind {
GenericParamKind::Lifetime => {}
@@ -933,8 +929,7 @@ pub fn noop_visit_where_predicate<T: MutVisitor>(pred: &mut WherePredicate, vis:
visit_vec(bounds, |bound| noop_visit_param_bound(bound, vis));
}
WherePredicate::EqPredicate(ep) => {
- let WhereEqPredicate { id, span, lhs_ty, rhs_ty } = ep;
- vis.visit_id(id);
+ let WhereEqPredicate { span, lhs_ty, rhs_ty } = ep;
vis.visit_span(span);
vis.visit_ty(lhs_ty);
vis.visit_ty(rhs_ty);
@@ -977,7 +972,7 @@ pub fn noop_flat_map_field_def<T: MutVisitor>(
visitor.visit_vis(vis);
visitor.visit_id(id);
visitor.visit_ty(ty);
- visit_thin_attrs(attrs, visitor);
+ visit_attrs(attrs, visitor);
smallvec![fd]
}
@@ -990,7 +985,7 @@ pub fn noop_flat_map_expr_field<T: MutVisitor>(
vis.visit_expr(expr);
vis.visit_id(id);
vis.visit_span(span);
- visit_thin_attrs(attrs, vis);
+ visit_attrs(attrs, vis);
smallvec![f]
}
@@ -1430,7 +1425,7 @@ pub fn noop_visit_expr<T: MutVisitor>(
}
vis.visit_id(id);
vis.visit_span(span);
- visit_thin_attrs(attrs, vis);
+ visit_attrs(attrs, vis);
visit_lazy_tts(tokens, vis);
}
@@ -1476,7 +1471,7 @@ pub fn noop_flat_map_stmt_kind<T: MutVisitor>(
StmtKind::MacCall(mut mac) => {
let MacCallStmt { mac: mac_, style: _, attrs, tokens } = mac.deref_mut();
vis.visit_mac_call(mac_);
- visit_thin_attrs(attrs, vis);
+ visit_attrs(attrs, vis);
visit_lazy_tts(tokens, vis);
smallvec![StmtKind::MacCall(mac)]
}
@@ -1486,7 +1481,7 @@ pub fn noop_flat_map_stmt_kind<T: MutVisitor>(
pub fn noop_visit_vis<T: MutVisitor>(visibility: &mut Visibility, vis: &mut T) {
match &mut visibility.kind {
VisibilityKind::Public | VisibilityKind::Inherited => {}
- VisibilityKind::Restricted { path, id } => {
+ VisibilityKind::Restricted { path, id, shorthand: _ } => {
vis.visit_path(path);
vis.visit_id(id);
}
@@ -1511,12 +1506,6 @@ impl<T: DummyAstNode + 'static> DummyAstNode for P<T> {
}
}
-impl<T> DummyAstNode for ThinVec<T> {
- fn dummy() -> Self {
- Default::default()
- }
-}
-
impl DummyAstNode for Item {
fn dummy() -> Self {
Item {
diff --git a/compiler/rustc_ast/src/node_id.rs b/compiler/rustc_ast/src/node_id.rs
index 7f928cb57..7b5acc3f4 100644
--- a/compiler/rustc_ast/src/node_id.rs
+++ b/compiler/rustc_ast/src/node_id.rs
@@ -13,7 +13,7 @@ rustc_index::newtype_index! {
}
}
-rustc_data_structures::define_id_collections!(NodeMap, NodeSet, NodeId);
+rustc_data_structures::define_id_collections!(NodeMap, NodeSet, NodeMapEntry, NodeId);
/// The [`NodeId`] used to represent the root of the crate.
pub const CRATE_NODE_ID: NodeId = NodeId::from_u32(0);
diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs
index 85d9687c6..97dfb7837 100644
--- a/compiler/rustc_ast/src/token.rs
+++ b/compiler/rustc_ast/src/token.rs
@@ -398,6 +398,30 @@ impl Token {
}
}
+ /// Returns `true` if the token can appear at the start of an pattern.
+ ///
+ /// Shamelessly borrowed from `can_begin_expr`, only used for diagnostics right now.
+ pub fn can_begin_pattern(&self) -> bool {
+ match self.uninterpolate().kind {
+ Ident(name, is_raw) =>
+ ident_can_begin_expr(name, self.span, is_raw), // value name or keyword
+ | OpenDelim(Delimiter::Bracket | Delimiter::Parenthesis) // tuple or array
+ | Literal(..) // literal
+ | BinOp(Minus) // unary minus
+ | BinOp(And) // reference
+ | AndAnd // double reference
+ // DotDotDot is no longer supported
+ | DotDot | DotDotDot | DotDotEq // ranges
+ | Lt | BinOp(Shl) // associated path
+ | ModSep => true, // global path
+ Interpolated(ref nt) => matches!(**nt, NtLiteral(..) |
+ NtPat(..) |
+ NtBlock(..) |
+ NtPath(..)),
+ _ => false,
+ }
+ }
+
/// Returns `true` if the token can appear at the start of a type.
pub fn can_begin_type(&self) -> bool {
match self.uninterpolate().kind {
@@ -436,6 +460,31 @@ impl Token {
|| self == &OpenDelim(Delimiter::Parenthesis)
}
+ /// Returns `true` if the token can appear at the start of an item.
+ pub fn can_begin_item(&self) -> bool {
+ match self.kind {
+ Ident(name, _) => [
+ kw::Fn,
+ kw::Use,
+ kw::Struct,
+ kw::Enum,
+ kw::Pub,
+ kw::Trait,
+ kw::Extern,
+ kw::Impl,
+ kw::Unsafe,
+ kw::Const,
+ kw::Static,
+ kw::Union,
+ kw::Macro,
+ kw::Mod,
+ kw::Type,
+ ]
+ .contains(&name),
+ _ => false,
+ }
+ }
+
/// Returns `true` if the token is any literal.
pub fn is_lit(&self) -> bool {
matches!(self.kind, Literal(..))
diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs
index 9e4a22e1f..875cd620d 100644
--- a/compiler/rustc_ast/src/tokenstream.rs
+++ b/compiler/rustc_ast/src/tokenstream.rs
@@ -121,12 +121,12 @@ where
}
}
-pub trait CreateTokenStream: sync::Send + sync::Sync {
- fn create_token_stream(&self) -> AttrAnnotatedTokenStream;
+pub trait ToAttrTokenStream: sync::Send + sync::Sync {
+ fn to_attr_token_stream(&self) -> AttrTokenStream;
}
-impl CreateTokenStream for AttrAnnotatedTokenStream {
- fn create_token_stream(&self) -> AttrAnnotatedTokenStream {
+impl ToAttrTokenStream for AttrTokenStream {
+ fn to_attr_token_stream(&self) -> AttrTokenStream {
self.clone()
}
}
@@ -135,68 +135,68 @@ impl CreateTokenStream for AttrAnnotatedTokenStream {
/// of an actual `TokenStream` until it is needed.
/// `Box` is here only to reduce the structure size.
#[derive(Clone)]
-pub struct LazyTokenStream(Lrc<Box<dyn CreateTokenStream>>);
+pub struct LazyAttrTokenStream(Lrc<Box<dyn ToAttrTokenStream>>);
-impl LazyTokenStream {
- pub fn new(inner: impl CreateTokenStream + 'static) -> LazyTokenStream {
- LazyTokenStream(Lrc::new(Box::new(inner)))
+impl LazyAttrTokenStream {
+ pub fn new(inner: impl ToAttrTokenStream + 'static) -> LazyAttrTokenStream {
+ LazyAttrTokenStream(Lrc::new(Box::new(inner)))
}
- pub fn create_token_stream(&self) -> AttrAnnotatedTokenStream {
- self.0.create_token_stream()
+ pub fn to_attr_token_stream(&self) -> AttrTokenStream {
+ self.0.to_attr_token_stream()
}
}
-impl fmt::Debug for LazyTokenStream {
+impl fmt::Debug for LazyAttrTokenStream {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(f, "LazyTokenStream({:?})", self.create_token_stream())
+ write!(f, "LazyAttrTokenStream({:?})", self.to_attr_token_stream())
}
}
-impl<S: Encoder> Encodable<S> for LazyTokenStream {
+impl<S: Encoder> Encodable<S> for LazyAttrTokenStream {
fn encode(&self, s: &mut S) {
// Used by AST json printing.
- Encodable::encode(&self.create_token_stream(), s);
+ Encodable::encode(&self.to_attr_token_stream(), s);
}
}
-impl<D: Decoder> Decodable<D> for LazyTokenStream {
+impl<D: Decoder> Decodable<D> for LazyAttrTokenStream {
fn decode(_d: &mut D) -> Self {
- panic!("Attempted to decode LazyTokenStream");
+ panic!("Attempted to decode LazyAttrTokenStream");
}
}
-impl<CTX> HashStable<CTX> for LazyTokenStream {
+impl<CTX> HashStable<CTX> for LazyAttrTokenStream {
fn hash_stable(&self, _hcx: &mut CTX, _hasher: &mut StableHasher) {
- panic!("Attempted to compute stable hash for LazyTokenStream");
+ panic!("Attempted to compute stable hash for LazyAttrTokenStream");
}
}
-/// A `AttrAnnotatedTokenStream` is similar to a `TokenStream`, but with extra
+/// An `AttrTokenStream` is similar to a `TokenStream`, but with extra
/// information about the tokens for attribute targets. This is used
/// during expansion to perform early cfg-expansion, and to process attributes
/// during proc-macro invocations.
#[derive(Clone, Debug, Default, Encodable, Decodable)]
-pub struct AttrAnnotatedTokenStream(pub Lrc<Vec<(AttrAnnotatedTokenTree, Spacing)>>);
+pub struct AttrTokenStream(pub Lrc<Vec<AttrTokenTree>>);
-/// Like `TokenTree`, but for `AttrAnnotatedTokenStream`
+/// Like `TokenTree`, but for `AttrTokenStream`.
#[derive(Clone, Debug, Encodable, Decodable)]
-pub enum AttrAnnotatedTokenTree {
- Token(Token),
- Delimited(DelimSpan, Delimiter, AttrAnnotatedTokenStream),
+pub enum AttrTokenTree {
+ Token(Token, Spacing),
+ Delimited(DelimSpan, Delimiter, AttrTokenStream),
/// Stores the attributes for an attribute target,
/// along with the tokens for that attribute target.
/// See `AttributesData` for more information
Attributes(AttributesData),
}
-impl AttrAnnotatedTokenStream {
- pub fn new(tokens: Vec<(AttrAnnotatedTokenTree, Spacing)>) -> AttrAnnotatedTokenStream {
- AttrAnnotatedTokenStream(Lrc::new(tokens))
+impl AttrTokenStream {
+ pub fn new(tokens: Vec<AttrTokenTree>) -> AttrTokenStream {
+ AttrTokenStream(Lrc::new(tokens))
}
- /// Converts this `AttrAnnotatedTokenStream` to a plain `TokenStream
- /// During conversion, `AttrAnnotatedTokenTree::Attributes` get 'flattened'
+ /// Converts this `AttrTokenStream` to a plain `TokenStream`.
+ /// During conversion, `AttrTokenTree::Attributes` get 'flattened'
/// back to a `TokenStream` of the form `outer_attr attr_target`.
/// If there are inner attributes, they are inserted into the proper
/// place in the attribute target tokens.
@@ -204,31 +204,27 @@ impl AttrAnnotatedTokenStream {
let trees: Vec<_> = self
.0
.iter()
- .flat_map(|tree| match &tree.0 {
- AttrAnnotatedTokenTree::Token(inner) => {
- smallvec![TokenTree::Token(inner.clone(), tree.1)].into_iter()
+ .flat_map(|tree| match &tree {
+ AttrTokenTree::Token(inner, spacing) => {
+ smallvec![TokenTree::Token(inner.clone(), *spacing)].into_iter()
}
- AttrAnnotatedTokenTree::Delimited(span, delim, stream) => {
+ AttrTokenTree::Delimited(span, delim, stream) => {
smallvec![TokenTree::Delimited(*span, *delim, stream.to_tokenstream()),]
.into_iter()
}
- AttrAnnotatedTokenTree::Attributes(data) => {
+ AttrTokenTree::Attributes(data) => {
let mut outer_attrs = Vec::new();
let mut inner_attrs = Vec::new();
for attr in &data.attrs {
match attr.style {
- crate::AttrStyle::Outer => {
- outer_attrs.push(attr);
- }
- crate::AttrStyle::Inner => {
- inner_attrs.push(attr);
- }
+ crate::AttrStyle::Outer => outer_attrs.push(attr),
+ crate::AttrStyle::Inner => inner_attrs.push(attr),
}
}
let mut target_tokens: Vec<_> = data
.tokens
- .create_token_stream()
+ .to_attr_token_stream()
.to_tokenstream()
.0
.iter()
@@ -239,9 +235,9 @@ impl AttrAnnotatedTokenStream {
// Check the last two trees (to account for a trailing semi)
for tree in target_tokens.iter_mut().rev().take(2) {
if let TokenTree::Delimited(span, delim, delim_tokens) = tree {
- // Inner attributes are only supported on extern blocks, functions, impls,
- // and modules. All of these have their inner attributes placed at
- // the beginning of the rightmost outermost braced group:
+ // Inner attributes are only supported on extern blocks, functions,
+ // impls, and modules. All of these have their inner attributes
+ // placed at the beginning of the rightmost outermost braced group:
// e.g. fn foo() { #![my_attr} }
//
// Therefore, we can insert them back into the right location
@@ -255,7 +251,7 @@ impl AttrAnnotatedTokenStream {
let mut builder = TokenStreamBuilder::new();
for inner_attr in inner_attrs {
- builder.push(inner_attr.tokens().to_tokenstream());
+ builder.push(inner_attr.tokens());
}
builder.push(delim_tokens.clone());
*tree = TokenTree::Delimited(*span, *delim, builder.build());
@@ -273,7 +269,7 @@ impl AttrAnnotatedTokenStream {
let mut flat: SmallVec<[_; 1]> = SmallVec::new();
for attr in outer_attrs {
// FIXME: Make this more efficient
- flat.extend(attr.tokens().to_tokenstream().0.clone().iter().cloned());
+ flat.extend(attr.tokens().0.clone().iter().cloned());
}
flat.extend(target_tokens);
flat.into_iter()
@@ -300,7 +296,7 @@ pub struct AttributesData {
pub attrs: AttrVec,
/// The underlying tokens for the attribute target that `attrs`
/// are applied to
- pub tokens: LazyTokenStream,
+ pub tokens: LazyAttrTokenStream,
}
/// A `TokenStream` is an abstract sequence of tokens, organized into [`TokenTree`]s.
@@ -363,12 +359,6 @@ impl TokenStream {
}
}
-impl From<(AttrAnnotatedTokenTree, Spacing)> for AttrAnnotatedTokenStream {
- fn from((tree, spacing): (AttrAnnotatedTokenTree, Spacing)) -> AttrAnnotatedTokenStream {
- AttrAnnotatedTokenStream::new(vec![(tree, spacing)])
- }
-}
-
impl iter::FromIterator<TokenTree> for TokenStream {
fn from_iter<I: IntoIterator<Item = TokenTree>>(iter: I) -> Self {
TokenStream::new(iter.into_iter().collect::<Vec<TokenTree>>())
@@ -420,21 +410,6 @@ impl TokenStream {
TokenStream(Lrc::new(self.0.iter().enumerate().map(|(i, tree)| f(i, tree)).collect()))
}
- fn opt_from_ast(node: &(impl HasAttrs + HasTokens)) -> Option<TokenStream> {
- let tokens = node.tokens()?;
- let attrs = node.attrs();
- let attr_annotated = if attrs.is_empty() {
- tokens.create_token_stream()
- } else {
- let attr_data = AttributesData { attrs: attrs.to_vec().into(), tokens: tokens.clone() };
- AttrAnnotatedTokenStream::new(vec![(
- AttrAnnotatedTokenTree::Attributes(attr_data),
- Spacing::Alone,
- )])
- };
- Some(attr_annotated.to_tokenstream())
- }
-
// 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)])
@@ -451,8 +426,18 @@ impl TokenStream {
}
pub fn from_ast(node: &(impl HasAttrs + HasSpan + HasTokens + fmt::Debug)) -> TokenStream {
- TokenStream::opt_from_ast(node)
- .unwrap_or_else(|| panic!("missing tokens for node at {:?}: {:?}", node.span(), node))
+ let Some(tokens) = node.tokens() else {
+ panic!("missing tokens for node at {:?}: {:?}", node.span(), node);
+ };
+ let attrs = node.attrs();
+ let attr_stream = if attrs.is_empty() {
+ tokens.to_attr_token_stream()
+ } else {
+ let attr_data =
+ AttributesData { attrs: attrs.iter().cloned().collect(), tokens: tokens.clone() };
+ AttrTokenStream::new(vec![AttrTokenTree::Attributes(attr_data)])
+ };
+ attr_stream.to_tokenstream()
}
pub fn from_nonterminal_ast(nt: &Nonterminal) -> TokenStream {
@@ -555,7 +540,7 @@ impl TokenStreamBuilder {
// Get the first stream, which will become the result stream.
// If it's `None`, create an empty stream.
- let mut iter = streams.drain(..);
+ let mut iter = streams.into_iter();
let mut res_stream_lrc = iter.next().unwrap().0;
// Append the subsequent elements to the result stream, after
diff --git a/compiler/rustc_ast/src/util/literal.rs b/compiler/rustc_ast/src/util/literal.rs
index 9c18f55c0..536b38560 100644
--- a/compiler/rustc_ast/src/util/literal.rs
+++ b/compiler/rustc_ast/src/util/literal.rs
@@ -9,7 +9,6 @@ use rustc_span::symbol::{kw, sym, Symbol};
use rustc_span::Span;
use std::ascii;
-use tracing::debug;
pub enum LitError {
NotLiteral,
@@ -23,7 +22,7 @@ pub enum LitError {
impl LitKind {
/// Converts literal token into a semantic literal.
- pub fn from_lit_token(lit: token::Lit) -> Result<LitKind, LitError> {
+ pub fn from_token_lit(lit: token::Lit) -> Result<LitKind, LitError> {
let token::Lit { kind, symbol, suffix } = lit;
if suffix.is_some() && !kind.may_have_suffix() {
return Err(LitError::InvalidSuffix);
@@ -146,14 +145,14 @@ impl LitKind {
LitKind::ByteStr(bytes.into())
}
- token::Err => LitKind::Err(symbol),
+ token::Err => LitKind::Err,
})
}
/// Attempts to recover a token 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 to_lit_token(&self) -> token::Lit {
+ pub fn to_token_lit(&self) -> token::Lit {
let (kind, symbol, suffix) = match *self {
LitKind::Str(symbol, ast::StrStyle::Cooked) => {
// Don't re-intern unless the escaped string is different.
@@ -164,12 +163,7 @@ impl LitKind {
}
LitKind::Str(symbol, ast::StrStyle::Raw(n)) => (token::StrRaw(n), symbol, None),
LitKind::ByteStr(ref bytes) => {
- let string = bytes
- .iter()
- .cloned()
- .flat_map(ascii::escape_default)
- .map(Into::<char>::into)
- .collect::<String>();
+ let string = bytes.escape_ascii().to_string();
(token::ByteStr, Symbol::intern(&string), None)
}
LitKind::Byte(byte) => {
@@ -199,7 +193,9 @@ impl LitKind {
let symbol = if value { kw::True } else { kw::False };
(token::Bool, symbol, None)
}
- LitKind::Err(symbol) => (token::Err, symbol, None),
+ // This only shows up in places like `-Zunpretty=hir` output, so we
+ // don't bother to produce something useful.
+ LitKind::Err => (token::Err, Symbol::intern("<bad-literal>"), None),
};
token::Lit::new(kind, symbol, suffix)
@@ -208,8 +204,8 @@ impl LitKind {
impl Lit {
/// Converts literal token into an AST literal.
- pub fn from_lit_token(token: token::Lit, span: Span) -> Result<Lit, LitError> {
- Ok(Lit { token, kind: LitKind::from_lit_token(token)?, span })
+ 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.
@@ -232,21 +228,21 @@ impl Lit {
_ => return Err(LitError::NotLiteral),
};
- Lit::from_lit_token(lit, token.span)
+ 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: kind.to_lit_token(), kind, span }
+ Lit { token_lit: kind.to_token_lit(), kind, span }
}
/// Losslessly convert an AST literal into a token.
pub fn to_token(&self) -> Token {
- let kind = match self.token.kind {
- token::Bool => token::Ident(self.token.symbol, false),
- _ => token::Literal(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)
}
diff --git a/compiler/rustc_ast/src/util/parser.rs b/compiler/rustc_ast/src/util/parser.rs
index 74b7fe9e2..6c5c7f66f 100644
--- a/compiler/rustc_ast/src/util/parser.rs
+++ b/compiler/rustc_ast/src/util/parser.rs
@@ -297,11 +297,11 @@ impl ExprPrecedence {
match self {
ExprPrecedence::Closure => PREC_CLOSURE,
- ExprPrecedence::Break |
- ExprPrecedence::Continue |
- ExprPrecedence::Ret |
- ExprPrecedence::Yield |
- ExprPrecedence::Yeet => PREC_JUMP,
+ ExprPrecedence::Break
+ | ExprPrecedence::Continue
+ | ExprPrecedence::Ret
+ | ExprPrecedence::Yield
+ | ExprPrecedence::Yeet => PREC_JUMP,
// `Range` claims to have higher precedence than `Assign`, but `x .. x = x` fails to
// parse, instead of parsing as `(x .. x) = x`. Giving `Range` a lower precedence
@@ -318,43 +318,43 @@ impl ExprPrecedence {
ExprPrecedence::AssignOp => AssocOp::Assign.precedence() as i8,
// Unary, prefix
- ExprPrecedence::Box |
- ExprPrecedence::AddrOf |
+ ExprPrecedence::Box
+ | ExprPrecedence::AddrOf
// Here `let pats = expr` has `let pats =` as a "unary" prefix of `expr`.
// However, this is not exactly right. When `let _ = a` is the LHS of a binop we
// need parens sometimes. E.g. we can print `(let _ = a) && b` as `let _ = a && b`
// but we need to print `(let _ = a) < b` as-is with parens.
- ExprPrecedence::Let |
- ExprPrecedence::Unary => PREC_PREFIX,
+ | ExprPrecedence::Let
+ | ExprPrecedence::Unary => PREC_PREFIX,
// Unary, postfix
- ExprPrecedence::Await |
- ExprPrecedence::Call |
- ExprPrecedence::MethodCall |
- ExprPrecedence::Field |
- ExprPrecedence::Index |
- ExprPrecedence::Try |
- ExprPrecedence::InlineAsm |
- ExprPrecedence::Mac => PREC_POSTFIX,
+ ExprPrecedence::Await
+ | ExprPrecedence::Call
+ | ExprPrecedence::MethodCall
+ | ExprPrecedence::Field
+ | ExprPrecedence::Index
+ | ExprPrecedence::Try
+ | ExprPrecedence::InlineAsm
+ | ExprPrecedence::Mac => PREC_POSTFIX,
// Never need parens
- ExprPrecedence::Array |
- ExprPrecedence::Repeat |
- ExprPrecedence::Tup |
- ExprPrecedence::Lit |
- ExprPrecedence::Path |
- ExprPrecedence::Paren |
- ExprPrecedence::If |
- ExprPrecedence::While |
- ExprPrecedence::ForLoop |
- ExprPrecedence::Loop |
- ExprPrecedence::Match |
- ExprPrecedence::ConstBlock |
- ExprPrecedence::Block |
- ExprPrecedence::TryBlock |
- ExprPrecedence::Async |
- ExprPrecedence::Struct |
- ExprPrecedence::Err => PREC_PAREN,
+ ExprPrecedence::Array
+ | ExprPrecedence::Repeat
+ | ExprPrecedence::Tup
+ | ExprPrecedence::Lit
+ | ExprPrecedence::Path
+ | ExprPrecedence::Paren
+ | ExprPrecedence::If
+ | ExprPrecedence::While
+ | ExprPrecedence::ForLoop
+ | ExprPrecedence::Loop
+ | ExprPrecedence::Match
+ | ExprPrecedence::ConstBlock
+ | ExprPrecedence::Block
+ | ExprPrecedence::TryBlock
+ | ExprPrecedence::Async
+ | ExprPrecedence::Struct
+ | ExprPrecedence::Err => PREC_PAREN,
}
}
}
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index d9594b323..1d0de5a4b 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -156,8 +156,8 @@ pub trait Visitor<'ast>: Sized {
fn visit_where_predicate(&mut self, p: &'ast WherePredicate) {
walk_where_predicate(self, p)
}
- fn visit_fn(&mut self, fk: FnKind<'ast>, s: Span, _: NodeId) {
- walk_fn(self, fk, s)
+ fn visit_fn(&mut self, fk: FnKind<'ast>, _: Span, _: NodeId) {
+ walk_fn(self, fk)
}
fn visit_assoc_item(&mut self, i: &'ast AssocItem, ctxt: AssocCtxt) {
walk_assoc_item(self, i, ctxt)
@@ -168,8 +168,8 @@ pub trait Visitor<'ast>: Sized {
fn visit_param_bound(&mut self, bounds: &'ast GenericBound, _ctxt: BoundKind) {
walk_param_bound(self, bounds)
}
- fn visit_poly_trait_ref(&mut self, t: &'ast PolyTraitRef, m: &'ast TraitBoundModifier) {
- walk_poly_trait_ref(self, t, m)
+ fn visit_poly_trait_ref(&mut self, t: &'ast PolyTraitRef) {
+ walk_poly_trait_ref(self, t)
}
fn visit_variant_data(&mut self, s: &'ast VariantData) {
walk_struct_def(self, s)
@@ -177,14 +177,8 @@ pub trait Visitor<'ast>: Sized {
fn visit_field_def(&mut self, s: &'ast FieldDef) {
walk_field_def(self, s)
}
- fn visit_enum_def(
- &mut self,
- enum_definition: &'ast EnumDef,
- generics: &'ast Generics,
- item_id: NodeId,
- _: Span,
- ) {
- walk_enum_def(self, enum_definition, generics, item_id)
+ fn visit_enum_def(&mut self, enum_definition: &'ast EnumDef) {
+ walk_enum_def(self, enum_definition)
}
fn visit_variant(&mut self, v: &'ast Variant) {
walk_variant(self, v)
@@ -207,11 +201,11 @@ pub trait Visitor<'ast>: Sized {
fn visit_use_tree(&mut self, use_tree: &'ast UseTree, id: NodeId, _nested: bool) {
walk_use_tree(self, use_tree, id)
}
- fn visit_path_segment(&mut self, path_span: Span, path_segment: &'ast PathSegment) {
- walk_path_segment(self, path_span, path_segment)
+ fn visit_path_segment(&mut self, path_segment: &'ast PathSegment) {
+ walk_path_segment(self, path_segment)
}
- fn visit_generic_args(&mut self, path_span: Span, generic_args: &'ast GenericArgs) {
- walk_generic_args(self, path_span, generic_args)
+ fn visit_generic_args(&mut self, generic_args: &'ast GenericArgs) {
+ walk_generic_args(self, generic_args)
}
fn visit_generic_arg(&mut self, generic_arg: &'ast GenericArg) {
walk_generic_arg(self, generic_arg)
@@ -287,11 +281,8 @@ pub fn walk_lifetime<'a, V: Visitor<'a>>(visitor: &mut V, lifetime: &'a Lifetime
visitor.visit_ident(lifetime.ident);
}
-pub fn walk_poly_trait_ref<'a, V>(
- visitor: &mut V,
- trait_ref: &'a PolyTraitRef,
- _: &TraitBoundModifier,
-) where
+pub fn walk_poly_trait_ref<'a, V>(visitor: &mut V, trait_ref: &'a PolyTraitRef)
+where
V: Visitor<'a>,
{
walk_list!(visitor, visit_generic_param, &trait_ref.bound_generic_params);
@@ -334,7 +325,7 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
}
ItemKind::Enum(ref enum_definition, ref generics) => {
visitor.visit_generics(generics);
- visitor.visit_enum_def(enum_definition, generics, item.id, item.span)
+ visitor.visit_enum_def(enum_definition)
}
ItemKind::Impl(box Impl {
defaultness: _,
@@ -377,12 +368,7 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
walk_list!(visitor, visit_attribute, &item.attrs);
}
-pub fn walk_enum_def<'a, V: Visitor<'a>>(
- visitor: &mut V,
- enum_definition: &'a EnumDef,
- _: &'a Generics,
- _: NodeId,
-) {
+pub fn walk_enum_def<'a, V: Visitor<'a>>(visitor: &mut V, enum_definition: &'a EnumDef) {
walk_list!(visitor, visit_variant, &enum_definition.variants);
}
@@ -449,7 +435,7 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) {
pub fn walk_path<'a, V: Visitor<'a>>(visitor: &mut V, path: &'a Path) {
for segment in &path.segments {
- visitor.visit_path_segment(path.span, segment);
+ visitor.visit_path_segment(segment);
}
}
@@ -471,18 +457,14 @@ 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,
- path_span: Span,
- segment: &'a PathSegment,
-) {
+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 {
- visitor.visit_generic_args(path_span, args);
+ visitor.visit_generic_args(args);
}
}
-pub fn walk_generic_args<'a, V>(visitor: &mut V, _path_span: Span, generic_args: &'a GenericArgs)
+pub fn walk_generic_args<'a, V>(visitor: &mut V, generic_args: &'a GenericArgs)
where
V: Visitor<'a>,
{
@@ -516,7 +498,7 @@ 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 {
- visitor.visit_generic_args(gen_args.span(), gen_args);
+ visitor.visit_generic_args(gen_args);
}
match constraint.kind {
AssocConstraintKind::Equality { ref term } => match term {
@@ -598,7 +580,7 @@ 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, modifier),
+ GenericBound::Trait(ref typ, ref _modifier) => visitor.visit_poly_trait_ref(typ),
GenericBound::Outlives(ref lifetime) => {
visitor.visit_lifetime(lifetime, LifetimeCtxt::Bound)
}
@@ -673,7 +655,7 @@ pub fn walk_fn_decl<'a, V: Visitor<'a>>(visitor: &mut V, function_declaration: &
visitor.visit_fn_ret_ty(&function_declaration.output);
}
-pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>, _span: Span) {
+pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>) {
match kind {
FnKind::Fn(_, _, sig, _, generics, body) => {
visitor.visit_generics(generics);
@@ -814,7 +796,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
walk_list!(visitor, visit_expr, arguments);
}
ExprKind::MethodCall(ref segment, ref arguments, _span) => {
- visitor.visit_path_segment(expression.span, segment);
+ visitor.visit_path_segment(segment);
walk_list!(visitor, visit_expr, arguments);
}
ExprKind::Binary(_, ref left_expression, ref right_expression) => {
@@ -935,14 +917,14 @@ pub fn walk_arm<'a, V: Visitor<'a>>(visitor: &mut V, arm: &'a Arm) {
}
pub fn walk_vis<'a, V: Visitor<'a>>(visitor: &mut V, vis: &'a Visibility) {
- if let VisibilityKind::Restricted { ref path, id } = vis.kind {
+ if let VisibilityKind::Restricted { ref path, id, shorthand: _ } = vis.kind {
visitor.visit_path(path, id);
}
}
pub fn walk_attribute<'a, V: Visitor<'a>>(visitor: &mut V, attr: &'a Attribute) {
match attr.kind {
- AttrKind::Normal(ref item, ref _tokens) => walk_mac_args(visitor, &item.args),
+ AttrKind::Normal(ref normal) => walk_mac_args(visitor, &normal.item.args),
AttrKind::DocComment(..) => {}
}
}