diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:03:36 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:03:36 +0000 |
commit | 17d40c6057c88f4c432b0d7bac88e1b84cb7e67f (patch) | |
tree | 3f66c4a5918660bb8a758ab6cda5ff8ee4f6cdcd /compiler/rustc_ast | |
parent | Adding upstream version 1.64.0+dfsg1. (diff) | |
download | rustc-17d40c6057c88f4c432b0d7bac88e1b84cb7e67f.tar.xz rustc-17d40c6057c88f4c432b0d7bac88e1b84cb7e67f.zip |
Adding upstream version 1.65.0+dfsg1.upstream/1.65.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
32 files changed, 1927 insertions, 1394 deletions
diff --git a/compiler/rustc_ast/Cargo.toml b/compiler/rustc_ast/Cargo.toml index 9822e9864..c24180bac 100644 --- a/compiler/rustc_ast/Cargo.toml +++ b/compiler/rustc_ast/Cargo.toml @@ -7,12 +7,13 @@ edition = "2021" doctest = false [dependencies] -rustc_serialize = { path = "../rustc_serialize" } -tracing = "0.1" -rustc_span = { path = "../rustc_span" } +bitflags = "1.2.1" rustc_data_structures = { path = "../rustc_data_structures" } rustc_index = { path = "../rustc_index" } rustc_lexer = { path = "../rustc_lexer" } rustc_macros = { path = "../rustc_macros" } +rustc_serialize = { path = "../rustc_serialize" } +rustc_span = { path = "../rustc_span" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } -bitflags = "1.2.1" +thin-vec = "0.2.8" +tracing = "0.1" 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(..) => {} } } diff --git a/compiler/rustc_ast_lowering/Cargo.toml b/compiler/rustc_ast_lowering/Cargo.toml index 39ba62ef2..ce1c8d499 100644 --- a/compiler/rustc_ast_lowering/Cargo.toml +++ b/compiler/rustc_ast_lowering/Cargo.toml @@ -8,16 +8,18 @@ doctest = false [dependencies] rustc_arena = { path = "../rustc_arena" } -tracing = "0.1" +rustc_ast = { path = "../rustc_ast" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } -rustc_hir = { path = "../rustc_hir" } -rustc_target = { path = "../rustc_target" } rustc_data_structures = { path = "../rustc_data_structures" } +rustc_errors = { path = "../rustc_errors" } +rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } rustc_middle = { path = "../rustc_middle" } +rustc_macros = { path = "../rustc_macros" } rustc_query_system = { path = "../rustc_query_system" } -rustc_span = { path = "../rustc_span" } -rustc_errors = { path = "../rustc_errors" } rustc_session = { path = "../rustc_session" } -rustc_ast = { path = "../rustc_ast" } +rustc_span = { path = "../rustc_span" } +rustc_target = { path = "../rustc_target" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } +thin-vec = "0.2.8" +tracing = "0.1" diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index 4166b4fc2..24672efc6 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -1,11 +1,17 @@ use crate::{ImplTraitContext, ImplTraitPosition, ParamMode, ResolverAstLoweringExt}; +use super::errors::{ + AbiSpecifiedMultipleTimes, AttSyntaxOnlyX86, ClobberAbiNotSupported, + InlineAsmUnsupportedTarget, InvalidAbiClobberAbi, InvalidAsmTemplateModifierConst, + InvalidAsmTemplateModifierRegClass, InvalidAsmTemplateModifierRegClassSub, + InvalidAsmTemplateModifierSym, InvalidRegister, InvalidRegisterClass, RegisterClassOnlyClobber, + RegisterConflict, +}; use super::LoweringContext; use rustc_ast::ptr::P; use rustc_ast::*; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::definitions::DefPathData; @@ -26,13 +32,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let asm_arch = if self.tcx.sess.opts.actually_rustdoc { None } else { self.tcx.sess.asm_arch }; if asm_arch.is_none() && !self.tcx.sess.opts.actually_rustdoc { - struct_span_err!( - self.tcx.sess, - sp, - E0472, - "inline assembly is unsupported on this target" - ) - .emit(); + self.tcx.sess.emit_err(InlineAsmUnsupportedTarget { span: sp }); } if let Some(asm_arch) = asm_arch { // Inline assembly is currently only stable for these architectures. @@ -59,10 +59,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { && !matches!(asm_arch, Some(asm::InlineAsmArch::X86 | asm::InlineAsmArch::X86_64)) && !self.tcx.sess.opts.actually_rustdoc { - self.tcx - .sess - .struct_span_err(sp, "the `att_syntax` option is only supported on x86") - .emit(); + self.tcx.sess.emit_err(AttSyntaxOnlyX86 { span: sp }); } if asm.options.contains(InlineAsmOptions::MAY_UNWIND) && !self.tcx.features().asm_unwind { feature_err( @@ -82,51 +79,37 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // If the abi was already in the list, emit an error match clobber_abis.get(&abi) { Some((prev_name, prev_sp)) => { - let mut err = self.tcx.sess.struct_span_err( - *abi_span, - &format!("`{}` ABI specified multiple times", prev_name), - ); - err.span_label(*prev_sp, "previously specified here"); - // Multiple different abi names may actually be the same ABI // If the specified ABIs are not the same name, alert the user that they resolve to the same ABI let source_map = self.tcx.sess.source_map(); - if source_map.span_to_snippet(*prev_sp) - != source_map.span_to_snippet(*abi_span) - { - err.note("these ABIs are equivalent on the current target"); - } + let equivalent = (source_map.span_to_snippet(*prev_sp) + != source_map.span_to_snippet(*abi_span)) + .then_some(()); - err.emit(); + self.tcx.sess.emit_err(AbiSpecifiedMultipleTimes { + abi_span: *abi_span, + prev_name: *prev_name, + prev_span: *prev_sp, + equivalent, + }); } None => { - clobber_abis.insert(abi, (abi_name, *abi_span)); + clobber_abis.insert(abi, (*abi_name, *abi_span)); } } } Err(&[]) => { - self.tcx - .sess - .struct_span_err( - *abi_span, - "`clobber_abi` is not supported on this target", - ) - .emit(); + self.tcx.sess.emit_err(ClobberAbiNotSupported { abi_span: *abi_span }); } Err(supported_abis) => { - let mut err = self - .tcx - .sess - .struct_span_err(*abi_span, "invalid ABI for `clobber_abi`"); let mut abis = format!("`{}`", supported_abis[0]); for m in &supported_abis[1..] { let _ = write!(abis, ", `{}`", m); } - err.note(&format!( - "the following ABIs are supported on this target: {}", - abis - )); - err.emit(); + self.tcx.sess.emit_err(InvalidAbiClobberAbi { + abi_span: *abi_span, + supported_abis: abis, + }); } } } @@ -141,24 +124,28 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { .iter() .map(|(op, op_sp)| { let lower_reg = |reg| match reg { - InlineAsmRegOrRegClass::Reg(s) => { + InlineAsmRegOrRegClass::Reg(reg) => { asm::InlineAsmRegOrRegClass::Reg(if let Some(asm_arch) = asm_arch { - asm::InlineAsmReg::parse(asm_arch, s).unwrap_or_else(|e| { - let msg = format!("invalid register `{}`: {}", s, e); - sess.struct_span_err(*op_sp, &msg).emit(); + asm::InlineAsmReg::parse(asm_arch, reg).unwrap_or_else(|error| { + sess.emit_err(InvalidRegister { op_span: *op_sp, reg, error }); asm::InlineAsmReg::Err }) } else { asm::InlineAsmReg::Err }) } - InlineAsmRegOrRegClass::RegClass(s) => { + InlineAsmRegOrRegClass::RegClass(reg_class) => { asm::InlineAsmRegOrRegClass::RegClass(if let Some(asm_arch) = asm_arch { - asm::InlineAsmRegClass::parse(asm_arch, s).unwrap_or_else(|e| { - let msg = format!("invalid register class `{}`: {}", s, e); - sess.struct_span_err(*op_sp, &msg).emit(); - asm::InlineAsmRegClass::Err - }) + asm::InlineAsmRegClass::parse(asm_arch, reg_class).unwrap_or_else( + |error| { + sess.emit_err(InvalidRegisterClass { + op_span: *op_sp, + reg_class, + error, + }); + asm::InlineAsmRegClass::Err + }, + ) } else { asm::InlineAsmRegClass::Err }) @@ -168,26 +155,26 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let op = match *op { InlineAsmOperand::In { reg, ref expr } => hir::InlineAsmOperand::In { reg: lower_reg(reg), - expr: self.lower_expr_mut(expr), + expr: self.lower_expr(expr), }, InlineAsmOperand::Out { reg, late, ref expr } => hir::InlineAsmOperand::Out { reg: lower_reg(reg), late, - expr: expr.as_ref().map(|expr| self.lower_expr_mut(expr)), + expr: expr.as_ref().map(|expr| self.lower_expr(expr)), }, InlineAsmOperand::InOut { reg, late, ref expr } => { hir::InlineAsmOperand::InOut { reg: lower_reg(reg), late, - expr: self.lower_expr_mut(expr), + expr: self.lower_expr(expr), } } InlineAsmOperand::SplitInOut { reg, late, ref in_expr, ref out_expr } => { hir::InlineAsmOperand::SplitInOut { reg: lower_reg(reg), late, - in_expr: self.lower_expr_mut(in_expr), - out_expr: out_expr.as_ref().map(|expr| self.lower_expr_mut(expr)), + in_expr: self.lower_expr(in_expr), + out_expr: out_expr.as_ref().map(|expr| self.lower_expr(expr)), } } InlineAsmOperand::Const { ref anon_const } => { @@ -233,7 +220,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &sym.qself, &sym.path, ParamMode::Optional, - ImplTraitContext::Disallowed(ImplTraitPosition::Path), + &ImplTraitContext::Disallowed(ImplTraitPosition::Path), ); hir::InlineAsmOperand::SymStatic { path, def_id } } else { @@ -282,50 +269,39 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } let valid_modifiers = class.valid_modifiers(asm_arch.unwrap()); if !valid_modifiers.contains(&modifier) { - let mut err = sess.struct_span_err( - placeholder_span, - "invalid asm template modifier for this register class", - ); - err.span_label(placeholder_span, "template modifier"); - err.span_label(op_sp, "argument"); - if !valid_modifiers.is_empty() { + let sub = if !valid_modifiers.is_empty() { let mut mods = format!("`{}`", valid_modifiers[0]); for m in &valid_modifiers[1..] { let _ = write!(mods, ", `{}`", m); } - err.note(&format!( - "the `{}` register class supports \ - the following template modifiers: {}", - class.name(), - mods - )); + InvalidAsmTemplateModifierRegClassSub::SupportModifier { + class_name: class.name(), + modifiers: mods, + } } else { - err.note(&format!( - "the `{}` register class does not support template modifiers", - class.name() - )); - } - err.emit(); + InvalidAsmTemplateModifierRegClassSub::DoesNotSupportModifier { + class_name: class.name(), + } + }; + sess.emit_err(InvalidAsmTemplateModifierRegClass { + placeholder_span, + op_span: op_sp, + sub, + }); } } hir::InlineAsmOperand::Const { .. } => { - let mut err = sess.struct_span_err( + sess.emit_err(InvalidAsmTemplateModifierConst { placeholder_span, - "asm template modifiers are not allowed for `const` arguments", - ); - err.span_label(placeholder_span, "template modifier"); - err.span_label(op_sp, "argument"); - err.emit(); + op_span: op_sp, + }); } hir::InlineAsmOperand::SymFn { .. } | hir::InlineAsmOperand::SymStatic { .. } => { - let mut err = sess.struct_span_err( + sess.emit_err(InvalidAsmTemplateModifierSym { placeholder_span, - "asm template modifiers are not allowed for `sym` arguments", - ); - err.span_label(placeholder_span, "template modifier"); - err.span_label(op_sp, "argument"); - err.emit(); + op_span: op_sp, + }); } } } @@ -346,12 +322,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // require that the operand name an explicit register, not a // register class. if reg_class.is_clobber_only(asm_arch.unwrap()) && !op.is_clobber() { - let msg = format!( - "register class `{}` can only be used as a clobber, \ - not as an input or output", - reg_class.name() - ); - sess.struct_span_err(op_sp, &msg).emit(); + sess.emit_err(RegisterClassOnlyClobber { + op_span: op_sp, + reg_class_name: reg_class.name(), + }); continue; } @@ -391,16 +365,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { unreachable!(); }; - let msg = format!( - "register `{}` conflicts with register `{}`", - reg.name(), - reg2.name() - ); - let mut err = sess.struct_span_err(op_sp, &msg); - err.span_label(op_sp, &format!("register `{}`", reg.name())); - err.span_label(op_sp2, &format!("register `{}`", reg2.name())); - - match (op, op2) { + let in_out = match (op, op2) { ( hir::InlineAsmOperand::In { .. }, hir::InlineAsmOperand::Out { late, .. }, @@ -411,14 +376,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ) => { assert!(!*late); let out_op_sp = if input { op_sp2 } else { op_sp }; - let msg = "use `lateout` instead of \ - `out` to avoid conflict"; - err.span_help(out_op_sp, msg); - } - _ => {} - } + Some(out_op_sp) + }, + _ => None, + }; - err.emit(); + sess.emit_err(RegisterConflict { + op_span1: op_sp, + op_span2: op_sp2, + reg1_name: reg.name(), + reg2_name: reg2.name(), + in_out + }); } Entry::Vacant(v) => { if r == reg { diff --git a/compiler/rustc_ast_lowering/src/block.rs b/compiler/rustc_ast_lowering/src/block.rs index 7cbfe143b..12a0cc0d2 100644 --- a/compiler/rustc_ast_lowering/src/block.rs +++ b/compiler/rustc_ast_lowering/src/block.rs @@ -1,8 +1,6 @@ use crate::{ImplTraitContext, ImplTraitPosition, LoweringContext}; use rustc_ast::{Block, BlockCheckMode, Local, LocalKind, Stmt, StmtKind}; use rustc_hir as hir; -use rustc_session::parse::feature_err; -use rustc_span::sym; use smallvec::SmallVec; @@ -87,20 +85,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let ty = l .ty .as_ref() - .map(|t| self.lower_ty(t, ImplTraitContext::Disallowed(ImplTraitPosition::Variable))); + .map(|t| self.lower_ty(t, &ImplTraitContext::Disallowed(ImplTraitPosition::Variable))); let init = l.kind.init().map(|init| self.lower_expr(init)); let hir_id = self.lower_node_id(l.id); let pat = self.lower_pat(&l.pat); let els = if let LocalKind::InitElse(_, els) = &l.kind { - if !self.tcx.features().let_else { - feature_err( - &self.tcx.sess.parse_sess, - sym::let_else, - l.span, - "`let...else` statements are unstable", - ) - .emit(); - } Some(self.lower_block(els, false)) } else { None diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs new file mode 100644 index 000000000..c87d0ca96 --- /dev/null +++ b/compiler/rustc_ast_lowering/src/errors.rs @@ -0,0 +1,347 @@ +use rustc_errors::{fluent, AddSubdiagnostic, Applicability, Diagnostic, DiagnosticArgFromDisplay}; +use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic}; +use rustc_span::{symbol::Ident, Span, Symbol}; + +#[derive(SessionDiagnostic, Clone, Copy)] +#[diag(ast_lowering::generic_type_with_parentheses, code = "E0214")] +pub struct GenericTypeWithParentheses { + #[primary_span] + #[label] + pub span: Span, + #[subdiagnostic] + pub sub: Option<UseAngleBrackets>, +} + +#[derive(Clone, Copy)] +pub struct UseAngleBrackets { + pub open_param: Span, + pub close_param: Span, +} + +impl AddSubdiagnostic for UseAngleBrackets { + fn add_to_diagnostic(self, diag: &mut Diagnostic) { + diag.multipart_suggestion( + fluent::ast_lowering::use_angle_brackets, + vec![(self.open_param, String::from("<")), (self.close_param, String::from(">"))], + Applicability::MaybeIncorrect, + ); + } +} + +#[derive(SessionDiagnostic)] +#[help] +#[diag(ast_lowering::invalid_abi, code = "E0703")] +pub struct InvalidAbi { + #[primary_span] + #[label] + pub span: Span, + pub abi: Symbol, + pub valid_abis: String, +} + +#[derive(SessionDiagnostic, Clone, Copy)] +#[diag(ast_lowering::assoc_ty_parentheses)] +pub struct AssocTyParentheses { + #[primary_span] + pub span: Span, + #[subdiagnostic] + pub sub: AssocTyParenthesesSub, +} + +#[derive(Clone, Copy)] +pub enum AssocTyParenthesesSub { + Empty { parentheses_span: Span }, + NotEmpty { open_param: Span, close_param: Span }, +} + +impl AddSubdiagnostic for AssocTyParenthesesSub { + fn add_to_diagnostic(self, diag: &mut Diagnostic) { + match self { + Self::Empty { parentheses_span } => diag.multipart_suggestion( + fluent::ast_lowering::remove_parentheses, + vec![(parentheses_span, String::new())], + Applicability::MaybeIncorrect, + ), + Self::NotEmpty { open_param, close_param } => diag.multipart_suggestion( + fluent::ast_lowering::use_angle_brackets, + vec![(open_param, String::from("<")), (close_param, String::from(">"))], + Applicability::MaybeIncorrect, + ), + }; + } +} + +#[derive(SessionDiagnostic)] +#[diag(ast_lowering::misplaced_impl_trait, code = "E0562")] +pub struct MisplacedImplTrait<'a> { + #[primary_span] + pub span: Span, + pub position: DiagnosticArgFromDisplay<'a>, +} + +#[derive(SessionDiagnostic, Clone, Copy)] +#[diag(ast_lowering::rustc_box_attribute_error)] +pub struct RustcBoxAttributeError { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic, Clone, Copy)] +#[diag(ast_lowering::underscore_expr_lhs_assign)] +pub struct UnderscoreExprLhsAssign { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(SessionDiagnostic, Clone, Copy)] +#[diag(ast_lowering::base_expression_double_dot)] +pub struct BaseExpressionDoubleDot { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(SessionDiagnostic, Clone, Copy)] +#[diag(ast_lowering::await_only_in_async_fn_and_blocks, code = "E0728")] +pub struct AwaitOnlyInAsyncFnAndBlocks { + #[primary_span] + #[label] + pub dot_await_span: Span, + #[label(ast_lowering::this_not_async)] + pub item_span: Option<Span>, +} + +#[derive(SessionDiagnostic, Clone, Copy)] +#[diag(ast_lowering::generator_too_many_parameters, code = "E0628")] +pub struct GeneratorTooManyParameters { + #[primary_span] + pub fn_decl_span: Span, +} + +#[derive(SessionDiagnostic, Clone, Copy)] +#[diag(ast_lowering::closure_cannot_be_static, code = "E0697")] +pub struct ClosureCannotBeStatic { + #[primary_span] + pub fn_decl_span: Span, +} + +#[derive(SessionDiagnostic, Clone, Copy)] +#[help] +#[diag(ast_lowering::async_non_move_closure_not_supported, code = "E0708")] +pub struct AsyncNonMoveClosureNotSupported { + #[primary_span] + pub fn_decl_span: Span, +} + +#[derive(SessionDiagnostic, Clone, Copy)] +#[diag(ast_lowering::functional_record_update_destructuring_assignment)] +pub struct FunctionalRecordUpdateDestructuringAssignemnt { + #[primary_span] + #[suggestion(code = "", applicability = "machine-applicable")] + pub span: Span, +} + +#[derive(SessionDiagnostic, Clone, Copy)] +#[diag(ast_lowering::async_generators_not_supported, code = "E0727")] +pub struct AsyncGeneratorsNotSupported { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic, Clone, Copy)] +#[diag(ast_lowering::inline_asm_unsupported_target, code = "E0472")] +pub struct InlineAsmUnsupportedTarget { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic, Clone, Copy)] +#[diag(ast_lowering::att_syntax_only_x86)] +pub struct AttSyntaxOnlyX86 { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic, Clone, Copy)] +#[diag(ast_lowering::abi_specified_multiple_times)] +pub struct AbiSpecifiedMultipleTimes { + #[primary_span] + pub abi_span: Span, + pub prev_name: Symbol, + #[label] + pub prev_span: Span, + #[note] + pub equivalent: Option<()>, +} + +#[derive(SessionDiagnostic, Clone, Copy)] +#[diag(ast_lowering::clobber_abi_not_supported)] +pub struct ClobberAbiNotSupported { + #[primary_span] + pub abi_span: Span, +} + +#[derive(SessionDiagnostic)] +#[note] +#[diag(ast_lowering::invalid_abi_clobber_abi)] +pub struct InvalidAbiClobberAbi { + #[primary_span] + pub abi_span: Span, + pub supported_abis: String, +} + +#[derive(SessionDiagnostic, Clone, Copy)] +#[diag(ast_lowering::invalid_register)] +pub struct InvalidRegister<'a> { + #[primary_span] + pub op_span: Span, + pub reg: Symbol, + pub error: &'a str, +} + +#[derive(SessionDiagnostic, Clone, Copy)] +#[diag(ast_lowering::invalid_register_class)] +pub struct InvalidRegisterClass<'a> { + #[primary_span] + pub op_span: Span, + pub reg_class: Symbol, + pub error: &'a str, +} + +#[derive(SessionDiagnostic)] +#[diag(ast_lowering::invalid_asm_template_modifier_reg_class)] +pub struct InvalidAsmTemplateModifierRegClass { + #[primary_span] + #[label(ast_lowering::template_modifier)] + pub placeholder_span: Span, + #[label(ast_lowering::argument)] + pub op_span: Span, + #[subdiagnostic] + pub sub: InvalidAsmTemplateModifierRegClassSub, +} + +#[derive(SessionSubdiagnostic)] +pub enum InvalidAsmTemplateModifierRegClassSub { + #[note(ast_lowering::support_modifiers)] + SupportModifier { class_name: Symbol, modifiers: String }, + #[note(ast_lowering::does_not_support_modifiers)] + DoesNotSupportModifier { class_name: Symbol }, +} + +#[derive(SessionDiagnostic, Clone, Copy)] +#[diag(ast_lowering::invalid_asm_template_modifier_const)] +pub struct InvalidAsmTemplateModifierConst { + #[primary_span] + #[label(ast_lowering::template_modifier)] + pub placeholder_span: Span, + #[label(ast_lowering::argument)] + pub op_span: Span, +} + +#[derive(SessionDiagnostic, Clone, Copy)] +#[diag(ast_lowering::invalid_asm_template_modifier_sym)] +pub struct InvalidAsmTemplateModifierSym { + #[primary_span] + #[label(ast_lowering::template_modifier)] + pub placeholder_span: Span, + #[label(ast_lowering::argument)] + pub op_span: Span, +} + +#[derive(SessionDiagnostic, Clone, Copy)] +#[diag(ast_lowering::register_class_only_clobber)] +pub struct RegisterClassOnlyClobber { + #[primary_span] + pub op_span: Span, + pub reg_class_name: Symbol, +} + +#[derive(SessionDiagnostic, Clone, Copy)] +#[diag(ast_lowering::register_conflict)] +pub struct RegisterConflict<'a> { + #[primary_span] + #[label(ast_lowering::register1)] + pub op_span1: Span, + #[label(ast_lowering::register2)] + pub op_span2: Span, + pub reg1_name: &'a str, + pub reg2_name: &'a str, + #[help] + pub in_out: Option<Span>, +} + +#[derive(SessionDiagnostic, Clone, Copy)] +#[help] +#[diag(ast_lowering::sub_tuple_binding)] +pub struct SubTupleBinding<'a> { + #[primary_span] + #[label] + #[suggestion_verbose( + ast_lowering::sub_tuple_binding_suggestion, + code = "..", + applicability = "maybe-incorrect" + )] + pub span: Span, + pub ident: Ident, + pub ident_name: Symbol, + pub ctx: &'a str, +} + +#[derive(SessionDiagnostic, Clone, Copy)] +#[diag(ast_lowering::extra_double_dot)] +pub struct ExtraDoubleDot<'a> { + #[primary_span] + #[label] + pub span: Span, + #[label(ast_lowering::previously_used_here)] + pub prev_span: Span, + pub ctx: &'a str, +} + +#[derive(SessionDiagnostic, Clone, Copy)] +#[note] +#[diag(ast_lowering::misplaced_double_dot)] +pub struct MisplacedDoubleDot { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic, Clone, Copy)] +#[diag(ast_lowering::misplaced_relax_trait_bound)] +pub struct MisplacedRelaxTraitBound { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic, Clone, Copy)] +#[diag(ast_lowering::not_supported_for_lifetime_binder_async_closure)] +pub struct NotSupportedForLifetimeBinderAsyncClosure { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic, Clone, Copy)] +#[diag(ast_lowering::arbitrary_expression_in_pattern)] +pub struct ArbitraryExpressionInPattern { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic, Clone, Copy)] +#[diag(ast_lowering::inclusive_range_with_no_end)] +pub struct InclusiveRangeWithNoEnd { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic, Clone, Copy)] +#[diag(ast_lowering::trait_fn_async, code = "E0706")] +#[note] +#[note(ast_lowering::note2)] +pub struct TraitFnAsync { + #[primary_span] + pub fn_span: Span, + #[label] + pub span: Span, +} diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index fb6715ff1..7b8070d3c 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -1,19 +1,23 @@ +use super::errors::{ + AsyncGeneratorsNotSupported, AsyncNonMoveClosureNotSupported, AwaitOnlyInAsyncFnAndBlocks, + BaseExpressionDoubleDot, ClosureCannotBeStatic, FunctionalRecordUpdateDestructuringAssignemnt, + GeneratorTooManyParameters, InclusiveRangeWithNoEnd, NotSupportedForLifetimeBinderAsyncClosure, + RustcBoxAttributeError, UnderscoreExprLhsAssign, +}; use super::ResolverAstLoweringExt; use super::{ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs}; use crate::{FnDeclKind, ImplTraitPosition}; - use rustc_ast::attr; use rustc_ast::ptr::P as AstP; use rustc_ast::*; use rustc_data_structures::stack::ensure_sufficient_stack; -use rustc_data_structures::thin_vec::ThinVec; -use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def::Res; use rustc_hir::definitions::DefPathData; use rustc_span::source_map::{respan, DesugaringKind, Span, Spanned}; use rustc_span::symbol::{sym, Ident}; use rustc_span::DUMMY_SP; +use thin_vec::thin_vec; impl<'hir> LoweringContext<'_, 'hir> { fn lower_exprs(&mut self, exprs: &[AstP<Expr>]) -> &'hir [hir::Expr<'hir>] { @@ -46,13 +50,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let hir_id = self.lower_node_id(e.id); return hir::Expr { hir_id, kind, span: self.lower_span(e.span) }; } else { - self.tcx.sess - .struct_span_err( - e.span, - "#[rustc_box] requires precisely one argument \ - and no other attributes are allowed", - ) - .emit(); + self.tcx.sess.emit_err(RustcBoxAttributeError { span: e.span }); hir::ExprKind::Err } } else if let Some(legacy_args) = self.resolver.legacy_const_generic_args(f) { @@ -68,10 +66,12 @@ impl<'hir> LoweringContext<'_, 'hir> { seg, ParamMode::Optional, ParenthesizedGenericArgs::Err, - ImplTraitContext::Disallowed(ImplTraitPosition::Path), + &ImplTraitContext::Disallowed(ImplTraitPosition::Path), )); - let args = self.lower_exprs(args); - hir::ExprKind::MethodCall(hir_seg, args, self.lower_span(span)) + let receiver = self.lower_expr(&args[0]); + let args = + self.arena.alloc_from_iter(args[1..].iter().map(|x| self.lower_expr_mut(x))); + hir::ExprKind::MethodCall(hir_seg, receiver, args, self.lower_span(span)) } ExprKind::Binary(binop, ref lhs, ref rhs) => { let binop = self.lower_binop(binop); @@ -90,13 +90,13 @@ impl<'hir> LoweringContext<'_, 'hir> { ExprKind::Cast(ref expr, ref ty) => { let expr = self.lower_expr(expr); let ty = - self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)); + self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)); hir::ExprKind::Cast(expr, ty) } ExprKind::Type(ref expr, ref ty) => { let expr = self.lower_expr(expr); let ty = - self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)); + self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)); hir::ExprKind::Type(expr, ty) } ExprKind::AddrOf(k, m, ref ohs) => { @@ -146,13 +146,19 @@ impl<'hir> LoweringContext<'_, 'hir> { |this| this.with_new_scopes(|this| this.lower_block_expr(block)), ), ExprKind::Await(ref expr) => { - let span = if expr.span.hi() < e.span.hi() { - expr.span.shrink_to_hi().with_hi(e.span.hi()) + let dot_await_span = if expr.span.hi() < e.span.hi() { + let span_with_whitespace = self + .tcx + .sess + .source_map() + .span_extend_while(expr.span, char::is_whitespace) + .unwrap_or(expr.span); + span_with_whitespace.shrink_to_hi().with_hi(e.span.hi()) } else { // this is a recovered `await expr` e.span }; - self.lower_expr_await(span, expr) + self.lower_expr_await(dot_await_span, expr) } ExprKind::Closure( ref binder, @@ -210,13 +216,7 @@ impl<'hir> LoweringContext<'_, 'hir> { self.lower_expr_range(e.span, e1.as_deref(), e2.as_deref(), lims) } ExprKind::Underscore => { - self.tcx - .sess.struct_span_err( - e.span, - "in expressions, `_` can only be used on the left-hand side of an assignment", - ) - .span_label(e.span, "`_` not allowed here") - .emit(); + self.tcx.sess.emit_err(UnderscoreExprLhsAssign { span: e.span }); hir::ExprKind::Err } ExprKind::Path(ref qself, ref path) => { @@ -225,7 +225,7 @@ impl<'hir> LoweringContext<'_, 'hir> { qself, path, ParamMode::Optional, - ImplTraitContext::Disallowed(ImplTraitPosition::Path), + &ImplTraitContext::Disallowed(ImplTraitPosition::Path), ); hir::ExprKind::Path(qpath) } @@ -248,11 +248,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let rest = match &se.rest { StructRest::Base(e) => Some(self.lower_expr(e)), StructRest::Rest(sp) => { - self.tcx - .sess - .struct_span_err(*sp, "base expression required after `..`") - .span_label(*sp, "add a base expression here") - .emit(); + self.tcx.sess.emit_err(BaseExpressionDoubleDot { span: *sp }); Some(&*self.arena.alloc(self.expr_err(*sp))) } StructRest::None => None, @@ -263,7 +259,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &se.qself, &se.path, ParamMode::Optional, - ImplTraitContext::Disallowed(ImplTraitPosition::Path), + &ImplTraitContext::Disallowed(ImplTraitPosition::Path), )), self.arena .alloc_from_iter(se.fields.iter().map(|x| self.lower_expr_field(x))), @@ -446,12 +442,12 @@ impl<'hir> LoweringContext<'_, 'hir> { let lowered_cond = self.with_loop_condition_scope(|t| t.lower_expr(cond)); let new_cond = self.manage_let_cond(lowered_cond); let then = self.lower_block_expr(body); - let expr_break = self.expr_break(span, ThinVec::new()); + let expr_break = self.expr_break(span, AttrVec::new()); let stmt_break = self.stmt_expr(span, expr_break); let else_blk = self.block_all(span, arena_vec![self; stmt_break], None); - let else_expr = self.arena.alloc(self.expr_block(else_blk, ThinVec::new())); + let else_expr = self.arena.alloc(self.expr_block(else_blk, AttrVec::new())); let if_kind = hir::ExprKind::If(new_cond, self.arena.alloc(then), Some(else_expr)); - let if_expr = self.expr(span, if_kind, ThinVec::new()); + let if_expr = self.expr(span, if_kind, AttrVec::new()); let block = self.block_expr(self.arena.alloc(if_expr)); let span = self.lower_span(span.with_hi(cond.span.hi())); let opt_label = self.lower_label(opt_label); @@ -510,7 +506,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let constructor = self.arena.alloc(self.expr_lang_item_path( method_span, lang_item, - ThinVec::new(), + AttrVec::new(), None, )); self.expr_call(overall_span, constructor, std::slice::from_ref(expr)) @@ -562,7 +558,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ) -> hir::ExprKind<'hir> { let output = match ret_ty { Some(ty) => hir::FnRetTy::Return( - self.lower_ty(&ty, ImplTraitContext::Disallowed(ImplTraitPosition::AsyncBlock)), + self.lower_ty(&ty, &ImplTraitContext::Disallowed(ImplTraitPosition::AsyncBlock)), ), None => hir::FnRetTy::DefaultReturn(self.lower_span(span)), }; @@ -587,7 +583,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let (pat, task_context_hid) = self.pat_ident_binding_mode( span, Ident::with_dummy_span(sym::_task_context), - hir::BindingAnnotation::Mutable, + hir::BindingAnnotation::MUT, ); let param = hir::Param { hir_id: self.next_id(), @@ -633,7 +629,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let gen_future = self.expr_lang_item_path( unstable_span, hir::LangItem::FromGenerator, - ThinVec::new(), + AttrVec::new(), None, ); @@ -661,17 +657,10 @@ impl<'hir> LoweringContext<'_, 'hir> { match self.generator_kind { Some(hir::GeneratorKind::Async(_)) => {} Some(hir::GeneratorKind::Gen) | None => { - let mut err = struct_span_err!( - self.tcx.sess, + self.tcx.sess.emit_err(AwaitOnlyInAsyncFnAndBlocks { dot_await_span, - E0728, - "`await` is only allowed inside `async` functions and blocks" - ); - err.span_label(dot_await_span, "only allowed inside `async` functions and blocks"); - if let Some(item_sp) = self.current_item { - err.span_label(item_sp, "this is not `async`"); - } - err.emit(); + item_span: self.current_item, + }); } } let span = self.mark_span_with_reason(DesugaringKind::Await, dot_await_span, None); @@ -688,7 +677,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // this name to identify what is being awaited by a suspended async functions. let awaitee_ident = Ident::with_dummy_span(sym::__awaitee); let (awaitee_pat, awaitee_pat_hid) = - self.pat_ident_binding_mode(span, awaitee_ident, hir::BindingAnnotation::Mutable); + self.pat_ident_binding_mode(span, awaitee_ident, hir::BindingAnnotation::MUT); let task_context_ident = Ident::with_dummy_span(sym::_task_context); @@ -745,7 +734,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let break_x = self.with_loop_scope(loop_node_id, move |this| { let expr_break = hir::ExprKind::Break(this.lower_loop_destination(None), Some(x_expr)); - this.arena.alloc(this.expr(gen_future_span, expr_break, ThinVec::new())) + this.arena.alloc(this.expr(gen_future_span, expr_break, AttrVec::new())) }); self.arm(ready_pat, break_x) }; @@ -778,7 +767,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let yield_expr = self.expr( span, hir::ExprKind::Yield(unit, hir::YieldSource::Await { expr: Some(expr_hir_id) }), - ThinVec::new(), + AttrVec::new(), ); let yield_expr = self.arena.alloc(yield_expr); @@ -866,7 +855,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params); // Lower outside new scope to preserve `is_in_loop_condition`. - let fn_decl = self.lower_fn_decl(decl, None, FnDeclKind::Closure, None); + let fn_decl = self.lower_fn_decl(decl, None, fn_decl_span, FnDeclKind::Closure, None); let c = self.arena.alloc(hir::Closure { binder: binder_clause, @@ -891,13 +880,7 @@ impl<'hir> LoweringContext<'_, 'hir> { match generator_kind { Some(hir::GeneratorKind::Gen) => { if decl.inputs.len() > 1 { - struct_span_err!( - self.tcx.sess, - fn_decl_span, - E0628, - "too many parameters for a generator (expected 0 or 1 parameters)" - ) - .emit(); + self.tcx.sess.emit_err(GeneratorTooManyParameters { fn_decl_span }); } Some(movability) } @@ -906,13 +889,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } None => { if movability == Movability::Static { - struct_span_err!( - self.tcx.sess, - fn_decl_span, - E0697, - "closures cannot be static" - ) - .emit(); + self.tcx.sess.emit_err(ClosureCannotBeStatic { fn_decl_span }); } None } @@ -945,10 +922,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn_decl_span: Span, ) -> hir::ExprKind<'hir> { if let &ClosureBinder::For { span, .. } = binder { - self.tcx.sess.span_err( - span, - "`for<...>` binders on `async` closures are not currently supported", - ); + self.tcx.sess.emit_err(NotSupportedForLifetimeBinderAsyncClosure { span }); } let (binder_clause, generic_params) = self.lower_closure_binder(binder); @@ -959,17 +933,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let body = self.with_new_scopes(|this| { // FIXME(cramertj): allow `async` non-`move` closures with arguments. if capture_clause == CaptureBy::Ref && !decl.inputs.is_empty() { - struct_span_err!( - this.tcx.sess, - fn_decl_span, - E0708, - "`async` non-`move` closures with parameters are not currently supported", - ) - .help( - "consider using `let` statements to manually capture \ - variables by reference before entering an `async move` closure", - ) - .emit(); + this.tcx.sess.emit_err(AsyncNonMoveClosureNotSupported { fn_decl_span }); } // Transform `async |x: u8| -> X { ... }` into @@ -985,17 +949,17 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::AsyncGeneratorKind::Closure, |this| this.with_new_scopes(|this| this.lower_expr_mut(body)), ); - this.expr(fn_decl_span, async_body, ThinVec::new()) + this.expr(fn_decl_span, async_body, AttrVec::new()) }); body_id }); let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params); - // We need to lower the declaration outside the new scope, because we // have to conserve the state of being inside a loop condition for the // closure argument types. - let fn_decl = self.lower_fn_decl(&outer_decl, None, FnDeclKind::Closure, None); + let fn_decl = + self.lower_fn_decl(&outer_decl, None, fn_decl_span, FnDeclKind::Closure, None); let c = self.arena.alloc(hir::Closure { binder: binder_clause, @@ -1165,11 +1129,14 @@ impl<'hir> LoweringContext<'_, 'hir> { qself, path, ParamMode::Optional, - ImplTraitContext::Disallowed(ImplTraitPosition::Path), + &ImplTraitContext::Disallowed(ImplTraitPosition::Path), ); // Destructure like a tuple struct. - let tuple_struct_pat = - hir::PatKind::TupleStruct(qpath, pats, rest.map(|r| r.0)); + let tuple_struct_pat = hir::PatKind::TupleStruct( + qpath, + pats, + hir::DotDotPos::new(rest.map(|r| r.0)), + ); return self.pat_without_dbm(lhs.span, tuple_struct_pat); } } @@ -1181,7 +1148,7 @@ impl<'hir> LoweringContext<'_, 'hir> { qself, path, ParamMode::Optional, - ImplTraitContext::Disallowed(ImplTraitPosition::Path), + &ImplTraitContext::Disallowed(ImplTraitPosition::Path), ); // Destructure like a unit struct. let unit_struct_pat = hir::PatKind::Path(qpath); @@ -1205,24 +1172,13 @@ impl<'hir> LoweringContext<'_, 'hir> { &se.qself, &se.path, ParamMode::Optional, - ImplTraitContext::Disallowed(ImplTraitPosition::Path), + &ImplTraitContext::Disallowed(ImplTraitPosition::Path), ); let fields_omitted = match &se.rest { StructRest::Base(e) => { - self.tcx - .sess - .struct_span_err( - e.span, - "functional record updates are not allowed in destructuring \ - assignments", - ) - .span_suggestion( - e.span, - "consider removing the trailing pattern", - "", - rustc_errors::Applicability::MachineApplicable, - ) - .emit(); + self.tcx.sess.emit_err(FunctionalRecordUpdateDestructuringAssignemnt { + span: e.span, + }); true } StructRest::Rest(_) => true, @@ -1235,13 +1191,13 @@ impl<'hir> LoweringContext<'_, 'hir> { ExprKind::Tup(elements) => { let (pats, rest) = self.destructure_sequence(elements, "tuple", eq_sign_span, assignments); - let tuple_pat = hir::PatKind::Tuple(pats, rest.map(|r| r.0)); + let tuple_pat = hir::PatKind::Tuple(pats, hir::DotDotPos::new(rest.map(|r| r.0))); return self.pat_without_dbm(lhs.span, tuple_pat); } ExprKind::Paren(e) => { // We special-case `(..)` for consistency with patterns. if let ExprKind::Range(None, None, RangeLimits::HalfOpen) = e.kind { - let tuple_pat = hir::PatKind::Tuple(&[], Some(0)); + let tuple_pat = hir::PatKind::Tuple(&[], hir::DotDotPos::new(Some(0))); return self.pat_without_dbm(lhs.span, tuple_pat); } else { return self.destructure_assign_mut(e, eq_sign_span, assignments); @@ -1255,7 +1211,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let ident = self.expr_ident(lhs.span, ident, binding); let assign = hir::ExprKind::Assign(self.lower_expr(lhs), ident, self.lower_span(eq_sign_span)); - let expr = self.expr(lhs.span, assign, ThinVec::new()); + let expr = self.expr(lhs.span, assign, AttrVec::new()); assignments.push(self.stmt_expr(lhs.span, expr)); pat } @@ -1297,7 +1253,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let fn_path = hir::QPath::LangItem(hir::LangItem::RangeInclusiveNew, self.lower_span(span), None); let fn_expr = - self.arena.alloc(self.expr(span, hir::ExprKind::Path(fn_path), ThinVec::new())); + self.arena.alloc(self.expr(span, hir::ExprKind::Path(fn_path), AttrVec::new())); hir::ExprKind::Call(fn_expr, arena_vec![self; e1, e2]) } @@ -1317,7 +1273,13 @@ impl<'hir> LoweringContext<'_, 'hir> { (Some(..), Some(..), HalfOpen) => hir::LangItem::Range, (None, Some(..), Closed) => hir::LangItem::RangeToInclusive, (Some(..), Some(..), Closed) => unreachable!(), - (_, None, Closed) => self.diagnostic().span_fatal(span, "inclusive range with no end"), + (start, None, Closed) => { + self.tcx.sess.emit_err(InclusiveRangeWithNoEnd { span }); + match start { + Some(..) => hir::LangItem::RangeFrom, + None => hir::LangItem::RangeFull, + } + } }; let fields = self.arena.alloc_from_iter( @@ -1404,8 +1366,10 @@ impl<'hir> LoweringContext<'_, 'hir> { } fn lower_expr_field(&mut self, f: &ExprField) -> hir::ExprField<'hir> { + let hir_id = self.lower_node_id(f.id); + self.lower_attrs(hir_id, &f.attrs); hir::ExprField { - hir_id: self.next_id(), + hir_id, ident: self.lower_ident(f.ident), expr: self.lower_expr(&f.expr), span: self.lower_span(f.span), @@ -1417,13 +1381,7 @@ impl<'hir> LoweringContext<'_, 'hir> { match self.generator_kind { Some(hir::GeneratorKind::Gen) => {} Some(hir::GeneratorKind::Async(_)) => { - struct_span_err!( - self.tcx.sess, - span, - E0727, - "`async` generators are not yet supported" - ) - .emit(); + self.tcx.sess.emit_err(AsyncGeneratorsNotSupported { span }); } None => self.generator_kind = Some(hir::GeneratorKind::Gen), } @@ -1468,7 +1426,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // `None => break` let none_arm = { let break_expr = - self.with_loop_scope(e.id, |this| this.expr_break_alloc(for_span, ThinVec::new())); + self.with_loop_scope(e.id, |this| this.expr_break_alloc(for_span, AttrVec::new())); let pat = self.pat_none(for_span); self.arm(pat, break_expr) }; @@ -1477,14 +1435,14 @@ impl<'hir> LoweringContext<'_, 'hir> { let some_arm = { let some_pat = self.pat_some(pat_span, pat); let body_block = self.with_loop_scope(e.id, |this| this.lower_block(body, false)); - let body_expr = self.arena.alloc(self.expr_block(body_block, ThinVec::new())); + let body_expr = self.arena.alloc(self.expr_block(body_block, AttrVec::new())); self.arm(some_pat, body_expr) }; // `mut iter` let iter = Ident::with_dummy_span(sym::iter); let (iter_pat, iter_pat_nid) = - self.pat_ident_binding_mode(head_span, iter, hir::BindingAnnotation::Mutable); + self.pat_ident_binding_mode(head_span, iter, hir::BindingAnnotation::MUT); // `match Iterator::next(&mut iter) { ... }` let match_expr = { @@ -1534,15 +1492,13 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::MatchSource::ForLoopDesugar, )); - let attrs: Vec<_> = e.attrs.iter().map(|a| self.lower_attr(a)).collect(); - // This is effectively `{ let _result = ...; _result }`. // The construct was introduced in #21984 and is necessary to make sure that // temporaries in the `head` expression are dropped and do not leak to the // surrounding scope of the `match` since the `match` is not a terminating scope. // // Also, add the attributes to the outer returned expr node. - self.expr_drop_temps_mut(for_span, match_expr, attrs.into()) + self.expr_drop_temps_mut(for_span, match_expr, e.attrs.clone()) } /// Desugar `ExprKind::Try` from: `<expr>?` into: @@ -1592,9 +1548,9 @@ impl<'hir> LoweringContext<'_, 'hir> { let uc_nested = attr::mk_nested_word_item(uc_ident); attr::mk_list_item(allow_ident, vec![uc_nested]) }; - attr::mk_attr_outer(allow) + attr::mk_attr_outer(&self.tcx.sess.parse_sess.attr_id_generator, allow) }; - let attrs = vec![attr]; + let attrs: AttrVec = thin_vec![attr]; // `ControlFlow::Continue(val) => #[allow(unreachable_code)] val,` let continue_arm = { @@ -1604,7 +1560,7 @@ impl<'hir> LoweringContext<'_, 'hir> { span, val_ident, val_pat_nid, - ThinVec::from(attrs.clone()), + attrs.clone(), )); let continue_pat = self.pat_cf_continue(unstable_span, val_pat); self.arm(continue_pat, val_expr) @@ -1623,7 +1579,6 @@ impl<'hir> LoweringContext<'_, 'hir> { self.arena.alloc(residual_expr), unstable_span, ); - let thin_attrs = ThinVec::from(attrs); let ret_expr = if let Some(catch_node) = self.catch_scope { let target_id = Ok(self.lower_node_id(catch_node)); self.arena.alloc(self.expr( @@ -1632,13 +1587,13 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::Destination { label: None, target_id }, Some(from_residual_expr), ), - thin_attrs, + attrs, )) } else { self.arena.alloc(self.expr( try_span, hir::ExprKind::Ret(Some(from_residual_expr)), - thin_attrs, + attrs, )) }; @@ -1726,7 +1681,7 @@ impl<'hir> LoweringContext<'_, 'hir> { arms: &'hir [hir::Arm<'hir>], source: hir::MatchSource, ) -> hir::Expr<'hir> { - self.expr(span, hir::ExprKind::Match(arg, arms, source), ThinVec::new()) + self.expr(span, hir::ExprKind::Match(arg, arms, source), AttrVec::new()) } fn expr_break(&mut self, span: Span, attrs: AttrVec) -> hir::Expr<'hir> { @@ -1743,12 +1698,12 @@ impl<'hir> LoweringContext<'_, 'hir> { self.expr( span, hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Mut, e), - ThinVec::new(), + AttrVec::new(), ) } fn expr_unit(&mut self, sp: Span) -> &'hir hir::Expr<'hir> { - self.arena.alloc(self.expr(sp, hir::ExprKind::Tup(&[]), ThinVec::new())) + self.arena.alloc(self.expr(sp, hir::ExprKind::Tup(&[]), AttrVec::new())) } fn expr_call_mut( @@ -1757,7 +1712,7 @@ impl<'hir> LoweringContext<'_, 'hir> { e: &'hir hir::Expr<'hir>, args: &'hir [hir::Expr<'hir>], ) -> hir::Expr<'hir> { - self.expr(span, hir::ExprKind::Call(e, args), ThinVec::new()) + self.expr(span, hir::ExprKind::Call(e, args), AttrVec::new()) } fn expr_call( @@ -1777,7 +1732,7 @@ impl<'hir> LoweringContext<'_, 'hir> { hir_id: Option<hir::HirId>, ) -> hir::Expr<'hir> { let path = - self.arena.alloc(self.expr_lang_item_path(span, lang_item, ThinVec::new(), hir_id)); + self.arena.alloc(self.expr_lang_item_path(span, lang_item, AttrVec::new(), hir_id)); self.expr_call_mut(span, path, args) } @@ -1820,7 +1775,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ident: Ident, binding: hir::HirId, ) -> hir::Expr<'hir> { - self.expr_ident_with_attrs(sp, ident, binding, ThinVec::new()) + self.expr_ident_with_attrs(sp, ident, binding, AttrVec::new()) } fn expr_ident_with_attrs( @@ -1830,12 +1785,14 @@ impl<'hir> LoweringContext<'_, 'hir> { binding: hir::HirId, attrs: AttrVec, ) -> hir::Expr<'hir> { + let hir_id = self.next_id(); + let res = Res::Local(binding); let expr_path = hir::ExprKind::Path(hir::QPath::Resolved( None, self.arena.alloc(hir::Path { span: self.lower_span(span), - res: Res::Local(binding), - segments: arena_vec![self; hir::PathSegment::from_ident(ident)], + res, + segments: arena_vec![self; hir::PathSegment::new(ident, hir_id, res)], }), )); @@ -1858,13 +1815,13 @@ impl<'hir> LoweringContext<'_, 'hir> { }), None, ), - ThinVec::new(), + AttrVec::new(), ) } fn expr_block_empty(&mut self, span: Span) -> &'hir hir::Expr<'hir> { let blk = self.block_all(span, &[], None); - let expr = self.expr_block(blk, ThinVec::new()); + let expr = self.expr_block(blk, AttrVec::new()); self.arena.alloc(expr) } diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs index d5af74d47..85846b567 100644 --- a/compiler/rustc_ast_lowering/src/index.rs +++ b/compiler/rustc_ast_lowering/src/index.rs @@ -11,8 +11,6 @@ use rustc_session::Session; use rustc_span::source_map::SourceMap; use rustc_span::{Span, DUMMY_SP}; -use tracing::debug; - /// A visitor that walks over the HIR and collects `Node`s into a HIR map. pub(super) struct NodeCollector<'a, 'hir> { /// Source map @@ -31,7 +29,7 @@ pub(super) struct NodeCollector<'a, 'hir> { definitions: &'a definitions::Definitions, } -#[tracing::instrument(level = "debug", skip(sess, definitions, bodies))] +#[instrument(level = "debug", skip(sess, definitions, bodies))] pub(super) fn index_hir<'hir>( sess: &Session, definitions: &definitions::Definitions, @@ -67,10 +65,11 @@ pub(super) fn index_hir<'hir>( } impl<'a, 'hir> NodeCollector<'a, 'hir> { - #[tracing::instrument(level = "debug", skip(self))] + #[instrument(level = "debug", skip(self))] fn insert(&mut self, span: Span, hir_id: HirId, node: Node<'hir>) { debug_assert_eq!(self.owner, hir_id.owner); debug_assert_ne!(hir_id.local_id.as_u32(), 0); + debug_assert_ne!(hir_id.local_id, self.parent_node); // Make sure that the DepNode of some node coincides with the HirId // owner of that node. @@ -142,7 +141,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { }); } - #[tracing::instrument(level = "debug", skip(self))] + #[instrument(level = "debug", skip(self))] fn visit_item(&mut self, i: &'hir Item<'hir>) { debug_assert_eq!(i.def_id, self.owner); self.with_parent(i.hir_id(), |this| { @@ -156,7 +155,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { }); } - #[tracing::instrument(level = "debug", skip(self))] + #[instrument(level = "debug", skip(self))] fn visit_foreign_item(&mut self, fi: &'hir ForeignItem<'hir>) { debug_assert_eq!(fi.def_id, self.owner); self.with_parent(fi.hir_id(), |this| { @@ -175,7 +174,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { }) } - #[tracing::instrument(level = "debug", skip(self))] + #[instrument(level = "debug", skip(self))] fn visit_trait_item(&mut self, ti: &'hir TraitItem<'hir>) { debug_assert_eq!(ti.def_id, self.owner); self.with_parent(ti.hir_id(), |this| { @@ -183,7 +182,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { }); } - #[tracing::instrument(level = "debug", skip(self))] + #[instrument(level = "debug", skip(self))] fn visit_impl_item(&mut self, ii: &'hir ImplItem<'hir>) { debug_assert_eq!(ii.def_id, self.owner); self.with_parent(ii.hir_id(), |this| { @@ -199,6 +198,13 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { }); } + fn visit_pat_field(&mut self, field: &'hir PatField<'hir>) { + self.insert(field.span, field.hir_id, Node::PatField(field)); + self.with_parent(field.hir_id, |this| { + intravisit::walk_pat_field(this, field); + }); + } + fn visit_arm(&mut self, arm: &'hir Arm<'hir>) { let node = Node::Arm(arm); @@ -225,6 +231,13 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { }); } + fn visit_expr_field(&mut self, field: &'hir ExprField<'hir>) { + self.insert(field.span, field.hir_id, Node::ExprField(field)); + self.with_parent(field.hir_id, |this| { + intravisit::walk_expr_field(this, field); + }); + } + fn visit_stmt(&mut self, stmt: &'hir Stmt<'hir>) { self.insert(stmt.span, stmt.hir_id, Node::Stmt(stmt)); @@ -233,11 +246,9 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { }); } - fn visit_path_segment(&mut self, path_span: Span, path_segment: &'hir PathSegment<'hir>) { - if let Some(hir_id) = path_segment.hir_id { - self.insert(path_span, hir_id, Node::PathSegment(path_segment)); - } - intravisit::walk_path_segment(self, path_span, path_segment); + fn visit_path_segment(&mut self, path_segment: &'hir PathSegment<'hir>) { + self.insert(path_segment.ident.span, path_segment.hir_id, Node::PathSegment(path_segment)); + intravisit::walk_path_segment(self, path_segment); } fn visit_ty(&mut self, ty: &'hir Ty<'hir>) { @@ -269,12 +280,12 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { fk: intravisit::FnKind<'hir>, fd: &'hir FnDecl<'hir>, b: BodyId, - s: Span, + _: Span, id: HirId, ) { assert_eq!(self.owner, id.owner); assert_eq!(self.parent_node, id.local_id); - intravisit::walk_fn(self, fk, fd, b, s, id); + intravisit::walk_fn(self, fk, fd, b, id); } fn visit_block(&mut self, block: &'hir Block<'hir>) { @@ -295,14 +306,14 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { self.insert(lifetime.span, lifetime.hir_id, Node::Lifetime(lifetime)); } - fn visit_variant(&mut self, v: &'hir Variant<'hir>, g: &'hir Generics<'hir>, item_id: HirId) { + fn visit_variant(&mut self, v: &'hir Variant<'hir>) { self.insert(v.span, v.id, Node::Variant(v)); self.with_parent(v.id, |this| { // Register the constructor of this variant. if let Some(ctor_hir_id) = v.data.ctor_hir_id() { this.insert(v.span, ctor_hir_id, Node::Ctor(&v.data)); } - intravisit::walk_variant(this, v, g, item_id); + intravisit::walk_variant(this, v); }); } diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index ee4c0036f..550833275 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1,5 +1,6 @@ +use super::errors::{InvalidAbi, MisplacedRelaxTraitBound}; use super::ResolverAstLoweringExt; -use super::{AstOwner, ImplTraitContext, ImplTraitPosition}; +use super::{Arena, AstOwner, ImplTraitContext, ImplTraitPosition}; use super::{FnDeclKind, LoweringContext, ParamMode}; use rustc_ast::ptr::P; @@ -7,7 +8,6 @@ use rustc_ast::visit::AssocCtxt; use rustc_ast::*; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sorted_map::SortedMap; -use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID}; @@ -25,6 +25,7 @@ use std::iter; pub(super) struct ItemLowerer<'a, 'hir> { pub(super) tcx: TyCtxt<'hir>, pub(super) resolver: &'a mut ResolverAstLowering, + pub(super) ast_arena: &'a Arena<'static>, pub(super) ast_index: &'a IndexVec<LocalDefId, AstOwner<'a>>, pub(super) owners: &'a mut IndexVec<LocalDefId, hir::MaybeOwner<&'hir hir::OwnerInfo<'hir>>>, } @@ -60,6 +61,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { tcx: self.tcx, resolver: self.resolver, arena: self.tcx.hir_arena, + ast_arena: self.ast_arena, // HirId handling. bodies: Vec::new(), @@ -85,6 +87,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { allow_try_trait: Some([sym::try_trait_v2, sym::yeet_desugar_details][..].into()), allow_gen_future: Some([sym::gen_future][..].into()), allow_into_future: Some([sym::into_future][..].into()), + generics_def_id_map: Default::default(), }; lctx.with_hir_id_owner(owner, |lctx| f(lctx)); @@ -120,7 +123,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { self.with_lctx(CRATE_NODE_ID, |lctx| { let module = lctx.lower_mod(&c.items, &c.spans); lctx.lower_attrs(hir::CRATE_HIR_ID, &c.attrs); - hir::OwnerNode::Crate(lctx.arena.alloc(module)) + hir::OwnerNode::Crate(module) }) } @@ -158,14 +161,18 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { } impl<'hir> LoweringContext<'_, 'hir> { - pub(super) fn lower_mod(&mut self, items: &[P<Item>], spans: &ModSpans) -> hir::Mod<'hir> { - hir::Mod { + pub(super) fn lower_mod( + &mut self, + items: &[P<Item>], + spans: &ModSpans, + ) -> &'hir hir::Mod<'hir> { + self.arena.alloc(hir::Mod { spans: hir::ModSpans { inner_span: self.lower_span(spans.inner_span), inject_use_span: self.lower_span(spans.inject_use_span), }, item_ids: self.arena.alloc_from_iter(items.iter().flat_map(|x| self.lower_item_ref(x))), - } + }) } pub(super) fn lower_item_ref(&mut self, i: &Item) -> SmallVec<[hir::ItemId; 1]> { @@ -259,10 +266,10 @@ impl<'hir> LoweringContext<'_, 'hir> { let body_id = this.lower_maybe_async_body(span, &decl, asyncness, body.as_deref()); - let itctx = ImplTraitContext::Universal; - let (generics, decl) = this.lower_generics(generics, id, itctx, |this| { + let mut itctx = ImplTraitContext::Universal; + let (generics, decl) = this.lower_generics(generics, id, &mut itctx, |this| { let ret_id = asyncness.opt_return_id(); - this.lower_fn_decl(&decl, Some(id), FnDeclKind::Fn, ret_id) + this.lower_fn_decl(&decl, Some(id), fn_sig_span, FnDeclKind::Fn, ret_id) }); let sig = hir::FnSig { decl, @@ -306,8 +313,8 @@ impl<'hir> LoweringContext<'_, 'hir> { let (generics, ty) = self.lower_generics( &generics, id, - ImplTraitContext::Disallowed(ImplTraitPosition::Generic), - |this| this.lower_ty(ty, ImplTraitContext::TypeAliasesOpaqueTy), + &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + |this| this.lower_ty(ty, &ImplTraitContext::TypeAliasesOpaqueTy), ); hir::ItemKind::TyAlias(ty, generics) } @@ -319,7 +326,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let (generics, ty) = self.lower_generics( &generics, id, - ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| this.arena.alloc(this.ty(span, hir::TyKind::Err)), ); hir::ItemKind::TyAlias(ty, generics) @@ -328,7 +335,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let (generics, variants) = self.lower_generics( generics, id, - ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| { this.arena.alloc_from_iter( enum_definition.variants.iter().map(|x| this.lower_variant(x)), @@ -341,7 +348,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let (generics, struct_def) = self.lower_generics( generics, id, - ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| this.lower_variant_data(hir_id, struct_def), ); hir::ItemKind::Struct(struct_def, generics) @@ -350,7 +357,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let (generics, vdata) = self.lower_generics( generics, id, - ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| this.lower_variant_data(hir_id, vdata), ); hir::ItemKind::Union(vdata, generics) @@ -378,18 +385,18 @@ impl<'hir> LoweringContext<'_, 'hir> { // method, it will not be considered an in-band // lifetime to be added, but rather a reference to a // parent lifetime. - let itctx = ImplTraitContext::Universal; + let mut itctx = ImplTraitContext::Universal; let (generics, (trait_ref, lowered_ty)) = - self.lower_generics(ast_generics, id, itctx, |this| { + self.lower_generics(ast_generics, id, &mut itctx, |this| { let trait_ref = trait_ref.as_ref().map(|trait_ref| { this.lower_trait_ref( trait_ref, - ImplTraitContext::Disallowed(ImplTraitPosition::Trait), + &ImplTraitContext::Disallowed(ImplTraitPosition::Trait), ) }); let lowered_ty = this - .lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)); + .lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)); (trait_ref, lowered_ty) }); @@ -428,11 +435,11 @@ impl<'hir> LoweringContext<'_, 'hir> { let (generics, (unsafety, items, bounds)) = self.lower_generics( generics, id, - ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| { let bounds = this.lower_param_bounds( bounds, - ImplTraitContext::Disallowed(ImplTraitPosition::Bound), + &ImplTraitContext::Disallowed(ImplTraitPosition::Bound), ); let items = this.arena.alloc_from_iter( items.iter().map(|item| this.lower_trait_item_ref(item)), @@ -447,11 +454,11 @@ impl<'hir> LoweringContext<'_, 'hir> { let (generics, bounds) = self.lower_generics( generics, id, - ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| { this.lower_param_bounds( bounds, - ImplTraitContext::Disallowed(ImplTraitPosition::Bound), + &ImplTraitContext::Disallowed(ImplTraitPosition::Bound), ) }, ); @@ -474,7 +481,7 @@ impl<'hir> LoweringContext<'_, 'hir> { span: Span, body: Option<&Expr>, ) -> (&'hir hir::Ty<'hir>, hir::BodyId) { - let ty = self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)); + let ty = self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)); (ty, self.lower_const_body(span, body)) } @@ -647,12 +654,18 @@ impl<'hir> LoweringContext<'_, 'hir> { kind: match i.kind { ForeignItemKind::Fn(box Fn { ref sig, ref generics, .. }) => { let fdec = &sig.decl; - let itctx = ImplTraitContext::Universal; + let mut itctx = ImplTraitContext::Universal; let (generics, (fn_dec, fn_args)) = - self.lower_generics(generics, i.id, itctx, |this| { + self.lower_generics(generics, i.id, &mut itctx, |this| { ( // Disallow `impl Trait` in foreign items. - this.lower_fn_decl(fdec, None, FnDeclKind::ExternFn, None), + this.lower_fn_decl( + fdec, + None, + sig.span, + FnDeclKind::ExternFn, + None, + ), this.lower_fn_params_to_names(fdec), ) }); @@ -661,7 +674,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } ForeignItemKind::Static(ref t, m, _) => { let ty = - self.lower_ty(t, ImplTraitContext::Disallowed(ImplTraitPosition::Type)); + self.lower_ty(t, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)); hir::ForeignItemKind::Static(ty, m) } ForeignItemKind::TyAlias(..) => hir::ForeignItemKind::Type, @@ -729,11 +742,11 @@ impl<'hir> LoweringContext<'_, 'hir> { qself, path, ParamMode::ExplicitNamed, // no `'_` in declarations (Issue #61124) - ImplTraitContext::Disallowed(ImplTraitPosition::Path), + &ImplTraitContext::Disallowed(ImplTraitPosition::Path), ); self.arena.alloc(t) } else { - self.lower_ty(&f.ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)) + self.lower_ty(&f.ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)) }; let hir_id = self.lower_node_id(f.id); self.lower_attrs(hir_id, &f.attrs); @@ -756,14 +769,20 @@ impl<'hir> LoweringContext<'_, 'hir> { let (generics, kind, has_default) = match i.kind { AssocItemKind::Const(_, ref ty, ref default) => { - let ty = self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)); + let ty = self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)); let body = default.as_ref().map(|x| self.lower_const_body(i.span, Some(x))); (hir::Generics::empty(), hir::TraitItemKind::Const(ty, body), body.is_some()) } AssocItemKind::Fn(box Fn { ref sig, ref generics, body: None, .. }) => { + let asyncness = sig.header.asyncness; let names = self.lower_fn_params_to_names(&sig.decl); - let (generics, sig) = - self.lower_method_sig(generics, sig, i.id, FnDeclKind::Trait, None); + let (generics, sig) = self.lower_method_sig( + generics, + sig, + i.id, + FnDeclKind::Trait, + asyncness.opt_return_id(), + ); (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)), false) } AssocItemKind::Fn(box Fn { ref sig, ref generics, body: Some(ref body), .. }) => { @@ -791,15 +810,15 @@ impl<'hir> LoweringContext<'_, 'hir> { let (generics, kind) = self.lower_generics( &generics, i.id, - ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| { let ty = ty.as_ref().map(|x| { - this.lower_ty(x, ImplTraitContext::Disallowed(ImplTraitPosition::Type)) + this.lower_ty(x, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)) }); hir::TraitItemKind::Type( this.lower_param_bounds( bounds, - ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), ), ty, ) @@ -852,7 +871,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let (generics, kind) = match &i.kind { AssocItemKind::Const(_, ty, expr) => { - let ty = self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)); + let ty = self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)); ( hir::Generics::empty(), hir::ImplItemKind::Const(ty, self.lower_const_body(i.span, expr.as_deref())), @@ -879,14 +898,14 @@ impl<'hir> LoweringContext<'_, 'hir> { self.lower_generics( &generics, i.id, - ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| match ty { None => { let ty = this.arena.alloc(this.ty(i.span, hir::TyKind::Err)); hir::ImplItemKind::TyAlias(ty) } Some(ty) => { - let ty = this.lower_ty(ty, ImplTraitContext::TypeAliasesOpaqueTy); + let ty = this.lower_ty(ty, &ImplTraitContext::TypeAliasesOpaqueTy); hir::ImplItemKind::TyAlias(ty) } }, @@ -947,7 +966,11 @@ impl<'hir> LoweringContext<'_, 'hir> { params: &'hir [hir::Param<'hir>], value: hir::Expr<'hir>, ) -> hir::BodyId { - let body = hir::Body { generator_kind: self.generator_kind, params, value }; + let body = hir::Body { + generator_kind: self.generator_kind, + params, + value: self.arena.alloc(value), + }; let id = body.id(); debug_assert_eq!(id.hir_id.owner, self.current_hir_id_owner); self.bodies.push((id.hir_id.local_id, self.arena.alloc(body))); @@ -1074,12 +1097,9 @@ impl<'hir> LoweringContext<'_, 'hir> { // Check if this is a binding pattern, if so, we can optimize and avoid adding a // `let <pat> = __argN;` statement. In this case, we do not rename the parameter. let (ident, is_simple_parameter) = match parameter.pat.kind { - hir::PatKind::Binding( - hir::BindingAnnotation::Unannotated | hir::BindingAnnotation::Mutable, - _, - ident, - _, - ) => (ident, true), + hir::PatKind::Binding(hir::BindingAnnotation(ByRef::No, _), _, ident, _) => { + (ident, true) + } // For `ref mut` or wildcard arguments, we can't reuse the binding, but // we can keep the same name for the parameter. // This lets rustdoc render it correctly in documentation. @@ -1144,7 +1164,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let (move_pat, move_id) = this.pat_ident_binding_mode( desugared_span, ident, - hir::BindingAnnotation::Mutable, + hir::BindingAnnotation::MUT, ); let move_expr = this.expr_ident(desugared_span, ident, new_parameter_id); let move_stmt = this.stmt_let_pat( @@ -1225,12 +1245,12 @@ impl<'hir> LoweringContext<'_, 'hir> { sig: &FnSig, id: NodeId, kind: FnDeclKind, - is_async: Option<NodeId>, + is_async: Option<(NodeId, Span)>, ) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) { let header = self.lower_fn_header(sig.header); - let itctx = ImplTraitContext::Universal; - let (generics, decl) = self.lower_generics(generics, id, itctx, |this| { - this.lower_fn_decl(&sig.decl, Some(id), kind, is_async) + let mut itctx = ImplTraitContext::Universal; + let (generics, decl) = self.lower_generics(generics, id, &mut itctx, |this| { + this.lower_fn_decl(&sig.decl, Some(id), sig.span, kind, is_async) }); (generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) }) } @@ -1260,10 +1280,11 @@ impl<'hir> LoweringContext<'_, 'hir> { } fn error_on_invalid_abi(&self, abi: StrLit) { - struct_span_err!(self.tcx.sess, abi.span, E0703, "invalid ABI: found `{}`", abi.symbol) - .span_label(abi.span, "invalid ABI") - .help(&format!("valid ABIs: {}", abi::all_names().join(", "))) - .emit(); + self.tcx.sess.emit_err(InvalidAbi { + span: abi.span, + abi: abi.symbol, + valid_abis: abi::all_names().join(", "), + }); } fn lower_asyncness(&mut self, a: Async) -> hir::IsAsync { @@ -1294,7 +1315,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &mut self, generics: &Generics, parent_node_id: NodeId, - itctx: ImplTraitContext, + itctx: &ImplTraitContext, f: impl FnOnce(&mut Self) -> T, ) -> (&'hir hir::Generics<'hir>, T) { debug_assert!(self.impl_trait_defs.is_empty()); @@ -1338,11 +1359,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } let is_param = *is_param.get_or_insert_with(compute_is_param); if !is_param { - self.diagnostic().span_err( - bound.span(), - "`?Trait` bounds are only permitted at the \ - point where a type parameter is declared", - ); + self.tcx.sess.emit_err(MisplacedRelaxTraitBound { span: bound.span() }); } } } @@ -1403,7 +1420,7 @@ impl<'hir> LoweringContext<'_, 'hir> { id: NodeId, kind: &GenericParamKind, bounds: &[GenericBound], - itctx: ImplTraitContext, + itctx: &ImplTraitContext, origin: PredicateOrigin, ) -> Option<hir::WherePredicate<'hir>> { // Do not create a clause if we do not have anything inside it. @@ -1434,10 +1451,14 @@ impl<'hir> LoweringContext<'_, 'hir> { GenericParamKind::Const { .. } => None, GenericParamKind::Type { .. } => { let def_id = self.local_def_id(id).to_def_id(); + let hir_id = self.next_id(); + let res = Res::Def(DefKind::TyParam, def_id); let ty_path = self.arena.alloc(hir::Path { span: param_span, - res: Res::Def(DefKind::TyParam, def_id), - segments: self.arena.alloc_from_iter([hir::PathSegment::from_ident(ident)]), + res, + segments: self + .arena + .alloc_from_iter([hir::PathSegment::new(ident, hir_id, res)]), }); let ty_id = self.next_id(); let bounded_ty = @@ -1475,11 +1496,11 @@ impl<'hir> LoweringContext<'_, 'hir> { }) => hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate { bound_generic_params: self.lower_generic_params(bound_generic_params), bounded_ty: self - .lower_ty(bounded_ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)), + .lower_ty(bounded_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)), bounds: self.arena.alloc_from_iter(bounds.iter().map(|bound| { self.lower_param_bound( bound, - ImplTraitContext::Disallowed(ImplTraitPosition::Bound), + &ImplTraitContext::Disallowed(ImplTraitPosition::Bound), ) })), span: self.lower_span(span), @@ -1494,17 +1515,16 @@ impl<'hir> LoweringContext<'_, 'hir> { lifetime: self.lower_lifetime(lifetime), bounds: self.lower_param_bounds( bounds, - ImplTraitContext::Disallowed(ImplTraitPosition::Bound), + &ImplTraitContext::Disallowed(ImplTraitPosition::Bound), ), in_where_clause: true, }), - WherePredicate::EqPredicate(WhereEqPredicate { id, ref lhs_ty, ref rhs_ty, span }) => { + WherePredicate::EqPredicate(WhereEqPredicate { ref lhs_ty, ref rhs_ty, span }) => { hir::WherePredicate::EqPredicate(hir::WhereEqPredicate { - hir_id: self.lower_node_id(id), lhs_ty: self - .lower_ty(lhs_ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)), + .lower_ty(lhs_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)), rhs_ty: self - .lower_ty(rhs_ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)), + .lower_ty(rhs_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)), span: self.lower_span(span), }) } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 224dc3c23..9012aa704 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -32,14 +32,20 @@ #![feature(box_patterns)] #![feature(let_chains)] -#![feature(let_else)] +#![cfg_attr(bootstrap, feature(let_else))] #![feature(never_type)] #![recursion_limit = "256"] #![allow(rustc::potential_query_instability)] +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate tracing; +use crate::errors::{AssocTyParentheses, AssocTyParenthesesSub, MisplacedImplTrait, TraitFnAsync}; + +use rustc_arena::declare_arena; +use rustc_ast::ptr::P; use rustc_ast::visit; use rustc_ast::{self as ast, *}; use rustc_ast_pretty::pprust; @@ -49,7 +55,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sorted_map::SortedMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::Lrc; -use rustc_errors::{struct_span_err, Applicability, Handler}; +use rustc_errors::{DiagnosticArgFromDisplay, Handler, StashKey}; use rustc_hir as hir; use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res}; use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID}; @@ -75,6 +81,7 @@ macro_rules! arena_vec { mod asm; mod block; +mod errors; mod expr; mod index; mod item; @@ -89,6 +96,13 @@ struct LoweringContext<'a, 'hir> { /// Used to allocate HIR nodes. arena: &'hir hir::Arena<'hir>, + /// Used to allocate temporary AST nodes for use during lowering. + /// This allows us to create "fake" AST -- these nodes can sometimes + /// be allocated on the stack, but other times we need them to live longer + /// than the current stack frame, so they can be collected into vectors + /// and things like that. + ast_arena: &'a Arena<'static>, + /// Bodies inside the owner being lowered. bodies: Vec<(hir::ItemLocalId, &'hir hir::Body<'hir>)>, /// Attributes inside the owner being lowered. @@ -126,8 +140,23 @@ struct LoweringContext<'a, 'hir> { allow_try_trait: Option<Lrc<[Symbol]>>, allow_gen_future: Option<Lrc<[Symbol]>>, allow_into_future: Option<Lrc<[Symbol]>>, + + /// Mapping from generics `def_id`s to TAIT generics `def_id`s. + /// For each captured lifetime (e.g., 'a), we create a new lifetime parameter that is a generic + /// defined on the TAIT, so we have type Foo<'a1> = ... and we establish a mapping in this + /// field from the original parameter 'a to the new parameter 'a1. + generics_def_id_map: Vec<FxHashMap<LocalDefId, LocalDefId>>, } +declare_arena!([ + [] tys: rustc_ast::Ty, + [] aba: rustc_ast::AngleBracketedArgs, + [] ptr: rustc_ast::PolyTraitRef, + // This _marker field is needed because `declare_arena` creates `Arena<'tcx>` and we need to + // use `'tcx`. If we don't have this we get a compile error. + [] _marker: std::marker::PhantomData<&'tcx ()>, +]); + trait ResolverAstLoweringExt { fn legacy_const_generic_args(&self, expr: &Expr) -> Option<Vec<usize>>; fn get_partial_res(&self, id: NodeId) -> Option<PartialRes>; @@ -136,12 +165,6 @@ trait ResolverAstLoweringExt { fn get_lifetime_res(&self, id: NodeId) -> Option<LifetimeRes>; fn take_extra_lifetime_params(&mut self, id: NodeId) -> Vec<(Ident, NodeId, LifetimeRes)>; fn decl_macro_kind(&self, def_id: LocalDefId) -> MacroKind; - /// Record the map from `from` local def id to `to` local def id, on `generics_def_id_map` - /// field. - fn record_def_id_remap(&mut self, from: LocalDefId, to: LocalDefId); - /// Get the previously recorded `to` local def id given the `from` local def id, obtained using - /// `generics_def_id_map` field. - fn get_remapped_def_id(&self, local_def_id: LocalDefId) -> LocalDefId; } impl ResolverAstLoweringExt for ResolverAstLowering { @@ -209,41 +232,6 @@ impl ResolverAstLoweringExt for ResolverAstLowering { fn decl_macro_kind(&self, def_id: LocalDefId) -> MacroKind { self.builtin_macro_kinds.get(&def_id).copied().unwrap_or(MacroKind::Bang) } - - /// Push a remapping into the top-most map. - /// Panics if no map has been pushed. - /// Remapping is used when creating lowering `-> impl Trait` return - /// types to create the resulting opaque type. - #[tracing::instrument(level = "debug", skip(self))] - fn record_def_id_remap(&mut self, from: LocalDefId, to: LocalDefId) { - self.generics_def_id_map.last_mut().expect("no map pushed").insert(from, to); - } - - fn get_remapped_def_id(&self, mut local_def_id: LocalDefId) -> LocalDefId { - // `generics_def_id_map` is a stack of mappings. As we go deeper in impl traits nesting we - // push new mappings so we need to try first the latest mappings, hence `iter().rev()`. - // - // Consider: - // - // `fn test<'a, 'b>() -> impl Trait<&'a u8, Ty = impl Sized + 'b> {}` - // - // We would end with a generics_def_id_map like: - // - // `[[fn#'b -> impl_trait#'b], [fn#'b -> impl_sized#'b]]` - // - // for the opaque type generated on `impl Sized + 'b`, We want the result to be: - // impl_sized#'b, so iterating forward is the wrong thing to do. - for map in self.generics_def_id_map.iter().rev() { - if let Some(r) = map.get(&local_def_id) { - debug!("def_id_remapper: remapping from `{local_def_id:?}` to `{r:?}`"); - local_def_id = *r; - } else { - debug!("def_id_remapper: no remapping for `{local_def_id:?}` found in map"); - } - } - - local_def_id - } } /// Context of `impl Trait` in code, which determines whether it is allowed in an HIR subtree, @@ -264,6 +252,7 @@ enum ImplTraitContext { ReturnPositionOpaqueTy { /// Origin: Either OpaqueTyOrigin::FnReturn or OpaqueTyOrigin::AsyncFn, origin: hir::OpaqueTyOrigin, + in_trait: bool, }, /// Impl trait in type aliases. TypeAliasesOpaqueTy, @@ -323,7 +312,7 @@ impl std::fmt::Display for ImplTraitPosition { } } -#[derive(Debug)] +#[derive(Debug, PartialEq, Eq)] enum FnDeclKind { Fn, Inherent, @@ -335,9 +324,17 @@ enum FnDeclKind { } impl FnDeclKind { - fn impl_trait_return_allowed(&self) -> bool { + fn impl_trait_return_allowed(&self, tcx: TyCtxt<'_>) -> bool { match self { FnDeclKind::Fn | FnDeclKind::Inherent => true, + FnDeclKind::Impl if tcx.features().return_position_impl_trait_in_trait => true, + _ => false, + } + } + + fn impl_trait_in_trait_allowed(&self, tcx: TyCtxt<'_>) -> bool { + match self { + FnDeclKind::Trait if tcx.features().return_position_impl_trait_in_trait => true, _ => false, } } @@ -430,10 +427,13 @@ pub fn lower_to_hir<'hir>(tcx: TyCtxt<'hir>, (): ()) -> hir::Crate<'hir> { tcx.definitions_untracked().def_index_count(), ); + let ast_arena = Arena::default(); + for def_id in ast_index.indices() { item::ItemLowerer { tcx, resolver: &mut resolver, + ast_arena: &ast_arena, ast_index: &ast_index, owners: &mut owners, } @@ -500,6 +500,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } /// Given the id of some node in the AST, finds the `LocalDefId` associated with it by the name + /// resolver (if any). + fn orig_opt_local_def_id(&self, node: NodeId) -> Option<LocalDefId> { + self.resolver.node_id_to_def_id.get(&node).map(|local_def_id| *local_def_id) + } + + fn orig_local_def_id(&self, node: NodeId) -> LocalDefId { + self.orig_opt_local_def_id(node) + .unwrap_or_else(|| panic!("no entry for node id: `{:?}`", node)) + } + + /// Given the id of some node in the AST, finds the `LocalDefId` associated with it by the name /// resolver (if any), after applying any remapping from `get_remapped_def_id`. /// /// For example, in a function like `fn foo<'a>(x: &'a u32)`, @@ -513,16 +524,36 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// we would create an opaque type `type FooReturn<'a1> = impl Debug + 'a1`. /// When lowering the `Debug + 'a` bounds, we add a remapping to map `'a` to `'a1`. fn opt_local_def_id(&self, node: NodeId) -> Option<LocalDefId> { - self.resolver - .node_id_to_def_id - .get(&node) - .map(|local_def_id| self.resolver.get_remapped_def_id(*local_def_id)) + self.orig_opt_local_def_id(node).map(|local_def_id| self.get_remapped_def_id(local_def_id)) } fn local_def_id(&self, node: NodeId) -> LocalDefId { self.opt_local_def_id(node).unwrap_or_else(|| panic!("no entry for node id: `{:?}`", node)) } + /// Get the previously recorded `to` local def id given the `from` local def id, obtained using + /// `generics_def_id_map` field. + fn get_remapped_def_id(&self, local_def_id: LocalDefId) -> LocalDefId { + // `generics_def_id_map` is a stack of mappings. As we go deeper in impl traits nesting we + // push new mappings, so we first need to get the latest (innermost) mappings, hence `iter().rev()`. + // + // Consider: + // + // `fn test<'a, 'b>() -> impl Trait<&'a u8, Ty = impl Sized + 'b> {}` + // + // We would end with a generics_def_id_map like: + // + // `[[fn#'b -> impl_trait#'b], [fn#'b -> impl_sized#'b]]` + // + // for the opaque type generated on `impl Sized + 'b`, we want the result to be: impl_sized#'b. + // So, if we were trying to find first from the start (outermost) would give the wrong result, impl_trait#'b. + self.generics_def_id_map + .iter() + .rev() + .find_map(|map| map.get(&local_def_id).map(|local_def_id| *local_def_id)) + .unwrap_or(local_def_id) + } + /// Freshen the `LoweringContext` and ready it to lower a nested item. /// The lowered item is registered into `self.children`. /// @@ -591,9 +622,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { remap: FxHashMap<LocalDefId, LocalDefId>, f: impl FnOnce(&mut Self) -> R, ) -> R { - self.resolver.generics_def_id_map.push(remap); + self.generics_def_id_map.push(remap); let res = f(self); - self.resolver.generics_def_id_map.pop(); + self.generics_def_id_map.pop(); res } @@ -644,14 +675,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ) -> (Fingerprint, Fingerprint) { self.tcx.with_stable_hashing_context(|mut hcx| { let mut stable_hasher = StableHasher::new(); - hcx.with_hir_bodies(true, node.def_id(), bodies, |hcx| { + hcx.with_hir_bodies(node.def_id(), bodies, |hcx| { node.hash_stable(hcx, &mut stable_hasher) }); let hash_including_bodies = stable_hasher.finish(); let mut stable_hasher = StableHasher::new(); - hcx.with_hir_bodies(false, node.def_id(), bodies, |hcx| { - node.hash_stable(hcx, &mut stable_hasher) - }); + hcx.without_hir_bodies(|hcx| node.hash_stable(hcx, &mut stable_hasher)); let hash_without_bodies = stable_hasher.finish(); (hash_including_bodies, hash_without_bodies) }) @@ -663,6 +692,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// actually used in the HIR, as that would trigger an assertion in the /// `HirIdValidator` later on, which makes sure that all `NodeId`s got mapped /// properly. Calling the method twice with the same `NodeId` is fine though. + #[instrument(level = "debug", skip(self), ret)] fn lower_node_id(&mut self, ast_node_id: NodeId) -> hir::HirId { assert_ne!(ast_node_id, DUMMY_NODE_ID); @@ -696,6 +726,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } /// Generate a new `HirId` without a backing `NodeId`. + #[instrument(level = "debug", skip(self), ret)] fn next_id(&mut self) -> hir::HirId { let owner = self.current_hir_id_owner; let local_id = self.item_local_id_counter; @@ -767,7 +798,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } /// Converts a lifetime into a new generic parameter. - #[tracing::instrument(level = "debug", skip(self))] + #[instrument(level = "debug", skip(self))] fn lifetime_res_to_generic_param( &mut self, ident: Ident, @@ -811,7 +842,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// name resolver owing to lifetime elision; this also populates the resolver's node-id->def-id /// map, so that later calls to `opt_node_id_to_def_id` that refer to these extra lifetime /// parameters will be successful. - #[tracing::instrument(level = "debug", skip(self))] + #[instrument(level = "debug", skip(self))] #[inline] fn lower_lifetime_binder( &mut self, @@ -874,14 +905,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // the `HirId`s. We don't actually need HIR version of attributes anyway. // Tokens are also not needed after macro expansion and parsing. let kind = match attr.kind { - AttrKind::Normal(ref item, _) => AttrKind::Normal( - AttrItem { - path: item.path.clone(), - args: self.lower_mac_args(&item.args), + AttrKind::Normal(ref normal) => AttrKind::Normal(P(NormalAttr { + item: AttrItem { + path: normal.item.path.clone(), + args: self.lower_mac_args(&normal.item.args), tokens: None, }, - None, - ), + tokens: None, + })), AttrKind::DocComment(comment_kind, data) => AttrKind::DocComment(comment_kind, data), }; @@ -929,8 +960,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { lit.clone() } else { Lit { - token: token::Lit::new(token::LitKind::Err, kw::Empty, None), - kind: LitKind::Err(kw::Empty), + token_lit: token::Lit::new(token::LitKind::Err, kw::Empty, None), + kind: LitKind::Err, span: DUMMY_SP, } }; @@ -956,7 +987,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_assoc_ty_constraint( &mut self, constraint: &AssocConstraint, - itctx: ImplTraitContext, + itctx: &ImplTraitContext, ) -> hir::TypeBinding<'hir> { debug!("lower_assoc_ty_constraint(constraint={:?}, itctx={:?})", constraint, itctx); // lower generic arguments of identifier in constraint @@ -967,18 +998,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } GenericArgs::Parenthesized(ref data) => { self.emit_bad_parenthesized_trait_in_assoc_ty(data); - self.lower_angle_bracketed_parameter_data( - &data.as_angle_bracketed_args(), - ParamMode::Explicit, - itctx, - ) - .0 + let aba = self.ast_arena.aba.alloc(data.as_angle_bracketed_args()); + self.lower_angle_bracketed_parameter_data(aba, ParamMode::Explicit, itctx).0 } }; gen_args_ctor.into_generic_args(self) } else { self.arena.alloc(hir::GenericArgs::none()) }; + let itctx_tait = &ImplTraitContext::TypeAliasesOpaqueTy; let kind = match constraint.kind { AssocConstraintKind::Equality { ref term } => { @@ -1016,9 +1044,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // then to an opaque type). // // FIXME: this is only needed until `impl Trait` is allowed in type aliases. - ImplTraitContext::Disallowed(_) if self.is_in_dyn_type => { - (true, ImplTraitContext::TypeAliasesOpaqueTy) - } + ImplTraitContext::Disallowed(_) if self.is_in_dyn_type => (true, itctx_tait), // We are in the parameter position, but not within a dyn type: // @@ -1040,15 +1066,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.with_dyn_type_scope(false, |this| { let node_id = this.next_node_id(); - let ty = this.lower_ty( - &Ty { - id: node_id, - kind: TyKind::ImplTrait(impl_trait_node_id, bounds.clone()), - span: this.lower_span(constraint.span), - tokens: None, - }, - itctx, - ); + let ty = this.ast_arena.tys.alloc(Ty { + id: node_id, + kind: TyKind::ImplTrait(impl_trait_node_id, bounds.clone()), + span: this.lower_span(constraint.span), + tokens: None, + }); + let ty = this.lower_ty(ty, itctx); hir::TypeBindingKind::Equality { term: ty.into() } }) @@ -1072,19 +1096,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } fn emit_bad_parenthesized_trait_in_assoc_ty(&self, data: &ParenthesizedArgs) { - let mut err = self.tcx.sess.struct_span_err( - data.span, - "parenthesized generic arguments cannot be used in associated type constraints", - ); // Suggest removing empty parentheses: "Trait()" -> "Trait" - if data.inputs.is_empty() { + let sub = if data.inputs.is_empty() { let parentheses_span = data.inputs_span.shrink_to_lo().to(data.inputs_span.shrink_to_hi()); - err.multipart_suggestion( - "remove these parentheses", - vec![(parentheses_span, String::new())], - Applicability::MaybeIncorrect, - ); + AssocTyParenthesesSub::Empty { parentheses_span } } // Suggest replacing parentheses with angle brackets `Trait(params...)` to `Trait<params...>` else { @@ -1098,20 +1114,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // End of last argument to end of parameters let close_param = data.inputs.last().unwrap().span.shrink_to_hi().to(data.inputs_span.shrink_to_hi()); - err.multipart_suggestion( - &format!("use angle brackets instead",), - vec![(open_param, String::from("<")), (close_param, String::from(">"))], - Applicability::MaybeIncorrect, - ); - } - err.emit(); + AssocTyParenthesesSub::NotEmpty { open_param, close_param } + }; + self.tcx.sess.emit_err(AssocTyParentheses { span: data.span, sub }); } #[instrument(level = "debug", skip(self))] fn lower_generic_arg( &mut self, arg: &ast::GenericArg, - itctx: ImplTraitContext, + itctx: &ImplTraitContext, ) -> hir::GenericArg<'hir> { match arg { ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(<)), @@ -1163,7 +1175,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } _ => {} } - GenericArg::Type(self.lower_ty_direct(&ty, itctx)) + GenericArg::Type(self.lower_ty(&ty, itctx)) } ast::GenericArg::Const(ct) => GenericArg::Const(ConstArg { value: self.lower_anon_const(&ct), @@ -1173,7 +1185,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } #[instrument(level = "debug", skip(self))] - fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext) -> &'hir hir::Ty<'hir> { + fn lower_ty(&mut self, t: &Ty, itctx: &ImplTraitContext) -> &'hir hir::Ty<'hir> { self.arena.alloc(self.lower_ty_direct(t, itctx)) } @@ -1183,11 +1195,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { qself: &Option<QSelf>, path: &Path, param_mode: ParamMode, - itctx: ImplTraitContext, + itctx: &ImplTraitContext, ) -> hir::Ty<'hir> { // Check whether we should interpret this as a bare trait object. // This check mirrors the one in late resolution. We only introduce this special case in - // the rare occurence we need to lower `Fresh` anonymous lifetimes. + // the rare occurrence we need to lower `Fresh` anonymous lifetimes. // The other cases when a qpath should be opportunistically made a trait object are handled // by `ty_path`. if qself.is_none() @@ -1196,19 +1208,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { && let Res::Def(DefKind::Trait | DefKind::TraitAlias, _) = partial_res.base_res() { let (bounds, lifetime_bound) = self.with_dyn_type_scope(true, |this| { + let poly_trait_ref = this.ast_arena.ptr.alloc(PolyTraitRef { + bound_generic_params: vec![], + trait_ref: TraitRef { path: path.clone(), ref_id: t.id }, + span: t.span + }); let bound = this.lower_poly_trait_ref( - &PolyTraitRef { - bound_generic_params: vec![], - trait_ref: TraitRef { path: path.clone(), ref_id: t.id }, - span: t.span - }, + poly_trait_ref, itctx, ); let bounds = this.arena.alloc_from_iter([bound]); let lifetime_bound = this.elided_dyn_bound(t.span); (bounds, lifetime_bound) }); - let kind = hir::TyKind::TraitObject(bounds, lifetime_bound, TraitObjectSyntax::None); + let kind = hir::TyKind::TraitObject(bounds, &lifetime_bound, TraitObjectSyntax::None); return hir::Ty { kind, span: self.lower_span(t.span), hir_id: self.next_id() }; } @@ -1225,7 +1238,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.ty(span, hir::TyKind::Tup(tys)) } - fn lower_ty_direct(&mut self, t: &Ty, itctx: ImplTraitContext) -> hir::Ty<'hir> { + fn lower_ty_direct(&mut self, t: &Ty, itctx: &ImplTraitContext) -> hir::Ty<'hir> { let kind = match t.kind { TyKind::Infer => hir::TyKind::Infer, TyKind::Err => hir::TyKind::Err, @@ -1241,7 +1254,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } else { self.next_node_id() }; - let span = self.tcx.sess.source_map().next_point(t.span.shrink_to_lo()); + let span = self.tcx.sess.source_map().start_point(t.span); Lifetime { ident: Ident::new(kw::UnderscoreLifetime, span), id } }); let lifetime = self.lower_lifetime(®ion); @@ -1253,7 +1266,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { generic_params, unsafety: self.lower_unsafety(f.unsafety), abi: self.lower_extern(f.ext), - decl: self.lower_fn_decl(&f.decl, None, FnDeclKind::Pointer, None), + decl: self.lower_fn_decl(&f.decl, None, t.span, FnDeclKind::Pointer, None), param_names: self.lower_fn_params_to_names(&f.decl), })) } @@ -1268,14 +1281,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { return self.lower_path_ty(t, qself, path, ParamMode::Explicit, itctx); } TyKind::ImplicitSelf => { + let hir_id = self.next_id(); let res = self.expect_full_res(t.id); let res = self.lower_res(res); hir::TyKind::Path(hir::QPath::Resolved( None, self.arena.alloc(hir::Path { res, - segments: arena_vec![self; hir::PathSegment::from_ident( - Ident::with_dummy_span(kw::SelfUpper) + segments: arena_vec![self; hir::PathSegment::new( + Ident::with_dummy_span(kw::SelfUpper), + hir_id, + res )], span: self.lower_span(t.span), }), @@ -1318,19 +1334,23 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { TyKind::ImplTrait(def_node_id, ref bounds) => { let span = t.span; match itctx { - ImplTraitContext::ReturnPositionOpaqueTy { origin } => { - self.lower_opaque_impl_trait(span, origin, def_node_id, bounds, itctx) - } - ImplTraitContext::TypeAliasesOpaqueTy => { - let nested_itctx = ImplTraitContext::TypeAliasesOpaqueTy; - self.lower_opaque_impl_trait( + ImplTraitContext::ReturnPositionOpaqueTy { origin, in_trait } => self + .lower_opaque_impl_trait( span, - hir::OpaqueTyOrigin::TyAlias, + *origin, def_node_id, bounds, - nested_itctx, - ) - } + *in_trait, + itctx, + ), + ImplTraitContext::TypeAliasesOpaqueTy => self.lower_opaque_impl_trait( + span, + hir::OpaqueTyOrigin::TyAlias, + def_node_id, + bounds, + false, + &ImplTraitContext::TypeAliasesOpaqueTy, + ), ImplTraitContext::Universal => { let span = t.span; let ident = Ident::from_str_and_span(&pprust::ty_to_string(t), span); @@ -1342,15 +1362,26 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } path } + ImplTraitContext::Disallowed( + position @ (ImplTraitPosition::TraitReturn | ImplTraitPosition::ImplReturn), + ) => { + self.tcx + .sess + .create_feature_err( + MisplacedImplTrait { + span: t.span, + position: DiagnosticArgFromDisplay(&position), + }, + sym::return_position_impl_trait_in_trait, + ) + .emit(); + hir::TyKind::Err + } ImplTraitContext::Disallowed(position) => { - let mut err = struct_span_err!( - self.tcx.sess, - t.span, - E0562, - "`impl Trait` only allowed in function and inherent method return types, not in {}", - position - ); - err.emit(); + self.tcx.sess.emit_err(MisplacedImplTrait { + span: t.span, + position: DiagnosticArgFromDisplay(&position), + }); hir::TyKind::Err } } @@ -1397,14 +1428,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// added explicitly in the HIR). But this includes all the lifetimes, and we only want to /// capture the lifetimes that are referenced in the bounds. Therefore, we add *extra* lifetime parameters /// for the lifetimes that get captured (`'x`, in our example above) and reference those. - #[tracing::instrument(level = "debug", skip(self))] + #[instrument(level = "debug", skip(self), ret)] fn lower_opaque_impl_trait( &mut self, span: Span, origin: hir::OpaqueTyOrigin, opaque_ty_node_id: NodeId, bounds: &GenericBounds, - itctx: ImplTraitContext, + in_trait: bool, + itctx: &ImplTraitContext, ) -> hir::TyKind<'hir> { // Make sure we know that some funky desugaring has been going on here. // This is a first: there is code in other places like for loop @@ -1492,6 +1524,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }), bounds: hir_bounds, origin, + in_trait, }; debug!(?opaque_ty_item); @@ -1518,7 +1551,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { debug!(?lifetimes); // `impl Trait` now just becomes `Foo<'a, 'b, ..>`. - hir::TyKind::OpaqueDef(hir::ItemId { def_id: opaque_ty_def_id }, lifetimes) + hir::TyKind::OpaqueDef(hir::ItemId { def_id: opaque_ty_def_id }, lifetimes, in_trait) } /// Registers a new opaque type with the proper `NodeId`s and @@ -1577,7 +1610,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { LifetimeRes::Fresh { param, binder: _ } => { debug_assert_eq!(lifetime.ident.name, kw::UnderscoreLifetime); - if let Some(old_def_id) = self.opt_local_def_id(param) && remapping.get(&old_def_id).is_none() { + if let Some(old_def_id) = self.orig_opt_local_def_id(param) && remapping.get(&old_def_id).is_none() { let node_id = self.next_node_id(); let new_def_id = self.create_def( @@ -1626,19 +1659,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // `fn_def_id`: if `Some`, impl Trait arguments are lowered into generic parameters on the // given DefId, otherwise impl Trait is disallowed. Must be `Some` if // `make_ret_async` is also `Some`. - // `impl_trait_return_allow`: determines whether `impl Trait` can be used in return position. - // This guards against trait declarations and implementations where `impl Trait` is - // disallowed. // `make_ret_async`: if `Some`, converts `-> T` into `-> impl Future<Output = T>` in the // return type. This is used for `async fn` declarations. The `NodeId` is the ID of the - // return type `impl Trait` item. - #[tracing::instrument(level = "debug", skip(self))] + // return type `impl Trait` item, and the `Span` points to the `async` keyword. + #[instrument(level = "debug", skip(self))] fn lower_fn_decl( &mut self, decl: &FnDecl, fn_node_id: Option<NodeId>, + fn_span: Span, kind: FnDeclKind, - make_ret_async: Option<NodeId>, + make_ret_async: Option<(NodeId, Span)>, ) -> &'hir hir::FnDecl<'hir> { let c_variadic = decl.c_variadic(); @@ -1651,11 +1682,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } let inputs = self.arena.alloc_from_iter(inputs.iter().map(|param| { if fn_node_id.is_some() { - self.lower_ty_direct(¶m.ty, ImplTraitContext::Universal) + self.lower_ty_direct(¶m.ty, &ImplTraitContext::Universal) } else { self.lower_ty_direct( ¶m.ty, - ImplTraitContext::Disallowed(match kind { + &ImplTraitContext::Disallowed(match kind { FnDeclKind::Fn | FnDeclKind::Inherent => { unreachable!("fn should allow in-band lifetimes") } @@ -1669,20 +1700,63 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } })); - let output = if let Some(ret_id) = make_ret_async { - self.lower_async_fn_ret_ty( - &decl.output, - fn_node_id.expect("`make_ret_async` but no `fn_def_id`"), - ret_id, - ) + let output = if let Some((ret_id, span)) = make_ret_async { + match kind { + FnDeclKind::Trait => { + if !kind.impl_trait_in_trait_allowed(self.tcx) { + self.tcx + .sess + .create_feature_err( + TraitFnAsync { fn_span, span }, + sym::return_position_impl_trait_in_trait, + ) + .emit(); + } + self.lower_async_fn_ret_ty( + &decl.output, + fn_node_id.expect("`make_ret_async` but no `fn_def_id`"), + ret_id, + true, + ) + } + _ => { + if !kind.impl_trait_return_allowed(self.tcx) { + if kind == FnDeclKind::Impl { + self.tcx + .sess + .create_feature_err( + TraitFnAsync { fn_span, span }, + sym::return_position_impl_trait_in_trait, + ) + .emit(); + } else { + self.tcx.sess.emit_err(TraitFnAsync { fn_span, span }); + } + } + self.lower_async_fn_ret_ty( + &decl.output, + fn_node_id.expect("`make_ret_async` but no `fn_def_id`"), + ret_id, + false, + ) + } + } } else { match decl.output { FnRetTy::Ty(ref ty) => { - let context = match fn_node_id { - Some(fn_node_id) if kind.impl_trait_return_allowed() => { + let mut context = match fn_node_id { + Some(fn_node_id) if kind.impl_trait_return_allowed(self.tcx) => { + let fn_def_id = self.local_def_id(fn_node_id); + ImplTraitContext::ReturnPositionOpaqueTy { + origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), + in_trait: false, + } + } + Some(fn_node_id) if kind.impl_trait_in_trait_allowed(self.tcx) => { let fn_def_id = self.local_def_id(fn_node_id); ImplTraitContext::ReturnPositionOpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), + in_trait: true, } } _ => ImplTraitContext::Disallowed(match kind { @@ -1696,7 +1770,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { FnDeclKind::Impl => ImplTraitPosition::ImplReturn, }), }; - hir::FnRetTy::Return(self.lower_ty(ty, context)) + hir::FnRetTy::Return(self.lower_ty(ty, &mut context)) } FnRetTy::Default(span) => hir::FnRetTy::DefaultReturn(self.lower_span(span)), } @@ -1707,10 +1781,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { output, c_variadic, implicit_self: decl.inputs.get(0).map_or(hir::ImplicitSelfKind::None, |arg| { - use BindingMode::{ByRef, ByValue}; let is_mutable_pat = matches!( arg.pat.kind, - PatKind::Ident(ByValue(Mutability::Mut) | ByRef(Mutability::Mut), ..) + PatKind::Ident(hir::BindingAnnotation(_, Mutability::Mut), ..) ); match arg.ty.kind { @@ -1741,12 +1814,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // `output`: unlowered output type (`T` in `-> T`) // `fn_def_id`: `DefId` of the parent function (used to create child impl trait definition) // `opaque_ty_node_id`: `NodeId` of the opaque `impl Trait` type that should be created - #[tracing::instrument(level = "debug", skip(self))] + #[instrument(level = "debug", skip(self))] fn lower_async_fn_ret_ty( &mut self, output: &FnRetTy, fn_node_id: NodeId, opaque_ty_node_id: NodeId, + in_trait: bool, ) -> hir::FnRetTy<'hir> { let span = output.span(); @@ -1805,7 +1879,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let extra_lifetime_params = self.resolver.take_extra_lifetime_params(opaque_ty_node_id); debug!(?extra_lifetime_params); for (ident, outer_node_id, outer_res) in extra_lifetime_params { - let outer_def_id = self.local_def_id(outer_node_id); + let outer_def_id = self.orig_local_def_id(outer_node_id); let inner_node_id = self.next_node_id(); // Add a definition for the in scope lifetime def. @@ -1873,8 +1947,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // // Then, we will create `fn foo(..) -> Foo<'_, '_>`, and // hence the elision takes place at the fn site. - let future_bound = - this.lower_async_fn_output_type_to_future_bound(output, fn_def_id, span); + let future_bound = this.lower_async_fn_output_type_to_future_bound( + output, + span, + ImplTraitContext::ReturnPositionOpaqueTy { + origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), + in_trait, + }, + ); let generic_params = this.arena.alloc_from_iter(collected_lifetimes.iter().map( |&(new_node_id, lifetime, _)| { @@ -1912,6 +1992,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }), bounds: arena_vec![this; future_bound], origin: hir::OpaqueTyOrigin::AsyncFn(fn_def_id), + in_trait, }; trace!("exist ty from async fn def id: {:#?}", opaque_ty_def_id); @@ -1948,8 +2029,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let res = res.unwrap_or( self.resolver.get_lifetime_res(lifetime.id).unwrap_or(LifetimeRes::Error), ); - let l = self.new_named_lifetime_with_res(id, span, ident, res); - hir::GenericArg::Lifetime(l) + hir::GenericArg::Lifetime(self.new_named_lifetime_with_res(id, span, ident, res)) }, )); @@ -1957,8 +2037,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Foo = impl Trait` is, internally, created as a child of the // async fn, so the *type parameters* are inherited. It's // only the lifetime parameters that we must supply. - let opaque_ty_ref = - hir::TyKind::OpaqueDef(hir::ItemId { def_id: opaque_ty_def_id }, generic_args); + let opaque_ty_ref = hir::TyKind::OpaqueDef( + hir::ItemId { def_id: opaque_ty_def_id }, + generic_args, + in_trait, + ); let opaque_ty = self.ty(opaque_ty_span, opaque_ty_ref); hir::FnRetTy::Return(self.arena.alloc(opaque_ty)) } @@ -1967,8 +2050,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_async_fn_output_type_to_future_bound( &mut self, output: &FnRetTy, - fn_def_id: LocalDefId, span: Span, + mut nested_impl_trait_context: ImplTraitContext, ) -> hir::GenericBound<'hir> { // Compute the `T` in `Future<Output = T>` from the return type. let output_ty = match output { @@ -1976,10 +2059,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Not `OpaqueTyOrigin::AsyncFn`: that's only used for the // `impl Future` opaque type that `async fn` implicitly // generates. - let context = ImplTraitContext::ReturnPositionOpaqueTy { - origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), - }; - self.lower_ty(ty, context) + self.lower_ty(ty, &mut nested_impl_trait_context) } FnRetTy::Default(ret_ty_span) => self.arena.alloc(self.ty_tup(*ret_ty_span, &[])), }; @@ -2005,7 +2085,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_param_bound( &mut self, tpb: &GenericBound, - itctx: ImplTraitContext, + itctx: &ImplTraitContext, ) -> hir::GenericBound<'hir> { match tpb { GenericBound::Trait(p, modifier) => hir::GenericBound::Trait( @@ -2018,24 +2098,24 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } - fn lower_lifetime(&mut self, l: &Lifetime) -> hir::Lifetime { + fn lower_lifetime(&mut self, l: &Lifetime) -> &'hir hir::Lifetime { let span = self.lower_span(l.ident.span); let ident = self.lower_ident(l.ident); self.new_named_lifetime(l.id, l.id, span, ident) } - #[tracing::instrument(level = "debug", skip(self))] + #[instrument(level = "debug", skip(self))] fn new_named_lifetime_with_res( &mut self, id: NodeId, span: Span, ident: Ident, res: LifetimeRes, - ) -> hir::Lifetime { + ) -> &'hir hir::Lifetime { let name = match res { LifetimeRes::Param { param, .. } => { let p_name = ParamName::Plain(ident); - let param = self.resolver.get_remapped_def_id(param); + let param = self.get_remapped_def_id(param); hir::LifetimeName::Param(param, p_name) } @@ -2052,17 +2132,21 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }; debug!(?name); - hir::Lifetime { hir_id: self.lower_node_id(id), span: self.lower_span(span), name } + self.arena.alloc(hir::Lifetime { + hir_id: self.lower_node_id(id), + span: self.lower_span(span), + name, + }) } - #[tracing::instrument(level = "debug", skip(self))] + #[instrument(level = "debug", skip(self))] fn new_named_lifetime( &mut self, id: NodeId, new_id: NodeId, span: Span, ident: Ident, - ) -> hir::Lifetime { + ) -> &'hir hir::Lifetime { let res = self.resolver.get_lifetime_res(id).unwrap_or(LifetimeRes::Error); self.new_named_lifetime_with_res(new_id, span, ident, res) } @@ -2117,7 +2201,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { GenericParamKind::Type { ref default, .. } => { let kind = hir::GenericParamKind::Type { default: default.as_ref().map(|x| { - self.lower_ty(x, ImplTraitContext::Disallowed(ImplTraitPosition::Type)) + self.lower_ty(x, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)) }), synthetic: false, }; @@ -2125,7 +2209,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { (hir::ParamName::Plain(self.lower_ident(param.ident)), kind) } GenericParamKind::Const { ref ty, kw_span: _, ref default } => { - let ty = self.lower_ty(&ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)); + let ty = self.lower_ty(&ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)); let default = default.as_ref().map(|def| self.lower_anon_const(def)); ( hir::ParamName::Plain(self.lower_ident(param.ident)), @@ -2135,7 +2219,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } - fn lower_trait_ref(&mut self, p: &TraitRef, itctx: ImplTraitContext) -> hir::TraitRef<'hir> { + fn lower_trait_ref(&mut self, p: &TraitRef, itctx: &ImplTraitContext) -> hir::TraitRef<'hir> { let path = match self.lower_qpath(p.ref_id, &None, &p.path, ParamMode::Explicit, itctx) { hir::QPath::Resolved(None, path) => path, qpath => panic!("lower_trait_ref: unexpected QPath `{:?}`", qpath), @@ -2143,11 +2227,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::TraitRef { path, hir_ref_id: self.lower_node_id(p.ref_id) } } - #[tracing::instrument(level = "debug", skip(self))] + #[instrument(level = "debug", skip(self))] fn lower_poly_trait_ref( &mut self, p: &PolyTraitRef, - itctx: ImplTraitContext, + itctx: &ImplTraitContext, ) -> hir::PolyTraitRef<'hir> { let bound_generic_params = self.lower_lifetime_binder(p.trait_ref.ref_id, &p.bound_generic_params); @@ -2155,14 +2239,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::PolyTraitRef { bound_generic_params, trait_ref, span: self.lower_span(p.span) } } - fn lower_mt(&mut self, mt: &MutTy, itctx: ImplTraitContext) -> hir::MutTy<'hir> { + fn lower_mt(&mut self, mt: &MutTy, itctx: &ImplTraitContext) -> hir::MutTy<'hir> { hir::MutTy { ty: self.lower_ty(&mt.ty, itctx), mutbl: mt.mutbl } } + #[instrument(level = "debug", skip(self), ret)] fn lower_param_bounds( &mut self, bounds: &[GenericBound], - itctx: ImplTraitContext, + itctx: &ImplTraitContext, ) -> hir::GenericBounds<'hir> { self.arena.alloc_from_iter(self.lower_param_bounds_mut(bounds, itctx)) } @@ -2170,11 +2255,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_param_bounds_mut<'s>( &'s mut self, bounds: &'s [GenericBound], - itctx: ImplTraitContext, + itctx: &'s ImplTraitContext, ) -> impl Iterator<Item = hir::GenericBound<'hir>> + Captures<'s> + Captures<'a> { bounds.iter().map(move |bound| self.lower_param_bound(bound, itctx)) } + #[instrument(level = "debug", skip(self), ret)] fn lower_generic_and_bounds( &mut self, node_id: NodeId, @@ -2200,16 +2286,19 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { node_id, &GenericParamKind::Type { default: None }, bounds, - ImplTraitContext::Universal, + &ImplTraitContext::Universal, hir::PredicateOrigin::ImplTrait, ); + let hir_id = self.next_id(); + let res = Res::Def(DefKind::TyParam, def_id.to_def_id()); let ty = hir::TyKind::Path(hir::QPath::Resolved( None, self.arena.alloc(hir::Path { span: self.lower_span(span), - res: Res::Def(DefKind::TyParam, def_id.to_def_id()), - segments: arena_vec![self; hir::PathSegment::from_ident(self.lower_ident(ident))], + res, + segments: + arena_vec![self; hir::PathSegment::new(self.lower_ident(ident), hir_id, res)], }), )); @@ -2235,7 +2324,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { c.value.span, "using `_` for array lengths is unstable", ) - .emit(); + .stash(c.value.span, StashKey::UnderscoreForArrayLengths); hir::ArrayLen::Body(self.lower_anon_const(c)) } } @@ -2372,11 +2461,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } fn pat_ident(&mut self, span: Span, ident: Ident) -> (&'hir hir::Pat<'hir>, hir::HirId) { - self.pat_ident_binding_mode(span, ident, hir::BindingAnnotation::Unannotated) + self.pat_ident_binding_mode(span, ident, hir::BindingAnnotation::NONE) } fn pat_ident_mut(&mut self, span: Span, ident: Ident) -> (hir::Pat<'hir>, hir::HirId) { - self.pat_ident_binding_mode_mut(span, ident, hir::BindingAnnotation::Unannotated) + self.pat_ident_binding_mode_mut(span, ident, hir::BindingAnnotation::NONE) } fn pat_ident_binding_mode( @@ -2465,14 +2554,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// bound, like the bound in `Box<dyn Debug>`. This method is not invoked /// when the bound is written, even if it is written with `'_` like in /// `Box<dyn Debug + '_>`. In those cases, `lower_lifetime` is invoked. - fn elided_dyn_bound(&mut self, span: Span) -> hir::Lifetime { + fn elided_dyn_bound(&mut self, span: Span) -> &'hir hir::Lifetime { let r = hir::Lifetime { hir_id: self.next_id(), span: self.lower_span(span), name: hir::LifetimeName::ImplicitObjectLifetimeDefault, }; debug!("elided_dyn_bound: r={:?}", r); - r + self.arena.alloc(r) } } diff --git a/compiler/rustc_ast_lowering/src/lifetime_collector.rs b/compiler/rustc_ast_lowering/src/lifetime_collector.rs index 81006e00f..914fc5f58 100644 --- a/compiler/rustc_ast_lowering/src/lifetime_collector.rs +++ b/compiler/rustc_ast_lowering/src/lifetime_collector.rs @@ -1,9 +1,6 @@ use super::ResolverAstLoweringExt; use rustc_ast::visit::{self, BoundKind, LifetimeCtxt, Visitor}; -use rustc_ast::{ - FnRetTy, GenericBounds, Lifetime, NodeId, PathSegment, PolyTraitRef, TraitBoundModifier, Ty, - TyKind, -}; +use rustc_ast::{FnRetTy, GenericBounds, Lifetime, NodeId, PathSegment, PolyTraitRef, Ty, TyKind}; use rustc_hir::def::LifetimeRes; use rustc_middle::span_bug; use rustc_middle::ty::ResolverAstLowering; @@ -66,15 +63,15 @@ impl<'ast> Visitor<'ast> for LifetimeCollectVisitor<'ast> { self.record_lifetime_use(*lifetime); } - fn visit_path_segment(&mut self, path_span: Span, path_segment: &'ast PathSegment) { - self.record_elided_anchor(path_segment.id, path_span); - visit::walk_path_segment(self, path_span, path_segment); + fn visit_path_segment(&mut self, path_segment: &'ast PathSegment) { + self.record_elided_anchor(path_segment.id, path_segment.ident.span); + visit::walk_path_segment(self, path_segment); } - fn visit_poly_trait_ref(&mut self, t: &'ast PolyTraitRef, m: &'ast TraitBoundModifier) { + fn visit_poly_trait_ref(&mut self, t: &'ast PolyTraitRef) { self.current_binders.push(t.trait_ref.ref_id); - visit::walk_poly_trait_ref(self, t, m); + visit::walk_poly_trait_ref(self, t); self.current_binders.pop(); } diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index bd2e76e55..1ea76fdbf 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -1,3 +1,6 @@ +use super::errors::{ + ArbitraryExpressionInPattern, ExtraDoubleDot, MisplacedDoubleDot, SubTupleBinding, +}; use super::ResolverAstLoweringExt; use super::{ImplTraitContext, LoweringContext, ParamMode}; use crate::ImplTraitPosition; @@ -5,7 +8,6 @@ use crate::ImplTraitPosition; use rustc_ast::ptr::P; use rustc_ast::*; use rustc_data_structures::stack::ensure_sufficient_stack; -use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::def::Res; use rustc_span::symbol::Ident; @@ -22,7 +24,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let node = loop { match pattern.kind { PatKind::Wild => break hir::PatKind::Wild, - PatKind::Ident(ref binding_mode, ident, ref sub) => { + PatKind::Ident(binding_mode, ident, ref sub) => { let lower_sub = |this: &mut Self| sub.as_ref().map(|s| this.lower_pat(&*s)); break self.lower_pat_ident(pattern, binding_mode, ident, lower_sub); } @@ -35,7 +37,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { qself, path, ParamMode::Optional, - ImplTraitContext::Disallowed(ImplTraitPosition::Path), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Path), ); let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple struct"); break hir::PatKind::TupleStruct(qpath, pats, ddpos); @@ -51,7 +53,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { qself, path, ParamMode::Optional, - ImplTraitContext::Disallowed(ImplTraitPosition::Path), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Path), ); break hir::PatKind::Path(qpath); } @@ -61,15 +63,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { qself, path, ParamMode::Optional, - ImplTraitContext::Disallowed(ImplTraitPosition::Path), + &mut ImplTraitContext::Disallowed(ImplTraitPosition::Path), ); - let fs = self.arena.alloc_from_iter(fields.iter().map(|f| hir::PatField { - hir_id: self.next_id(), - ident: self.lower_ident(f.ident), - pat: self.lower_pat(&f.pat), - is_shorthand: f.is_shorthand, - span: self.lower_span(f.span), + let fs = self.arena.alloc_from_iter(fields.iter().map(|f| { + let hir_id = self.lower_node_id(f.id); + self.lower_attrs(hir_id, &f.attrs); + + hir::PatField { + hir_id, + ident: self.lower_ident(f.ident), + pat: self.lower_pat(&f.pat), + is_shorthand: f.is_shorthand, + span: self.lower_span(f.span), + } })); break hir::PatKind::Struct(qpath, fs, etc); } @@ -109,7 +116,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &mut self, pats: &[P<Pat>], ctx: &str, - ) -> (&'hir [hir::Pat<'hir>], Option<usize>) { + ) -> (&'hir [hir::Pat<'hir>], hir::DotDotPos) { let mut elems = Vec::with_capacity(pats.len()); let mut rest = None; @@ -129,20 +136,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // This is not allowed as a sub-tuple pattern PatKind::Ident(ref _bm, ident, Some(ref sub)) if sub.is_rest() => { let sp = pat.span; - self.diagnostic() - .struct_span_err( - sp, - &format!("`{} @` is not allowed in a {}", ident.name, ctx), - ) - .span_label(sp, "this is only allowed in slice patterns") - .help("remove this and bind each tuple field independently") - .span_suggestion_verbose( - sp, - &format!("if you don't need to use the contents of {}, discard the tuple's remaining fields", ident), - "..", - Applicability::MaybeIncorrect, - ) - .emit(); + self.tcx.sess.emit_err(SubTupleBinding { + span: sp, + ident_name: ident.name, + ident, + ctx, + }); } _ => {} } @@ -161,7 +160,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } - (self.arena.alloc_from_iter(elems), rest.map(|(ddpos, _)| ddpos)) + (self.arena.alloc_from_iter(elems), hir::DotDotPos::new(rest.map(|(ddpos, _)| ddpos))) } /// Lower a slice pattern of form `[pat_0, ..., pat_n]` into @@ -177,9 +176,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let mut prev_rest_span = None; // Lowers `$bm $ident @ ..` to `$bm $ident @ _`. - let lower_rest_sub = |this: &mut Self, pat, bm, ident, sub| { + let lower_rest_sub = |this: &mut Self, pat, ann, ident, sub| { let lower_sub = |this: &mut Self| Some(this.pat_wild_with_node_id_of(sub)); - let node = this.lower_pat_ident(pat, bm, ident, lower_sub); + let node = this.lower_pat_ident(pat, ann, ident, lower_sub); this.pat_with_node_id_of(pat, node) }; @@ -195,9 +194,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } // Found a sub-slice pattern `$binding_mode $ident @ ..`. // Record, lower it to `$binding_mode $ident @ _`, and stop here. - PatKind::Ident(ref bm, ident, Some(ref sub)) if sub.is_rest() => { + PatKind::Ident(ann, ident, Some(ref sub)) if sub.is_rest() => { prev_rest_span = Some(sub.span); - slice = Some(self.arena.alloc(lower_rest_sub(self, pat, bm, ident, sub))); + slice = Some(self.arena.alloc(lower_rest_sub(self, pat, ann, ident, sub))); break; } // It was not a subslice pattern so lower it normally. @@ -210,9 +209,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // There was a previous subslice pattern; make sure we don't allow more. let rest_span = match pat.kind { PatKind::Rest => Some(pat.span), - PatKind::Ident(ref bm, ident, Some(ref sub)) if sub.is_rest() => { + PatKind::Ident(ann, ident, Some(ref sub)) if sub.is_rest() => { // #69103: Lower into `binding @ _` as above to avoid ICEs. - after.push(lower_rest_sub(self, pat, bm, ident, sub)); + after.push(lower_rest_sub(self, pat, ann, ident, sub)); Some(sub.span) } _ => None, @@ -236,7 +235,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_pat_ident( &mut self, p: &Pat, - binding_mode: &BindingMode, + annotation: BindingAnnotation, ident: Ident, lower_sub: impl FnOnce(&mut Self) -> Option<&'hir hir::Pat<'hir>>, ) -> hir::PatKind<'hir> { @@ -249,29 +248,24 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }; hir::PatKind::Binding( - self.lower_binding_mode(binding_mode), + annotation, self.lower_node_id(canonical_id), self.lower_ident(ident), lower_sub(self), ) } - Some(res) => hir::PatKind::Path(hir::QPath::Resolved( - None, - self.arena.alloc(hir::Path { - span: self.lower_span(ident.span), - res: self.lower_res(res), - segments: arena_vec![self; hir::PathSegment::from_ident(self.lower_ident(ident))], - }), - )), - } - } - - fn lower_binding_mode(&mut self, b: &BindingMode) -> hir::BindingAnnotation { - match *b { - BindingMode::ByValue(Mutability::Not) => hir::BindingAnnotation::Unannotated, - BindingMode::ByRef(Mutability::Not) => hir::BindingAnnotation::Ref, - BindingMode::ByValue(Mutability::Mut) => hir::BindingAnnotation::Mutable, - BindingMode::ByRef(Mutability::Mut) => hir::BindingAnnotation::RefMut, + Some(res) => { + let hir_id = self.next_id(); + let res = self.lower_res(res); + hir::PatKind::Path(hir::QPath::Resolved( + None, + self.arena.alloc(hir::Path { + span: self.lower_span(ident.span), + res, + segments: arena_vec![self; hir::PathSegment::new(self.lower_ident(ident), hir_id, res)], + }), + )) + } } } @@ -291,19 +285,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// Emit a friendly error for extra `..` patterns in a tuple/tuple struct/slice pattern. pub(crate) fn ban_extra_rest_pat(&self, sp: Span, prev_sp: Span, ctx: &str) { - self.diagnostic() - .struct_span_err(sp, &format!("`..` can only be used once per {} pattern", ctx)) - .span_label(sp, &format!("can only be used once per {} pattern", ctx)) - .span_label(prev_sp, "previously used here") - .emit(); + self.tcx.sess.emit_err(ExtraDoubleDot { span: sp, prev_span: prev_sp, ctx }); } /// Used to ban the `..` pattern in places it shouldn't be semantically. fn ban_illegal_rest_pat(&self, sp: Span) -> hir::PatKind<'hir> { - self.diagnostic() - .struct_span_err(sp, "`..` patterns are not allowed here") - .note("only allowed in tuple, tuple struct, and slice patterns") - .emit(); + self.tcx.sess.emit_err(MisplacedDoubleDot { span: sp }); // We're not in a list context so `..` can be reasonably treated // as `_` because it should always be valid and roughly matches the @@ -340,8 +327,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ExprKind::Path(..) if allow_paths => {} ExprKind::Unary(UnOp::Neg, ref inner) if matches!(inner.kind, ExprKind::Lit(_)) => {} _ => { - self.diagnostic() - .span_err(expr.span, "arbitrary expressions aren't allowed in patterns"); + self.tcx.sess.emit_err(ArbitraryExpressionInPattern { span: expr.span }); return self.arena.alloc(self.expr_err(expr.span)); } } diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index 393be3b45..6bb1bb9ea 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -1,11 +1,11 @@ use crate::ImplTraitPosition; +use super::errors::{GenericTypeWithParentheses, UseAngleBrackets}; use super::ResolverAstLoweringExt; use super::{GenericArgsCtor, LifetimeRes, ParenthesizedGenericArgs}; use super::{ImplTraitContext, LoweringContext, ParamMode}; use rustc_ast::{self as ast, *}; -use rustc_errors::{struct_span_err, Applicability}; use rustc_hir as hir; use rustc_hir::def::{DefKind, PartialRes, Res}; use rustc_hir::GenericArg; @@ -13,7 +13,6 @@ use rustc_span::symbol::{kw, Ident}; use rustc_span::{BytePos, Span, DUMMY_SP}; use smallvec::smallvec; -use tracing::debug; impl<'a, 'hir> LoweringContext<'a, 'hir> { #[instrument(level = "trace", skip(self))] @@ -23,7 +22,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { qself: &Option<QSelf>, p: &Path, param_mode: ParamMode, - itctx: ImplTraitContext, + itctx: &ImplTraitContext, ) -> hir::QPath<'hir> { let qself_position = qself.as_ref().map(|q| q.position); let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty, itctx)); @@ -157,7 +156,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { segment, param_mode, ParenthesizedGenericArgs::Err, - ImplTraitContext::Disallowed(ImplTraitPosition::Path), + &ImplTraitContext::Disallowed(ImplTraitPosition::Path), ) })), span: self.lower_span(p.span), @@ -181,11 +180,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { segment: &PathSegment, param_mode: ParamMode, parenthesized_generic_args: ParenthesizedGenericArgs, - itctx: ImplTraitContext, + itctx: &ImplTraitContext, ) -> hir::PathSegment<'hir> { debug!("path_span: {:?}, lower_path_segment(segment: {:?})", path_span, segment,); let (mut generic_args, infer_args) = if let Some(ref generic_args) = segment.args { - let msg = "parenthesized type parameters may only be used with a `Fn` trait"; match **generic_args { GenericArgs::AngleBracketed(ref data) => { self.lower_angle_bracketed_parameter_data(data, param_mode, itctx) @@ -193,10 +191,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { GenericArgs::Parenthesized(ref data) => match parenthesized_generic_args { ParenthesizedGenericArgs::Ok => self.lower_parenthesized_parameter_data(data), ParenthesizedGenericArgs::Err => { - let mut err = struct_span_err!(self.tcx.sess, data.span, E0214, "{}", msg); - err.span_label(data.span, "only `Fn` traits may use parentheses"); // Suggest replacing parentheses with angle brackets `Trait(params...)` to `Trait<params...>` - if !data.inputs.is_empty() { + let sub = if !data.inputs.is_empty() { // Start of the span to the 1st character of 1st argument let open_param = data.inputs_span.shrink_to_lo().to(data .inputs @@ -212,16 +208,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { .span .shrink_to_hi() .to(data.inputs_span.shrink_to_hi()); - err.multipart_suggestion( - &format!("use angle brackets instead",), - vec![ - (open_param, String::from("<")), - (close_param, String::from(">")), - ], - Applicability::MaybeIncorrect, - ); - } - err.emit(); + + Some(UseAngleBrackets { open_param, close_param }) + } else { + None + }; + self.tcx.sess.emit_err(GenericTypeWithParentheses { span: data.span, sub }); ( self.lower_angle_bracketed_parameter_data( &data.as_angle_bracketed_args(), @@ -258,16 +250,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } let res = self.expect_full_res(segment.id); - let id = self.lower_node_id(segment.id); + let hir_id = self.lower_node_id(segment.id); debug!( "lower_path_segment: ident={:?} original-id={:?} new-id={:?}", - segment.ident, segment.id, id, + segment.ident, segment.id, hir_id, ); hir::PathSegment { ident: self.lower_ident(segment.ident), - hir_id: Some(id), - res: Some(self.lower_res(res)), + hir_id, + res: self.lower_res(res), infer_args, args: if generic_args.is_empty() && generic_args.span.is_empty() { None @@ -324,7 +316,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &mut self, data: &AngleBracketedArgs, param_mode: ParamMode, - itctx: ImplTraitContext, + itctx: &ImplTraitContext, ) -> (GenericArgsCtor<'hir>, bool) { let has_non_lt_args = data.args.iter().any(|arg| match arg { AngleBracketedArg::Arg(ast::GenericArg::Lifetime(_)) @@ -358,15 +350,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // we generally don't permit such things (see #51008). let ParenthesizedArgs { span, inputs, inputs_span, output } = data; let inputs = self.arena.alloc_from_iter(inputs.iter().map(|ty| { - self.lower_ty_direct(ty, ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitParam)) + self.lower_ty_direct(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitParam)) })); let output_ty = match output { FnRetTy::Ty(ty) => { - self.lower_ty(&ty, ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitReturn)) + self.lower_ty(&ty, &ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitReturn)) } FnRetTy::Default(_) => self.arena.alloc(self.ty_tup(*span, &[])), }; - let args = smallvec![GenericArg::Type(self.ty_tup(*inputs_span, inputs))]; + let args = smallvec![GenericArg::Type(self.arena.alloc(self.ty_tup(*inputs_span, inputs)))]; let binding = self.output_ty_binding(output_ty.span, output_ty); ( GenericArgsCtor { diff --git a/compiler/rustc_ast_passes/Cargo.toml b/compiler/rustc_ast_passes/Cargo.toml index 22742b2ad..37eff9207 100644 --- a/compiler/rustc_ast_passes/Cargo.toml +++ b/compiler/rustc_ast_passes/Cargo.toml @@ -11,6 +11,7 @@ rustc_attr = { path = "../rustc_attr" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_feature = { path = "../rustc_feature" } +rustc_macros = { path = "../rustc_macros" } rustc_parse = { path = "../rustc_parse" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 2d9d0073f..b1d10e07a 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -13,9 +13,7 @@ use rustc_ast::walk_list; use rustc_ast::*; use rustc_ast_pretty::pprust::{self, State}; use rustc_data_structures::fx::FxHashMap; -use rustc_errors::{ - error_code, pluralize, struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, -}; +use rustc_errors::{error_code, fluent, pluralize, struct_span_err, Applicability}; use rustc_parse::validate_attr; use rustc_session::lint::builtin::{ DEPRECATED_WHERE_CLAUSE_LOCATION, MISSING_ABI, PATTERNS_IN_FNS_WITHOUT_BODY, @@ -29,6 +27,8 @@ use rustc_target::spec::abi; use std::mem; use std::ops::{Deref, DerefMut}; +use crate::errors::*; + const MORE_EXTERN: &str = "for more information, visit https://doc.rust-lang.org/std/keyword.extern.html"; @@ -121,30 +121,9 @@ impl<'a> AstValidator<'a> { fn ban_let_expr(&self, expr: &'a Expr, forbidden_let_reason: ForbiddenLetReason) { let sess = &self.session; if sess.opts.unstable_features.is_nightly_build() { - let err = "`let` expressions are not supported here"; - let mut diag = sess.struct_span_err(expr.span, err); - diag.note("only supported directly in conditions of `if` and `while` expressions"); - match forbidden_let_reason { - ForbiddenLetReason::GenericForbidden => {} - ForbiddenLetReason::NotSupportedOr(span) => { - diag.span_note( - span, - "`||` operators are not supported in let chain expressions", - ); - } - ForbiddenLetReason::NotSupportedParentheses(span) => { - diag.span_note( - span, - "`let`s wrapped in parentheses are not supported in a context with let \ - chains", - ); - } - } - diag.emit(); + sess.emit_err(ForbiddenLet { span: expr.span, reason: forbidden_let_reason }); } else { - sess.struct_span_err(expr.span, "expected expression, found statement (`let`)") - .note("variable declaration using `let` is a statement") - .emit(); + sess.emit_err(ForbiddenLetStable { span: expr.span }); } } @@ -175,7 +154,7 @@ impl<'a> AstValidator<'a> { DEPRECATED_WHERE_CLAUSE_LOCATION, id, where_clauses.0.1, - "where clause not allowed here", + fluent::ast_passes::deprecated_where_clause_location, BuiltinLintDiagnostics::DeprecatedWhereclauseLocation( where_clauses.1.1.shrink_to_hi(), suggestion, @@ -205,10 +184,7 @@ impl<'a> AstValidator<'a> { AssocConstraintKind::Equality { .. } => {} AssocConstraintKind::Bound { .. } => { if self.is_assoc_ty_bound_banned { - self.err_handler().span_err( - constraint.span, - "associated type bounds are not allowed within structs, enums, or unions", - ); + self.session.emit_err(ForbiddenAssocConstraint { span: constraint.span }); } } } @@ -247,11 +223,9 @@ impl<'a> AstValidator<'a> { for (i, segment) in path.segments.iter().enumerate() { // Allow `impl Trait` iff we're on the final path segment if i == path.segments.len() - 1 { - self.visit_path_segment(path.span, segment); + self.visit_path_segment(segment); } else { - self.with_banned_impl_trait(|this| { - this.visit_path_segment(path.span, segment) - }); + self.with_banned_impl_trait(|this| this.visit_path_segment(segment)); } } } @@ -280,38 +254,33 @@ impl<'a> AstValidator<'a> { fn check_lifetime(&self, ident: Ident) { let valid_names = [kw::UnderscoreLifetime, kw::StaticLifetime, kw::Empty]; if !valid_names.contains(&ident.name) && ident.without_first_quote().is_reserved() { - self.err_handler().span_err(ident.span, "lifetimes cannot use keyword names"); + self.session.emit_err(KeywordLifetime { span: ident.span }); } } fn check_label(&self, ident: Ident) { if ident.without_first_quote().is_reserved() { - self.err_handler() - .span_err(ident.span, &format!("invalid label name `{}`", ident.name)); + self.session.emit_err(InvalidLabel { span: ident.span, name: ident.name }); } } - fn invalid_visibility(&self, vis: &Visibility, note: Option<&str>) { + fn invalid_visibility(&self, vis: &Visibility, note: Option<InvalidVisibilityNote>) { if let VisibilityKind::Inherited = vis.kind { return; } - let mut err = - struct_span_err!(self.session, vis.span, E0449, "unnecessary visibility qualifier"); - if vis.kind.is_pub() { - err.span_label(vis.span, "`pub` not permitted here because it's implied"); - } - if let Some(note) = note { - err.note(note); - } - err.emit(); + self.session.emit_err(InvalidVisibility { + span: vis.span, + implied: if vis.kind.is_pub() { Some(vis.span) } else { None }, + note, + }); } fn check_decl_no_pat(decl: &FnDecl, mut report_err: impl FnMut(Span, Option<Ident>, bool)) { for Param { pat, .. } in &decl.inputs { match pat.kind { - PatKind::Ident(BindingMode::ByValue(Mutability::Not), _, None) | PatKind::Wild => {} - PatKind::Ident(BindingMode::ByValue(Mutability::Mut), ident, None) => { + PatKind::Ident(BindingAnnotation::NONE, _, None) | PatKind::Wild => {} + PatKind::Ident(BindingAnnotation::MUT, ident, None) => { report_err(pat.span, Some(ident), true) } _ => report_err(pat.span, None, false), @@ -319,31 +288,9 @@ impl<'a> AstValidator<'a> { } } - fn check_trait_fn_not_async(&self, fn_span: Span, asyncness: Async) { - if let Async::Yes { span, .. } = asyncness { - struct_span_err!( - self.session, - fn_span, - E0706, - "functions in traits cannot be declared `async`" - ) - .span_label(span, "`async` because of this") - .note("`async` trait functions are not currently supported") - .note("consider using the `async-trait` crate: https://crates.io/crates/async-trait") - .emit(); - } - } - fn check_trait_fn_not_const(&self, constness: Const) { if let Const::Yes(span) = constness { - struct_span_err!( - self.session, - span, - E0379, - "functions in traits cannot be declared const" - ) - .span_label(span, "functions in traits cannot be const") - .emit(); + self.session.emit_err(TraitFnConst { span }); } } @@ -356,8 +303,7 @@ impl<'a> AstValidator<'a> { GenericParamKind::Lifetime { .. } => { if !param.bounds.is_empty() { let spans: Vec<_> = param.bounds.iter().map(|b| b.span()).collect(); - self.err_handler() - .span_err(spans, "lifetime bounds cannot be used in this context"); + self.session.emit_err(ForbiddenLifetimeBound { spans }); } None } @@ -365,10 +311,7 @@ impl<'a> AstValidator<'a> { }) .collect(); if !non_lt_param_spans.is_empty() { - self.err_handler().span_err( - non_lt_param_spans, - "only lifetime parameters can be used in this context", - ); + self.session.emit_err(ForbiddenNonLifetimeParam { spans: non_lt_param_spans }); } } @@ -385,10 +328,7 @@ impl<'a> AstValidator<'a> { let max_num_args: usize = u16::MAX.into(); if fn_decl.inputs.len() > max_num_args { let Param { span, .. } = fn_decl.inputs[0]; - self.err_handler().span_fatal( - span, - &format!("function can not have more than {} arguments", max_num_args), - ); + self.session.emit_fatal(FnParamTooMany { span, max_num_args }); } } @@ -396,19 +336,13 @@ impl<'a> AstValidator<'a> { match &*fn_decl.inputs { [Param { ty, span, .. }] => { if let TyKind::CVarArgs = ty.kind { - self.err_handler().span_err( - *span, - "C-variadic function must be declared with at least one named argument", - ); + self.session.emit_err(FnParamCVarArgsOnly { span: *span }); } } [ps @ .., _] => { for Param { ty, span, .. } in ps { if let TyKind::CVarArgs = ty.kind { - self.err_handler().span_err( - *span, - "`...` must be the last argument of a C-variadic function", - ); + self.session.emit_err(FnParamCVarArgsNotLast { span: *span }); } } } @@ -435,19 +369,9 @@ impl<'a> AstValidator<'a> { }) .for_each(|attr| { if attr.is_doc_comment() { - self.err_handler() - .struct_span_err( - attr.span, - "documentation comments cannot be applied to function parameters", - ) - .span_label(attr.span, "doc comments are not allowed here") - .emit(); + self.session.emit_err(FnParamDocComment { span: attr.span }); } else { - self.err_handler().span_err( - attr.span, - "allow, cfg, cfg_attr, deny, expect, \ - forbid, and warn are the only allowed built-in attributes in function parameters", - ); + self.session.emit_err(FnParamForbiddenAttr { span: attr.span }); } }); } @@ -455,14 +379,7 @@ impl<'a> AstValidator<'a> { fn check_decl_self_param(&self, fn_decl: &FnDecl, self_semantic: SelfSemantic) { if let (SelfSemantic::No, [param, ..]) = (self_semantic, &*fn_decl.inputs) { if param.is_self() { - self.err_handler() - .struct_span_err( - param.span, - "`self` parameter is only allowed in associated functions", - ) - .span_label(param.span, "not semantically valid as function parameter") - .note("associated functions are those in `impl` or `trait` definitions") - .emit(); + self.session.emit_err(FnParamForbiddenSelf { span: param.span }); } } } @@ -470,47 +387,20 @@ impl<'a> AstValidator<'a> { fn check_defaultness(&self, span: Span, defaultness: Defaultness) { if let Defaultness::Default(def_span) = defaultness { let span = self.session.source_map().guess_head_span(span); - self.err_handler() - .struct_span_err(span, "`default` is only allowed on items in trait impls") - .span_label(def_span, "`default` because of this") - .emit(); + self.session.emit_err(ForbiddenDefault { span, def_span }); } } - fn error_item_without_body(&self, sp: Span, ctx: &str, msg: &str, sugg: &str) { - self.error_item_without_body_with_help(sp, ctx, msg, sugg, |_| ()); - } - - fn error_item_without_body_with_help( - &self, - sp: Span, - ctx: &str, - msg: &str, - sugg: &str, - help: impl FnOnce(&mut DiagnosticBuilder<'_, ErrorGuaranteed>), - ) { + /// If `sp` ends with a semicolon, returns it as a `Span` + /// Otherwise, returns `sp.shrink_to_hi()` + fn ending_semi_or_hi(&self, sp: Span) -> Span { let source_map = self.session.source_map(); let end = source_map.end_point(sp); - let replace_span = if source_map.span_to_snippet(end).map(|s| s == ";").unwrap_or(false) { + + if source_map.span_to_snippet(end).map(|s| s == ";").unwrap_or(false) { end } else { sp.shrink_to_hi() - }; - let mut err = self.err_handler().struct_span_err(sp, msg); - err.span_suggestion( - replace_span, - &format!("provide a definition for the {}", ctx), - sugg, - Applicability::HasPlaceholders, - ); - help(&mut err); - err.emit(); - } - - fn check_impl_item_provided<T>(&self, sp: Span, body: &Option<T>, ctx: &str, sugg: &str) { - if body.is_none() { - let msg = format!("associated {} in `impl` without body", ctx); - self.error_item_without_body(sp, ctx, &msg, sugg); } } @@ -947,10 +837,10 @@ fn validate_generic_param_order( let (kind, bounds, span) = (¶m.kind, ¶m.bounds, ident.span); let (ord_kind, ident) = match ¶m.kind { GenericParamKind::Lifetime => (ParamKindOrd::Lifetime, ident.to_string()), - GenericParamKind::Type { default: _ } => (ParamKindOrd::Type, ident.to_string()), + GenericParamKind::Type { default: _ } => (ParamKindOrd::TypeOrConst, ident.to_string()), GenericParamKind::Const { ref ty, kw_span: _, default: _ } => { let ty = pprust::ty_to_string(ty); - (ParamKindOrd::Const, format!("const {}: {}", ident, ty)) + (ParamKindOrd::TypeOrConst, format!("const {}: {}", ident, ty)) } }; param_idents.push((kind, ord_kind, bounds, idx, ident)); @@ -1180,7 +1070,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.invalid_visibility( &item.vis, - Some("place qualifiers on individual impl items instead"), + Some(InvalidVisibilityNote::IndividualImplItems), ); if let Unsafe::Yes(span) = unsafety { error(span, "unsafe").code(error_code!(E0197)).emit(); @@ -1203,37 +1093,23 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.check_defaultness(item.span, defaultness); if body.is_none() { - let msg = "free function without a body"; - let ext = sig.header.ext; - - let f = |e: &mut DiagnosticBuilder<'_, _>| { - if let Extern::Implicit(start_span) | Extern::Explicit(_, start_span) = &ext - { - let start_suggestion = if let Extern::Explicit(abi, _) = ext { - format!("extern \"{}\" {{", abi.symbol_unescaped) - } else { - "extern {".to_owned() - }; - - let end_suggestion = " }".to_owned(); - let end_span = item.span.shrink_to_hi(); - - e - .multipart_suggestion( - "if you meant to declare an externally defined function, use an `extern` block", - vec![(*start_span, start_suggestion), (end_span, end_suggestion)], - Applicability::MaybeIncorrect, - ); - } - }; - - self.error_item_without_body_with_help( - item.span, - "function", - msg, - " { <body> }", - f, - ); + self.session.emit_err(FnWithoutBody { + span: item.span, + replace_span: self.ending_semi_or_hi(item.span), + extern_block_suggestion: match sig.header.ext { + Extern::None => None, + Extern::Implicit(start_span) => Some(ExternBlockSuggestion { + start_span, + end_span: item.span.shrink_to_hi(), + abi: None, + }), + Extern::Explicit(abi, start_span) => Some(ExternBlockSuggestion { + start_span, + end_span: item.span.shrink_to_hi(), + abi: Some(abi.symbol_unescaped), + }), + }, + }); } self.visit_vis(&item.vis); @@ -1248,7 +1124,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { let old_item = mem::replace(&mut self.extern_mod, Some(item)); self.invalid_visibility( &item.vis, - Some("place qualifiers on individual foreign items instead"), + Some(InvalidVisibilityNote::IndividualForeignItems), ); if let Unsafe::Yes(span) = unsafety { self.err_handler().span_err(span, "extern block cannot be declared unsafe"); @@ -1339,12 +1215,16 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } ItemKind::Const(def, .., None) => { self.check_defaultness(item.span, def); - let msg = "free constant item without body"; - self.error_item_without_body(item.span, "constant", msg, " = <expr>;"); + self.session.emit_err(ConstWithoutBody { + span: item.span, + replace_span: self.ending_semi_or_hi(item.span), + }); } ItemKind::Static(.., None) => { - let msg = "free static item without body"; - self.error_item_without_body(item.span, "static", msg, " = <expr>;"); + self.session.emit_err(StaticWithoutBody { + span: item.span, + replace_span: self.ending_semi_or_hi(item.span), + }); } ItemKind::TyAlias(box TyAlias { defaultness, @@ -1355,8 +1235,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> { }) => { self.check_defaultness(item.span, defaultness); if ty.is_none() { - let msg = "free type alias without body"; - self.error_item_without_body(item.span, "type", msg, " = <type>;"); + self.session.emit_err(TyAliasWithoutBody { + span: item.span, + replace_span: self.ending_semi_or_hi(item.span), + }); } self.check_type_no_bounds(bounds, "this context"); if where_clauses.1.0 { @@ -1409,7 +1291,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } // Mirrors `visit::walk_generic_args`, but tracks relevant state. - fn visit_generic_args(&mut self, _: Span, generic_args: &'a GenericArgs) { + fn visit_generic_args(&mut self, generic_args: &'a GenericArgs) { match *generic_args { GenericArgs::AngleBracketed(ref data) => { self.check_generic_args_before_constraints(data); @@ -1548,25 +1430,17 @@ impl<'a> Visitor<'a> for AstValidator<'a> { visit::walk_param_bound(self, bound) } - fn visit_poly_trait_ref(&mut self, t: &'a PolyTraitRef, m: &'a TraitBoundModifier) { + fn visit_poly_trait_ref(&mut self, t: &'a PolyTraitRef) { self.check_late_bound_lifetime_defs(&t.bound_generic_params); - visit::walk_poly_trait_ref(self, t, m); + visit::walk_poly_trait_ref(self, t); } fn visit_variant_data(&mut self, s: &'a VariantData) { self.with_banned_assoc_ty_bound(|this| visit::walk_struct_def(this, s)) } - fn visit_enum_def( - &mut self, - enum_definition: &'a EnumDef, - generics: &'a Generics, - item_id: NodeId, - _: Span, - ) { - self.with_banned_assoc_ty_bound(|this| { - visit::walk_enum_def(this, enum_definition, generics, item_id) - }) + fn visit_enum_def(&mut self, enum_definition: &'a EnumDef) { + self.with_banned_assoc_ty_bound(|this| visit::walk_enum_def(this, enum_definition)) } fn visit_fn(&mut self, fk: FnKind<'a>, span: Span, id: NodeId) { @@ -1653,7 +1527,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { matches!(fk.header(), Some(FnHeader { constness: Const::Yes(_), .. })) || matches!(fk.ctxt(), Some(FnCtxt::Assoc(_))); - self.with_tilde_const(tilde_const_allowed, |this| visit::walk_fn(this, fk, span)); + self.with_tilde_const(tilde_const_allowed, |this| visit::walk_fn(this, fk)); } fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) { @@ -1668,10 +1542,20 @@ impl<'a> Visitor<'a> for AstValidator<'a> { if ctxt == AssocCtxt::Impl { match &item.kind { AssocItemKind::Const(_, _, body) => { - self.check_impl_item_provided(item.span, body, "constant", " = <expr>;"); + if body.is_none() { + self.session.emit_err(AssocConstWithoutBody { + span: item.span, + replace_span: self.ending_semi_or_hi(item.span), + }); + } } AssocItemKind::Fn(box Fn { body, .. }) => { - self.check_impl_item_provided(item.span, body, "function", " { <body> }"); + if body.is_none() { + self.session.emit_err(AssocFnWithoutBody { + span: item.span, + replace_span: self.ending_semi_or_hi(item.span), + }); + } } AssocItemKind::TyAlias(box TyAlias { generics, @@ -1681,7 +1565,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> { ty, .. }) => { - self.check_impl_item_provided(item.span, ty, "type", " = <type>;"); + if ty.is_none() { + self.session.emit_err(AssocTypeWithoutBody { + span: item.span, + replace_span: self.ending_semi_or_hi(item.span), + }); + } self.check_type_no_bounds(bounds, "`impl`s"); if ty.is_some() { self.check_gat_where( @@ -1699,7 +1588,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.invalid_visibility(&item.vis, None); if let AssocItemKind::Fn(box Fn { sig, .. }) = &item.kind { self.check_trait_fn_not_const(sig.header.constness); - self.check_trait_fn_not_async(item.span, sig.header.asyncness); } } @@ -1896,14 +1784,14 @@ pub fn check_crate(session: &Session, krate: &Crate, lints: &mut LintBuffer) -> /// Used to forbid `let` expressions in certain syntactic locations. #[derive(Clone, Copy)] -enum ForbiddenLetReason { +pub(crate) enum ForbiddenLetReason { /// `let` is not valid and the source environment is not important GenericForbidden, /// A let chain with the `||` operator NotSupportedOr(Span), /// A let chain with invalid parentheses /// - /// For exemple, `let 1 = 1 && (expr && expr)` is allowed + /// For example, `let 1 = 1 && (expr && expr)` is allowed /// but `(let 1 = 1 && (let 1 = 1 && (let 1 = 1))) && let a = 1` is not NotSupportedParentheses(Span), } diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs new file mode 100644 index 000000000..4f3b09c58 --- /dev/null +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -0,0 +1,245 @@ +//! Errors emitted by ast_passes. + +use rustc_errors::{fluent, AddSubdiagnostic, Applicability, Diagnostic}; +use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic}; +use rustc_span::{Span, Symbol}; + +use crate::ast_validation::ForbiddenLetReason; + +#[derive(SessionDiagnostic)] +#[diag(ast_passes::forbidden_let)] +#[note] +pub struct ForbiddenLet { + #[primary_span] + pub span: Span, + #[subdiagnostic] + pub(crate) reason: ForbiddenLetReason, +} + +impl AddSubdiagnostic for ForbiddenLetReason { + fn add_to_diagnostic(self, diag: &mut Diagnostic) { + match self { + Self::GenericForbidden => {} + Self::NotSupportedOr(span) => { + diag.span_note(span, fluent::ast_passes::not_supported_or); + } + Self::NotSupportedParentheses(span) => { + diag.span_note(span, fluent::ast_passes::not_supported_parentheses); + } + } + } +} + +#[derive(SessionDiagnostic)] +#[diag(ast_passes::forbidden_let_stable)] +#[note] +pub struct ForbiddenLetStable { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(ast_passes::forbidden_assoc_constraint)] +pub struct ForbiddenAssocConstraint { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(ast_passes::keyword_lifetime)] +pub struct KeywordLifetime { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(ast_passes::invalid_label)] +pub struct InvalidLabel { + #[primary_span] + pub span: Span, + pub name: Symbol, +} + +#[derive(SessionDiagnostic)] +#[diag(ast_passes::invalid_visibility, code = "E0449")] +pub struct InvalidVisibility { + #[primary_span] + pub span: Span, + #[label(ast_passes::implied)] + pub implied: Option<Span>, + #[subdiagnostic] + pub note: Option<InvalidVisibilityNote>, +} + +#[derive(SessionSubdiagnostic)] +pub enum InvalidVisibilityNote { + #[note(ast_passes::individual_impl_items)] + IndividualImplItems, + #[note(ast_passes::individual_foreign_items)] + IndividualForeignItems, +} + +#[derive(SessionDiagnostic)] +#[diag(ast_passes::trait_fn_const, code = "E0379")] +pub struct TraitFnConst { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(ast_passes::forbidden_lifetime_bound)] +pub struct ForbiddenLifetimeBound { + #[primary_span] + pub spans: Vec<Span>, +} + +#[derive(SessionDiagnostic)] +#[diag(ast_passes::forbidden_non_lifetime_param)] +pub struct ForbiddenNonLifetimeParam { + #[primary_span] + pub spans: Vec<Span>, +} + +#[derive(SessionDiagnostic)] +#[diag(ast_passes::fn_param_too_many)] +pub struct FnParamTooMany { + #[primary_span] + pub span: Span, + pub max_num_args: usize, +} + +#[derive(SessionDiagnostic)] +#[diag(ast_passes::fn_param_c_var_args_only)] +pub struct FnParamCVarArgsOnly { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(ast_passes::fn_param_c_var_args_not_last)] +pub struct FnParamCVarArgsNotLast { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(ast_passes::fn_param_doc_comment)] +pub struct FnParamDocComment { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(ast_passes::fn_param_forbidden_attr)] +pub struct FnParamForbiddenAttr { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(ast_passes::fn_param_forbidden_self)] +#[note] +pub struct FnParamForbiddenSelf { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(ast_passes::forbidden_default)] +pub struct ForbiddenDefault { + #[primary_span] + pub span: Span, + #[label] + pub def_span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(ast_passes::assoc_const_without_body)] +pub struct AssocConstWithoutBody { + #[primary_span] + pub span: Span, + #[suggestion(code = " = <expr>;", applicability = "has-placeholders")] + pub replace_span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(ast_passes::assoc_fn_without_body)] +pub struct AssocFnWithoutBody { + #[primary_span] + pub span: Span, + #[suggestion(code = " {{ <body> }}", applicability = "has-placeholders")] + pub replace_span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(ast_passes::assoc_type_without_body)] +pub struct AssocTypeWithoutBody { + #[primary_span] + pub span: Span, + #[suggestion(code = " = <type>;", applicability = "has-placeholders")] + pub replace_span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(ast_passes::const_without_body)] +pub struct ConstWithoutBody { + #[primary_span] + pub span: Span, + #[suggestion(code = " = <expr>;", applicability = "has-placeholders")] + pub replace_span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(ast_passes::static_without_body)] +pub struct StaticWithoutBody { + #[primary_span] + pub span: Span, + #[suggestion(code = " = <expr>;", applicability = "has-placeholders")] + pub replace_span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(ast_passes::ty_alias_without_body)] +pub struct TyAliasWithoutBody { + #[primary_span] + pub span: Span, + #[suggestion(code = " = <type>;", applicability = "has-placeholders")] + pub replace_span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(ast_passes::fn_without_body)] +pub struct FnWithoutBody { + #[primary_span] + pub span: Span, + #[suggestion(code = " {{ <body> }}", applicability = "has-placeholders")] + pub replace_span: Span, + #[subdiagnostic] + pub extern_block_suggestion: Option<ExternBlockSuggestion>, +} + +pub struct ExternBlockSuggestion { + pub start_span: Span, + pub end_span: Span, + pub abi: Option<Symbol>, +} + +impl AddSubdiagnostic for ExternBlockSuggestion { + fn add_to_diagnostic(self, diag: &mut Diagnostic) { + let start_suggestion = if let Some(abi) = self.abi { + format!("extern \"{}\" {{", abi) + } else { + "extern {".to_owned() + }; + let end_suggestion = " }".to_owned(); + + diag.multipart_suggestion( + fluent::ast_passes::extern_block_suggestion, + vec![(self.start_span, start_suggestion), (self.end_span, end_suggestion)], + Applicability::MaybeIncorrect, + ); + } +} diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 789eca1f0..aeff73c5b 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -2,17 +2,15 @@ use rustc_ast as ast; use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor}; use rustc_ast::{AssocConstraint, AssocConstraintKind, NodeId}; use rustc_ast::{PatKind, RangeEnd, VariantData}; -use rustc_errors::{struct_span_err, Applicability}; +use rustc_errors::{struct_span_err, Applicability, StashKey}; +use rustc_feature::Features; use rustc_feature::{AttributeGate, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP}; -use rustc_feature::{Features, GateIssue}; -use rustc_session::parse::{feature_err, feature_err_issue}; +use rustc_session::parse::{feature_err, feature_warn}; use rustc_session::Session; use rustc_span::source_map::Spanned; use rustc_span::symbol::sym; use rustc_span::Span; -use tracing::debug; - macro_rules! gate_feature_fn { ($visitor: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr, $help: expr) => {{ let (visitor, has_feature, span, name, explain, help) = @@ -20,9 +18,7 @@ macro_rules! gate_feature_fn { let has_feature: bool = has_feature(visitor.features); debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature); if !has_feature && !span.allows_unstable($name) { - feature_err_issue(&visitor.sess.parse_sess, name, span, GateIssue::Language, explain) - .help(help) - .emit(); + feature_err(&visitor.sess.parse_sess, name, span, explain).help(help).emit(); } }}; ($visitor: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr) => {{ @@ -31,8 +27,19 @@ macro_rules! gate_feature_fn { let has_feature: bool = has_feature(visitor.features); debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature); if !has_feature && !span.allows_unstable($name) { - feature_err_issue(&visitor.sess.parse_sess, name, span, GateIssue::Language, explain) - .emit(); + feature_err(&visitor.sess.parse_sess, name, span, explain).emit(); + } + }}; + (future_incompatible; $visitor: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr) => {{ + let (visitor, has_feature, span, name, explain) = + (&*$visitor, $has_feature, $span, $name, $explain); + let has_feature: bool = has_feature(visitor.features); + debug!( + "gate_feature(feature = {:?}, span = {:?}); has? {} (future_incompatible)", + name, span, has_feature + ); + if !has_feature && !span.allows_unstable($name) { + feature_warn(&visitor.sess.parse_sess, name, span, explain); } }}; } @@ -44,6 +51,9 @@ macro_rules! gate_feature_post { ($visitor: expr, $feature: ident, $span: expr, $explain: expr) => { gate_feature_fn!($visitor, |x: &Features| x.$feature, $span, sym::$feature, $explain) }; + (future_incompatible; $visitor: expr, $feature: ident, $span: expr, $explain: expr) => { + gate_feature_fn!(future_incompatible; $visitor, |x: &Features| x.$feature, $span, sym::$feature, $explain) + }; } pub fn check_attribute(attr: &ast::Attribute, sess: &Session, features: &Features) { @@ -330,25 +340,6 @@ impl<'a> PostExpansionVisitor<'a> { } } - fn check_gat(&self, generics: &ast::Generics, span: Span) { - if !generics.params.is_empty() { - gate_feature_post!( - &self, - generic_associated_types, - span, - "generic associated types are unstable" - ); - } - if !generics.where_clause.predicates.is_empty() { - gate_feature_post!( - &self, - generic_associated_types, - span, - "where clauses on associated types are unstable" - ); - } - } - /// Feature gate `impl Trait` inside `type Alias = $type_expr;`. fn check_impl_trait(&self, ty: &ast::Ty) { struct ImplTraitVisitor<'a> { @@ -417,6 +408,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { || attr.has_name(sym::stable) || attr.has_name(sym::rustc_const_unstable) || attr.has_name(sym::rustc_const_stable) + || attr.has_name(sym::rustc_default_body_unstable) { struct_span_err!( self.sess, @@ -562,6 +554,9 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { ast::TyKind::Never => { gate_feature_post!(&self, never_type, ty.span, "the `!` type is experimental"); } + ast::TyKind::TraitObject(_, ast::TraitObjectSyntax::DynStar, ..) => { + gate_feature_post!(&self, dyn_star, ty.span, "dyn* trait objects are unstable"); + } _ => {} } visit::walk_ty(self, ty) @@ -587,11 +582,10 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { { // When we encounter a statement of the form `foo: Ty = val;`, this will emit a type // ascription error, but the likely intention was to write a `let` statement. (#78907). - feature_err_issue( + feature_err( &self.sess.parse_sess, sym::type_ascription, lhs.span, - GateIssue::Language, "type ascription is experimental", ).span_suggestion_verbose( lhs.span.shrink_to_lo(), @@ -614,28 +608,27 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { ); } ast::ExprKind::Type(..) => { - // To avoid noise about type ascription in common syntax errors, only emit if it - // is the *only* error. if self.sess.parse_sess.span_diagnostic.err_count() == 0 { + // To avoid noise about type ascription in common syntax errors, + // only emit if it is the *only* error. gate_feature_post!( &self, type_ascription, e.span, "type ascription is experimental" ); + } else { + // And if it isn't, cancel the early-pass warning. + self.sess + .parse_sess + .span_diagnostic + .steal_diagnostic(e.span, StashKey::EarlySyntaxWarning) + .map(|err| err.cancel()); } } ast::ExprKind::TryBlock(_) => { gate_feature_post!(&self, try_blocks, e.span, "`try` expression is experimental"); } - ast::ExprKind::Block(_, Some(label)) => { - gate_feature_post!( - &self, - label_break_value, - label.ident.span, - "labels on blocks are unstable" - ); - } _ => {} } visit::walk_expr(self, e) @@ -690,7 +683,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { gate_feature_post!(&self, c_variadic, span, "C-variadic functions are unstable"); } - visit::walk_fn(self, fn_kind, span) + visit::walk_fn(self, fn_kind) } fn visit_assoc_constraint(&mut self, constraint: &'a AssocConstraint) { @@ -708,7 +701,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { fn visit_assoc_item(&mut self, i: &'a ast::AssocItem, ctxt: AssocCtxt) { let is_fn = match i.kind { ast::AssocItemKind::Fn(_) => true, - ast::AssocItemKind::TyAlias(box ast::TyAlias { ref generics, ref ty, .. }) => { + ast::AssocItemKind::TyAlias(box ast::TyAlias { ref ty, .. }) => { if let (Some(_), AssocCtxt::Trait) = (ty, ctxt) { gate_feature_post!( &self, @@ -720,7 +713,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { if let Some(ty) = ty { self.check_impl_trait(ty); } - self.check_gat(generics, i.span); false } _ => false, @@ -789,14 +781,12 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) { // All uses of `gate_all!` below this point were added in #65742, // and subsequently disabled (with the non-early gating readded). + // We emit an early future-incompatible warning for these. + // New syntax gates should go above here to get a hard error gate. macro_rules! gate_all { ($gate:ident, $msg:literal) => { - // FIXME(eddyb) do something more useful than always - // disabling these uses of early feature-gatings. - if false { - for span in spans.get(&sym::$gate).unwrap_or(&vec![]) { - gate_feature_post!(&visitor, $gate, *span, $msg); - } + for span in spans.get(&sym::$gate).unwrap_or(&vec![]) { + gate_feature_post!(future_incompatible; &visitor, $gate, *span, $msg); } }; } @@ -807,13 +797,8 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) { gate_all!(box_patterns, "box pattern syntax is experimental"); gate_all!(exclusive_range_pattern, "exclusive range pattern syntax is experimental"); gate_all!(try_blocks, "`try` blocks are unstable"); - gate_all!(label_break_value, "labels on blocks are unstable"); gate_all!(box_syntax, "box expression syntax is experimental; you can call `Box::new` instead"); - // To avoid noise about type ascription in common syntax errors, - // only emit if it is the *only* error. (Also check it last.) - if sess.parse_sess.span_diagnostic.err_count() == 0 { - gate_all!(type_ascription, "type ascription is experimental"); - } + gate_all!(type_ascription, "type ascription is experimental"); visit::walk_crate(&mut visitor, krate); } diff --git a/compiler/rustc_ast_passes/src/lib.rs b/compiler/rustc_ast_passes/src/lib.rs index 9d52c3288..8aa9d57f0 100644 --- a/compiler/rustc_ast_passes/src/lib.rs +++ b/compiler/rustc_ast_passes/src/lib.rs @@ -9,10 +9,14 @@ #![feature(if_let_guard)] #![feature(iter_is_partitioned)] #![feature(let_chains)] -#![feature(let_else)] +#![cfg_attr(bootstrap, feature(let_else))] #![recursion_limit = "256"] +#[macro_use] +extern crate tracing; + pub mod ast_validation; +mod errors; pub mod feature_gate; pub mod node_count; pub mod show_span; diff --git a/compiler/rustc_ast_passes/src/node_count.rs b/compiler/rustc_ast_passes/src/node_count.rs index 9c7369c83..fa42f8778 100644 --- a/compiler/rustc_ast_passes/src/node_count.rs +++ b/compiler/rustc_ast_passes/src/node_count.rs @@ -63,9 +63,9 @@ impl<'ast> Visitor<'ast> for NodeCounter { self.count += 1; walk_generics(self, g) } - fn visit_fn(&mut self, fk: visit::FnKind<'_>, s: Span, _: NodeId) { + fn visit_fn(&mut self, fk: visit::FnKind<'_>, _: Span, _: NodeId) { self.count += 1; - walk_fn(self, fk, s) + walk_fn(self, fk) } fn visit_assoc_item(&mut self, ti: &AssocItem, ctxt: AssocCtxt) { self.count += 1; @@ -79,9 +79,9 @@ impl<'ast> Visitor<'ast> for NodeCounter { self.count += 1; walk_param_bound(self, bounds) } - fn visit_poly_trait_ref(&mut self, t: &PolyTraitRef, m: &TraitBoundModifier) { + fn visit_poly_trait_ref(&mut self, t: &PolyTraitRef) { self.count += 1; - walk_poly_trait_ref(self, t, m) + walk_poly_trait_ref(self, t) } fn visit_variant_data(&mut self, s: &VariantData) { self.count += 1; @@ -91,15 +91,9 @@ impl<'ast> Visitor<'ast> for NodeCounter { self.count += 1; walk_field_def(self, s) } - fn visit_enum_def( - &mut self, - enum_definition: &EnumDef, - generics: &Generics, - item_id: NodeId, - _: Span, - ) { + fn visit_enum_def(&mut self, enum_definition: &EnumDef) { self.count += 1; - walk_enum_def(self, enum_definition, generics, item_id) + walk_enum_def(self, enum_definition) } fn visit_variant(&mut self, v: &Variant) { self.count += 1; @@ -121,9 +115,9 @@ impl<'ast> Visitor<'ast> for NodeCounter { self.count += 1; walk_use_tree(self, use_tree, id) } - fn visit_generic_args(&mut self, path_span: Span, generic_args: &GenericArgs) { + fn visit_generic_args(&mut self, generic_args: &GenericArgs) { self.count += 1; - walk_generic_args(self, path_span, generic_args) + walk_generic_args(self, generic_args) } fn visit_assoc_constraint(&mut self, constraint: &AssocConstraint) { self.count += 1; diff --git a/compiler/rustc_ast_pretty/src/lib.rs b/compiler/rustc_ast_pretty/src/lib.rs index 79178830b..bf094af5f 100644 --- a/compiler/rustc_ast_pretty/src/lib.rs +++ b/compiler/rustc_ast_pretty/src/lib.rs @@ -1,3 +1,5 @@ +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] #![feature(associated_type_bounds)] #![feature(box_patterns)] #![feature(with_negative_coherence)] diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 5eb7bf634..b87c6f78d 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -11,8 +11,8 @@ use rustc_ast::tokenstream::{TokenStream, TokenTree}; use rustc_ast::util::classify; use rustc_ast::util::comments::{gather_comments, Comment, CommentStyle}; use rustc_ast::util::parser; -use rustc_ast::{self as ast, BlockCheckMode, PatKind, RangeEnd, RangeSyntax}; -use rustc_ast::{attr, Term}; +use rustc_ast::{self as ast, BlockCheckMode, Mutability, PatKind, RangeEnd, RangeSyntax}; +use rustc_ast::{attr, BindingAnnotation, ByRef, Term}; use rustc_ast::{GenericArg, MacArgs, MacArgsEq}; use rustc_ast::{GenericBound, SelfKind, TraitBoundModifier}; use rustc_ast::{InlineAsmOperand, InlineAsmRegOrRegClass}; @@ -22,6 +22,7 @@ use rustc_span::source_map::{SourceMap, Spanned}; use rustc_span::symbol::{kw, sym, Ident, IdentPrinter, Symbol}; use rustc_span::{BytePos, FileName, Span}; +use rustc_ast::attr::AttrIdGenerator; use std::borrow::Cow; pub use self::delimited::IterDelimited; @@ -107,6 +108,7 @@ pub fn print_crate<'a>( ann: &'a dyn PpAnn, is_expanded: bool, edition: Edition, + g: &AttrIdGenerator, ) -> String { let mut s = State { s: pp::Printer::new(), comments: Some(Comments::new(sm, filename, input)), ann }; @@ -120,7 +122,7 @@ pub fn print_crate<'a>( // `#![feature(prelude_import)]` let pi_nested = attr::mk_nested_word_item(Ident::with_dummy_span(sym::prelude_import)); let list = attr::mk_list_item(Ident::with_dummy_span(sym::feature), vec![pi_nested]); - let fake_attr = attr::mk_attr_inner(list); + let fake_attr = attr::mk_attr_inner(g, list); s.print_attribute(&fake_attr); // Currently, in Rust 2018 we don't have `extern crate std;` at the crate @@ -128,7 +130,7 @@ pub fn print_crate<'a>( if edition == Edition::Edition2015 { // `#![no_std]` let no_std_meta = attr::mk_word_item(Ident::with_dummy_span(sym::no_std)); - let fake_attr = attr::mk_attr_inner(no_std_meta); + let fake_attr = attr::mk_attr_inner(g, no_std_meta); s.print_attribute(&fake_attr); } } @@ -372,7 +374,7 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere fn print_literal(&mut self, lit: &ast::Lit) { self.maybe_print_comment(lit.span.lo()); - self.word(lit.token.to_string()) + self.word(lit.token_lit.to_string()) } fn print_string(&mut self, st: &str, style: ast::StrStyle) { @@ -442,12 +444,12 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere } self.maybe_print_comment(attr.span.lo()); match attr.kind { - ast::AttrKind::Normal(ref item, _) => { + ast::AttrKind::Normal(ref normal) => { match attr.style { ast::AttrStyle::Inner => self.word("#!["), ast::AttrStyle::Outer => self.word("#["), } - self.print_attr_item(&item, attr.span); + self.print_attr_item(&normal.item, attr.span); self.word("]"); } ast::AttrKind::DocComment(comment_kind, data) => { @@ -1399,16 +1401,12 @@ impl<'a> State<'a> { is that it doesn't matter */ match pat.kind { PatKind::Wild => self.word("_"), - PatKind::Ident(binding_mode, ident, ref sub) => { - match binding_mode { - ast::BindingMode::ByRef(mutbl) => { - self.word_nbsp("ref"); - self.print_mutability(mutbl, false); - } - ast::BindingMode::ByValue(ast::Mutability::Not) => {} - ast::BindingMode::ByValue(ast::Mutability::Mut) => { - self.word_nbsp("mut"); - } + PatKind::Ident(BindingAnnotation(by_ref, mutbl), ident, ref sub) => { + if by_ref == ByRef::Yes { + self.word_nbsp("ref"); + } + if mutbl == Mutability::Mut { + self.word_nbsp("mut"); } self.print_ident(ident); if let Some(ref p) = *sub { @@ -1487,12 +1485,10 @@ impl<'a> State<'a> { } PatKind::Ref(ref inner, mutbl) => { self.word("&"); - if mutbl == ast::Mutability::Mut { + if mutbl == Mutability::Mut { self.word("mut "); } - if let PatKind::Ident(ast::BindingMode::ByValue(ast::Mutability::Mut), ..) = - inner.kind - { + if let PatKind::Ident(ast::BindingAnnotation::MUT, ..) = inner.kind { self.popen(); self.print_pat(inner); self.pclose(); diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs index f1caf22f3..54bac29a6 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs @@ -218,6 +218,8 @@ impl<'a> State<'a> { ast::ItemKind::GlobalAsm(ref asm) => { self.head(visibility_qualified(&item.vis, "global_asm!")); self.print_inline_asm(asm); + self.word(";"); + self.end(); self.end(); } ast::ItemKind::TyAlias(box ast::TyAlias { @@ -412,9 +414,9 @@ impl<'a> State<'a> { pub(crate) fn print_visibility(&mut self, vis: &ast::Visibility) { match vis.kind { ast::VisibilityKind::Public => self.word_nbsp("pub"), - ast::VisibilityKind::Restricted { ref path, .. } => { + ast::VisibilityKind::Restricted { ref path, id: _, shorthand } => { let path = Self::to_string(|s| s.print_path(path, false, 0)); - if path == "crate" || path == "self" || path == "super" { + if shorthand && (path == "crate" || path == "self" || path == "super") { self.word_nbsp(format!("pub({})", path)) } else { self.word_nbsp(format!("pub(in {})", path)) |