summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_ast
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--compiler/rustc_ast/Cargo.toml1
-rw-r--r--compiler/rustc_ast/src/ast.rs43
-rw-r--r--compiler/rustc_ast/src/lib.rs2
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs17
-rw-r--r--compiler/rustc_ast/src/token.rs49
-rw-r--r--compiler/rustc_ast/src/tokenstream.rs150
-rw-r--r--compiler/rustc_ast/src/util/parser.rs4
-rw-r--r--compiler/rustc_ast/src/visit.rs24
-rw-r--r--compiler/rustc_ast_lowering/src/asm.rs23
-rw-r--r--compiler/rustc_ast_lowering/src/errors.rs236
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs87
-rw-r--r--compiler/rustc_ast_lowering/src/index.rs22
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs99
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs158
-rw-r--r--compiler/rustc_ast_lowering/src/pat.rs2
-rw-r--r--compiler/rustc_ast_lowering/src/path.rs10
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs127
-rw-r--r--compiler/rustc_ast_passes/src/errors.rs127
-rw-r--r--compiler/rustc_ast_passes/src/feature_gate.rs291
-rw-r--r--compiler/rustc_ast_passes/src/lib.rs1
-rw-r--r--compiler/rustc_ast_pretty/Cargo.toml1
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state/expr.rs14
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state/item.rs2
23 files changed, 623 insertions, 867 deletions
diff --git a/compiler/rustc_ast/Cargo.toml b/compiler/rustc_ast/Cargo.toml
index c24180bac..fcbf96818 100644
--- a/compiler/rustc_ast/Cargo.toml
+++ b/compiler/rustc_ast/Cargo.toml
@@ -4,7 +4,6 @@ version = "0.0.0"
edition = "2021"
[lib]
-doctest = false
[dependencies]
bitflags = "1.2.1"
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index d86db8f8b..4ef43735a 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -1112,24 +1112,6 @@ pub struct Expr {
}
impl Expr {
- /// Returns `true` if this expression would be valid somewhere that expects a value;
- /// for example, an `if` condition.
- pub fn returns(&self) -> bool {
- if let ExprKind::Block(ref block, _) = self.kind {
- match block.stmts.last().map(|last_stmt| &last_stmt.kind) {
- // Implicit return
- Some(StmtKind::Expr(_)) => true,
- // Last statement is an explicit return?
- Some(StmtKind::Semi(expr)) => matches!(expr.kind, ExprKind::Ret(_)),
- // This is a block that doesn't end in either an implicit or explicit return.
- _ => false,
- }
- } else {
- // This is not a block, it is a value.
- true
- }
- }
-
/// Is this expr either `N`, or `{ N }`.
///
/// If this is not the case, name resolution does not resolve `N` when using
@@ -1338,14 +1320,13 @@ pub enum ExprKind {
///
/// The `PathSegment` represents the method name and its generic arguments
/// (within the angle brackets).
- /// The first element of the vector of an `Expr` is the expression that evaluates
- /// to the object on which the method is being called on (the receiver),
- /// and the remaining elements are the rest of the arguments.
- /// Thus, `x.foo::<Bar, Baz>(a, b, c, d)` is represented as
- /// `ExprKind::MethodCall(PathSegment { foo, [Bar, Baz] }, [x, a, b, c, d])`.
+ /// The standalone `Expr` is the receiver expression.
+ /// The vector of `Expr` is the arguments.
+ /// `x.foo::<Bar, Baz>(a, b, c, d)` is represented as
+ /// `ExprKind::MethodCall(PathSegment { foo, [Bar, Baz] }, x, [a, b, c, d])`.
/// This `Span` is the span of the function, without the dot and receiver
/// (e.g. `foo(a, b)` in `x.foo(a, b)`
- MethodCall(PathSegment, Vec<P<Expr>>, Span),
+ MethodCall(PathSegment, P<Expr>, Vec<P<Expr>>, Span),
/// A tuple (e.g., `(a, b, c, d)`).
Tup(Vec<P<Expr>>),
/// A binary operation (e.g., `a + b`, `a * b`).
@@ -2957,7 +2938,7 @@ pub enum AssocItemKind {
/// An associated function.
Fn(Box<Fn>),
/// An associated type.
- TyAlias(Box<TyAlias>),
+ Type(Box<TyAlias>),
/// A macro expanding to associated items.
MacCall(P<MacCall>),
}
@@ -2967,7 +2948,7 @@ impl AssocItemKind {
match *self {
Self::Const(defaultness, ..)
| Self::Fn(box Fn { defaultness, .. })
- | Self::TyAlias(box TyAlias { defaultness, .. }) => defaultness,
+ | Self::Type(box TyAlias { defaultness, .. }) => defaultness,
Self::MacCall(..) => Defaultness::Final,
}
}
@@ -2978,7 +2959,7 @@ impl From<AssocItemKind> for ItemKind {
match assoc_item_kind {
AssocItemKind::Const(a, b, c) => ItemKind::Const(a, b, c),
AssocItemKind::Fn(fn_kind) => ItemKind::Fn(fn_kind),
- AssocItemKind::TyAlias(ty_alias_kind) => ItemKind::TyAlias(ty_alias_kind),
+ AssocItemKind::Type(ty_alias_kind) => ItemKind::TyAlias(ty_alias_kind),
AssocItemKind::MacCall(a) => ItemKind::MacCall(a),
}
}
@@ -2991,7 +2972,7 @@ impl TryFrom<ItemKind> for AssocItemKind {
Ok(match item_kind {
ItemKind::Const(a, b, c) => AssocItemKind::Const(a, b, c),
ItemKind::Fn(fn_kind) => AssocItemKind::Fn(fn_kind),
- ItemKind::TyAlias(ty_alias_kind) => AssocItemKind::TyAlias(ty_alias_kind),
+ ItemKind::TyAlias(ty_kind) => AssocItemKind::Type(ty_kind),
ItemKind::MacCall(a) => AssocItemKind::MacCall(a),
_ => return Err(item_kind),
})
@@ -3043,14 +3024,13 @@ pub type ForeignItem = Item<ForeignItemKind>;
mod size_asserts {
use super::*;
use rustc_data_structures::static_assert_size;
- // These are in alphabetical order, which is easy to maintain.
+ // tidy-alphabetical-start
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);
@@ -3065,11 +3045,12 @@ mod size_asserts {
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!(PatKind, 96);
static_assert_size!(Stmt, 32);
static_assert_size!(StmtKind, 16);
static_assert_size!(Ty, 96);
static_assert_size!(TyKind, 72);
+ // tidy-alphabetical-end
}
diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs
index bd7a85b07..eeb7e56e2 100644
--- a/compiler/rustc_ast/src/lib.rs
+++ b/compiler/rustc_ast/src/lib.rs
@@ -13,9 +13,7 @@
#![feature(const_default_impls)]
#![feature(const_trait_impl)]
#![feature(if_let_guard)]
-#![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)]
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 9fd0b63c4..b970e57e0 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -152,6 +152,12 @@ pub trait MutVisitor: Sized {
noop_visit_expr(e, self);
}
+ /// This method is a hack to workaround unstable of `stmt_expr_attributes`.
+ /// It can be removed once that feature is stabilized.
+ fn visit_method_receiver_expr(&mut self, ex: &mut P<Expr>) {
+ self.visit_expr(ex)
+ }
+
fn filter_map_expr(&mut self, e: P<Expr>) -> Option<P<Expr>> {
noop_filter_map_expr(e, self)
}
@@ -1106,7 +1112,7 @@ pub fn noop_flat_map_assoc_item<T: MutVisitor>(
visit_fn_sig(sig, visitor);
visit_opt(body, |body| visitor.visit_block(body));
}
- AssocItemKind::TyAlias(box TyAlias {
+ AssocItemKind::Type(box TyAlias {
defaultness,
generics,
where_clauses,
@@ -1297,10 +1303,11 @@ pub fn noop_visit_expr<T: MutVisitor>(
vis.visit_expr(f);
visit_exprs(args, vis);
}
- ExprKind::MethodCall(PathSegment { ident, id, args }, exprs, span) => {
+ ExprKind::MethodCall(PathSegment { ident, id, args }, receiver, exprs, span) => {
vis.visit_ident(ident);
vis.visit_id(id);
visit_opt(args, |args| vis.visit_generic_args(args));
+ vis.visit_method_receiver_expr(receiver);
visit_exprs(exprs, vis);
vis.visit_span(span);
}
@@ -1588,3 +1595,9 @@ impl DummyAstNode for Crate {
}
}
}
+
+impl<N: DummyAstNode, T: DummyAstNode> DummyAstNode for crate::ast_traits::AstNodeWrapper<N, T> {
+ fn dummy() -> Self {
+ crate::ast_traits::AstNodeWrapper::new(N::dummy(), T::dummy())
+ }
+}
diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs
index 97dfb7837..83b10d906 100644
--- a/compiler/rustc_ast/src/token.rs
+++ b/compiler/rustc_ast/src/token.rs
@@ -13,7 +13,7 @@ use rustc_span::symbol::{kw, sym};
use rustc_span::symbol::{Ident, Symbol};
use rustc_span::{self, edition::Edition, Span, DUMMY_SP};
use std::borrow::Cow;
-use std::{fmt, mem};
+use std::fmt;
#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
pub enum CommentKind {
@@ -256,10 +256,6 @@ pub enum TokenKind {
Eof,
}
-// `TokenKind` is used a lot. Make sure it doesn't unintentionally get bigger.
-#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(TokenKind, 16);
-
#[derive(Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
pub struct Token {
pub kind: TokenKind,
@@ -335,11 +331,6 @@ impl Token {
Token::new(Ident(ident.name, ident.is_raw_guess()), ident.span)
}
- /// Return this token by value and leave a dummy token in its place.
- pub fn take(&mut self) -> Self {
- mem::replace(self, Token::dummy())
- }
-
/// For interpolated tokens, returns a span of the fragment to which the interpolated
/// token refers. For all other tokens this is just a regular span.
/// It is particularly important to use this for identifiers and lifetimes
@@ -354,17 +345,14 @@ impl Token {
}
pub fn is_op(&self) -> bool {
- !matches!(
- self.kind,
- OpenDelim(..)
- | CloseDelim(..)
- | Literal(..)
- | DocComment(..)
- | Ident(..)
- | Lifetime(..)
- | Interpolated(..)
- | Eof
- )
+ match self.kind {
+ Eq | Lt | Le | EqEq | Ne | Ge | Gt | AndAnd | OrOr | Not | Tilde | BinOp(_)
+ | BinOpEq(_) | At | Dot | DotDot | DotDotDot | DotDotEq | Comma | Semi | Colon
+ | ModSep | RArrow | LArrow | FatArrow | Pound | Dollar | Question | SingleQuote => true,
+
+ OpenDelim(..) | CloseDelim(..) | Literal(..) | DocComment(..) | Ident(..)
+ | Lifetime(..) | Interpolated(..) | Eof => false,
+ }
}
pub fn is_like_plus(&self) -> bool {
@@ -733,6 +721,7 @@ impl Token {
}
impl PartialEq<TokenKind> for Token {
+ #[inline]
fn eq(&self, rhs: &TokenKind) -> bool {
self.kind == *rhs
}
@@ -756,10 +745,6 @@ pub enum Nonterminal {
NtVis(P<ast::Visibility>),
}
-// `Nonterminal` is used a lot. Make sure it doesn't unintentionally get bigger.
-#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(Nonterminal, 16);
-
#[derive(Debug, Copy, Clone, PartialEq, Encodable, Decodable)]
pub enum NonterminalKind {
Item,
@@ -898,3 +883,17 @@ where
panic!("interpolated tokens should not be present in the HIR")
}
}
+
+// Some types are used a lot. Make sure they don't unintentionally get bigger.
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
+mod size_asserts {
+ use super::*;
+ use rustc_data_structures::static_assert_size;
+ // tidy-alphabetical-start
+ static_assert_size!(Lit, 12);
+ static_assert_size!(LitKind, 2);
+ static_assert_size!(Nonterminal, 16);
+ static_assert_size!(Token, 24);
+ static_assert_size!(TokenKind, 16);
+ // tidy-alphabetical-end
+}
diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs
index 875cd620d..015f5c1ee 100644
--- a/compiler/rustc_ast/src/tokenstream.rs
+++ b/compiler/rustc_ast/src/tokenstream.rs
@@ -47,10 +47,6 @@ pub enum TokenTree {
Delimited(DelimSpan, Delimiter, TokenStream),
}
-// This type is used a lot. Make sure it doesn't unintentionally get bigger.
-#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(TokenTree, 32);
-
// Ensure all fields of `TokenTree` is `Send` and `Sync`.
#[cfg(parallel_compiler)]
fn _dummy()
@@ -249,12 +245,12 @@ impl AttrTokenStream {
// properly implemented - we always synthesize fake tokens,
// so we never reach this code.
- let mut builder = TokenStreamBuilder::new();
+ let mut stream = TokenStream::default();
for inner_attr in inner_attrs {
- builder.push(inner_attr.tokens());
+ stream.push_stream(inner_attr.tokens());
}
- builder.push(delim_tokens.clone());
- *tree = TokenTree::Delimited(*span, *delim, builder.build());
+ stream.push_stream(delim_tokens.clone());
+ *tree = TokenTree::Delimited(*span, *delim, stream);
found = true;
break;
}
@@ -308,13 +304,20 @@ pub struct AttributesData {
#[derive(Clone, Debug, Default, Encodable, Decodable)]
pub struct TokenStream(pub(crate) Lrc<Vec<TokenTree>>);
-// `TokenStream` is used a lot. Make sure it doesn't unintentionally get bigger.
-#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(TokenStream, 8);
-
+/// Similar to `proc_macro::Spacing`, but for tokens.
+///
+/// Note that all `ast::TokenTree::Token` instances have a `Spacing`, but when
+/// we convert to `proc_macro::TokenTree` for proc macros only `Punct`
+/// `TokenTree`s have a `proc_macro::Spacing`.
#[derive(Clone, Copy, Debug, PartialEq, Encodable, Decodable, HashStable_Generic)]
pub enum Spacing {
+ /// The token is not immediately followed by an operator token (as
+ /// determined by `Token::is_op`). E.g. a `+` token is `Alone` in `+ =`,
+ /// `+/*foo*/=`, `+ident`, and `+()`.
Alone,
+
+ /// The token is immediately followed by an operator token. E.g. a `+`
+ /// token is `Joint` in `+=` and `++`.
Joint,
}
@@ -502,76 +505,49 @@ impl TokenStream {
self.trees().map(|tree| TokenStream::flatten_token_tree(tree)).collect()
}
-}
-// 99.5%+ of the time we have 1 or 2 elements in this vector.
-#[derive(Clone)]
-pub struct TokenStreamBuilder(SmallVec<[TokenStream; 2]>);
-
-impl TokenStreamBuilder {
- pub fn new() -> TokenStreamBuilder {
- TokenStreamBuilder(SmallVec::new())
- }
-
- pub fn push(&mut self, stream: TokenStream) {
- self.0.push(stream);
- }
-
- pub fn build(self) -> TokenStream {
- let mut streams = self.0;
- match streams.len() {
- 0 => TokenStream::default(),
- 1 => streams.pop().unwrap(),
- _ => {
- // We will extend the first stream in `streams` with the
- // elements from the subsequent streams. This requires using
- // `make_mut()` on the first stream, and in practice this
- // doesn't cause cloning 99.9% of the time.
- //
- // One very common use case is when `streams` has two elements,
- // where the first stream has any number of elements within
- // (often 1, but sometimes many more) and the second stream has
- // a single element within.
-
- // Determine how much the first stream will be extended.
- // Needed to avoid quadratic blow up from on-the-fly
- // reallocations (#57735).
- let num_appends = streams.iter().skip(1).map(|ts| ts.len()).sum();
-
- // Get the first stream, which will become the result stream.
- // If it's `None`, create an empty stream.
- let mut iter = streams.into_iter();
- let mut res_stream_lrc = iter.next().unwrap().0;
-
- // Append the subsequent elements to the result stream, after
- // reserving space for them.
- let res_vec_mut = Lrc::make_mut(&mut res_stream_lrc);
- res_vec_mut.reserve(num_appends);
- for stream in iter {
- let stream_iter = stream.0.iter().cloned();
-
- // If (a) `res_mut_vec` is not empty and the last tree
- // within it is a token tree marked with `Joint`, and (b)
- // `stream` is not empty and the first tree within it is a
- // token tree, and (c) the two tokens can be glued
- // together...
- if let Some(TokenTree::Token(last_tok, Spacing::Joint)) = res_vec_mut.last()
- && let Some(TokenTree::Token(tok, spacing)) = stream.0.first()
- && let Some(glued_tok) = last_tok.glue(&tok)
- {
- // ...then overwrite the last token tree in
- // `res_vec_mut` with the glued token, and skip the
- // first token tree from `stream`.
- *res_vec_mut.last_mut().unwrap() = TokenTree::Token(glued_tok, *spacing);
- res_vec_mut.extend(stream_iter.skip(1));
- } else {
- // Append all of `stream`.
- res_vec_mut.extend(stream_iter);
- }
- }
+ // If `vec` is not empty, try to glue `tt` onto its last token. The return
+ // value indicates if gluing took place.
+ fn try_glue_to_last(vec: &mut Vec<TokenTree>, tt: &TokenTree) -> bool {
+ if let Some(TokenTree::Token(last_tok, Spacing::Joint)) = vec.last()
+ && let TokenTree::Token(tok, spacing) = tt
+ && let Some(glued_tok) = last_tok.glue(&tok)
+ {
+ // ...then overwrite the last token tree in `vec` with the
+ // glued token, and skip the first token tree from `stream`.
+ *vec.last_mut().unwrap() = TokenTree::Token(glued_tok, *spacing);
+ true
+ } else {
+ false
+ }
+ }
- TokenStream(res_stream_lrc)
- }
+ // Push `tt` onto the end of the stream, possibly gluing it to the last
+ // token. Uses `make_mut` to maximize efficiency.
+ pub fn push_tree(&mut self, tt: TokenTree) {
+ let vec_mut = Lrc::make_mut(&mut self.0);
+
+ if Self::try_glue_to_last(vec_mut, &tt) {
+ // nothing else to do
+ } else {
+ vec_mut.push(tt);
+ }
+ }
+
+ // Push `stream` onto the end of the stream, possibly gluing the first
+ // token tree to the last token. (No other token trees will be glued.)
+ // Uses `make_mut` to maximize efficiency.
+ pub fn push_stream(&mut self, stream: TokenStream) {
+ let vec_mut = Lrc::make_mut(&mut self.0);
+
+ let stream_iter = stream.0.iter().cloned();
+
+ if let Some(first) = stream.0.first() && Self::try_glue_to_last(vec_mut, first) {
+ // Now skip the first token tree from `stream`.
+ vec_mut.extend(stream_iter.skip(1));
+ } else {
+ // Append all of `stream`.
+ vec_mut.extend(stream_iter);
}
}
}
@@ -664,3 +640,17 @@ impl DelimSpan {
self.open.with_hi(self.close.hi())
}
}
+
+// Some types are used a lot. Make sure they don't unintentionally get bigger.
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
+mod size_asserts {
+ use super::*;
+ use rustc_data_structures::static_assert_size;
+ // tidy-alphabetical-start
+ static_assert_size!(AttrTokenStream, 8);
+ static_assert_size!(AttrTokenTree, 32);
+ static_assert_size!(LazyAttrTokenStream, 8);
+ static_assert_size!(TokenStream, 8);
+ static_assert_size!(TokenTree, 32);
+ // tidy-alphabetical-end
+}
diff --git a/compiler/rustc_ast/src/util/parser.rs b/compiler/rustc_ast/src/util/parser.rs
index 6c5c7f66f..b40ad6f70 100644
--- a/compiler/rustc_ast/src/util/parser.rs
+++ b/compiler/rustc_ast/src/util/parser.rs
@@ -396,9 +396,9 @@ pub fn contains_exterior_struct_lit(value: &ast::Expr) -> bool {
contains_exterior_struct_lit(&x)
}
- ast::ExprKind::MethodCall(.., ref exprs, _) => {
+ ast::ExprKind::MethodCall(_, ref receiver, _, _) => {
// X { y: 1 }.bar(...)
- contains_exterior_struct_lit(&exprs[0])
+ contains_exterior_struct_lit(&receiver)
}
_ => false,
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index 1d0de5a4b..6f56c1ef0 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -140,6 +140,11 @@ pub trait Visitor<'ast>: Sized {
fn visit_expr(&mut self, ex: &'ast Expr) {
walk_expr(self, ex)
}
+ /// This method is a hack to workaround unstable of `stmt_expr_attributes`.
+ /// It can be removed once that feature is stabilized.
+ fn visit_method_receiver_expr(&mut self, ex: &'ast Expr) {
+ self.visit_expr(ex)
+ }
fn visit_expr_post(&mut self, _ex: &'ast Expr) {}
fn visit_ty(&mut self, t: &'ast Ty) {
walk_ty(self, t)
@@ -244,14 +249,12 @@ pub trait Visitor<'ast>: Sized {
#[macro_export]
macro_rules! walk_list {
- ($visitor: expr, $method: ident, $list: expr) => {
- for elem in $list {
- $visitor.$method(elem)
- }
- };
- ($visitor: expr, $method: ident, $list: expr, $($extra_args: expr),*) => {
- for elem in $list {
- $visitor.$method(elem, $($extra_args,)*)
+ ($visitor: expr, $method: ident, $list: expr $(, $($extra_args: expr),* )?) => {
+ {
+ #[cfg_attr(not(bootstrap), allow(for_loops_over_fallibles))]
+ for elem in $list {
+ $visitor.$method(elem $(, $($extra_args,)* )?)
+ }
}
}
}
@@ -685,7 +688,7 @@ pub fn walk_assoc_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem,
let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), ident, sig, vis, generics, body.as_deref());
visitor.visit_fn(kind, span, id);
}
- AssocItemKind::TyAlias(box TyAlias { generics, bounds, ty, .. }) => {
+ AssocItemKind::Type(box TyAlias { generics, bounds, ty, .. }) => {
visitor.visit_generics(generics);
walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
walk_list!(visitor, visit_ty, ty);
@@ -795,8 +798,9 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
visitor.visit_expr(callee_expression);
walk_list!(visitor, visit_expr, arguments);
}
- ExprKind::MethodCall(ref segment, ref arguments, _span) => {
+ ExprKind::MethodCall(ref segment, ref receiver, ref arguments, _span) => {
visitor.visit_path_segment(segment);
+ visitor.visit_expr(receiver);
walk_list!(visitor, visit_expr, arguments);
}
ExprKind::Binary(_, ref left_expression, ref right_expression) => {
diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs
index 24672efc6..450cdf246 100644
--- a/compiler/rustc_ast_lowering/src/asm.rs
+++ b/compiler/rustc_ast_lowering/src/asm.rs
@@ -192,26 +192,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
}
InlineAsmOperand::Sym { ref sym } => {
- if !self.tcx.features().asm_sym {
- feature_err(
- &sess.parse_sess,
- sym::asm_sym,
- *op_sp,
- "sym operands for inline assembly are unstable",
- )
- .emit();
- }
-
let static_def_id = self
.resolver
.get_partial_res(sym.id)
- .filter(|res| res.unresolved_segments() == 0)
- .and_then(|res| {
- if let Res::Def(DefKind::Static(_), def_id) = res.base_res() {
- Some(def_id)
- } else {
- None
- }
+ .and_then(|res| res.full_res())
+ .and_then(|res| match res {
+ Res::Def(DefKind::Static(_), def_id) => Some(def_id),
+ _ => None,
});
if let Some(def_id) = static_def_id {
@@ -237,7 +224,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// Wrap the expression in an AnonConst.
let parent_def_id = self.current_hir_id_owner;
let node_id = self.next_node_id();
- self.create_def(parent_def_id, node_id, DefPathData::AnonConst);
+ self.create_def(parent_def_id.def_id, node_id, DefPathData::AnonConst);
let anon_const = AnonConst { id: node_id, value: P(expr) };
hir::InlineAsmOperand::SymFn {
anon_const: self.lower_anon_const(&anon_const),
diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs
index c87d0ca96..157f46501 100644
--- a/compiler/rustc_ast_lowering/src/errors.rs
+++ b/compiler/rustc_ast_lowering/src/errors.rs
@@ -1,9 +1,9 @@
-use rustc_errors::{fluent, AddSubdiagnostic, Applicability, Diagnostic, DiagnosticArgFromDisplay};
-use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic};
+use rustc_errors::DiagnosticArgFromDisplay;
+use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_span::{symbol::Ident, Span, Symbol};
-#[derive(SessionDiagnostic, Clone, Copy)]
-#[diag(ast_lowering::generic_type_with_parentheses, code = "E0214")]
+#[derive(Diagnostic, Clone, Copy)]
+#[diag(ast_lowering_generic_type_with_parentheses, code = "E0214")]
pub struct GenericTypeWithParentheses {
#[primary_span]
#[label]
@@ -12,35 +12,42 @@ pub struct GenericTypeWithParentheses {
pub sub: Option<UseAngleBrackets>,
}
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Subdiagnostic)]
+#[multipart_suggestion(ast_lowering_use_angle_brackets, applicability = "maybe-incorrect")]
pub struct UseAngleBrackets {
+ #[suggestion_part(code = "<")]
pub open_param: Span,
+ #[suggestion_part(code = ">")]
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")]
+#[derive(Diagnostic)]
+#[diag(ast_lowering_invalid_abi, code = "E0703")]
+#[note]
pub struct InvalidAbi {
#[primary_span]
#[label]
pub span: Span,
pub abi: Symbol,
- pub valid_abis: String,
+ pub command: String,
+ #[subdiagnostic]
+ pub suggestion: Option<InvalidAbiSuggestion>,
+}
+
+#[derive(Subdiagnostic)]
+#[suggestion(
+ ast_lowering_invalid_abi_suggestion,
+ code = "{suggestion}",
+ applicability = "maybe-incorrect"
+)]
+pub struct InvalidAbiSuggestion {
+ #[primary_span]
+ pub span: Span,
+ pub suggestion: String,
}
-#[derive(SessionDiagnostic, Clone, Copy)]
-#[diag(ast_lowering::assoc_ty_parentheses)]
+#[derive(Diagnostic, Clone, Copy)]
+#[diag(ast_lowering_assoc_ty_parentheses)]
pub struct AssocTyParentheses {
#[primary_span]
pub span: Span,
@@ -48,123 +55,116 @@ pub struct AssocTyParentheses {
pub sub: AssocTyParenthesesSub,
}
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Subdiagnostic)]
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")]
+ #[multipart_suggestion(ast_lowering_remove_parentheses)]
+ Empty {
+ #[suggestion_part(code = "")]
+ parentheses_span: Span,
+ },
+ #[multipart_suggestion(ast_lowering_use_angle_brackets)]
+ NotEmpty {
+ #[suggestion_part(code = "<")]
+ open_param: Span,
+ #[suggestion_part(code = ">")]
+ close_param: Span,
+ },
+}
+
+#[derive(Diagnostic)]
+#[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)]
+#[derive(Diagnostic, 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)]
+#[derive(Diagnostic, 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)]
+#[derive(Diagnostic, 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")]
+#[derive(Diagnostic, 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)]
+ #[label(ast_lowering_this_not_async)]
pub item_span: Option<Span>,
}
-#[derive(SessionDiagnostic, Clone, Copy)]
-#[diag(ast_lowering::generator_too_many_parameters, code = "E0628")]
+#[derive(Diagnostic, 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")]
+#[derive(Diagnostic, 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)]
+#[derive(Diagnostic, Clone, Copy)]
#[help]
-#[diag(ast_lowering::async_non_move_closure_not_supported, code = "E0708")]
+#[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)]
+#[derive(Diagnostic, 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")]
+#[derive(Diagnostic, 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")]
+#[derive(Diagnostic, 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)]
+#[derive(Diagnostic, 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)]
+#[derive(Diagnostic, Clone, Copy)]
+#[diag(ast_lowering_abi_specified_multiple_times)]
pub struct AbiSpecifiedMultipleTimes {
#[primary_span]
pub abi_span: Span,
@@ -175,24 +175,24 @@ pub struct AbiSpecifiedMultipleTimes {
pub equivalent: Option<()>,
}
-#[derive(SessionDiagnostic, Clone, Copy)]
-#[diag(ast_lowering::clobber_abi_not_supported)]
+#[derive(Diagnostic, Clone, Copy)]
+#[diag(ast_lowering_clobber_abi_not_supported)]
pub struct ClobberAbiNotSupported {
#[primary_span]
pub abi_span: Span,
}
-#[derive(SessionDiagnostic)]
+#[derive(Diagnostic)]
#[note]
-#[diag(ast_lowering::invalid_abi_clobber_abi)]
+#[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)]
+#[derive(Diagnostic, Clone, Copy)]
+#[diag(ast_lowering_invalid_register)]
pub struct InvalidRegister<'a> {
#[primary_span]
pub op_span: Span,
@@ -200,8 +200,8 @@ pub struct InvalidRegister<'a> {
pub error: &'a str,
}
-#[derive(SessionDiagnostic, Clone, Copy)]
-#[diag(ast_lowering::invalid_register_class)]
+#[derive(Diagnostic, Clone, Copy)]
+#[diag(ast_lowering_invalid_register_class)]
pub struct InvalidRegisterClass<'a> {
#[primary_span]
pub op_span: Span,
@@ -209,61 +209,61 @@ pub struct InvalidRegisterClass<'a> {
pub error: &'a str,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_lowering::invalid_asm_template_modifier_reg_class)]
+#[derive(Diagnostic)]
+#[diag(ast_lowering_invalid_asm_template_modifier_reg_class)]
pub struct InvalidAsmTemplateModifierRegClass {
#[primary_span]
- #[label(ast_lowering::template_modifier)]
+ #[label(ast_lowering_template_modifier)]
pub placeholder_span: Span,
- #[label(ast_lowering::argument)]
+ #[label(ast_lowering_argument)]
pub op_span: Span,
#[subdiagnostic]
pub sub: InvalidAsmTemplateModifierRegClassSub,
}
-#[derive(SessionSubdiagnostic)]
+#[derive(Subdiagnostic)]
pub enum InvalidAsmTemplateModifierRegClassSub {
- #[note(ast_lowering::support_modifiers)]
+ #[note(ast_lowering_support_modifiers)]
SupportModifier { class_name: Symbol, modifiers: String },
- #[note(ast_lowering::does_not_support_modifiers)]
+ #[note(ast_lowering_does_not_support_modifiers)]
DoesNotSupportModifier { class_name: Symbol },
}
-#[derive(SessionDiagnostic, Clone, Copy)]
-#[diag(ast_lowering::invalid_asm_template_modifier_const)]
+#[derive(Diagnostic, Clone, Copy)]
+#[diag(ast_lowering_invalid_asm_template_modifier_const)]
pub struct InvalidAsmTemplateModifierConst {
#[primary_span]
- #[label(ast_lowering::template_modifier)]
+ #[label(ast_lowering_template_modifier)]
pub placeholder_span: Span,
- #[label(ast_lowering::argument)]
+ #[label(ast_lowering_argument)]
pub op_span: Span,
}
-#[derive(SessionDiagnostic, Clone, Copy)]
-#[diag(ast_lowering::invalid_asm_template_modifier_sym)]
+#[derive(Diagnostic, Clone, Copy)]
+#[diag(ast_lowering_invalid_asm_template_modifier_sym)]
pub struct InvalidAsmTemplateModifierSym {
#[primary_span]
- #[label(ast_lowering::template_modifier)]
+ #[label(ast_lowering_template_modifier)]
pub placeholder_span: Span,
- #[label(ast_lowering::argument)]
+ #[label(ast_lowering_argument)]
pub op_span: Span,
}
-#[derive(SessionDiagnostic, Clone, Copy)]
-#[diag(ast_lowering::register_class_only_clobber)]
+#[derive(Diagnostic, 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)]
+#[derive(Diagnostic, Clone, Copy)]
+#[diag(ast_lowering_register_conflict)]
pub struct RegisterConflict<'a> {
#[primary_span]
- #[label(ast_lowering::register1)]
+ #[label(ast_lowering_register1)]
pub op_span1: Span,
- #[label(ast_lowering::register2)]
+ #[label(ast_lowering_register2)]
pub op_span2: Span,
pub reg1_name: &'a str,
pub reg2_name: &'a str,
@@ -271,14 +271,14 @@ pub struct RegisterConflict<'a> {
pub in_out: Option<Span>,
}
-#[derive(SessionDiagnostic, Clone, Copy)]
+#[derive(Diagnostic, Clone, Copy)]
#[help]
-#[diag(ast_lowering::sub_tuple_binding)]
+#[diag(ast_lowering_sub_tuple_binding)]
pub struct SubTupleBinding<'a> {
#[primary_span]
#[label]
#[suggestion_verbose(
- ast_lowering::sub_tuple_binding_suggestion,
+ ast_lowering_sub_tuple_binding_suggestion,
code = "..",
applicability = "maybe-incorrect"
)]
@@ -288,57 +288,57 @@ pub struct SubTupleBinding<'a> {
pub ctx: &'a str,
}
-#[derive(SessionDiagnostic, Clone, Copy)]
-#[diag(ast_lowering::extra_double_dot)]
+#[derive(Diagnostic, Clone, Copy)]
+#[diag(ast_lowering_extra_double_dot)]
pub struct ExtraDoubleDot<'a> {
#[primary_span]
#[label]
pub span: Span,
- #[label(ast_lowering::previously_used_here)]
+ #[label(ast_lowering_previously_used_here)]
pub prev_span: Span,
pub ctx: &'a str,
}
-#[derive(SessionDiagnostic, Clone, Copy)]
+#[derive(Diagnostic, Clone, Copy)]
#[note]
-#[diag(ast_lowering::misplaced_double_dot)]
+#[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)]
+#[derive(Diagnostic, 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)]
+#[derive(Diagnostic, 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)]
+#[derive(Diagnostic, 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)]
+#[derive(Diagnostic, 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")]
+#[derive(Diagnostic, Clone, Copy)]
+#[diag(ast_lowering_trait_fn_async, code = "E0706")]
#[note]
-#[note(ast_lowering::note2)]
+#[note(note2)]
pub struct TraitFnAsync {
#[primary_span]
pub fn_span: Span,
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index 7b8070d3c..ec9c39350 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -60,7 +60,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
hir::ExprKind::Call(f, self.lower_exprs(args))
}
}
- ExprKind::MethodCall(ref seg, ref args, span) => {
+ ExprKind::MethodCall(ref seg, ref receiver, ref args, span) => {
let hir_seg = self.arena.alloc(self.lower_path_segment(
e.span,
seg,
@@ -68,9 +68,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
ParenthesizedGenericArgs::Err,
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
));
- let receiver = self.lower_expr(&args[0]);
+ let receiver = self.lower_expr(receiver);
let args =
- self.arena.alloc_from_iter(args[1..].iter().map(|x| self.lower_expr_mut(x)));
+ self.arena.alloc_from_iter(args.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) => {
@@ -359,7 +359,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let node_id = self.next_node_id();
// Add a definition for the in-band const def.
- self.create_def(parent_def_id, node_id, DefPathData::AnonConst);
+ self.create_def(parent_def_id.def_id, node_id, DefPathData::AnonConst);
let anon_const = AnonConst { id: node_id, value: arg };
generic_args.push(AngleBracketedArg::Arg(GenericArg::Const(anon_const)));
@@ -387,32 +387,58 @@ impl<'hir> LoweringContext<'_, 'hir> {
then: &Block,
else_opt: Option<&Expr>,
) -> hir::ExprKind<'hir> {
- let lowered_cond = self.lower_expr(cond);
- let new_cond = self.manage_let_cond(lowered_cond);
+ let lowered_cond = self.lower_cond(cond);
let then_expr = self.lower_block_expr(then);
if let Some(rslt) = else_opt {
- hir::ExprKind::If(new_cond, self.arena.alloc(then_expr), Some(self.lower_expr(rslt)))
+ hir::ExprKind::If(
+ lowered_cond,
+ self.arena.alloc(then_expr),
+ Some(self.lower_expr(rslt)),
+ )
} else {
- hir::ExprKind::If(new_cond, self.arena.alloc(then_expr), None)
+ hir::ExprKind::If(lowered_cond, self.arena.alloc(then_expr), None)
}
}
- // If `cond` kind is `let`, returns `let`. Otherwise, wraps and returns `cond`
- // in a temporary block.
- fn manage_let_cond(&mut self, cond: &'hir hir::Expr<'hir>) -> &'hir hir::Expr<'hir> {
- fn has_let_expr<'hir>(expr: &'hir hir::Expr<'hir>) -> bool {
- match expr.kind {
- hir::ExprKind::Binary(_, lhs, rhs) => has_let_expr(lhs) || has_let_expr(rhs),
- hir::ExprKind::Let(..) => true,
+ // Lowers a condition (i.e. `cond` in `if cond` or `while cond`), wrapping it in a terminating scope
+ // so that temporaries created in the condition don't live beyond it.
+ fn lower_cond(&mut self, cond: &Expr) -> &'hir hir::Expr<'hir> {
+ fn has_let_expr(expr: &Expr) -> bool {
+ match &expr.kind {
+ ExprKind::Binary(_, lhs, rhs) => has_let_expr(lhs) || has_let_expr(rhs),
+ ExprKind::Let(..) => true,
_ => false,
}
}
- if has_let_expr(cond) {
- cond
- } else {
- let reason = DesugaringKind::CondTemporary;
- let span_block = self.mark_span_with_reason(reason, cond.span, None);
- self.expr_drop_temps(span_block, cond, AttrVec::new())
+
+ // We have to take special care for `let` exprs in the condition, e.g. in
+ // `if let pat = val` or `if foo && let pat = val`, as we _do_ want `val` to live beyond the
+ // condition in this case.
+ //
+ // In order to mantain the drop behavior for the non `let` parts of the condition,
+ // we still wrap them in terminating scopes, e.g. `if foo && let pat = val` essentially
+ // gets transformed into `if { let _t = foo; _t } && let pat = val`
+ match &cond.kind {
+ ExprKind::Binary(op @ Spanned { node: ast::BinOpKind::And, .. }, lhs, rhs)
+ if has_let_expr(cond) =>
+ {
+ let op = self.lower_binop(*op);
+ let lhs = self.lower_cond(lhs);
+ let rhs = self.lower_cond(rhs);
+
+ self.arena.alloc(self.expr(
+ cond.span,
+ hir::ExprKind::Binary(op, lhs, rhs),
+ AttrVec::new(),
+ ))
+ }
+ ExprKind::Let(..) => self.lower_expr(cond),
+ _ => {
+ let cond = self.lower_expr(cond);
+ let reason = DesugaringKind::CondTemporary;
+ let span_block = self.mark_span_with_reason(reason, cond.span, None);
+ self.expr_drop_temps(span_block, cond, AttrVec::new())
+ }
}
}
@@ -439,14 +465,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
body: &Block,
opt_label: Option<Label>,
) -> hir::ExprKind<'hir> {
- let lowered_cond = self.with_loop_condition_scope(|t| t.lower_expr(cond));
- let new_cond = self.manage_let_cond(lowered_cond);
+ let lowered_cond = self.with_loop_condition_scope(|t| t.lower_cond(cond));
let then = self.lower_block_expr(body);
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, AttrVec::new()));
- let if_kind = hir::ExprKind::If(new_cond, self.arena.alloc(then), Some(else_expr));
+ let if_kind = hir::ExprKind::If(lowered_cond, self.arena.alloc(then), Some(else_expr));
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()));
@@ -1044,9 +1069,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
if let ExprKind::Path(qself, path) = &expr.kind {
// Does the path resolve to something disallowed in a tuple struct/variant pattern?
if let Some(partial_res) = self.resolver.get_partial_res(expr.id) {
- if partial_res.unresolved_segments() == 0
- && !partial_res.base_res().expected_in_tuple_struct_pat()
- {
+ if let Some(res) = partial_res.full_res() && !res.expected_in_tuple_struct_pat() {
return None;
}
}
@@ -1066,9 +1089,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
if let ExprKind::Path(qself, path) = &expr.kind {
// Does the path resolve to something disallowed in a unit struct/variant pattern?
if let Some(partial_res) = self.resolver.get_partial_res(expr.id) {
- if partial_res.unresolved_segments() == 0
- && !partial_res.base_res().expected_in_unit_struct_pat()
- {
+ if let Some(res) = partial_res.full_res() && !res.expected_in_unit_struct_pat() {
return None;
}
}
@@ -1609,11 +1630,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
/// Desugar `ExprKind::Yeet` from: `do yeet <expr>` into:
- /// ```rust
+ /// ```ignore(illustrative)
/// // If there is an enclosing `try {...}`:
- /// break 'catch_target FromResidual::from_residual(Yeet(residual)),
+ /// break 'catch_target FromResidual::from_residual(Yeet(residual));
/// // Otherwise:
- /// return FromResidual::from_residual(Yeet(residual)),
+ /// return FromResidual::from_residual(Yeet(residual));
/// ```
/// But to simplify this, there's a `from_yeet` lang item function which
/// handles the combined `FromResidual::from_residual(Yeet(residual))`.
diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs
index 85846b567..f1851d7b4 100644
--- a/compiler/rustc_ast_lowering/src/index.rs
+++ b/compiler/rustc_ast_lowering/src/index.rs
@@ -24,7 +24,7 @@ pub(super) struct NodeCollector<'a, 'hir> {
/// The parent of this node
parent_node: hir::ItemLocalId,
- owner: LocalDefId,
+ owner: OwnerId,
definitions: &'a definitions::Definitions,
}
@@ -81,9 +81,9 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
current_dep_node_owner={} ({:?}), hir_id.owner={} ({:?})",
self.source_map.span_to_diagnostic_string(span),
node,
- self.definitions.def_path(self.owner).to_string_no_crate_verbose(),
+ self.definitions.def_path(self.owner.def_id).to_string_no_crate_verbose(),
self.owner,
- self.definitions.def_path(hir_id.owner).to_string_no_crate_verbose(),
+ self.definitions.def_path(hir_id.owner.def_id).to_string_no_crate_verbose(),
hir_id.owner,
)
}
@@ -112,19 +112,19 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
fn visit_nested_item(&mut self, item: ItemId) {
debug!("visit_nested_item: {:?}", item);
- self.insert_nested(item.def_id);
+ self.insert_nested(item.owner_id.def_id);
}
fn visit_nested_trait_item(&mut self, item_id: TraitItemId) {
- self.insert_nested(item_id.def_id);
+ self.insert_nested(item_id.owner_id.def_id);
}
fn visit_nested_impl_item(&mut self, item_id: ImplItemId) {
- self.insert_nested(item_id.def_id);
+ self.insert_nested(item_id.owner_id.def_id);
}
fn visit_nested_foreign_item(&mut self, foreign_id: ForeignItemId) {
- self.insert_nested(foreign_id.def_id);
+ self.insert_nested(foreign_id.owner_id.def_id);
}
fn visit_nested_body(&mut self, id: BodyId) {
@@ -143,7 +143,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
#[instrument(level = "debug", skip(self))]
fn visit_item(&mut self, i: &'hir Item<'hir>) {
- debug_assert_eq!(i.def_id, self.owner);
+ debug_assert_eq!(i.owner_id, self.owner);
self.with_parent(i.hir_id(), |this| {
if let ItemKind::Struct(ref struct_def, _) = i.kind {
// If this is a tuple or unit-like struct, register the constructor.
@@ -157,7 +157,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
#[instrument(level = "debug", skip(self))]
fn visit_foreign_item(&mut self, fi: &'hir ForeignItem<'hir>) {
- debug_assert_eq!(fi.def_id, self.owner);
+ debug_assert_eq!(fi.owner_id, self.owner);
self.with_parent(fi.hir_id(), |this| {
intravisit::walk_foreign_item(this, fi);
});
@@ -176,7 +176,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
#[instrument(level = "debug", skip(self))]
fn visit_trait_item(&mut self, ti: &'hir TraitItem<'hir>) {
- debug_assert_eq!(ti.def_id, self.owner);
+ debug_assert_eq!(ti.owner_id, self.owner);
self.with_parent(ti.hir_id(), |this| {
intravisit::walk_trait_item(this, ti);
});
@@ -184,7 +184,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
#[instrument(level = "debug", skip(self))]
fn visit_impl_item(&mut self, ii: &'hir ImplItem<'hir>) {
- debug_assert_eq!(ii.def_id, self.owner);
+ debug_assert_eq!(ii.owner_id, self.owner);
self.with_parent(ii.hir_id(), |this| {
intravisit::walk_impl_item(this, ii);
});
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index 550833275..76316a574 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -1,4 +1,4 @@
-use super::errors::{InvalidAbi, MisplacedRelaxTraitBound};
+use super::errors::{InvalidAbi, InvalidAbiSuggestion, MisplacedRelaxTraitBound};
use super::ResolverAstLoweringExt;
use super::{Arena, AstOwner, ImplTraitContext, ImplTraitPosition};
use super::{FnDeclKind, LoweringContext, ParamMode};
@@ -14,9 +14,10 @@ use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
use rustc_hir::PredicateOrigin;
use rustc_index::vec::{Idx, IndexVec};
use rustc_middle::ty::{DefIdTree, ResolverAstLowering, TyCtxt};
+use rustc_span::lev_distance::find_best_match_for_name;
use rustc_span::source_map::DesugaringKind;
use rustc_span::symbol::{kw, sym, Ident};
-use rustc_span::Span;
+use rustc_span::{Span, Symbol};
use rustc_target::spec::abi;
use smallvec::{smallvec, SmallVec};
@@ -67,7 +68,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
bodies: Vec::new(),
attrs: SortedMap::default(),
children: FxHashMap::default(),
- current_hir_id_owner: CRATE_DEF_ID,
+ current_hir_id_owner: hir::CRATE_OWNER_ID,
item_local_id_counter: hir::ItemLocalId::new(0),
node_id_to_local_id: Default::default(),
local_id_to_def_id: SortedMap::new(),
@@ -176,7 +177,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
pub(super) fn lower_item_ref(&mut self, i: &Item) -> SmallVec<[hir::ItemId; 1]> {
- let mut node_ids = smallvec![hir::ItemId { def_id: self.local_def_id(i.id) }];
+ let mut node_ids =
+ smallvec![hir::ItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } }];
if let ItemKind::Use(ref use_tree) = &i.kind {
self.lower_item_id_use_tree(use_tree, i.id, &mut node_ids);
}
@@ -192,7 +194,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
match tree.kind {
UseTreeKind::Nested(ref nested_vec) => {
for &(ref nested, id) in nested_vec {
- vec.push(hir::ItemId { def_id: self.local_def_id(id) });
+ vec.push(hir::ItemId {
+ owner_id: hir::OwnerId { def_id: self.local_def_id(id) },
+ });
self.lower_item_id_use_tree(nested, id, vec);
}
}
@@ -201,7 +205,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
for (_, &id) in
iter::zip(self.expect_full_res_from_use(base_id).skip(1), &[id1, id2])
{
- vec.push(hir::ItemId { def_id: self.local_def_id(id) });
+ vec.push(hir::ItemId {
+ owner_id: hir::OwnerId { def_id: self.local_def_id(id) },
+ });
}
}
}
@@ -214,7 +220,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let attrs = self.lower_attrs(hir_id, &i.attrs);
let kind = self.lower_item_kind(i.span, i.id, hir_id, &mut ident, attrs, vis_span, &i.kind);
let item = hir::Item {
- def_id: hir_id.expect_owner(),
+ owner_id: hir_id.expect_owner(),
ident: self.lower_ident(ident),
kind,
vis_span,
@@ -539,7 +545,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
let ident = *ident;
let mut path = path.clone();
for seg in &mut path.segments {
- seg.id = self.next_node_id();
+ // Give the cloned segment the same resolution information
+ // as the old one (this is needed for stability checking).
+ let new_id = self.next_node_id();
+ self.resolver.clone_res(seg.id, new_id);
+ seg.id = new_id;
}
let span = path.span;
@@ -552,7 +562,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
let item = hir::Item {
- def_id: new_id,
+ owner_id: hir::OwnerId { def_id: new_id },
ident: this.lower_ident(ident),
kind,
vis_span,
@@ -608,7 +618,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
// Give the segments new node-ids since they are being cloned.
for seg in &mut prefix.segments {
- seg.id = self.next_node_id();
+ // Give the cloned segment the same resolution information
+ // as the old one (this is needed for stability checking).
+ let new_id = self.next_node_id();
+ self.resolver.clone_res(seg.id, new_id);
+ seg.id = new_id;
}
// Each `use` import is an item and thus are owners of the
@@ -626,7 +640,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
let item = hir::Item {
- def_id: new_hir_id,
+ owner_id: hir::OwnerId { def_id: new_hir_id },
ident: this.lower_ident(ident),
kind,
vis_span,
@@ -646,10 +660,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn lower_foreign_item(&mut self, i: &ForeignItem) -> &'hir hir::ForeignItem<'hir> {
let hir_id = self.lower_node_id(i.id);
- let def_id = hir_id.expect_owner();
+ let owner_id = hir_id.expect_owner();
self.lower_attrs(hir_id, &i.attrs);
let item = hir::ForeignItem {
- def_id,
+ owner_id,
ident: self.lower_ident(i.ident),
kind: match i.kind {
ForeignItemKind::Fn(box Fn { ref sig, ref generics, .. }) => {
@@ -688,7 +702,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn lower_foreign_item_ref(&mut self, i: &ForeignItem) -> hir::ForeignItemRef {
hir::ForeignItemRef {
- id: hir::ForeignItemId { def_id: self.local_def_id(i.id) },
+ id: hir::ForeignItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } },
ident: self.lower_ident(i.ident),
span: self.lower_span(i.span),
}
@@ -798,7 +812,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
);
(generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)), true)
}
- AssocItemKind::TyAlias(box TyAlias {
+ AssocItemKind::Type(box TyAlias {
ref generics,
where_clauses,
ref bounds,
@@ -831,7 +845,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
self.lower_attrs(hir_id, &i.attrs);
let item = hir::TraitItem {
- def_id: trait_item_def_id,
+ owner_id: trait_item_def_id,
ident: self.lower_ident(i.ident),
generics,
kind,
@@ -844,13 +858,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn lower_trait_item_ref(&mut self, i: &AssocItem) -> hir::TraitItemRef {
let kind = match &i.kind {
AssocItemKind::Const(..) => hir::AssocItemKind::Const,
- AssocItemKind::TyAlias(..) => hir::AssocItemKind::Type,
+ AssocItemKind::Type(..) => hir::AssocItemKind::Type,
AssocItemKind::Fn(box Fn { sig, .. }) => {
hir::AssocItemKind::Fn { has_self: sig.decl.has_self() }
}
AssocItemKind::MacCall(..) => unimplemented!(),
};
- let id = hir::TraitItemId { def_id: self.local_def_id(i.id) };
+ let id = hir::TraitItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } };
hir::TraitItemRef {
id,
ident: self.lower_ident(i.ident),
@@ -892,7 +906,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
(generics, hir::ImplItemKind::Fn(sig, body_id))
}
- AssocItemKind::TyAlias(box TyAlias { generics, where_clauses, ty, .. }) => {
+ AssocItemKind::Type(box TyAlias { generics, where_clauses, ty, .. }) => {
let mut generics = generics.clone();
add_ty_alias_where_clause(&mut generics, *where_clauses, false);
self.lower_generics(
@@ -902,11 +916,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
|this| match ty {
None => {
let ty = this.arena.alloc(this.ty(i.span, hir::TyKind::Err));
- hir::ImplItemKind::TyAlias(ty)
+ hir::ImplItemKind::Type(ty)
}
Some(ty) => {
let ty = this.lower_ty(ty, &ImplTraitContext::TypeAliasesOpaqueTy);
- hir::ImplItemKind::TyAlias(ty)
+ hir::ImplItemKind::Type(ty)
}
},
)
@@ -917,7 +931,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let hir_id = self.lower_node_id(i.id);
self.lower_attrs(hir_id, &i.attrs);
let item = hir::ImplItem {
- def_id: hir_id.expect_owner(),
+ owner_id: hir_id.expect_owner(),
ident: self.lower_ident(i.ident),
generics,
kind,
@@ -930,18 +944,21 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn lower_impl_item_ref(&mut self, i: &AssocItem) -> hir::ImplItemRef {
hir::ImplItemRef {
- id: hir::ImplItemId { def_id: self.local_def_id(i.id) },
+ id: hir::ImplItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } },
ident: self.lower_ident(i.ident),
span: self.lower_span(i.span),
kind: match &i.kind {
AssocItemKind::Const(..) => hir::AssocItemKind::Const,
- AssocItemKind::TyAlias(..) => hir::AssocItemKind::Type,
+ AssocItemKind::Type(..) => hir::AssocItemKind::Type,
AssocItemKind::Fn(box Fn { sig, .. }) => {
hir::AssocItemKind::Fn { has_self: sig.decl.has_self() }
}
AssocItemKind::MacCall(..) => unimplemented!(),
},
- trait_item_def_id: self.resolver.get_partial_res(i.id).map(|r| r.base_res().def_id()),
+ trait_item_def_id: self
+ .resolver
+ .get_partial_res(i.id)
+ .map(|r| r.expect_full_res().def_id()),
}
}
@@ -1049,9 +1066,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
asyncness: Async,
body: Option<&Block>,
) -> hir::BodyId {
- let closure_id = match asyncness {
- Async::Yes { closure_id, .. } => closure_id,
- Async::No => return self.lower_fn_body_block(span, decl, body),
+ let (closure_id, body) = match (asyncness, body) {
+ (Async::Yes { closure_id, .. }, Some(body)) => (closure_id, body),
+ _ => return self.lower_fn_body_block(span, decl, body),
};
self.lower_body(|this| {
@@ -1193,16 +1210,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
parameters.push(new_parameter);
}
- let body_span = body.map_or(span, |b| b.span);
let async_expr = this.make_async_expr(
CaptureBy::Value,
closure_id,
None,
- body_span,
+ body.span,
hir::AsyncGeneratorKind::Fn,
|this| {
// Create a block from the user's function body:
- let user_body = this.lower_block_expr_opt(body_span, body);
+ let user_body = this.lower_block_expr(body);
// Transform into `drop-temps { <user-body> }`, an expression:
let desugared_span =
@@ -1234,7 +1250,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
(
this.arena.alloc_from_iter(parameters),
- this.expr(body_span, async_expr, AttrVec::new()),
+ this.expr(body.span, async_expr, AttrVec::new()),
)
})
}
@@ -1280,10 +1296,19 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
fn error_on_invalid_abi(&self, abi: StrLit) {
+ let abi_names = abi::enabled_names(self.tcx.features(), abi.span)
+ .iter()
+ .map(|s| Symbol::intern(s))
+ .collect::<Vec<_>>();
+ let suggested_name = find_best_match_for_name(&abi_names, abi.symbol_unescaped, None);
self.tcx.sess.emit_err(InvalidAbi {
+ abi: abi.symbol_unescaped,
span: abi.span,
- abi: abi.symbol,
- valid_abis: abi::all_names().join(", "),
+ suggestion: suggested_name.map(|suggested_name| InvalidAbiSuggestion {
+ span: abi.span,
+ suggestion: format!("\"{suggested_name}\""),
+ }),
+ command: "rustc --print=calling-conventions".to_string(),
});
}
@@ -1335,9 +1360,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
match self
.resolver
.get_partial_res(bound_pred.bounded_ty.id)
- .map(|d| (d.base_res(), d.unresolved_segments()))
+ .and_then(|r| r.full_res())
{
- Some((Res::Def(DefKind::TyParam, def_id), 0))
+ Some(Res::Def(DefKind::TyParam, def_id))
if bound_pred.bound_generic_params.is_empty() =>
{
generics
@@ -1464,6 +1489,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let bounded_ty =
self.ty_path(ty_id, param_span, hir::QPath::Resolved(None, ty_path));
Some(hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
+ hir_id: self.next_id(),
bounded_ty: self.arena.alloc(bounded_ty),
bounds,
span,
@@ -1494,6 +1520,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
ref bounds,
span,
}) => hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
+ hir_id: self.next_id(),
bound_generic_params: self.lower_generic_params(bound_generic_params),
bounded_ty: self
.lower_ty(bounded_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)),
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 9012aa704..ff29d15f1 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -32,7 +32,6 @@
#![feature(box_patterns)]
#![feature(let_chains)]
-#![cfg_attr(bootstrap, feature(let_else))]
#![feature(never_type)]
#![recursion_limit = "256"]
#![allow(rustc::potential_query_instability)]
@@ -62,8 +61,8 @@ use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
use rustc_hir::definitions::DefPathData;
use rustc_hir::{ConstArg, GenericArg, ItemLocalId, ParamName, TraitCandidate};
use rustc_index::vec::{Idx, IndexVec};
-use rustc_middle::span_bug;
use rustc_middle::ty::{ResolverAstLowering, TyCtxt};
+use rustc_middle::{bug, span_bug};
use rustc_session::parse::feature_err;
use rustc_span::hygiene::MacroKind;
use rustc_span::source_map::DesugaringKind;
@@ -126,7 +125,7 @@ struct LoweringContext<'a, 'hir> {
is_in_trait_impl: bool,
is_in_dyn_type: bool,
- current_hir_id_owner: LocalDefId,
+ current_hir_id_owner: hir::OwnerId,
item_local_id_counter: hir::ItemLocalId,
local_id_to_def_id: SortedMap<ItemLocalId, LocalDefId>,
trait_map: FxHashMap<ItemLocalId, Box<[TraitCandidate]>>,
@@ -161,6 +160,10 @@ trait ResolverAstLoweringExt {
fn legacy_const_generic_args(&self, expr: &Expr) -> Option<Vec<usize>>;
fn get_partial_res(&self, id: NodeId) -> Option<PartialRes>;
fn get_import_res(&self, id: NodeId) -> PerNS<Option<Res<NodeId>>>;
+ // Clones the resolution (if any) on 'source' and applies it
+ // to 'target'. Used when desugaring a `UseTreeKind::Nested` to
+ // multiple `UseTreeKind::Simple`s
+ fn clone_res(&mut self, source: NodeId, target: NodeId);
fn get_label_res(&self, id: NodeId) -> Option<NodeId>;
fn get_lifetime_res(&self, id: NodeId) -> Option<LifetimeRes>;
fn take_extra_lifetime_params(&mut self, id: NodeId) -> Vec<(Ident, NodeId, LifetimeRes)>;
@@ -176,12 +179,7 @@ impl ResolverAstLoweringExt for ResolverAstLowering {
return None;
}
- let partial_res = self.partial_res_map.get(&expr.id)?;
- if partial_res.unresolved_segments() != 0 {
- return None;
- }
-
- if let Res::Def(DefKind::Fn, def_id) = partial_res.base_res() {
+ if let Res::Def(DefKind::Fn, def_id) = self.partial_res_map.get(&expr.id)?.full_res()? {
// We only support cross-crate argument rewriting. Uses
// within the same crate should be updated to use the new
// const generics style.
@@ -198,6 +196,12 @@ impl ResolverAstLoweringExt for ResolverAstLowering {
None
}
+ fn clone_res(&mut self, source: NodeId, target: NodeId) {
+ if let Some(res) = self.partial_res_map.get(&source) {
+ self.partial_res_map.insert(target, *res);
+ }
+ }
+
/// Obtains resolution for a `NodeId` with a single resolution.
fn get_partial_res(&self, id: NodeId) -> Option<PartialRes> {
self.partial_res_map.get(&id).copied()
@@ -324,17 +328,20 @@ enum FnDeclKind {
}
impl FnDeclKind {
- fn impl_trait_return_allowed(&self, tcx: TyCtxt<'_>) -> bool {
+ fn impl_trait_allowed(&self, tcx: TyCtxt<'_>) -> bool {
match self {
FnDeclKind::Fn | FnDeclKind::Inherent => true,
FnDeclKind::Impl if tcx.features().return_position_impl_trait_in_trait => true,
+ FnDeclKind::Trait if tcx.features().return_position_impl_trait_in_trait => true,
_ => false,
}
}
- fn impl_trait_in_trait_allowed(&self, tcx: TyCtxt<'_>) -> bool {
+ fn async_fn_allowed(&self, tcx: TyCtxt<'_>) -> bool {
match self {
- FnDeclKind::Trait if tcx.features().return_position_impl_trait_in_trait => true,
+ FnDeclKind::Fn | FnDeclKind::Inherent => true,
+ FnDeclKind::Impl if tcx.features().async_fn_in_trait => true,
+ FnDeclKind::Trait if tcx.features().async_fn_in_trait => true,
_ => false,
}
}
@@ -572,7 +579,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let current_node_ids = std::mem::take(&mut self.node_id_to_local_id);
let current_id_to_def_id = std::mem::take(&mut self.local_id_to_def_id);
let current_trait_map = std::mem::take(&mut self.trait_map);
- let current_owner = std::mem::replace(&mut self.current_hir_id_owner, def_id);
+ let current_owner =
+ std::mem::replace(&mut self.current_hir_id_owner, hir::OwnerId { def_id });
let current_local_counter =
std::mem::replace(&mut self.item_local_id_counter, hir::ItemLocalId::new(1));
let current_impl_trait_defs = std::mem::take(&mut self.impl_trait_defs);
@@ -587,7 +595,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
debug_assert_eq!(_old, None);
let item = f(self);
- debug_assert_eq!(def_id, item.def_id());
+ debug_assert_eq!(def_id, item.def_id().def_id);
// `f` should have consumed all the elements in these vectors when constructing `item`.
debug_assert!(self.impl_trait_defs.is_empty());
debug_assert!(self.impl_trait_bounds.is_empty());
@@ -753,12 +761,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
fn expect_full_res(&mut self, id: NodeId) -> Res<NodeId> {
- self.resolver.get_partial_res(id).map_or(Res::Err, |pr| {
- if pr.unresolved_segments() != 0 {
- panic!("path not fully resolved: {:?}", pr);
- }
- pr.base_res()
- })
+ self.resolver.get_partial_res(id).map_or(Res::Err, |pr| pr.expect_full_res())
}
fn expect_full_res_from_use(&mut self, id: NodeId) -> impl Iterator<Item = Res<NodeId>> {
@@ -786,7 +789,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
/// Mark a span as relative to the current owning item.
fn lower_span(&self, span: Span) -> Span {
if self.tcx.sess.opts.unstable_opts.incremental_relative_spans {
- span.with_parent(Some(self.current_hir_id_owner))
+ span.with_parent(Some(self.current_hir_id_owner.def_id))
} else {
// Do not make spans relative when not using incremental compilation.
span
@@ -812,7 +815,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
LifetimeRes::Fresh { param, .. } => {
// Late resolution delegates to us the creation of the `LocalDefId`.
let _def_id = self.create_def(
- self.current_hir_id_owner,
+ self.current_hir_id_owner.def_id,
param,
DefPathData::LifetimeNs(kw::UnderscoreLifetime),
);
@@ -1060,9 +1063,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// Desugar `AssocTy: Bounds` into `AssocTy = impl Bounds`. We do this by
// constructing the HIR for `impl bounds...` and then lowering that.
- let parent_def_id = self.current_hir_id_owner;
let impl_trait_node_id = self.next_node_id();
- self.create_def(parent_def_id, impl_trait_node_id, DefPathData::ImplTrait);
self.with_dyn_type_scope(false, |this| {
let node_id = this.next_node_id();
@@ -1140,8 +1141,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// type and value namespaces. If we resolved the path in the value namespace, we
// transform it into a generic const argument.
TyKind::Path(ref qself, ref path) => {
- if let Some(partial_res) = self.resolver.get_partial_res(ty.id) {
- let res = partial_res.base_res();
+ if let Some(res) = self
+ .resolver
+ .get_partial_res(ty.id)
+ .and_then(|partial_res| partial_res.full_res())
+ {
if !res.matches_ns(Namespace::TypeNS) {
debug!(
"lower_generic_arg: Lowering type argument as const argument: {:?}",
@@ -1154,7 +1158,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let node_id = self.next_node_id();
// Add a definition for the in-band const def.
- self.create_def(parent_def_id, node_id, DefPathData::AnonConst);
+ self.create_def(
+ parent_def_id.def_id,
+ node_id,
+ DefPathData::AnonConst,
+ );
let span = self.lower_span(ty.span);
let path_expr = Expr {
@@ -1204,8 +1212,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// by `ty_path`.
if qself.is_none()
&& let Some(partial_res) = self.resolver.get_partial_res(t.id)
- && partial_res.unresolved_segments() == 0
- && let Res::Def(DefKind::Trait | DefKind::TraitAlias, _) = partial_res.base_res()
+ && let Some(Res::Def(DefKind::Trait | DefKind::TraitAlias, _)) = partial_res.full_res()
{
let (bounds, lifetime_bound) = self.with_dyn_type_scope(true, |this| {
let poly_trait_ref = this.ast_arena.ptr.alloc(PolyTraitRef {
@@ -1349,9 +1356,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
def_node_id,
bounds,
false,
- &ImplTraitContext::TypeAliasesOpaqueTy,
+ itctx,
),
ImplTraitContext::Universal => {
+ self.create_def(
+ self.current_hir_id_owner.def_id,
+ def_node_id,
+ DefPathData::ImplTrait,
+ );
let span = t.span;
let ident = Ident::from_str_and_span(&pprust::ty_to_string(t), span);
let (param, bounds, path) =
@@ -1445,7 +1457,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// frequently opened issues show.
let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::OpaqueTy, span, None);
- let opaque_ty_def_id = self.local_def_id(opaque_ty_node_id);
+ let opaque_ty_def_id = match origin {
+ hir::OpaqueTyOrigin::TyAlias => self.create_def(
+ self.current_hir_id_owner.def_id,
+ opaque_ty_node_id,
+ DefPathData::ImplTrait,
+ ),
+ hir::OpaqueTyOrigin::FnReturn(fn_def_id) => {
+ self.create_def(fn_def_id, opaque_ty_node_id, DefPathData::ImplTrait)
+ }
+ hir::OpaqueTyOrigin::AsyncFn(..) => bug!("unreachable"),
+ };
debug!(?opaque_ty_def_id);
// Contains the new lifetime definitions created for the TAIT (if any).
@@ -1551,7 +1573,11 @@ 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, in_trait)
+ hir::TyKind::OpaqueDef(
+ hir::ItemId { owner_id: hir::OwnerId { def_id: opaque_ty_def_id } },
+ lifetimes,
+ in_trait,
+ )
}
/// Registers a new opaque type with the proper `NodeId`s and
@@ -1567,7 +1593,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// Generate an `type Foo = impl Trait;` declaration.
trace!("registering opaque type with id {:#?}", opaque_ty_id);
let opaque_ty_item = hir::Item {
- def_id: opaque_ty_id,
+ owner_id: hir::OwnerId { def_id: opaque_ty_id },
ident: Ident::empty(),
kind: opaque_ty_item_kind,
vis_span: self.lower_span(span.shrink_to_lo()),
@@ -1701,62 +1727,38 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}));
let output = if let Some((ret_id, span)) = make_ret_async {
- match kind {
- FnDeclKind::Trait => {
- if !kind.impl_trait_in_trait_allowed(self.tcx) {
+ if !kind.async_fn_allowed(self.tcx) {
+ match kind {
+ FnDeclKind::Trait | FnDeclKind::Impl => {
self.tcx
.sess
.create_feature_err(
TraitFnAsync { fn_span, span },
- sym::return_position_impl_trait_in_trait,
+ sym::async_fn_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.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,
- )
}
}
+
+ self.lower_async_fn_ret_ty(
+ &decl.output,
+ fn_node_id.expect("`make_ret_async` but no `fn_def_id`"),
+ ret_id,
+ matches!(kind, FnDeclKind::Trait),
+ )
} else {
match decl.output {
FnRetTy::Ty(ref ty) => {
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) => {
+ Some(fn_node_id) if kind.impl_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,
+ in_trait: matches!(kind, FnDeclKind::Trait),
}
}
_ => ImplTraitContext::Disallowed(match kind {
@@ -1950,9 +1952,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
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,
+ if in_trait && !this.tcx.features().return_position_impl_trait_in_trait {
+ ImplTraitContext::Disallowed(ImplTraitPosition::TraitReturn)
+ } else {
+ ImplTraitContext::ReturnPositionOpaqueTy {
+ origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
+ in_trait,
+ }
},
);
@@ -2038,7 +2044,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// 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 },
+ hir::ItemId { owner_id: hir::OwnerId { def_id: opaque_ty_def_id } },
generic_args,
in_trait,
);
diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs
index 1ea76fdbf..1af1633b5 100644
--- a/compiler/rustc_ast_lowering/src/pat.rs
+++ b/compiler/rustc_ast_lowering/src/pat.rs
@@ -239,7 +239,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
ident: Ident,
lower_sub: impl FnOnce(&mut Self) -> Option<&'hir hir::Pat<'hir>>,
) -> hir::PatKind<'hir> {
- match self.resolver.get_partial_res(p.id).map(|d| d.base_res()) {
+ match self.resolver.get_partial_res(p.id).map(|d| d.expect_full_res()) {
// `None` can occur in body-less function signatures
res @ (None | Some(Res::Local(_))) => {
let canonical_id = match res {
diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs
index 6bb1bb9ea..888776ccc 100644
--- a/compiler/rustc_ast_lowering/src/path.rs
+++ b/compiler/rustc_ast_lowering/src/path.rs
@@ -29,11 +29,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let partial_res =
self.resolver.get_partial_res(id).unwrap_or_else(|| PartialRes::new(Res::Err));
+ let base_res = partial_res.base_res();
+ let unresolved_segments = partial_res.unresolved_segments();
let path_span_lo = p.span.shrink_to_lo();
- let proj_start = p.segments.len() - partial_res.unresolved_segments();
+ let proj_start = p.segments.len() - unresolved_segments;
let path = self.arena.alloc(hir::Path {
- res: self.lower_res(partial_res.base_res()),
+ res: self.lower_res(base_res),
segments: self.arena.alloc_from_iter(p.segments[..proj_start].iter().enumerate().map(
|(i, segment)| {
let param_mode = match (qself_position, param_mode) {
@@ -46,7 +48,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
_ => param_mode,
};
- let parenthesized_generic_args = match partial_res.base_res() {
+ let parenthesized_generic_args = match base_res {
// `a::b::Trait(Args)`
Res::Def(DefKind::Trait, _) if i + 1 == proj_start => {
ParenthesizedGenericArgs::Ok
@@ -83,7 +85,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// Simple case, either no projections, or only fully-qualified.
// E.g., `std::mem::size_of` or `<I as Iterator>::Item`.
- if partial_res.unresolved_segments() == 0 {
+ if unresolved_segments == 0 {
return hir::QPath::Resolved(qself, path);
}
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index b1d10e07a..036643244 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -14,6 +14,7 @@ use rustc_ast::*;
use rustc_ast_pretty::pprust::{self, State};
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::{error_code, fluent, pluralize, struct_span_err, Applicability};
+use rustc_macros::Subdiagnostic;
use rustc_parse::validate_attr;
use rustc_session::lint::builtin::{
DEPRECATED_WHERE_CLAUSE_LOCATION, MISSING_ABI, PATTERNS_IN_FNS_WITHOUT_BODY,
@@ -38,6 +39,13 @@ enum SelfSemantic {
No,
}
+/// What is the context that prevents using `~const`?
+enum DisallowTildeConstContext<'a> {
+ TraitObject,
+ ImplTrait,
+ Fn(FnKind<'a>),
+}
+
struct AstValidator<'a> {
session: &'a Session,
@@ -56,7 +64,7 @@ struct AstValidator<'a> {
/// e.g., `impl Iterator<Item = impl Debug>`.
outer_impl_trait: Option<Span>,
- is_tilde_const_allowed: bool,
+ disallow_tilde_const: Option<DisallowTildeConstContext<'a>>,
/// Used to ban `impl Trait` in path projections like `<impl Iterator>::Item`
/// or `Foo::Bar<impl Trait>`
@@ -93,18 +101,26 @@ impl<'a> AstValidator<'a> {
self.is_impl_trait_banned = old;
}
- fn with_tilde_const(&mut self, allowed: bool, f: impl FnOnce(&mut Self)) {
- let old = mem::replace(&mut self.is_tilde_const_allowed, allowed);
+ fn with_tilde_const(
+ &mut self,
+ disallowed: Option<DisallowTildeConstContext<'a>>,
+ f: impl FnOnce(&mut Self),
+ ) {
+ let old = mem::replace(&mut self.disallow_tilde_const, disallowed);
f(self);
- self.is_tilde_const_allowed = old;
+ self.disallow_tilde_const = old;
}
fn with_tilde_const_allowed(&mut self, f: impl FnOnce(&mut Self)) {
- self.with_tilde_const(true, f)
+ self.with_tilde_const(None, f)
}
- fn with_banned_tilde_const(&mut self, f: impl FnOnce(&mut Self)) {
- self.with_tilde_const(false, f)
+ fn with_banned_tilde_const(
+ &mut self,
+ ctx: DisallowTildeConstContext<'a>,
+ f: impl FnOnce(&mut Self),
+ ) {
+ self.with_tilde_const(Some(ctx), f)
}
fn with_let_management(
@@ -154,7 +170,7 @@ impl<'a> AstValidator<'a> {
DEPRECATED_WHERE_CLAUSE_LOCATION,
id,
where_clauses.0.1,
- fluent::ast_passes::deprecated_where_clause_location,
+ fluent::ast_passes_deprecated_where_clause_location,
BuiltinLintDiagnostics::DeprecatedWhereclauseLocation(
where_clauses.1.1.shrink_to_hi(),
suggestion,
@@ -172,7 +188,7 @@ impl<'a> AstValidator<'a> {
fn with_impl_trait(&mut self, outer: Option<Span>, f: impl FnOnce(&mut Self)) {
let old = mem::replace(&mut self.outer_impl_trait, outer);
if outer.is_some() {
- self.with_banned_tilde_const(f);
+ self.with_banned_tilde_const(DisallowTildeConstContext::ImplTrait, f);
} else {
f(self);
}
@@ -197,7 +213,10 @@ impl<'a> AstValidator<'a> {
TyKind::ImplTrait(..) => {
self.with_impl_trait(Some(t.span), |this| visit::walk_ty(this, t))
}
- TyKind::TraitObject(..) => self.with_banned_tilde_const(|this| visit::walk_ty(this, t)),
+ TyKind::TraitObject(..) => self
+ .with_banned_tilde_const(DisallowTildeConstContext::TraitObject, |this| {
+ visit::walk_ty(this, t)
+ }),
TyKind::Path(ref qself, ref path) => {
// We allow these:
// - `Option<impl Trait>`
@@ -233,20 +252,6 @@ impl<'a> AstValidator<'a> {
}
}
- fn visit_struct_field_def(&mut self, field: &'a FieldDef) {
- if let Some(ident) = field.ident {
- if ident.name == kw::Underscore {
- self.visit_vis(&field.vis);
- self.visit_ident(ident);
- self.visit_ty_common(&field.ty);
- self.walk_ty(&field.ty);
- walk_list!(self, visit_attribute, &field.attrs);
- return;
- }
- }
- self.visit_field_def(field);
- }
-
fn err_handler(&self) -> &rustc_errors::Handler {
&self.session.diagnostic()
}
@@ -987,8 +992,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
visit::walk_lifetime(self, lifetime);
}
- fn visit_field_def(&mut self, s: &'a FieldDef) {
- visit::walk_field_def(self, s)
+ fn visit_field_def(&mut self, field: &'a FieldDef) {
+ visit::walk_field_def(self, field)
}
fn visit_item(&mut self, item: &'a Item) {
@@ -1176,42 +1181,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
self.check_mod_file_item_asciionly(item.ident);
}
}
- ItemKind::Struct(ref vdata, ref generics) => match vdata {
- // Duplicating the `Visitor` logic allows catching all cases
- // of `Anonymous(Struct, Union)` outside of a field struct or union.
- //
- // Inside `visit_ty` the validator catches every `Anonymous(Struct, Union)` it
- // encounters, and only on `ItemKind::Struct` and `ItemKind::Union`
- // it uses `visit_ty_common`, which doesn't contain that specific check.
- VariantData::Struct(ref fields, ..) => {
- self.visit_vis(&item.vis);
- self.visit_ident(item.ident);
- self.visit_generics(generics);
- self.with_banned_assoc_ty_bound(|this| {
- walk_list!(this, visit_struct_field_def, fields);
- });
- walk_list!(self, visit_attribute, &item.attrs);
- return;
- }
- _ => {}
- },
- ItemKind::Union(ref vdata, ref generics) => {
+ ItemKind::Union(ref vdata, ..) => {
if vdata.fields().is_empty() {
self.err_handler().span_err(item.span, "unions cannot have zero fields");
}
- match vdata {
- VariantData::Struct(ref fields, ..) => {
- self.visit_vis(&item.vis);
- self.visit_ident(item.ident);
- self.visit_generics(generics);
- self.with_banned_assoc_ty_bound(|this| {
- walk_list!(this, visit_struct_field_def, fields);
- });
- walk_list!(self, visit_attribute, &item.attrs);
- return;
- }
- _ => {}
- }
}
ItemKind::Const(def, .., None) => {
self.check_defaultness(item.span, def);
@@ -1411,13 +1384,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
);
err.emit();
}
- (_, TraitBoundModifier::MaybeConst) => {
- if !self.is_tilde_const_allowed {
- self.err_handler()
- .struct_span_err(bound.span(), "`~const` is not allowed here")
- .note("only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions")
- .emit();
- }
+ (_, TraitBoundModifier::MaybeConst) if let Some(reason) = &self.disallow_tilde_const => {
+ let mut err = self.err_handler().struct_span_err(bound.span(), "`~const` is not allowed here");
+ match reason {
+ DisallowTildeConstContext::TraitObject => err.note("trait objects cannot have `~const` trait bounds"),
+ DisallowTildeConstContext::ImplTrait => err.note("`impl Trait`s cannot have `~const` trait bounds"),
+ DisallowTildeConstContext::Fn(FnKind::Closure(..)) => err.note("closures cannot have `~const` trait bounds"),
+ DisallowTildeConstContext::Fn(FnKind::Fn(_, ident, ..)) => err.span_note(ident.span, "this function is not `const`, so it cannot have `~const` trait bounds"),
+ };
+ err.emit();
}
(_, TraitBoundModifier::MaybeConstMaybe) => {
self.err_handler()
@@ -1524,10 +1499,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
}
let tilde_const_allowed =
- matches!(fk.header(), Some(FnHeader { constness: Const::Yes(_), .. }))
+ matches!(fk.header(), Some(FnHeader { constness: ast::Const::Yes(_), .. }))
|| matches!(fk.ctxt(), Some(FnCtxt::Assoc(_)));
- self.with_tilde_const(tilde_const_allowed, |this| visit::walk_fn(this, fk));
+ let disallowed = (!tilde_const_allowed).then(|| DisallowTildeConstContext::Fn(fk));
+
+ self.with_tilde_const(disallowed, |this| visit::walk_fn(this, fk));
}
fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
@@ -1557,7 +1534,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
});
}
}
- AssocItemKind::TyAlias(box TyAlias {
+ AssocItemKind::Type(box TyAlias {
generics,
where_clauses,
where_predicates_split,
@@ -1596,7 +1573,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
}
match item.kind {
- AssocItemKind::TyAlias(box TyAlias { ref generics, ref bounds, ref ty, .. })
+ AssocItemKind::Type(box TyAlias { ref generics, ref bounds, ref ty, .. })
if ctxt == AssocCtxt::Trait =>
{
self.visit_vis(&item.vis);
@@ -1771,7 +1748,7 @@ pub fn check_crate(session: &Session, krate: &Crate, lints: &mut LintBuffer) ->
in_const_trait_impl: false,
has_proc_macro_decls: false,
outer_impl_trait: None,
- is_tilde_const_allowed: false,
+ disallow_tilde_const: None,
is_impl_trait_banned: false,
is_assoc_ty_bound_banned: false,
forbidden_let_reason: Some(ForbiddenLetReason::GenericForbidden),
@@ -1783,15 +1760,17 @@ pub fn check_crate(session: &Session, krate: &Crate, lints: &mut LintBuffer) ->
}
/// Used to forbid `let` expressions in certain syntactic locations.
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Subdiagnostic)]
pub(crate) enum ForbiddenLetReason {
/// `let` is not valid and the source environment is not important
GenericForbidden,
/// A let chain with the `||` operator
- NotSupportedOr(Span),
+ #[note(not_supported_or)]
+ NotSupportedOr(#[primary_span] Span),
/// A let chain with invalid parentheses
///
/// 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),
+ #[note(not_supported_parentheses)]
+ NotSupportedParentheses(#[primary_span] Span),
}
diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs
index 4f3b09c58..59f582f10 100644
--- a/compiler/rustc_ast_passes/src/errors.rs
+++ b/compiler/rustc_ast_passes/src/errors.rs
@@ -1,13 +1,13 @@
//! Errors emitted by ast_passes.
-use rustc_errors::{fluent, AddSubdiagnostic, Applicability, Diagnostic};
-use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic};
+use rustc_errors::{fluent, AddToDiagnostic, Applicability, Diagnostic, SubdiagnosticMessage};
+use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_span::{Span, Symbol};
use crate::ast_validation::ForbiddenLetReason;
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::forbidden_let)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_forbidden_let)]
#[note]
pub struct ForbiddenLet {
#[primary_span]
@@ -16,130 +16,116 @@ pub struct ForbiddenLet {
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)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_forbidden_let_stable)]
#[note]
pub struct ForbiddenLetStable {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::forbidden_assoc_constraint)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_forbidden_assoc_constraint)]
pub struct ForbiddenAssocConstraint {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::keyword_lifetime)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_keyword_lifetime)]
pub struct KeywordLifetime {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::invalid_label)]
+#[derive(Diagnostic)]
+#[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")]
+#[derive(Diagnostic)]
+#[diag(ast_passes_invalid_visibility, code = "E0449")]
pub struct InvalidVisibility {
#[primary_span]
pub span: Span,
- #[label(ast_passes::implied)]
+ #[label(implied)]
pub implied: Option<Span>,
#[subdiagnostic]
pub note: Option<InvalidVisibilityNote>,
}
-#[derive(SessionSubdiagnostic)]
+#[derive(Subdiagnostic)]
pub enum InvalidVisibilityNote {
- #[note(ast_passes::individual_impl_items)]
+ #[note(individual_impl_items)]
IndividualImplItems,
- #[note(ast_passes::individual_foreign_items)]
+ #[note(individual_foreign_items)]
IndividualForeignItems,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::trait_fn_const, code = "E0379")]
+#[derive(Diagnostic)]
+#[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)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_forbidden_lifetime_bound)]
pub struct ForbiddenLifetimeBound {
#[primary_span]
pub spans: Vec<Span>,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::forbidden_non_lifetime_param)]
+#[derive(Diagnostic)]
+#[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)]
+#[derive(Diagnostic)]
+#[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)]
+#[derive(Diagnostic)]
+#[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)]
+#[derive(Diagnostic)]
+#[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)]
+#[derive(Diagnostic)]
+#[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)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_fn_param_forbidden_attr)]
pub struct FnParamForbiddenAttr {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::fn_param_forbidden_self)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_fn_param_forbidden_self)]
#[note]
pub struct FnParamForbiddenSelf {
#[primary_span]
@@ -147,8 +133,8 @@ pub struct FnParamForbiddenSelf {
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::forbidden_default)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_forbidden_default)]
pub struct ForbiddenDefault {
#[primary_span]
pub span: Span,
@@ -156,8 +142,8 @@ pub struct ForbiddenDefault {
pub def_span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::assoc_const_without_body)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_assoc_const_without_body)]
pub struct AssocConstWithoutBody {
#[primary_span]
pub span: Span,
@@ -165,8 +151,8 @@ pub struct AssocConstWithoutBody {
pub replace_span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::assoc_fn_without_body)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_assoc_fn_without_body)]
pub struct AssocFnWithoutBody {
#[primary_span]
pub span: Span,
@@ -174,8 +160,8 @@ pub struct AssocFnWithoutBody {
pub replace_span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::assoc_type_without_body)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_assoc_type_without_body)]
pub struct AssocTypeWithoutBody {
#[primary_span]
pub span: Span,
@@ -183,8 +169,8 @@ pub struct AssocTypeWithoutBody {
pub replace_span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::const_without_body)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_const_without_body)]
pub struct ConstWithoutBody {
#[primary_span]
pub span: Span,
@@ -192,8 +178,8 @@ pub struct ConstWithoutBody {
pub replace_span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::static_without_body)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_static_without_body)]
pub struct StaticWithoutBody {
#[primary_span]
pub span: Span,
@@ -201,8 +187,8 @@ pub struct StaticWithoutBody {
pub replace_span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::ty_alias_without_body)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_ty_alias_without_body)]
pub struct TyAliasWithoutBody {
#[primary_span]
pub span: Span,
@@ -210,8 +196,8 @@ pub struct TyAliasWithoutBody {
pub replace_span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::fn_without_body)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_fn_without_body)]
pub struct FnWithoutBody {
#[primary_span]
pub span: Span,
@@ -227,8 +213,11 @@ pub struct ExternBlockSuggestion {
pub abi: Option<Symbol>,
}
-impl AddSubdiagnostic for ExternBlockSuggestion {
- fn add_to_diagnostic(self, diag: &mut Diagnostic) {
+impl AddToDiagnostic for ExternBlockSuggestion {
+ fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
+ where
+ F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
+ {
let start_suggestion = if let Some(abi) = self.abi {
format!("extern \"{}\" {{", abi)
} else {
@@ -237,7 +226,7 @@ impl AddSubdiagnostic for ExternBlockSuggestion {
let end_suggestion = " }".to_owned();
diag.multipart_suggestion(
- fluent::ast_passes::extern_block_suggestion,
+ fluent::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 aeff73c5b..546010135 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -1,15 +1,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_ast::{PatKind, RangeEnd};
use rustc_errors::{struct_span_err, Applicability, StashKey};
-use rustc_feature::Features;
-use rustc_feature::{AttributeGate, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
-use rustc_session::parse::{feature_err, feature_warn};
+use rustc_feature::{AttributeGate, BuiltinAttribute, Features, GateIssue, BUILTIN_ATTRIBUTE_MAP};
+use rustc_session::parse::{feature_err, feature_err_issue, feature_warn};
use rustc_session::Session;
use rustc_span::source_map::Spanned;
use rustc_span::symbol::sym;
use rustc_span::Span;
+use rustc_target::spec::abi;
macro_rules! gate_feature_fn {
($visitor: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr, $help: expr) => {{
@@ -84,210 +84,26 @@ impl<'a> PostExpansionVisitor<'a> {
}
}
- match symbol_unescaped.as_str() {
- // Stable
- "Rust" | "C" | "cdecl" | "stdcall" | "fastcall" | "aapcs" | "win64" | "sysv64"
- | "system" => {}
- "rust-intrinsic" => {
- gate_feature_post!(&self, intrinsics, span, "intrinsics are subject to change");
- }
- "platform-intrinsic" => {
- gate_feature_post!(
- &self,
- platform_intrinsics,
- span,
- "platform intrinsics are experimental and possibly buggy"
- );
- }
- "vectorcall" => {
- gate_feature_post!(
- &self,
- abi_vectorcall,
- span,
- "vectorcall is experimental and subject to change"
- );
- }
- "thiscall" => {
- gate_feature_post!(
- &self,
- abi_thiscall,
- span,
- "thiscall is experimental and subject to change"
- );
- }
- "rust-call" => {
- gate_feature_post!(
- &self,
- unboxed_closures,
- span,
- "rust-call ABI is subject to change"
- );
- }
- "rust-cold" => {
- gate_feature_post!(
- &self,
- rust_cold_cc,
- span,
- "rust-cold is experimental and subject to change"
- );
- }
- "ptx-kernel" => {
- gate_feature_post!(
- &self,
- abi_ptx,
- span,
- "PTX ABIs are experimental and subject to change"
- );
- }
- "unadjusted" => {
- gate_feature_post!(
- &self,
- abi_unadjusted,
- span,
- "unadjusted ABI is an implementation detail and perma-unstable"
- );
- }
- "msp430-interrupt" => {
- gate_feature_post!(
- &self,
- abi_msp430_interrupt,
- span,
- "msp430-interrupt ABI is experimental and subject to change"
- );
- }
- "x86-interrupt" => {
- gate_feature_post!(
- &self,
- abi_x86_interrupt,
- span,
- "x86-interrupt ABI is experimental and subject to change"
- );
- }
- "amdgpu-kernel" => {
- gate_feature_post!(
- &self,
- abi_amdgpu_kernel,
- span,
- "amdgpu-kernel ABI is experimental and subject to change"
- );
- }
- "avr-interrupt" | "avr-non-blocking-interrupt" => {
- gate_feature_post!(
- &self,
- abi_avr_interrupt,
- span,
- "avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change"
- );
- }
- "efiapi" => {
- gate_feature_post!(
- &self,
- abi_efiapi,
- span,
- "efiapi ABI is experimental and subject to change"
- );
- }
- "C-cmse-nonsecure-call" => {
- gate_feature_post!(
- &self,
- abi_c_cmse_nonsecure_call,
+ match abi::is_enabled(&self.features, span, symbol_unescaped.as_str()) {
+ Ok(()) => (),
+ Err(abi::AbiDisabled::Unstable { feature, explain }) => {
+ feature_err_issue(
+ &self.sess.parse_sess,
+ feature,
span,
- "C-cmse-nonsecure-call ABI is experimental and subject to change"
- );
- }
- "C-unwind" => {
- gate_feature_post!(
- &self,
- c_unwind,
- span,
- "C-unwind ABI is experimental and subject to change"
- );
- }
- "stdcall-unwind" => {
- gate_feature_post!(
- &self,
- c_unwind,
- span,
- "stdcall-unwind ABI is experimental and subject to change"
- );
- }
- "system-unwind" => {
- gate_feature_post!(
- &self,
- c_unwind,
- span,
- "system-unwind ABI is experimental and subject to change"
- );
- }
- "thiscall-unwind" => {
- gate_feature_post!(
- &self,
- c_unwind,
- span,
- "thiscall-unwind ABI is experimental and subject to change"
- );
- }
- "cdecl-unwind" => {
- gate_feature_post!(
- &self,
- c_unwind,
- span,
- "cdecl-unwind ABI is experimental and subject to change"
- );
- }
- "fastcall-unwind" => {
- gate_feature_post!(
- &self,
- c_unwind,
- span,
- "fastcall-unwind ABI is experimental and subject to change"
- );
- }
- "vectorcall-unwind" => {
- gate_feature_post!(
- &self,
- c_unwind,
- span,
- "vectorcall-unwind ABI is experimental and subject to change"
- );
- }
- "aapcs-unwind" => {
- gate_feature_post!(
- &self,
- c_unwind,
- span,
- "aapcs-unwind ABI is experimental and subject to change"
- );
- }
- "win64-unwind" => {
- gate_feature_post!(
- &self,
- c_unwind,
- span,
- "win64-unwind ABI is experimental and subject to change"
- );
- }
- "sysv64-unwind" => {
- gate_feature_post!(
- &self,
- c_unwind,
- span,
- "sysv64-unwind ABI is experimental and subject to change"
- );
- }
- "wasm" => {
- gate_feature_post!(
- &self,
- wasm_abi,
- span,
- "wasm ABI is experimental and subject to change"
- );
+ GateIssue::Language,
+ explain,
+ )
+ .emit();
}
- abi => {
+ Err(abi::AbiDisabled::Unrecognized) => {
if self.sess.opts.pretty.map_or(true, |ppm| ppm.needs_hir()) {
self.sess.parse_sess.span_diagnostic.delay_span_bug(
span,
- &format!("unrecognized ABI not caught in lowering: {}", abi),
+ &format!(
+ "unrecognized ABI not caught in lowering: {}",
+ symbol_unescaped.as_str()
+ ),
);
}
}
@@ -300,46 +116,6 @@ impl<'a> PostExpansionVisitor<'a> {
}
}
- fn maybe_report_invalid_custom_discriminants(&self, variants: &[ast::Variant]) {
- let has_fields = variants.iter().any(|variant| match variant.data {
- VariantData::Tuple(..) | VariantData::Struct(..) => true,
- VariantData::Unit(..) => false,
- });
-
- let discriminant_spans = variants
- .iter()
- .filter(|variant| match variant.data {
- VariantData::Tuple(..) | VariantData::Struct(..) => false,
- VariantData::Unit(..) => true,
- })
- .filter_map(|variant| variant.disr_expr.as_ref().map(|c| c.value.span))
- .collect::<Vec<_>>();
-
- if !discriminant_spans.is_empty() && has_fields {
- let mut err = feature_err(
- &self.sess.parse_sess,
- sym::arbitrary_enum_discriminant,
- discriminant_spans.clone(),
- "custom discriminant values are not allowed in enums with tuple or struct variants",
- );
- for sp in discriminant_spans {
- err.span_label(sp, "disallowed custom discriminant");
- }
- for variant in variants.iter() {
- match &variant.data {
- VariantData::Struct(..) => {
- err.span_label(variant.span, "struct variant defined here");
- }
- VariantData::Tuple(..) => {
- err.span_label(variant.span, "tuple variant defined here");
- }
- VariantData::Unit(..) => {}
- }
- }
- err.emit();
- }
- }
-
/// Feature gate `impl Trait` inside `type Alias = $type_expr;`.
fn check_impl_trait(&self, ty: &ast::Ty) {
struct ImplTraitVisitor<'a> {
@@ -457,26 +233,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
}
}
- ast::ItemKind::Enum(ast::EnumDef { ref variants, .. }, ..) => {
- for variant in variants {
- match (&variant.data, &variant.disr_expr) {
- (ast::VariantData::Unit(..), _) => {}
- (_, Some(disr_expr)) => gate_feature_post!(
- &self,
- arbitrary_enum_discriminant,
- disr_expr.value.span,
- "discriminants on non-unit variants are experimental"
- ),
- _ => {}
- }
- }
-
- let has_feature = self.features.arbitrary_enum_discriminant;
- if !has_feature && !i.span.allows_unstable(sym::arbitrary_enum_discriminant) {
- self.maybe_report_invalid_custom_discriminants(&variants);
- }
- }
-
ast::ItemKind::Impl(box ast::Impl { polarity, defaultness, ref of_trait, .. }) => {
if let ast::ImplPolarity::Negative(span) = polarity {
gate_feature_post!(
@@ -645,7 +401,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
if let PatKind::Range(Some(_), None, Spanned { .. }) = inner_pat.kind {
gate_feature_post!(
&self,
- half_open_range_patterns,
+ half_open_range_patterns_in_slices,
pat.span,
"`X..` patterns in slices are experimental"
);
@@ -701,7 +457,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 ty, .. }) => {
+ ast::AssocItemKind::Type(box ast::TyAlias { ref ty, .. }) => {
if let (Some(_), AssocCtxt::Trait) = (ty, ctxt) {
gate_feature_post!(
&self,
@@ -773,7 +529,10 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
gate_all!(generators, "yield syntax is experimental");
gate_all!(raw_ref_op, "raw address of syntax is experimental");
gate_all!(const_trait_impl, "const trait impls are experimental");
- gate_all!(half_open_range_patterns, "half-open range patterns are unstable");
+ gate_all!(
+ half_open_range_patterns_in_slices,
+ "half-open range patterns in slices are unstable"
+ );
gate_all!(inline_const, "inline-const is experimental");
gate_all!(inline_const_pat, "inline-const in pattern position is experimental");
gate_all!(associated_const_equality, "associated const equality is incomplete");
diff --git a/compiler/rustc_ast_passes/src/lib.rs b/compiler/rustc_ast_passes/src/lib.rs
index 8aa9d57f0..f58fffc91 100644
--- a/compiler/rustc_ast_passes/src/lib.rs
+++ b/compiler/rustc_ast_passes/src/lib.rs
@@ -9,7 +9,6 @@
#![feature(if_let_guard)]
#![feature(iter_is_partitioned)]
#![feature(let_chains)]
-#![cfg_attr(bootstrap, feature(let_else))]
#![recursion_limit = "256"]
#[macro_use]
diff --git a/compiler/rustc_ast_pretty/Cargo.toml b/compiler/rustc_ast_pretty/Cargo.toml
index 5ad8714e9..a3e3e823b 100644
--- a/compiler/rustc_ast_pretty/Cargo.toml
+++ b/compiler/rustc_ast_pretty/Cargo.toml
@@ -4,7 +4,6 @@ version = "0.0.0"
edition = "2021"
[lib]
-doctest = false
[dependencies]
rustc_span = { path = "../rustc_span" }
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
index ead38caee..bcefa8ce0 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
@@ -193,9 +193,13 @@ impl<'a> State<'a> {
self.print_call_post(args)
}
- fn print_expr_method_call(&mut self, segment: &ast::PathSegment, args: &[P<ast::Expr>]) {
- let base_args = &args[1..];
- self.print_expr_maybe_paren(&args[0], parser::PREC_POSTFIX);
+ fn print_expr_method_call(
+ &mut self,
+ segment: &ast::PathSegment,
+ receiver: &ast::Expr,
+ base_args: &[P<ast::Expr>],
+ ) {
+ self.print_expr_maybe_paren(receiver, parser::PREC_POSTFIX);
self.word(".");
self.print_ident(segment.ident);
if let Some(ref args) = segment.args {
@@ -303,8 +307,8 @@ impl<'a> State<'a> {
ast::ExprKind::Call(ref func, ref args) => {
self.print_expr_call(func, &args);
}
- ast::ExprKind::MethodCall(ref segment, ref args, _) => {
- self.print_expr_method_call(segment, &args);
+ ast::ExprKind::MethodCall(ref segment, ref receiver, ref args, _) => {
+ self.print_expr_method_call(segment, &receiver, &args);
}
ast::ExprKind::Binary(op, ref lhs, ref rhs) => {
self.print_expr_binary(op, lhs, rhs);
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
index 54bac29a6..159853c9e 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
@@ -516,7 +516,7 @@ impl<'a> State<'a> {
ast::AssocItemKind::Const(def, ty, body) => {
self.print_item_const(ident, None, ty, body.as_deref(), vis, *def);
}
- ast::AssocItemKind::TyAlias(box ast::TyAlias {
+ ast::AssocItemKind::Type(box ast::TyAlias {
defaultness,
generics,
where_clauses,