,
- items: Vec>,
- },
+ Impl(Box),
/// A macro invocation.
///
/// E.g., `foo!(..)`.
@@ -2767,6 +2754,9 @@ pub enum ItemKind {
MacroDef(MacroDef),
}
+#[cfg(target_arch = "x86_64")]
+rustc_data_structures::static_assert_size!(ItemKind, 112);
+
impl ItemKind {
pub fn article(&self) -> &str {
use ItemKind::*;
@@ -2801,14 +2791,14 @@ impl ItemKind {
pub fn generics(&self) -> Option<&Generics> {
match self {
- Self::Fn(_, _, generics, _)
- | Self::TyAlias(_, generics, ..)
+ Self::Fn(box FnKind(_, _, generics, _))
+ | Self::TyAlias(box TyAliasKind(_, generics, ..))
| Self::Enum(_, generics)
| Self::Struct(_, generics)
| Self::Union(_, generics)
- | Self::Trait(_, _, generics, ..)
+ | Self::Trait(box TraitKind(_, _, generics, ..))
| Self::TraitAlias(generics, _)
- | Self::Impl { generics, .. } => Some(generics),
+ | Self::Impl(box ImplKind { generics, .. }) => Some(generics),
_ => None,
}
}
@@ -2831,17 +2821,22 @@ pub enum AssocItemKind {
/// If `def` is parsed, then the constant is provided, and otherwise required.
Const(Defaultness, P, Option>),
/// An associated function.
- Fn(Defaultness, FnSig, Generics, Option
>),
+ Fn(Box),
/// An associated type.
- TyAlias(Defaultness, Generics, GenericBounds, Option>),
+ TyAlias(Box),
/// A macro expanding to associated items.
MacCall(MacCall),
}
+#[cfg(target_arch = "x86_64")]
+rustc_data_structures::static_assert_size!(AssocItemKind, 72);
+
impl AssocItemKind {
pub fn defaultness(&self) -> Defaultness {
match *self {
- Self::Const(def, ..) | Self::Fn(def, ..) | Self::TyAlias(def, ..) => def,
+ Self::Const(def, ..)
+ | Self::Fn(box FnKind(def, ..))
+ | Self::TyAlias(box TyAliasKind(def, ..)) => def,
Self::MacCall(..) => Defaultness::Final,
}
}
@@ -2851,8 +2846,8 @@ impl From for ItemKind {
fn from(assoc_item_kind: AssocItemKind) -> ItemKind {
match assoc_item_kind {
AssocItemKind::Const(a, b, c) => ItemKind::Const(a, b, c),
- AssocItemKind::Fn(a, b, c, d) => ItemKind::Fn(a, b, c, d),
- AssocItemKind::TyAlias(a, b, c, d) => ItemKind::TyAlias(a, b, c, d),
+ AssocItemKind::Fn(fn_kind) => ItemKind::Fn(fn_kind),
+ AssocItemKind::TyAlias(ty_alias_kind) => ItemKind::TyAlias(ty_alias_kind),
AssocItemKind::MacCall(a) => ItemKind::MacCall(a),
}
}
@@ -2864,8 +2859,8 @@ impl TryFrom for AssocItemKind {
fn try_from(item_kind: ItemKind) -> Result {
Ok(match item_kind {
ItemKind::Const(a, b, c) => AssocItemKind::Const(a, b, c),
- ItemKind::Fn(a, b, c, d) => AssocItemKind::Fn(a, b, c, d),
- ItemKind::TyAlias(a, b, c, d) => AssocItemKind::TyAlias(a, b, c, d),
+ ItemKind::Fn(fn_kind) => AssocItemKind::Fn(fn_kind),
+ ItemKind::TyAlias(ty_alias_kind) => AssocItemKind::TyAlias(ty_alias_kind),
ItemKind::MacCall(a) => AssocItemKind::MacCall(a),
_ => return Err(item_kind),
})
@@ -2877,20 +2872,23 @@ impl TryFrom for AssocItemKind {
pub enum ForeignItemKind {
/// A foreign static item (`static FOO: u8`).
Static(P, Mutability, Option>),
- /// A foreign function.
- Fn(Defaultness, FnSig, Generics, Option
>),
- /// A foreign type.
- TyAlias(Defaultness, Generics, GenericBounds, Option
>),
+ /// An foreign function.
+ Fn(Box),
+ /// An foreign type.
+ TyAlias(Box),
/// A macro expanding to foreign items.
MacCall(MacCall),
}
+#[cfg(target_arch = "x86_64")]
+rustc_data_structures::static_assert_size!(ForeignItemKind, 72);
+
impl From for ItemKind {
fn from(foreign_item_kind: ForeignItemKind) -> ItemKind {
match foreign_item_kind {
ForeignItemKind::Static(a, b, c) => ItemKind::Static(a, b, c),
- ForeignItemKind::Fn(a, b, c, d) => ItemKind::Fn(a, b, c, d),
- ForeignItemKind::TyAlias(a, b, c, d) => ItemKind::TyAlias(a, b, c, d),
+ ForeignItemKind::Fn(fn_kind) => ItemKind::Fn(fn_kind),
+ ForeignItemKind::TyAlias(ty_alias_kind) => ItemKind::TyAlias(ty_alias_kind),
ForeignItemKind::MacCall(a) => ItemKind::MacCall(a),
}
}
@@ -2902,8 +2900,8 @@ impl TryFrom for ForeignItemKind {
fn try_from(item_kind: ItemKind) -> Result {
Ok(match item_kind {
ItemKind::Static(a, b, c) => ForeignItemKind::Static(a, b, c),
- ItemKind::Fn(a, b, c, d) => ForeignItemKind::Fn(a, b, c, d),
- ItemKind::TyAlias(a, b, c, d) => ForeignItemKind::TyAlias(a, b, c, d),
+ ItemKind::Fn(fn_kind) => ForeignItemKind::Fn(fn_kind),
+ ItemKind::TyAlias(ty_alias_kind) => ForeignItemKind::TyAlias(ty_alias_kind),
ItemKind::MacCall(a) => ForeignItemKind::MacCall(a),
_ => return Err(item_kind),
})
@@ -2911,3 +2909,69 @@ impl TryFrom for ForeignItemKind {
}
pub type ForeignItem = Item;
+
+pub trait HasTokens {
+ /// Called by `Parser::collect_tokens` to store the collected
+ /// tokens inside an AST node
+ fn finalize_tokens(&mut self, tokens: LazyTokenStream);
+}
+
+impl HasTokens for P {
+ fn finalize_tokens(&mut self, tokens: LazyTokenStream) {
+ (**self).finalize_tokens(tokens);
+ }
+}
+
+impl HasTokens for Option {
+ fn finalize_tokens(&mut self, tokens: LazyTokenStream) {
+ if let Some(inner) = self {
+ inner.finalize_tokens(tokens);
+ }
+ }
+}
+
+impl HasTokens for Attribute {
+ fn finalize_tokens(&mut self, tokens: LazyTokenStream) {
+ match &mut self.kind {
+ AttrKind::Normal(_, attr_tokens) => {
+ if attr_tokens.is_none() {
+ *attr_tokens = Some(tokens);
+ }
+ }
+ AttrKind::DocComment(..) => {
+ panic!("Called finalize_tokens on doc comment attr {:?}", self)
+ }
+ }
+ }
+}
+
+impl HasTokens for Stmt {
+ fn finalize_tokens(&mut self, tokens: LazyTokenStream) {
+ let stmt_tokens = match self.kind {
+ StmtKind::Local(ref mut local) => &mut local.tokens,
+ StmtKind::Item(ref mut item) => &mut item.tokens,
+ StmtKind::Expr(ref mut expr) | StmtKind::Semi(ref mut expr) => &mut expr.tokens,
+ StmtKind::Empty => return,
+ StmtKind::MacCall(ref mut mac) => &mut mac.tokens,
+ };
+ if stmt_tokens.is_none() {
+ *stmt_tokens = Some(tokens);
+ }
+ }
+}
+
+macro_rules! derive_has_tokens {
+ ($($ty:path),*) => { $(
+ impl HasTokens for $ty {
+ fn finalize_tokens(&mut self, tokens: LazyTokenStream) {
+ if self.tokens.is_none() {
+ self.tokens = Some(tokens);
+ }
+ }
+ }
+ )* }
+}
+
+derive_has_tokens! {
+ Item, Expr, Ty, AttrItem, Visibility, Path, Block, Pat
+}
diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs
index 19c7c479f0..4dcbe4831b 100644
--- a/compiler/rustc_ast/src/attr/mod.rs
+++ b/compiler/rustc_ast/src/attr/mod.rs
@@ -234,10 +234,7 @@ impl MetaItem {
}
pub fn is_word(&self) -> bool {
- match self.kind {
- MetaItemKind::Word => true,
- _ => false,
- }
+ matches!(self.kind, MetaItemKind::Word)
}
pub fn has_name(&self, name: Symbol) -> bool {
@@ -479,7 +476,7 @@ impl MetaItemKind {
pub fn mac_args(&self, span: Span) -> MacArgs {
match self {
MetaItemKind::Word => MacArgs::Empty,
- MetaItemKind::NameValue(lit) => MacArgs::Eq(span, lit.token_tree().into()),
+ MetaItemKind::NameValue(lit) => MacArgs::Eq(span, lit.to_token()),
MetaItemKind::List(list) => {
let mut tts = Vec::new();
for (i, item) in list.iter().enumerate() {
@@ -501,7 +498,10 @@ impl MetaItemKind {
match *self {
MetaItemKind::Word => vec![],
MetaItemKind::NameValue(ref lit) => {
- vec![TokenTree::token(token::Eq, span).into(), lit.token_tree().into()]
+ vec![
+ TokenTree::token(token::Eq, span).into(),
+ TokenTree::Token(lit.to_token()).into(),
+ ]
}
MetaItemKind::List(ref list) => {
let mut tokens = Vec::new();
@@ -526,7 +526,7 @@ impl MetaItemKind {
fn list_from_tokens(tokens: TokenStream) -> Option {
let mut tokens = tokens.into_trees().peekable();
let mut result = Vec::new();
- while let Some(..) = tokens.peek() {
+ while tokens.peek().is_some() {
let item = NestedMetaItem::from_tokens(&mut tokens)?;
result.push(item);
match tokens.next() {
@@ -557,10 +557,7 @@ impl MetaItemKind {
MetaItemKind::list_from_tokens(tokens.clone())
}
MacArgs::Delimited(..) => None,
- MacArgs::Eq(_, tokens) => {
- assert!(tokens.len() == 1);
- MetaItemKind::name_value_from_tokens(&mut tokens.trees())
- }
+ MacArgs::Eq(_, token) => Lit::from_token(token).ok().map(MetaItemKind::NameValue),
MacArgs::Empty => Some(MetaItemKind::Word),
}
}
@@ -595,7 +592,7 @@ impl NestedMetaItem {
fn token_trees_and_spacings(&self) -> Vec {
match *self {
NestedMetaItem::MetaItem(ref item) => item.token_trees_and_spacings(),
- NestedMetaItem::Literal(ref lit) => vec![lit.token_tree().into()],
+ NestedMetaItem::Literal(ref lit) => vec![TokenTree::Token(lit.to_token()).into()],
}
}
diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs
index 8a20dd7968..ddf52caed0 100644
--- a/compiler/rustc_ast/src/lib.rs
+++ b/compiler/rustc_ast/src/lib.rs
@@ -9,6 +9,7 @@
test(attr(deny(warnings)))
)]
#![feature(box_syntax)]
+#![feature(box_patterns)]
#![feature(const_fn)] // For the `transmute` in `P::new`
#![feature(const_fn_transmute)]
#![feature(const_panic)]
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 3889ede7f4..024d9687f3 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -28,7 +28,7 @@ pub trait ExpectOne {
impl ExpectOne for SmallVec {
fn expect_one(self, err: &'static str) -> A::Item {
- assert!(self.len() == 1, err);
+ assert!(self.len() == 1, "{}", err);
self.into_iter().next().unwrap()
}
}
@@ -365,18 +365,16 @@ pub fn visit_mac_args(args: &mut MacArgs, vis: &mut T) {
visit_delim_span(dspan, vis);
visit_tts(tokens, vis);
}
- MacArgs::Eq(eq_span, tokens) => {
+ MacArgs::Eq(eq_span, token) => {
vis.visit_span(eq_span);
- visit_tts(tokens, vis);
- // The value in `#[key = VALUE]` must be visited as an expression for backward
- // compatibility, so that macros can be expanded in that position.
- if !vis.token_visiting_enabled() {
- match Lrc::make_mut(&mut tokens.0).get_mut(0) {
- Some((TokenTree::Token(token), _spacing)) => match &mut token.kind {
- token::Interpolated(nt) => match Lrc::make_mut(nt) {
- token::NtExpr(expr) => vis.visit_expr(expr),
- t => panic!("unexpected token in key-value attribute: {:?}", t),
- },
+ if vis.token_visiting_enabled() {
+ visit_token(token, vis);
+ } else {
+ // The value in `#[key = VALUE]` must be visited as an expression for backward
+ // compatibility, so that macros can be expanded in that position.
+ match &mut token.kind {
+ token::Interpolated(nt) => match Lrc::make_mut(nt) {
+ token::NtExpr(expr) => vis.visit_expr(expr),
t => panic!("unexpected token in key-value attribute: {:?}", t),
},
t => panic!("unexpected token in key-value attribute: {:?}", t),
@@ -567,7 +565,7 @@ pub fn noop_visit_parenthesized_parameter_data(
args: &mut ParenthesizedArgs,
vis: &mut T,
) {
- let ParenthesizedArgs { inputs, output, span } = args;
+ let ParenthesizedArgs { inputs, output, span, .. } = args;
visit_vec(inputs, |input| vis.visit_ty(input));
noop_visit_fn_ret_ty(output, vis);
vis.visit_span(span);
@@ -790,8 +788,9 @@ pub fn noop_flat_map_generic_param(
GenericParamKind::Type { default } => {
visit_opt(default, |default| vis.visit_ty(default));
}
- GenericParamKind::Const { ty, kw_span: _ } => {
+ GenericParamKind::Const { ty, kw_span: _, default } => {
vis.visit_ty(ty);
+ visit_opt(default, |default| vis.visit_anon_const(default));
}
}
smallvec![param]
@@ -913,7 +912,7 @@ pub fn noop_visit_item_kind(kind: &mut ItemKind, vis: &mut T) {
vis.visit_ty(ty);
visit_opt(expr, |expr| vis.visit_expr(expr));
}
- ItemKind::Fn(_, sig, generics, body) => {
+ ItemKind::Fn(box FnKind(_, sig, generics, body)) => {
visit_fn_sig(sig, vis);
vis.visit_generics(generics);
visit_opt(body, |body| vis.visit_block(body));
@@ -921,7 +920,7 @@ pub fn noop_visit_item_kind(kind: &mut ItemKind, vis: &mut T) {
ItemKind::Mod(m) => vis.visit_mod(m),
ItemKind::ForeignMod(nm) => vis.visit_foreign_mod(nm),
ItemKind::GlobalAsm(_ga) => {}
- ItemKind::TyAlias(_, generics, bounds, ty) => {
+ ItemKind::TyAlias(box TyAliasKind(_, generics, bounds, ty)) => {
vis.visit_generics(generics);
visit_bounds(bounds, vis);
visit_opt(ty, |ty| vis.visit_ty(ty));
@@ -934,7 +933,7 @@ pub fn noop_visit_item_kind(kind: &mut ItemKind, vis: &mut T) {
vis.visit_variant_data(variant_data);
vis.visit_generics(generics);
}
- ItemKind::Impl {
+ ItemKind::Impl(box ImplKind {
unsafety: _,
polarity: _,
defaultness: _,
@@ -943,13 +942,13 @@ pub fn noop_visit_item_kind(kind: &mut ItemKind, vis: &mut T) {
of_trait,
self_ty,
items,
- } => {
+ }) => {
vis.visit_generics(generics);
visit_opt(of_trait, |trait_ref| vis.visit_trait_ref(trait_ref));
vis.visit_ty(self_ty);
items.flat_map_in_place(|item| vis.flat_map_impl_item(item));
}
- ItemKind::Trait(_is_auto, _unsafety, generics, bounds, items) => {
+ ItemKind::Trait(box TraitKind(.., generics, bounds, items)) => {
vis.visit_generics(generics);
visit_bounds(bounds, vis);
items.flat_map_in_place(|item| vis.flat_map_trait_item(item));
@@ -977,12 +976,12 @@ pub fn noop_flat_map_assoc_item(
visitor.visit_ty(ty);
visit_opt(expr, |expr| visitor.visit_expr(expr));
}
- AssocItemKind::Fn(_, sig, generics, body) => {
+ AssocItemKind::Fn(box FnKind(_, sig, generics, body)) => {
visitor.visit_generics(generics);
visit_fn_sig(sig, visitor);
visit_opt(body, |body| visitor.visit_block(body));
}
- AssocItemKind::TyAlias(_, generics, bounds, ty) => {
+ AssocItemKind::TyAlias(box TyAliasKind(_, generics, bounds, ty)) => {
visitor.visit_generics(generics);
visit_bounds(bounds, visitor);
visit_opt(ty, |ty| visitor.visit_ty(ty));
@@ -1067,12 +1066,12 @@ pub fn noop_flat_map_foreign_item(
visitor.visit_ty(ty);
visit_opt(expr, |expr| visitor.visit_expr(expr));
}
- ForeignItemKind::Fn(_, sig, generics, body) => {
+ ForeignItemKind::Fn(box FnKind(_, sig, generics, body)) => {
visitor.visit_generics(generics);
visit_fn_sig(sig, visitor);
visit_opt(body, |body| visitor.visit_block(body));
}
- ForeignItemKind::TyAlias(_, generics, bounds, ty) => {
+ ForeignItemKind::TyAlias(box TyAliasKind(_, generics, bounds, ty)) => {
visitor.visit_generics(generics);
visit_bounds(bounds, visitor);
visit_opt(ty, |ty| visitor.visit_ty(ty));
diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs
index a74464937c..90bfb01d6c 100644
--- a/compiler/rustc_ast/src/token.rs
+++ b/compiler/rustc_ast/src/token.rs
@@ -15,7 +15,7 @@ use rustc_span::hygiene::ExpnKind;
use rustc_span::source_map::SourceMap;
use rustc_span::symbol::{kw, sym};
use rustc_span::symbol::{Ident, Symbol};
-use rustc_span::{self, FileName, RealFileName, Span, DUMMY_SP};
+use rustc_span::{self, edition::Edition, FileName, RealFileName, Span, DUMMY_SP};
use std::borrow::Cow;
use std::{fmt, mem};
@@ -130,10 +130,7 @@ impl LitKind {
}
crate fn may_have_suffix(self) -> bool {
- match self {
- Integer | Float | Err => true,
- _ => false,
- }
+ matches!(self, Integer | Float | Err)
}
}
@@ -305,10 +302,7 @@ impl TokenKind {
}
pub fn should_end_const_arg(&self) -> bool {
- match self {
- Gt | Ge | BinOp(Shr) | BinOpEq(Shr) => true,
- _ => false,
- }
+ matches!(self, Gt | Ge | BinOp(Shr) | BinOpEq(Shr))
}
}
@@ -346,18 +340,21 @@ impl Token {
}
pub fn is_op(&self) -> bool {
- match self.kind {
- OpenDelim(..) | CloseDelim(..) | Literal(..) | DocComment(..) | Ident(..)
- | Lifetime(..) | Interpolated(..) | Eof => false,
- _ => true,
- }
+ !matches!(
+ self.kind,
+ OpenDelim(..)
+ | CloseDelim(..)
+ | Literal(..)
+ | DocComment(..)
+ | Ident(..)
+ | Lifetime(..)
+ | Interpolated(..)
+ | Eof
+ )
}
pub fn is_like_plus(&self) -> bool {
- match self.kind {
- BinOp(Plus) | BinOpEq(Plus) => true,
- _ => false,
- }
+ matches!(self.kind, BinOp(Plus) | BinOpEq(Plus))
}
/// Returns `true` if the token can appear at the start of an expression.
@@ -379,13 +376,10 @@ impl Token {
ModSep | // global path
Lifetime(..) | // labeled loop
Pound => true, // expression attributes
- Interpolated(ref nt) => match **nt {
- NtLiteral(..) |
+ Interpolated(ref nt) => matches!(**nt, NtLiteral(..) |
NtExpr(..) |
NtBlock(..) |
- NtPath(..) => true,
- _ => false,
- },
+ NtPath(..)),
_ => false,
}
}
@@ -405,10 +399,7 @@ impl Token {
Lifetime(..) | // lifetime bound in trait object
Lt | BinOp(Shl) | // associated path
ModSep => true, // global path
- Interpolated(ref nt) => match **nt {
- NtTy(..) | NtPath(..) => true,
- _ => false,
- },
+ Interpolated(ref nt) => matches!(**nt, NtTy(..) | NtPath(..)),
_ => false,
}
}
@@ -417,10 +408,7 @@ impl Token {
pub fn can_begin_const_arg(&self) -> bool {
match self.kind {
OpenDelim(Brace) => true,
- Interpolated(ref nt) => match **nt {
- NtExpr(..) | NtBlock(..) | NtLiteral(..) => true,
- _ => false,
- },
+ Interpolated(ref nt) => matches!(**nt, NtExpr(..) | NtBlock(..) | NtLiteral(..)),
_ => self.can_begin_literal_maybe_minus(),
}
}
@@ -436,10 +424,7 @@ impl Token {
/// Returns `true` if the token is any literal.
pub fn is_lit(&self) -> bool {
- match self.kind {
- Literal(..) => true,
- _ => false,
- }
+ matches!(self.kind, Literal(..))
}
/// Returns `true` if the token is any literal, a minus (which can prefix a literal,
@@ -705,7 +690,16 @@ pub enum NonterminalKind {
Item,
Block,
Stmt,
- Pat,
+ Pat2018 {
+ /// Keep track of whether the user used `:pat2018` or `:pat` and we inferred it from the
+ /// edition of the span. This is used for diagnostics.
+ inferred: bool,
+ },
+ Pat2021 {
+ /// Keep track of whether the user used `:pat2018` or `:pat` and we inferred it from the
+ /// edition of the span. This is used for diagnostics.
+ inferred: bool,
+ },
Expr,
Ty,
Ident,
@@ -718,12 +712,24 @@ pub enum NonterminalKind {
}
impl NonterminalKind {
- pub fn from_symbol(symbol: Symbol) -> Option {
+ /// The `edition` closure is used to get the edition for the given symbol. Doing
+ /// `span.edition()` is expensive, so we do it lazily.
+ pub fn from_symbol(
+ symbol: Symbol,
+ edition: impl FnOnce() -> Edition,
+ ) -> Option {
Some(match symbol {
sym::item => NonterminalKind::Item,
sym::block => NonterminalKind::Block,
sym::stmt => NonterminalKind::Stmt,
- sym::pat => NonterminalKind::Pat,
+ sym::pat => match edition() {
+ Edition::Edition2015 | Edition::Edition2018 => {
+ NonterminalKind::Pat2018 { inferred: true }
+ }
+ Edition::Edition2021 => NonterminalKind::Pat2021 { inferred: true },
+ },
+ sym::pat2018 => NonterminalKind::Pat2018 { inferred: false },
+ sym::pat2021 => NonterminalKind::Pat2021 { inferred: false },
sym::expr => NonterminalKind::Expr,
sym::ty => NonterminalKind::Ty,
sym::ident => NonterminalKind::Ident,
@@ -741,7 +747,10 @@ impl NonterminalKind {
NonterminalKind::Item => sym::item,
NonterminalKind::Block => sym::block,
NonterminalKind::Stmt => sym::stmt,
- NonterminalKind::Pat => sym::pat,
+ NonterminalKind::Pat2018 { inferred: false } => sym::pat2018,
+ NonterminalKind::Pat2021 { inferred: false } => sym::pat2021,
+ NonterminalKind::Pat2018 { inferred: true }
+ | NonterminalKind::Pat2021 { inferred: true } => sym::pat,
NonterminalKind::Expr => sym::expr,
NonterminalKind::Ty => sym::ty,
NonterminalKind::Ident => sym::ident,
@@ -762,7 +771,7 @@ impl fmt::Display for NonterminalKind {
}
impl Nonterminal {
- fn span(&self) -> Span {
+ pub fn span(&self) -> Span {
match self {
NtItem(item) => item.span,
NtBlock(block) => block.span,
diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs
index b2207f2281..9ac05f316f 100644
--- a/compiler/rustc_ast/src/tokenstream.rs
+++ b/compiler/rustc_ast/src/tokenstream.rs
@@ -1,15 +1,15 @@
//! # Token Streams
//!
//! `TokenStream`s represent syntactic objects before they are converted into ASTs.
-//! A `TokenStream` is, roughly speaking, a sequence (eg stream) of `TokenTree`s,
-//! which are themselves a single `Token` or a `Delimited` subsequence of tokens.
+//! A `TokenStream` is, roughly speaking, a sequence of [`TokenTree`]s,
+//! which are themselves a single [`Token`] or a `Delimited` subsequence of tokens.
//!
//! ## Ownership
//!
//! `TokenStream`s are persistent data structures constructed as ropes with reference
//! counted-children. In general, this means that calling an operation on a `TokenStream`
//! (such as `slice`) produces an entirely new `TokenStream` from the borrowed reference to
-//! the original. This essentially coerces `TokenStream`s into 'views' of their subparts,
+//! the original. This essentially coerces `TokenStream`s into "views" of their subparts,
//! and a borrowed `TokenStream` is sufficient to build an owned `TokenStream` without taking
//! ownership of the original.
@@ -24,9 +24,9 @@ use smallvec::{smallvec, SmallVec};
use std::{fmt, iter, mem};
-/// When the main rust parser encounters a syntax-extension invocation, it
-/// parses the arguments to the invocation as a token-tree. This is a very
-/// loose structure, such that all sorts of different AST-fragments can
+/// When the main Rust parser encounters a syntax-extension invocation, it
+/// parses the arguments to the invocation as a token tree. This is a very
+/// loose structure, such that all sorts of different AST fragments can
/// be passed to syntax extensions using a uniform type.
///
/// If the syntax extension is an MBE macro, it will attempt to match its
@@ -38,12 +38,18 @@ use std::{fmt, iter, mem};
/// Nothing special happens to misnamed or misplaced `SubstNt`s.
#[derive(Debug, Clone, PartialEq, Encodable, Decodable, HashStable_Generic)]
pub enum TokenTree {
- /// A single token
+ /// A single token.
Token(Token),
- /// A delimited sequence of token trees
+ /// A delimited sequence of token trees.
Delimited(DelimSpan, DelimToken, TokenStream),
}
+#[derive(Copy, Clone)]
+pub enum CanSynthesizeMissingTokens {
+ Yes,
+ No,
+}
+
// Ensure all fields of `TokenTree` is `Send` and `Sync`.
#[cfg(parallel_compiler)]
fn _dummy()
@@ -56,7 +62,7 @@ where
}
impl TokenTree {
- /// Checks if this TokenTree is equal to the other, regardless of span information.
+ /// Checks if this `TokenTree` is equal to the other, regardless of span information.
pub fn eq_unspanned(&self, other: &TokenTree) -> bool {
match (self, other) {
(TokenTree::Token(token), TokenTree::Token(token2)) => token.kind == token2.kind,
@@ -67,7 +73,7 @@ impl TokenTree {
}
}
- /// Retrieves the TokenTree's span.
+ /// Retrieves the `TokenTree`'s span.
pub fn span(&self) -> Span {
match self {
TokenTree::Token(token) => token.span,
@@ -121,20 +127,16 @@ where
}
pub trait CreateTokenStream: sync::Send + sync::Sync {
- fn add_trailing_semi(&self) -> Box;
fn create_token_stream(&self) -> TokenStream;
}
impl CreateTokenStream for TokenStream {
- fn add_trailing_semi(&self) -> Box {
- panic!("Cannot call `add_trailing_semi` on a `TokenStream`!");
- }
fn create_token_stream(&self) -> TokenStream {
self.clone()
}
}
-/// A lazy version of `TokenStream`, which defers creation
+/// A lazy version of [`TokenStream`], which defers creation
/// of an actual `TokenStream` until it is needed.
/// `Box` is here only to reduce the structure size.
#[derive(Clone)]
@@ -145,13 +147,6 @@ impl LazyTokenStream {
LazyTokenStream(Lrc::new(Box::new(inner)))
}
- /// Extends the captured stream by one token,
- /// which must be a trailing semicolon. This
- /// affects the `TokenStream` created by `make_tokenstream`.
- pub fn add_trailing_semi(&self) -> LazyTokenStream {
- LazyTokenStream(Lrc::new(self.0.add_trailing_semi()))
- }
-
pub fn create_token_stream(&self) -> TokenStream {
self.0.create_token_stream()
}
@@ -182,11 +177,12 @@ impl HashStable for LazyTokenStream {
}
}
-/// A `TokenStream` is an abstract sequence of tokens, organized into `TokenTree`s.
+/// A `TokenStream` is an abstract sequence of tokens, organized into [`TokenTree`]s.
///
/// The goal is for procedural macros to work with `TokenStream`s and `TokenTree`s
/// instead of a representation of the abstract syntax tree.
-/// Today's `TokenTree`s can still contain AST via `token::Interpolated` for back-compat.
+/// Today's `TokenTree`s can still contain AST via `token::Interpolated` for
+/// backwards compatability.
#[derive(Clone, Debug, Default, Encodable, Decodable)]
pub struct TokenStream(pub(crate) Lrc>);
@@ -423,7 +419,7 @@ impl TokenStreamBuilder {
}
}
-/// By-reference iterator over a `TokenStream`.
+/// By-reference iterator over a [`TokenStream`].
#[derive(Clone)]
pub struct CursorRef<'t> {
stream: &'t TokenStream,
@@ -451,8 +447,8 @@ impl<'t> Iterator for CursorRef<'t> {
}
}
-/// Owning by-value iterator over a `TokenStream`.
-/// FIXME: Many uses of this can be replaced with by-reference iterator to avoid clones.
+/// Owning by-value iterator over a [`TokenStream`].
+// FIXME: Many uses of this can be replaced with by-reference iterator to avoid clones.
#[derive(Clone)]
pub struct Cursor {
pub stream: TokenStream,
diff --git a/compiler/rustc_ast/src/util/classify.rs b/compiler/rustc_ast/src/util/classify.rs
index 60422a2e57..90786520fe 100644
--- a/compiler/rustc_ast/src/util/classify.rs
+++ b/compiler/rustc_ast/src/util/classify.rs
@@ -12,14 +12,14 @@ use crate::ast;
/// |x| 5
/// isn't parsed as (if true {...} else {...} | x) | 5
pub fn expr_requires_semi_to_be_stmt(e: &ast::Expr) -> bool {
- match e.kind {
+ !matches!(
+ e.kind,
ast::ExprKind::If(..)
- | ast::ExprKind::Match(..)
- | ast::ExprKind::Block(..)
- | ast::ExprKind::While(..)
- | ast::ExprKind::Loop(..)
- | ast::ExprKind::ForLoop(..)
- | ast::ExprKind::TryBlock(..) => false,
- _ => true,
- }
+ | ast::ExprKind::Match(..)
+ | ast::ExprKind::Block(..)
+ | ast::ExprKind::While(..)
+ | ast::ExprKind::Loop(..)
+ | ast::ExprKind::ForLoop(..)
+ | ast::ExprKind::TryBlock(..)
+ )
}
diff --git a/compiler/rustc_ast/src/util/comments.rs b/compiler/rustc_ast/src/util/comments.rs
index 5d994c9037..542a330a03 100644
--- a/compiler/rustc_ast/src/util/comments.rs
+++ b/compiler/rustc_ast/src/util/comments.rs
@@ -180,10 +180,8 @@ pub fn gather_comments(sm: &SourceMap, path: FileName, src: String) -> Vec {
if doc_style.is_none() {
- let code_to_the_right = match text[pos + token.len..].chars().next() {
- Some('\r' | '\n') => false,
- _ => true,
- };
+ let code_to_the_right =
+ !matches!(text[pos + token.len..].chars().next(), Some('\r' | '\n'));
let style = match (code_to_the_left, code_to_the_right) {
(_, true) => CommentStyle::Mixed,
(false, false) => CommentStyle::Isolated,
diff --git a/compiler/rustc_ast/src/util/literal.rs b/compiler/rustc_ast/src/util/literal.rs
index f6f1ad0a9c..2124f1efb9 100644
--- a/compiler/rustc_ast/src/util/literal.rs
+++ b/compiler/rustc_ast/src/util/literal.rs
@@ -2,7 +2,6 @@
use crate::ast::{self, Lit, LitKind};
use crate::token::{self, Token};
-use crate::tokenstream::TokenTree;
use rustc_lexer::unescape::{unescape_byte, unescape_char};
use rustc_lexer::unescape::{unescape_byte_literal, unescape_literal, Mode};
@@ -88,7 +87,6 @@ impl LitKind {
}
});
error?;
- buf.shrink_to_fit();
Symbol::intern(&buf)
} else {
symbol
@@ -106,7 +104,6 @@ impl LitKind {
}
});
error?;
- buf.shrink_to_fit();
LitKind::ByteStr(buf.into())
}
token::ByteStrRaw(_) => {
@@ -121,7 +118,6 @@ impl LitKind {
}
});
error?;
- buf.shrink_to_fit();
buf
} else {
symbol.to_string().into_bytes()
@@ -225,13 +221,13 @@ impl Lit {
Lit { token: kind.to_lit_token(), kind, span }
}
- /// Losslessly convert an AST literal into a token stream.
- pub fn token_tree(&self) -> TokenTree {
- let token = match self.token.kind {
+ /// Losslessly convert an AST literal into a token.
+ pub fn to_token(&self) -> Token {
+ let kind = match self.token.kind {
token::Bool => token::Ident(self.token.symbol, false),
_ => token::Literal(self.token),
};
- TokenTree::token(token, self.span)
+ Token::new(kind, self.span)
}
}
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index a420bb5635..c37d4cd9f7 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -15,7 +15,6 @@
use crate::ast::*;
use crate::token;
-use crate::tokenstream::TokenTree;
use rustc_span::symbol::{Ident, Symbol};
use rustc_span::Span;
@@ -293,7 +292,7 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
visitor.visit_ty(typ);
walk_list!(visitor, visit_expr, expr);
}
- ItemKind::Fn(_, ref sig, ref generics, ref body) => {
+ ItemKind::Fn(box FnKind(_, ref sig, ref generics, ref body)) => {
visitor.visit_generics(generics);
let kind = FnKind::Fn(FnCtxt::Free, item.ident, sig, &item.vis, body.as_deref());
visitor.visit_fn(kind, item.span, item.id)
@@ -303,7 +302,7 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
walk_list!(visitor, visit_foreign_item, &foreign_module.items);
}
ItemKind::GlobalAsm(ref ga) => visitor.visit_global_asm(ga),
- ItemKind::TyAlias(_, ref generics, ref bounds, ref ty) => {
+ ItemKind::TyAlias(box TyAliasKind(_, ref generics, ref bounds, ref ty)) => {
visitor.visit_generics(generics);
walk_list!(visitor, visit_param_bound, bounds);
walk_list!(visitor, visit_ty, ty);
@@ -312,7 +311,7 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
visitor.visit_generics(generics);
visitor.visit_enum_def(enum_definition, generics, item.id, item.span)
}
- ItemKind::Impl {
+ ItemKind::Impl(box ImplKind {
unsafety: _,
polarity: _,
defaultness: _,
@@ -321,7 +320,7 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
ref of_trait,
ref self_ty,
ref items,
- } => {
+ }) => {
visitor.visit_generics(generics);
walk_list!(visitor, visit_trait_ref, of_trait);
visitor.visit_ty(self_ty);
@@ -332,7 +331,7 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
visitor.visit_generics(generics);
visitor.visit_variant_data(struct_definition);
}
- ItemKind::Trait(.., ref generics, ref bounds, ref items) => {
+ ItemKind::Trait(box TraitKind(.., ref generics, ref bounds, ref items)) => {
visitor.visit_generics(generics);
walk_list!(visitor, visit_param_bound, bounds);
walk_list!(visitor, visit_assoc_item, items, AssocCtxt::Trait);
@@ -544,12 +543,12 @@ pub fn walk_foreign_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a ForeignI
visitor.visit_ty(ty);
walk_list!(visitor, visit_expr, expr);
}
- ForeignItemKind::Fn(_, sig, generics, body) => {
+ ForeignItemKind::Fn(box FnKind(_, sig, generics, body)) => {
visitor.visit_generics(generics);
let kind = FnKind::Fn(FnCtxt::Foreign, ident, sig, vis, body.as_deref());
visitor.visit_fn(kind, span, id);
}
- ForeignItemKind::TyAlias(_, generics, bounds, ty) => {
+ ForeignItemKind::TyAlias(box TyAliasKind(_, generics, bounds, ty)) => {
visitor.visit_generics(generics);
walk_list!(visitor, visit_param_bound, bounds);
walk_list!(visitor, visit_ty, ty);
@@ -578,7 +577,12 @@ pub fn walk_generic_param<'a, V: Visitor<'a>>(visitor: &mut V, param: &'a Generi
match param.kind {
GenericParamKind::Lifetime => (),
GenericParamKind::Type { ref default } => walk_list!(visitor, visit_ty, default),
- GenericParamKind::Const { ref ty, .. } => visitor.visit_ty(ty),
+ GenericParamKind::Const { ref ty, ref default, .. } => {
+ visitor.visit_ty(ty);
+ if let Some(default) = default {
+ visitor.visit_anon_const(default);
+ }
+ }
}
}
@@ -649,12 +653,12 @@ pub fn walk_assoc_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem,
visitor.visit_ty(ty);
walk_list!(visitor, visit_expr, expr);
}
- AssocItemKind::Fn(_, sig, generics, body) => {
+ AssocItemKind::Fn(box FnKind(_, sig, generics, body)) => {
visitor.visit_generics(generics);
let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), ident, sig, vis, body.as_deref());
visitor.visit_fn(kind, span, id);
}
- AssocItemKind::TyAlias(_, generics, bounds, ty) => {
+ AssocItemKind::TyAlias(box TyAliasKind(_, generics, bounds, ty)) => {
visitor.visit_generics(generics);
walk_list!(visitor, visit_param_bound, bounds);
walk_list!(visitor, visit_ty, ty);
@@ -900,12 +904,9 @@ pub fn walk_mac_args<'a, V: Visitor<'a>>(visitor: &mut V, args: &'a MacArgs) {
MacArgs::Delimited(_dspan, _delim, _tokens) => {}
// The value in `#[key = VALUE]` must be visited as an expression for backward
// compatibility, so that macros can be expanded in that position.
- MacArgs::Eq(_eq_span, tokens) => match tokens.trees_ref().next() {
- Some(TokenTree::Token(token)) => match &token.kind {
- token::Interpolated(nt) => match &**nt {
- token::NtExpr(expr) => visitor.visit_expr(expr),
- t => panic!("unexpected token in key-value attribute: {:?}", t),
- },
+ MacArgs::Eq(_eq_span, token) => match &token.kind {
+ token::Interpolated(nt) => match &**nt {
+ token::NtExpr(expr) => visitor.visit_expr(expr),
t => panic!("unexpected token in key-value attribute: {:?}", t),
},
t => panic!("unexpected token in key-value attribute: {:?}", t),
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index 9b1642df11..4d6afd2fe0 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -10,9 +10,9 @@ use rustc_errors::struct_span_err;
use rustc_hir as hir;
use rustc_hir::def::Res;
use rustc_session::parse::feature_err;
-use rustc_span::hygiene::ForLoopLoc;
use rustc_span::source_map::{respan, DesugaringKind, Span, Spanned};
use rustc_span::symbol::{sym, Ident, Symbol};
+use rustc_span::{hygiene::ForLoopLoc, DUMMY_SP};
use rustc_target::asm;
use std::collections::hash_map::Entry;
use std::fmt::Write;
@@ -87,9 +87,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
ExprKind::Let(ref pat, ref scrutinee) => {
self.lower_expr_let(e.span, pat, scrutinee)
}
- ExprKind::If(ref cond, ref then, ref else_opt) => {
- self.lower_expr_if(e.span, cond, then, else_opt.as_deref())
- }
+ ExprKind::If(ref cond, ref then, ref else_opt) => match cond.kind {
+ ExprKind::Let(ref pat, ref scrutinee) => {
+ self.lower_expr_if_let(e.span, pat, scrutinee, then, else_opt.as_deref())
+ }
+ _ => self.lower_expr_if(cond, then, else_opt.as_deref()),
+ },
ExprKind::While(ref cond, ref body, opt_label) => self
.with_loop_scope(e.id, |this| {
this.lower_expr_while_in_loop_scope(e.span, cond, body, opt_label)
@@ -99,6 +102,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
this.lower_block(body, false),
opt_label,
hir::LoopSource::Loop,
+ DUMMY_SP,
)
}),
ExprKind::TryBlock(ref body) => self.lower_expr_try_block(body),
@@ -337,10 +341,30 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn lower_expr_if(
&mut self,
- span: Span,
cond: &Expr,
then: &Block,
else_opt: Option<&Expr>,
+ ) -> hir::ExprKind<'hir> {
+ macro_rules! make_if {
+ ($opt:expr) => {{
+ let then_expr = self.lower_block_expr(then);
+ hir::ExprKind::If(self.lower_expr(cond), self.arena.alloc(then_expr), $opt)
+ }};
+ }
+ if let Some(rslt) = else_opt {
+ make_if!(Some(self.lower_expr(rslt)))
+ } else {
+ make_if!(None)
+ }
+ }
+
+ fn lower_expr_if_let(
+ &mut self,
+ span: Span,
+ pat: &Pat,
+ scrutinee: &Expr,
+ then: &Block,
+ else_opt: Option<&Expr>,
) -> hir::ExprKind<'hir> {
// FIXME(#53667): handle lowering of && and parens.
@@ -353,30 +377,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
let else_arm = self.arm(else_pat, else_expr);
// Handle then + scrutinee:
- let (then_pat, scrutinee, desugar) = match cond.kind {
- // ` => `:
- ExprKind::Let(ref pat, ref scrutinee) => {
- let scrutinee = self.lower_expr(scrutinee);
- let pat = self.lower_pat(pat);
- (pat, scrutinee, hir::MatchSource::IfLetDesugar { contains_else_clause })
- }
- // `true => `:
- _ => {
- // Lower condition:
- let cond = self.lower_expr(cond);
- let span_block =
- self.mark_span_with_reason(DesugaringKind::CondTemporary, cond.span, None);
- // Wrap in a construct equivalent to `{ let _t = $cond; _t }`
- // to preserve drop semantics since `if cond { ... }` does not
- // let temporaries live outside of `cond`.
- let cond = self.expr_drop_temps(span_block, cond, ThinVec::new());
- let pat = self.pat_bool(span, true);
- (pat, cond, hir::MatchSource::IfDesugar { contains_else_clause })
- }
- };
+ let scrutinee = self.lower_expr(scrutinee);
+ let then_pat = self.lower_pat(pat);
+
let then_expr = self.lower_block_expr(then);
let then_arm = self.arm(then_pat, self.arena.alloc(then_expr));
+ let desugar = hir::MatchSource::IfLetDesugar { contains_else_clause };
hir::ExprKind::Match(scrutinee, arena_vec![self; then_arm, else_arm], desugar)
}
@@ -447,7 +454,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
self.expr_match(span, scrutinee, arena_vec![self; then_arm, else_arm], desugar);
// `[opt_ident]: loop { ... }`
- hir::ExprKind::Loop(self.block_expr(self.arena.alloc(match_expr)), opt_label, source)
+ hir::ExprKind::Loop(
+ self.block_expr(self.arena.alloc(match_expr)),
+ opt_label,
+ source,
+ span.with_hi(cond.span.hi()),
+ )
}
/// Desugar `try { ; }` into `{ ; ::std::ops::Try::from_ok() }`,
@@ -742,7 +754,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
// loop { .. }
let loop_expr = self.arena.alloc(hir::Expr {
hir_id: loop_hir_id,
- kind: hir::ExprKind::Loop(loop_block, None, hir::LoopSource::Loop),
+ kind: hir::ExprKind::Loop(loop_block, None, hir::LoopSource::Loop, span),
span,
attrs: ThinVec::new(),
});
@@ -764,10 +776,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
body: &Expr,
fn_decl_span: Span,
) -> hir::ExprKind<'hir> {
- // Lower outside new scope to preserve `is_in_loop_condition`.
- let fn_decl = self.lower_fn_decl(decl, None, false, None);
-
- self.with_new_scopes(move |this| {
+ let (body_id, generator_option) = self.with_new_scopes(move |this| {
let prev = this.current_item;
this.current_item = Some(fn_decl_span);
let mut generator_kind = None;
@@ -779,8 +788,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
let generator_option =
this.generator_movability_for_fn(&decl, fn_decl_span, generator_kind, movability);
this.current_item = prev;
- hir::ExprKind::Closure(capture_clause, fn_decl, body_id, fn_decl_span, generator_option)
- })
+ (body_id, generator_option)
+ });
+
+ // Lower outside new scope to preserve `is_in_loop_condition`.
+ let fn_decl = self.lower_fn_decl(decl, None, false, None);
+
+ hir::ExprKind::Closure(capture_clause, fn_decl, body_id, fn_decl_span, generator_option)
}
fn generator_movability_for_fn(
@@ -826,12 +840,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
) -> hir::ExprKind<'hir> {
let outer_decl =
FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) };
- // We need to lower the declaration outside the new scope, because we
- // have to conserve the state of being inside a loop condition for the
- // closure argument types.
- let fn_decl = self.lower_fn_decl(&outer_decl, None, false, None);
- self.with_new_scopes(move |this| {
+ let body_id = self.with_new_scopes(|this| {
// FIXME(cramertj): allow `async` non-`move` closures with arguments.
if capture_clause == CaptureBy::Ref && !decl.inputs.is_empty() {
struct_span_err!(
@@ -862,8 +872,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
);
this.expr(fn_decl_span, async_body, ThinVec::new())
});
- hir::ExprKind::Closure(capture_clause, fn_decl, body_id, fn_decl_span, None)
- })
+ body_id
+ });
+
+ // We need to lower the declaration outside the new scope, because we
+ // have to conserve the state of being inside a loop condition for the
+ // closure argument types.
+ let fn_decl = self.lower_fn_decl(&outer_decl, None, false, None);
+
+ hir::ExprKind::Closure(capture_clause, fn_decl, body_id, fn_decl_span, None)
}
/// Destructure the LHS of complex assignments.
@@ -1703,7 +1720,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
);
// `[opt_ident]: loop { ... }`
- let kind = hir::ExprKind::Loop(loop_block, opt_label, hir::LoopSource::ForLoop);
+ let kind = hir::ExprKind::Loop(
+ loop_block,
+ opt_label,
+ hir::LoopSource::ForLoop,
+ e.span.with_hi(orig_head_span.hi()),
+ );
let loop_expr = self.arena.alloc(hir::Expr {
hir_id: self.lower_node_id(e.id),
kind,
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index eef6d38aa0..1efe83cace 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -67,7 +67,7 @@ impl<'a> Visitor<'a> for ItemLowerer<'a, '_, '_> {
if let Some(hir_id) = item_hir_id {
self.lctx.with_parent_item_lifetime_defs(hir_id, |this| {
let this = &mut ItemLowerer { lctx: this };
- if let ItemKind::Impl { ref of_trait, .. } = item.kind {
+ if let ItemKind::Impl(box ImplKind { ref of_trait, .. }) = item.kind {
this.with_trait_impl_ref(of_trait, |this| visit::walk_item(this, item));
} else {
visit::walk_item(this, item);
@@ -134,7 +134,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let old_len = self.in_scope_lifetimes.len();
let parent_generics = match self.items.get(&parent_hir_id).unwrap().kind {
- hir::ItemKind::Impl { ref generics, .. }
+ hir::ItemKind::Impl(hir::Impl { ref generics, .. })
| hir::ItemKind::Trait(_, _, ref generics, ..) => &generics.params[..],
_ => &[],
};
@@ -189,7 +189,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
vec
}
ItemKind::MacroDef(..) => SmallVec::new(),
- ItemKind::Fn(..) | ItemKind::Impl { of_trait: None, .. } => smallvec![i.id],
+ ItemKind::Fn(..) | ItemKind::Impl(box ImplKind { of_trait: None, .. }) => {
+ smallvec![i.id]
+ }
_ => smallvec![i.id],
};
@@ -276,12 +278,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
let (ty, body_id) = self.lower_const_item(t, span, e.as_deref());
hir::ItemKind::Const(ty, body_id)
}
- ItemKind::Fn(
+ ItemKind::Fn(box FnKind(
_,
FnSig { ref decl, header, span: fn_sig_span },
ref generics,
ref body,
- ) => {
+ )) => {
let fn_def_id = self.resolver.local_def_id(id);
self.with_new_scopes(|this| {
this.current_item = Some(ident.span);
@@ -310,21 +312,26 @@ impl<'hir> LoweringContext<'_, 'hir> {
);
let sig = hir::FnSig {
decl,
- header: this.lower_fn_header(header),
+ header: this.lower_fn_header(header, fn_sig_span, id),
span: fn_sig_span,
};
hir::ItemKind::Fn(sig, generics, body_id)
})
}
ItemKind::Mod(ref m) => hir::ItemKind::Mod(self.lower_mod(m)),
- ItemKind::ForeignMod(ref fm) => hir::ItemKind::ForeignMod {
- abi: fm.abi.map_or(abi::Abi::C, |abi| self.lower_abi(abi)),
- items: self
- .arena
- .alloc_from_iter(fm.items.iter().map(|x| self.lower_foreign_item_ref(x))),
- },
+ ItemKind::ForeignMod(ref fm) => {
+ if fm.abi.is_none() {
+ self.maybe_lint_missing_abi(span, id, abi::Abi::C);
+ }
+ hir::ItemKind::ForeignMod {
+ abi: fm.abi.map_or(abi::Abi::C, |abi| self.lower_abi(abi)),
+ items: self
+ .arena
+ .alloc_from_iter(fm.items.iter().map(|x| self.lower_foreign_item_ref(x))),
+ }
+ }
ItemKind::GlobalAsm(ref ga) => hir::ItemKind::GlobalAsm(self.lower_global_asm(ga)),
- ItemKind::TyAlias(_, ref gen, _, Some(ref ty)) => {
+ ItemKind::TyAlias(box TyAliasKind(_, ref gen, _, Some(ref ty))) => {
// We lower
//
// type Foo = impl Trait
@@ -343,7 +350,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let generics = self.lower_generics(gen, ImplTraitContext::disallowed());
hir::ItemKind::TyAlias(ty, generics)
}
- ItemKind::TyAlias(_, ref generics, _, None) => {
+ ItemKind::TyAlias(box TyAliasKind(_, ref generics, _, None)) => {
let ty = self.arena.alloc(self.ty(span, hir::TyKind::Err));
let generics = self.lower_generics(generics, ImplTraitContext::disallowed());
hir::ItemKind::TyAlias(ty, generics)
@@ -370,7 +377,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
self.lower_generics(generics, ImplTraitContext::disallowed()),
)
}
- ItemKind::Impl {
+ ItemKind::Impl(box ImplKind {
unsafety,
polarity,
defaultness,
@@ -379,7 +386,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
of_trait: ref trait_ref,
self_ty: ref ty,
items: ref impl_items,
- } => {
+ }) => {
let def_id = self.resolver.local_def_id(id);
// Lower the "impl header" first. This ordering is important
@@ -431,7 +438,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
// to not cause an assertion failure inside the `lower_defaultness` function.
let has_val = true;
let (defaultness, defaultness_span) = self.lower_defaultness(defaultness, has_val);
- hir::ItemKind::Impl {
+ hir::ItemKind::Impl(hir::Impl {
unsafety: self.lower_unsafety(unsafety),
polarity,
defaultness,
@@ -441,9 +448,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
of_trait: trait_ref,
self_ty: lowered_ty,
items: new_impl_items,
- }
+ })
}
- ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, ref items) => {
+ ItemKind::Trait(box TraitKind(
+ is_auto,
+ unsafety,
+ ref generics,
+ ref bounds,
+ ref items,
+ )) => {
let bounds = self.lower_param_bounds(bounds, ImplTraitContext::disallowed());
let items = self
.arena
@@ -693,7 +706,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
ident: i.ident,
attrs: self.lower_attrs(&i.attrs),
kind: match i.kind {
- ForeignItemKind::Fn(_, ref sig, ref generics, _) => {
+ ForeignItemKind::Fn(box FnKind(_, ref sig, ref generics, _)) => {
let fdec = &sig.decl;
let (generics, (fn_dec, fn_args)) = self.add_in_band_defs(
generics,
@@ -798,19 +811,19 @@ impl<'hir> LoweringContext<'_, 'hir> {
let body = default.as_ref().map(|x| self.lower_const_body(i.span, Some(x)));
(hir::Generics::empty(), hir::TraitItemKind::Const(ty, body))
}
- AssocItemKind::Fn(_, ref sig, ref generics, None) => {
+ AssocItemKind::Fn(box FnKind(_, ref sig, ref generics, None)) => {
let names = self.lower_fn_params_to_names(&sig.decl);
let (generics, sig) =
- self.lower_method_sig(generics, sig, trait_item_def_id, false, None);
+ self.lower_method_sig(generics, sig, trait_item_def_id, false, None, i.id);
(generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)))
}
- AssocItemKind::Fn(_, ref sig, ref generics, Some(ref body)) => {
+ AssocItemKind::Fn(box FnKind(_, ref sig, ref generics, Some(ref body))) => {
let body_id = self.lower_fn_body_block(i.span, &sig.decl, Some(body));
let (generics, sig) =
- self.lower_method_sig(generics, sig, trait_item_def_id, false, None);
+ self.lower_method_sig(generics, sig, trait_item_def_id, false, None, i.id);
(generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)))
}
- AssocItemKind::TyAlias(_, ref generics, ref bounds, ref default) => {
+ AssocItemKind::TyAlias(box TyAliasKind(_, ref generics, ref bounds, ref default)) => {
let ty = default.as_ref().map(|x| self.lower_ty(x, ImplTraitContext::disallowed()));
let generics = self.lower_generics(generics, ImplTraitContext::disallowed());
let kind = hir::TraitItemKind::Type(
@@ -836,10 +849,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn lower_trait_item_ref(&mut self, i: &AssocItem) -> hir::TraitItemRef {
let (kind, has_default) = match &i.kind {
AssocItemKind::Const(_, _, default) => (hir::AssocItemKind::Const, default.is_some()),
- AssocItemKind::TyAlias(_, _, _, default) => {
+ AssocItemKind::TyAlias(box TyAliasKind(_, _, _, default)) => {
(hir::AssocItemKind::Type, default.is_some())
}
- AssocItemKind::Fn(_, sig, _, default) => {
+ AssocItemKind::Fn(box FnKind(_, sig, _, default)) => {
(hir::AssocItemKind::Fn { has_self: sig.decl.has_self() }, default.is_some())
}
AssocItemKind::MacCall(..) => unimplemented!(),
@@ -865,7 +878,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
hir::ImplItemKind::Const(ty, self.lower_const_body(i.span, expr.as_deref())),
)
}
- AssocItemKind::Fn(_, sig, generics, body) => {
+ AssocItemKind::Fn(box FnKind(_, sig, generics, body)) => {
self.current_item = Some(i.span);
let asyncness = sig.header.asyncness;
let body_id =
@@ -877,11 +890,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
impl_item_def_id,
impl_trait_return_allow,
asyncness.opt_return_id(),
+ i.id,
);
(generics, hir::ImplItemKind::Fn(sig, body_id))
}
- AssocItemKind::TyAlias(_, generics, _, ty) => {
+ AssocItemKind::TyAlias(box TyAliasKind(_, generics, _, ty)) => {
let generics = self.lower_generics(generics, ImplTraitContext::disallowed());
let kind = match ty {
None => {
@@ -932,7 +946,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
kind: match &i.kind {
AssocItemKind::Const(..) => hir::AssocItemKind::Const,
AssocItemKind::TyAlias(..) => hir::AssocItemKind::Type,
- AssocItemKind::Fn(_, sig, ..) => {
+ AssocItemKind::Fn(box FnKind(_, sig, ..)) => {
hir::AssocItemKind::Fn { has_self: sig.decl.has_self() }
}
AssocItemKind::MacCall(..) => unimplemented!(),
@@ -1270,8 +1284,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn_def_id: LocalDefId,
impl_trait_return_allow: bool,
is_async: Option,
+ id: NodeId,
) -> (hir::Generics<'hir>, hir::FnSig<'hir>) {
- let header = self.lower_fn_header(sig.header);
+ let header = self.lower_fn_header(sig.header, sig.span, id);
let (generics, decl) = self.add_in_band_defs(
generics,
fn_def_id,
@@ -1288,12 +1303,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
(generics, hir::FnSig { header, decl, span: sig.span })
}
- fn lower_fn_header(&mut self, h: FnHeader) -> hir::FnHeader {
+ fn lower_fn_header(&mut self, h: FnHeader, span: Span, id: NodeId) -> hir::FnHeader {
hir::FnHeader {
unsafety: self.lower_unsafety(h.unsafety),
asyncness: self.lower_asyncness(h.asyncness),
constness: self.lower_constness(h.constness),
- abi: self.lower_extern(h.ext),
+ abi: self.lower_extern(h.ext, span, id),
}
}
@@ -1304,10 +1319,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
})
}
- pub(super) fn lower_extern(&mut self, ext: Extern) -> abi::Abi {
+ pub(super) fn lower_extern(&mut self, ext: Extern, span: Span, id: NodeId) -> abi::Abi {
match ext {
Extern::None => abi::Abi::Rust,
- Extern::Implicit => abi::Abi::C,
+ Extern::Implicit => {
+ self.maybe_lint_missing_abi(span, id, abi::Abi::C);
+ abi::Abi::C
+ }
Extern::Explicit(abi) => self.lower_abi(abi),
}
}
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 2e1b5a74a7..f076dca5cf 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -30,14 +30,14 @@
//! get confused if the spans from leaf AST nodes occur in multiple places
//! in the HIR, especially for multiple identifiers.
-#![feature(array_value_iter)]
#![feature(crate_visibility_modifier)]
#![feature(or_patterns)]
+#![feature(box_patterns)]
#![recursion_limit = "256"]
use rustc_ast::node_id::NodeMap;
use rustc_ast::token::{self, DelimToken, Nonterminal, Token};
-use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree};
+use rustc_ast::tokenstream::{CanSynthesizeMissingTokens, DelimSpan, TokenStream, TokenTree};
use rustc_ast::visit::{self, AssocCtxt, Visitor};
use rustc_ast::walk_list;
use rustc_ast::{self as ast, *};
@@ -53,13 +53,15 @@ use rustc_hir::definitions::{DefKey, DefPathData, Definitions};
use rustc_hir::intravisit;
use rustc_hir::{ConstArg, GenericArg, ParamName};
use rustc_index::vec::{Idx, IndexVec};
-use rustc_session::lint::{builtin::BARE_TRAIT_OBJECTS, BuiltinLintDiagnostics, LintBuffer};
+use rustc_session::lint::builtin::{BARE_TRAIT_OBJECTS, MISSING_ABI};
+use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer};
use rustc_session::parse::ParseSess;
use rustc_session::Session;
use rustc_span::hygiene::ExpnId;
-use rustc_span::source_map::{respan, DesugaringKind, ExpnData, ExpnKind};
+use rustc_span::source_map::{respan, DesugaringKind};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::Span;
+use rustc_target::spec::abi::Abi;
use smallvec::{smallvec, SmallVec};
use std::collections::BTreeMap;
@@ -206,7 +208,7 @@ pub trait ResolverAstLowering {
) -> LocalDefId;
}
-type NtToTokenstream = fn(&Nonterminal, &ParseSess, Span) -> TokenStream;
+type NtToTokenstream = fn(&Nonterminal, &ParseSess, CanSynthesizeMissingTokens) -> TokenStream;
/// Context of `impl Trait` in code, which determines whether it is allowed in an HIR subtree,
/// and if so, what meaning it has.
@@ -393,6 +395,42 @@ enum AnonymousLifetimeMode {
PassThrough,
}
+struct TokenStreamLowering<'a> {
+ parse_sess: &'a ParseSess,
+ synthesize_tokens: CanSynthesizeMissingTokens,
+ nt_to_tokenstream: NtToTokenstream,
+}
+
+impl<'a> TokenStreamLowering<'a> {
+ fn lower_token_stream(&mut self, tokens: TokenStream) -> TokenStream {
+ tokens.into_trees().flat_map(|tree| self.lower_token_tree(tree).into_trees()).collect()
+ }
+
+ fn lower_token_tree(&mut self, tree: TokenTree) -> TokenStream {
+ match tree {
+ TokenTree::Token(token) => self.lower_token(token),
+ TokenTree::Delimited(span, delim, tts) => {
+ TokenTree::Delimited(span, delim, self.lower_token_stream(tts)).into()
+ }
+ }
+ }
+
+ fn lower_token(&mut self, token: Token) -> TokenStream {
+ match token.kind {
+ token::Interpolated(nt) => {
+ let tts = (self.nt_to_tokenstream)(&nt, self.parse_sess, self.synthesize_tokens);
+ TokenTree::Delimited(
+ DelimSpan::from_single(token.span),
+ DelimToken::NoDelim,
+ self.lower_token_stream(tts),
+ )
+ .into()
+ }
+ _ => TokenTree::Token(token).into(),
+ }
+ }
+}
+
struct ImplTraitTypeIdVisitor<'a> {
ids: &'a mut SmallVec<[NodeId; 1]>,
}
@@ -463,13 +501,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
ItemKind::Struct(_, ref generics)
| ItemKind::Union(_, ref generics)
| ItemKind::Enum(_, ref generics)
- | ItemKind::TyAlias(_, ref generics, ..)
- | ItemKind::Trait(_, _, ref generics, ..) => {
+ | ItemKind::TyAlias(box TyAliasKind(_, ref generics, ..))
+ | ItemKind::Trait(box TraitKind(_, _, ref generics, ..)) => {
let def_id = self.lctx.resolver.local_def_id(item.id);
let count = generics
.params
.iter()
- .filter(|param| matches!(param.kind, ast::GenericParamKind::Lifetime { .. }))
+ .filter(|param| {
+ matches!(param.kind, ast::GenericParamKind::Lifetime { .. })
+ })
.count();
self.lctx.type_def_lifetime_params.insert(def_id.to_def_id(), count);
}
@@ -701,10 +741,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
span: Span,
allow_internal_unstable: Option>,
) -> Span {
- span.fresh_expansion(ExpnData {
- allow_internal_unstable,
- ..ExpnData::default(ExpnKind::Desugaring(reason), span, self.sess.edition(), None)
- })
+ span.mark_with_reason(allow_internal_unstable, reason, self.sess.edition())
}
fn with_anonymous_lifetime_mode(
@@ -955,42 +992,77 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
match *args {
MacArgs::Empty => MacArgs::Empty,
MacArgs::Delimited(dspan, delim, ref tokens) => {
- MacArgs::Delimited(dspan, delim, self.lower_token_stream(tokens.clone()))
- }
- MacArgs::Eq(eq_span, ref tokens) => {
- MacArgs::Eq(eq_span, self.lower_token_stream(tokens.clone()))
- }
- }
- }
-
- fn lower_token_stream(&mut self, tokens: TokenStream) -> TokenStream {
- tokens.into_trees().flat_map(|tree| self.lower_token_tree(tree).into_trees()).collect()
- }
-
- fn lower_token_tree(&mut self, tree: TokenTree) -> TokenStream {
- match tree {
- TokenTree::Token(token) => self.lower_token(token),
- TokenTree::Delimited(span, delim, tts) => {
- TokenTree::Delimited(span, delim, self.lower_token_stream(tts)).into()
- }
- }
- }
-
- fn lower_token(&mut self, token: Token) -> TokenStream {
- match token.kind {
- token::Interpolated(nt) => {
- let tts = (self.nt_to_tokenstream)(&nt, &self.sess.parse_sess, token.span);
- TokenTree::Delimited(
- DelimSpan::from_single(token.span),
- DelimToken::NoDelim,
- self.lower_token_stream(tts),
+ // This is either a non-key-value attribute, or a `macro_rules!` body.
+ // We either not have any nonterminals present (in the case of an attribute),
+ // or have tokens available for all nonterminals in the case of a nested
+ // `macro_rules`: e.g:
+ //
+ // ```rust
+ // macro_rules! outer {
+ // ($e:expr) => {
+ // macro_rules! inner {
+ // () => { $e }
+ // }
+ // }
+ // }
+ // ```
+ //
+ // In both cases, we don't want to synthesize any tokens
+ MacArgs::Delimited(
+ dspan,
+ delim,
+ self.lower_token_stream(tokens.clone(), CanSynthesizeMissingTokens::No),
)
- .into()
}
- _ => TokenTree::Token(token).into(),
+ // This is an inert key-value attribute - it will never be visible to macros
+ // after it gets lowered to HIR. Therefore, we can synthesize tokens with fake
+ // spans to handle nonterminals in `#[doc]` (e.g. `#[doc = $e]`).
+ MacArgs::Eq(eq_span, ref token) => {
+ // In valid code the value is always representable as a single literal token.
+ fn unwrap_single_token(sess: &Session, tokens: TokenStream, span: Span) -> Token {
+ if tokens.len() != 1 {
+ sess.diagnostic()
+ .delay_span_bug(span, "multiple tokens in key-value attribute's value");
+ }
+ match tokens.into_trees().next() {
+ Some(TokenTree::Token(token)) => token,
+ Some(TokenTree::Delimited(_, delim, tokens)) => {
+ if delim != token::NoDelim {
+ sess.diagnostic().delay_span_bug(
+ span,
+ "unexpected delimiter in key-value attribute's value",
+ )
+ }
+ unwrap_single_token(sess, tokens, span)
+ }
+ None => Token::dummy(),
+ }
+ }
+
+ let tokens = TokenStreamLowering {
+ parse_sess: &self.sess.parse_sess,
+ synthesize_tokens: CanSynthesizeMissingTokens::Yes,
+ nt_to_tokenstream: self.nt_to_tokenstream,
+ }
+ .lower_token(token.clone());
+ MacArgs::Eq(eq_span, unwrap_single_token(self.sess, tokens, token.span))
+ }
}
}
+ fn lower_token_stream(
+ &self,
+ tokens: TokenStream,
+ synthesize_tokens: CanSynthesizeMissingTokens,
+ ) -> TokenStream {
+ TokenStreamLowering {
+ parse_sess: &self.sess.parse_sess,
+ synthesize_tokens,
+ nt_to_tokenstream: self.nt_to_tokenstream,
+ }
+ .lower_token_stream(tokens)
+ }
+
/// Given an associated type constraint like one of these:
///
/// ```
@@ -1004,16 +1076,40 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
fn lower_assoc_ty_constraint(
&mut self,
constraint: &AssocTyConstraint,
- itctx: ImplTraitContext<'_, 'hir>,
+ mut itctx: ImplTraitContext<'_, 'hir>,
) -> hir::TypeBinding<'hir> {
debug!("lower_assoc_ty_constraint(constraint={:?}, itctx={:?})", constraint, itctx);
- if let Some(ref gen_args) = constraint.gen_args {
- self.sess.span_fatal(
- gen_args.span(),
- "generic associated types in trait paths are currently not implemented",
- );
- }
+ // lower generic arguments of identifier in constraint
+ let gen_args = if let Some(ref gen_args) = constraint.gen_args {
+ let gen_args_ctor = match gen_args {
+ GenericArgs::AngleBracketed(ref data) => {
+ self.lower_angle_bracketed_parameter_data(
+ data,
+ ParamMode::Explicit,
+ itctx.reborrow(),
+ )
+ .0
+ }
+ GenericArgs::Parenthesized(ref data) => {
+ let mut err = self.sess.struct_span_err(
+ gen_args.span(),
+ "parenthesized generic arguments cannot be used in associated type constraints"
+ );
+ // FIXME: try to write a suggestion here
+ err.emit();
+ self.lower_angle_bracketed_parameter_data(
+ &data.as_angle_bracketed_args(),
+ ParamMode::Explicit,
+ itctx.reborrow(),
+ )
+ .0
+ }
+ };
+ self.arena.alloc(gen_args_ctor.into_generic_args(&self.arena))
+ } else {
+ self.arena.alloc(hir::GenericArgs::none())
+ };
let kind = match constraint.kind {
AssocTyConstraintKind::Equality { ref ty } => {
@@ -1110,6 +1206,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
hir::TypeBinding {
hir_id: self.lower_node_id(constraint.id),
ident: constraint.ident,
+ gen_args,
kind,
span: constraint.span,
}
@@ -1220,6 +1317,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
TyKind::BareFn(ref f) => self.with_in_scope_lifetime_defs(&f.generic_params, |this| {
this.with_anonymous_lifetime_mode(AnonymousLifetimeMode::PassThrough, |this| {
+ let span = this.sess.source_map().next_point(t.span.shrink_to_lo());
hir::TyKind::BareFn(this.arena.alloc(hir::BareFnTy {
generic_params: this.lower_generic_params(
&f.generic_params,
@@ -1227,7 +1325,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
ImplTraitContext::disallowed(),
),
unsafety: this.lower_unsafety(f.unsafety),
- abi: this.lower_extern(f.ext),
+ abi: this.lower_extern(f.ext, span, t.id),
decl: this.lower_fn_decl(&f.decl, None, false, None),
param_names: this.lower_fn_params_to_names(&f.decl),
}))
@@ -1716,7 +1814,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
self.arena.alloc_from_iter(inputs.iter().map(|param| match param.pat.kind {
PatKind::Ident(_, ident, _) => ident,
- _ => Ident::new(kw::Invalid, param.pat.span),
+ _ => Ident::new(kw::Empty, param.pat.span),
}))
}
@@ -1806,12 +1904,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
output,
c_variadic,
implicit_self: decl.inputs.get(0).map_or(hir::ImplicitSelfKind::None, |arg| {
- let is_mutable_pat = match arg.pat.kind {
- PatKind::Ident(BindingMode::ByValue(mt) | BindingMode::ByRef(mt), _, _) => {
- mt == Mutability::Mut
- }
- _ => false,
- };
+ use BindingMode::{ByRef, ByValue};
+ let is_mutable_pat = matches!(
+ arg.pat.kind,
+ PatKind::Ident(ByValue(Mutability::Mut) | ByRef(Mutability::Mut), ..)
+ );
match arg.ty.kind {
TyKind::ImplicitSelf if is_mutable_pat => hir::ImplicitSelfKind::Mut,
@@ -2192,13 +2289,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
(hir::ParamName::Plain(param.ident), kind)
}
- GenericParamKind::Const { ref ty, kw_span: _ } => {
+ GenericParamKind::Const { ref ty, kw_span: _, ref default } => {
let ty = self
.with_anonymous_lifetime_mode(AnonymousLifetimeMode::ReportError, |this| {
this.lower_ty(&ty, ImplTraitContext::disallowed())
});
+ let default = default.as_ref().map(|def| self.lower_anon_const(def));
- (hir::ParamName::Plain(param.ident), hir::GenericParamKind::Const { ty })
+ (hir::ParamName::Plain(param.ident), hir::GenericParamKind::Const { ty, default })
}
};
@@ -2709,6 +2807,26 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
)
}
}
+
+ fn maybe_lint_missing_abi(&mut self, span: Span, id: NodeId, default: Abi) {
+ // FIXME(davidtwco): This is a hack to detect macros which produce spans of the
+ // call site which do not have a macro backtrace. See #61963.
+ let is_macro_callsite = self
+ .sess
+ .source_map()
+ .span_to_snippet(span)
+ .map(|snippet| snippet.starts_with("#["))
+ .unwrap_or(true);
+ if !is_macro_callsite {
+ self.resolver.lint_buffer().buffer_lint_with_diagnostic(
+ MISSING_ABI,
+ id,
+ span,
+ "extern declarations without an explicit ABI are deprecated",
+ BuiltinLintDiagnostics::MissingAbi(span, default),
+ )
+ }
+ }
}
fn body_ids(bodies: &BTreeMap>) -> Vec {
diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs
index 6afed355dc..cb4d5ea6ee 100644
--- a/compiler/rustc_ast_lowering/src/path.rs
+++ b/compiler/rustc_ast_lowering/src/path.rs
@@ -273,7 +273,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
if !generic_args.parenthesized && !has_lifetimes {
generic_args.args = self
.elided_path_lifetimes(
- first_generic_span.map(|s| s.shrink_to_lo()).unwrap_or(segment.ident.span),
+ first_generic_span.map_or(segment.ident.span, |s| s.shrink_to_lo()),
expected_lifetimes,
)
.map(GenericArg::Lifetime)
@@ -362,7 +362,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
}
- fn lower_angle_bracketed_parameter_data(
+ pub(crate) fn lower_angle_bracketed_parameter_data(
&mut self,
data: &AngleBracketedArgs,
param_mode: ParamMode,
@@ -401,15 +401,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// compatibility, even in contexts like an impl header where
// we generally don't permit such things (see #51008).
self.with_anonymous_lifetime_mode(AnonymousLifetimeMode::PassThrough, |this| {
- let &ParenthesizedArgs { ref inputs, ref output, span } = data;
+ let ParenthesizedArgs { span, inputs, inputs_span, output } = data;
let inputs = this.arena.alloc_from_iter(
inputs.iter().map(|ty| this.lower_ty_direct(ty, ImplTraitContext::disallowed())),
);
let output_ty = match output {
FnRetTy::Ty(ty) => this.lower_ty(&ty, ImplTraitContext::disallowed()),
- FnRetTy::Default(_) => this.arena.alloc(this.ty_tup(span, &[])),
+ FnRetTy::Default(_) => this.arena.alloc(this.ty_tup(*span, &[])),
};
- let args = smallvec![GenericArg::Type(this.ty_tup(span, inputs))];
+ let args = smallvec![GenericArg::Type(this.ty_tup(*inputs_span, inputs))];
let binding = this.output_ty_binding(output_ty.span, output_ty);
(
GenericArgsCtor { args, bindings: arena_vec![this; binding], parenthesized: true },
@@ -426,6 +426,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
) -> hir::TypeBinding<'hir> {
let ident = Ident::with_dummy_span(hir::FN_OUTPUT_NAME);
let kind = hir::TypeBindingKind::Equality { ty };
- hir::TypeBinding { hir_id: self.next_id(), span, ident, kind }
+ let args = arena_vec![self;];
+ let bindings = arena_vec![self;];
+ let gen_args = self.arena.alloc(hir::GenericArgs { args, bindings, parenthesized: false });
+ hir::TypeBinding { hir_id: self.next_id(), gen_args, span, ident, kind }
}
}
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index bf6d332217..8defd91c68 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -16,7 +16,7 @@ use rustc_data_structures::fx::FxHashMap;
use rustc_errors::{error_code, pluralize, struct_span_err, Applicability};
use rustc_parse::validate_attr;
use rustc_session::lint::builtin::PATTERNS_IN_FNS_WITHOUT_BODY;
-use rustc_session::lint::LintBuffer;
+use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer};
use rustc_session::Session;
use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::Span;
@@ -184,7 +184,7 @@ impl<'a> AstValidator<'a> {
}
fn check_lifetime(&self, ident: Ident) {
- let valid_names = [kw::UnderscoreLifetime, kw::StaticLifetime, kw::Invalid];
+ let valid_names = [kw::UnderscoreLifetime, kw::StaticLifetime, kw::Empty];
if !valid_names.contains(&ident.name) && ident.without_first_quote().is_reserved() {
self.err_handler().span_err(ident.span, "lifetimes cannot use keyword names");
}
@@ -213,14 +213,14 @@ impl<'a> AstValidator<'a> {
err.emit();
}
- fn check_decl_no_pat(decl: &FnDecl, mut report_err: impl FnMut(Span, bool)) {
+ fn check_decl_no_pat(decl: &FnDecl, mut report_err: impl FnMut(Span, Option, bool)) {
for Param { pat, .. } in &decl.inputs {
match pat.kind {
PatKind::Ident(BindingMode::ByValue(Mutability::Not), _, None) | PatKind::Wild => {}
- PatKind::Ident(BindingMode::ByValue(Mutability::Mut), _, None) => {
- report_err(pat.span, true)
+ PatKind::Ident(BindingMode::ByValue(Mutability::Mut), ident, None) => {
+ report_err(pat.span, Some(ident), true)
}
- _ => report_err(pat.span, false),
+ _ => report_err(pat.span, None, false),
}
}
}
@@ -717,35 +717,46 @@ impl<'a> AstValidator<'a> {
/// Checks that generic parameters are in the correct order,
/// which is lifetimes, then types and then consts. (`<'a, T, const N: usize>`)
-fn validate_generic_param_order<'a>(
+fn validate_generic_param_order(
sess: &Session,
handler: &rustc_errors::Handler,
- generics: impl Iterator- , Span, Option)>,
+ generics: &[GenericParam],
span: Span,
) {
let mut max_param: Option = None;
let mut out_of_order = FxHashMap::default();
let mut param_idents = vec![];
- for (kind, bounds, span, ident) in generics {
+ for param in generics {
+ let ident = Some(param.ident.to_string());
+ let (kind, bounds, span) = (¶m.kind, Some(&*param.bounds), param.ident.span);
+ let (ord_kind, ident) = match ¶m.kind {
+ GenericParamKind::Lifetime => (ParamKindOrd::Lifetime, ident),
+ GenericParamKind::Type { default: _ } => (ParamKindOrd::Type, ident),
+ GenericParamKind::Const { ref ty, kw_span: _, default: _ } => {
+ let ty = pprust::ty_to_string(ty);
+ let unordered = sess.features_untracked().const_generics;
+ (ParamKindOrd::Const { unordered }, Some(format!("const {}: {}", param.ident, ty)))
+ }
+ };
if let Some(ident) = ident {
- param_idents.push((kind, bounds, param_idents.len(), ident));
+ param_idents.push((kind, ord_kind, bounds, param_idents.len(), ident));
}
let max_param = &mut max_param;
match max_param {
- Some(max_param) if *max_param > kind => {
- let entry = out_of_order.entry(kind).or_insert((*max_param, vec![]));
+ Some(max_param) if *max_param > ord_kind => {
+ let entry = out_of_order.entry(ord_kind).or_insert((*max_param, vec![]));
entry.1.push(span);
}
- Some(_) | None => *max_param = Some(kind),
+ Some(_) | None => *max_param = Some(ord_kind),
};
}
let mut ordered_params = "<".to_string();
if !out_of_order.is_empty() {
- param_idents.sort_by_key(|&(po, _, i, _)| (po, i));
+ param_idents.sort_by_key(|&(_, po, _, i, _)| (po, i));
let mut first = true;
- for (_, bounds, _, ident) in param_idents {
+ for (kind, _, bounds, _, ident) in param_idents {
if !first {
ordered_params += ", ";
}
@@ -756,6 +767,16 @@ fn validate_generic_param_order<'a>(
ordered_params += &pprust::bounds_to_string(&bounds);
}
}
+ match kind {
+ GenericParamKind::Type { default: Some(default) } => {
+ ordered_params += " = ";
+ ordered_params += &pprust::ty_to_string(default);
+ }
+ GenericParamKind::Type { default: None } => (),
+ GenericParamKind::Lifetime => (),
+ // FIXME(const_generics_defaults)
+ GenericParamKind::Const { ty: _, kw_span: _, default: _ } => (),
+ }
first = false;
}
}
@@ -773,14 +794,12 @@ fn validate_generic_param_order<'a>(
err.span_suggestion(
span,
&format!(
- "reorder the parameters: lifetimes{}",
+ "reorder the parameters: lifetimes, {}",
if sess.features_untracked().const_generics {
- ", then consts and types"
- } else if sess.features_untracked().min_const_generics {
- ", then types, then consts"
+ "then consts and types"
} else {
- ", then types"
- },
+ "then types, then consts"
+ }
),
ordered_params.clone(),
Applicability::MachineApplicable,
@@ -815,7 +834,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
match ty.kind {
TyKind::BareFn(ref bfty) => {
self.check_fn_decl(&bfty.decl, SelfSemantic::No);
- Self::check_decl_no_pat(&bfty.decl, |span, _| {
+ Self::check_decl_no_pat(&bfty.decl, |span, _, _| {
struct_span_err!(
self.session,
span,
@@ -901,7 +920,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
}
match item.kind {
- ItemKind::Impl {
+ ItemKind::Impl(box ImplKind {
unsafety,
polarity,
defaultness: _,
@@ -910,7 +929,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
of_trait: Some(ref t),
ref self_ty,
items: _,
- } => {
+ }) => {
self.with_in_trait_impl(true, |this| {
this.invalid_visibility(&item.vis, None);
if let TyKind::Err = self_ty.kind {
@@ -938,7 +957,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
});
return; // Avoid visiting again.
}
- ItemKind::Impl {
+ ItemKind::Impl(box ImplKind {
unsafety,
polarity,
defaultness,
@@ -947,7 +966,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
of_trait: None,
ref self_ty,
items: _,
- } => {
+ }) => {
let error = |annotation_span, annotation| {
let mut err = self.err_handler().struct_span_err(
self_ty.span,
@@ -979,7 +998,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
.emit();
}
}
- ItemKind::Fn(def, _, _, ref body) => {
+ ItemKind::Fn(box FnKind(def, _, _, ref body)) => {
self.check_defaultness(item.span, def);
if body.is_none() {
@@ -1008,7 +1027,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
}
}
}
- ItemKind::Trait(is_auto, _, ref generics, ref bounds, ref trait_items) => {
+ ItemKind::Trait(box TraitKind(
+ is_auto,
+ _,
+ ref generics,
+ ref bounds,
+ ref trait_items,
+ )) => {
if is_auto == IsAuto::Yes {
// Auto traits cannot have generics, super traits nor contain items.
self.deny_generic_params(generics, item.ident.span);
@@ -1056,7 +1081,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
let msg = "free static item without body";
self.error_item_without_body(item.span, "static", msg, " = ;");
}
- ItemKind::TyAlias(def, _, ref bounds, ref body) => {
+ ItemKind::TyAlias(box TyAliasKind(def, _, ref bounds, ref body)) => {
self.check_defaultness(item.span, def);
if body.is_none() {
let msg = "free type alias without body";
@@ -1072,12 +1097,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
match &fi.kind {
- ForeignItemKind::Fn(def, sig, _, body) => {
+ ForeignItemKind::Fn(box FnKind(def, sig, _, body)) => {
self.check_defaultness(fi.span, *def);
self.check_foreign_fn_bodyless(fi.ident, body.as_deref());
self.check_foreign_fn_headerless(fi.ident, fi.span, sig.header);
}
- ForeignItemKind::TyAlias(def, generics, bounds, body) => {
+ ForeignItemKind::TyAlias(box TyAliasKind(def, generics, bounds, body)) => {
self.check_defaultness(fi.span, *def);
self.check_foreign_kind_bodyless(fi.ident, "type", body.as_ref().map(|b| b.span));
self.check_type_no_bounds(bounds, "`extern` blocks");
@@ -1152,22 +1177,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
validate_generic_param_order(
self.session,
self.err_handler(),
- generics.params.iter().map(|param| {
- let ident = Some(param.ident.to_string());
- let (kind, ident) = match ¶m.kind {
- GenericParamKind::Lifetime => (ParamKindOrd::Lifetime, ident),
- GenericParamKind::Type { default: _ } => (ParamKindOrd::Type, ident),
- GenericParamKind::Const { ref ty, kw_span: _ } => {
- let ty = pprust::ty_to_string(ty);
- let unordered = self.session.features_untracked().const_generics;
- (
- ParamKindOrd::Const { unordered },
- Some(format!("const {}: {}", param.ident, ty)),
- )
- }
- };
- (kind, Some(&*param.bounds), param.ident.span, ident)
- }),
+ &generics.params,
generics.span,
);
@@ -1208,11 +1218,11 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
}
fn visit_pat(&mut self, pat: &'a Pat) {
- match pat.kind {
- PatKind::Lit(ref expr) => {
+ match &pat.kind {
+ PatKind::Lit(expr) => {
self.check_expr_within_pat(expr, false);
}
- PatKind::Range(ref start, ref end, _) => {
+ PatKind::Range(start, end, _) => {
if let Some(expr) = start {
self.check_expr_within_pat(expr, true);
}
@@ -1285,7 +1295,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
// Functions without bodies cannot have patterns.
if let FnKind::Fn(ctxt, _, sig, _, None) = fk {
- Self::check_decl_no_pat(&sig.decl, |span, mut_ident| {
+ Self::check_decl_no_pat(&sig.decl, |span, ident, mut_ident| {
let (code, msg, label) = match ctxt {
FnCtxt::Foreign => (
error_code!(E0130),
@@ -1299,7 +1309,16 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
),
};
if mut_ident && matches!(ctxt, FnCtxt::Assoc(_)) {
- self.lint_buffer.buffer_lint(PATTERNS_IN_FNS_WITHOUT_BODY, id, span, msg);
+ if let Some(ident) = ident {
+ let diag = BuiltinLintDiagnostics::PatternsInFnsWithoutBody(span, ident);
+ self.lint_buffer.buffer_lint_with_diagnostic(
+ PATTERNS_IN_FNS_WITHOUT_BODY,
+ id,
+ span,
+ msg,
+ diag,
+ )
+ }
} else {
self.err_handler()
.struct_span_err(span, msg)
@@ -1323,10 +1342,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
AssocItemKind::Const(_, _, body) => {
self.check_impl_item_provided(item.span, body, "constant", " = ;");
}
- AssocItemKind::Fn(_, _, _, body) => {
+ AssocItemKind::Fn(box FnKind(_, _, _, body)) => {
self.check_impl_item_provided(item.span, body, "function", " { }");
}
- AssocItemKind::TyAlias(_, _, bounds, body) => {
+ AssocItemKind::TyAlias(box TyAliasKind(_, _, bounds, body)) => {
self.check_impl_item_provided(item.span, body, "type", " = ;");
self.check_type_no_bounds(bounds, "`impl`s");
}
@@ -1336,7 +1355,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
if ctxt == AssocCtxt::Trait || self.in_trait_impl {
self.invalid_visibility(&item.vis, None);
- if let AssocItemKind::Fn(_, sig, _, _) = &item.kind {
+ if let AssocItemKind::Fn(box FnKind(_, sig, _, _)) = &item.kind {
self.check_trait_fn_not_const(sig.header.constness);
self.check_trait_fn_not_async(item.span, sig.header.asyncness);
}
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index bb22267523..6514de2b81 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -1,7 +1,7 @@
use rustc_ast as ast;
use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
use rustc_ast::{AssocTyConstraint, AssocTyConstraintKind, NodeId};
-use rustc_ast::{GenericParam, GenericParamKind, PatKind, RangeEnd, VariantData};
+use rustc_ast::{PatKind, RangeEnd, VariantData};
use rustc_errors::struct_span_err;
use rustc_feature::{AttributeGate, BUILTIN_ATTRIBUTE_MAP};
use rustc_feature::{Features, GateIssue};
@@ -14,6 +14,17 @@ use rustc_span::Span;
use tracing::debug;
macro_rules! gate_feature_fn {
+ ($visitor: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr, $help: expr) => {{
+ let (visitor, has_feature, span, name, explain, help) =
+ (&*$visitor, $has_feature, $span, $name, $explain, $help);
+ let has_feature: bool = has_feature(visitor.features);
+ debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature);
+ if !has_feature && !span.allows_unstable($name) {
+ feature_err_issue(&visitor.sess.parse_sess, name, span, GateIssue::Language, explain)
+ .help(help)
+ .emit();
+ }
+ }};
($visitor: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr) => {{
let (visitor, has_feature, span, name, explain) =
(&*$visitor, $has_feature, $span, $name, $explain);
@@ -27,6 +38,9 @@ macro_rules! gate_feature_fn {
}
macro_rules! gate_feature_post {
+ ($visitor: expr, $feature: ident, $span: expr, $explain: expr, $help: expr) => {
+ gate_feature_fn!($visitor, |x: &Features| x.$feature, $span, sym::$feature, $explain, $help)
+ };
($visitor: expr, $feature: ident, $span: expr, $explain: expr) => {
gate_feature_fn!($visitor, |x: &Features| x.$feature, $span, sym::$feature, $explain)
};
@@ -142,6 +156,14 @@ impl<'a> PostExpansionVisitor<'a> {
"efiapi ABI is experimental and subject to change"
);
}
+ "C-cmse-nonsecure-call" => {
+ gate_feature_post!(
+ &self,
+ abi_c_cmse_nonsecure_call,
+ span,
+ "C-cmse-nonsecure-call ABI is experimental and subject to change"
+ );
+ }
abi => self
.sess
.parse_sess
@@ -351,12 +373,14 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
}
}
- ast::ItemKind::Impl { polarity, defaultness, ref of_trait, .. } => {
+ ast::ItemKind::Impl(box ast::ImplKind {
+ polarity, defaultness, ref of_trait, ..
+ }) => {
if let ast::ImplPolarity::Negative(span) = polarity {
gate_feature_post!(
&self,
negative_impls,
- span.to(of_trait.as_ref().map(|t| t.path.span).unwrap_or(span)),
+ span.to(of_trait.as_ref().map_or(span, |t| t.path.span)),
"negative trait bounds are not yet fully implemented; \
use marker types for now"
);
@@ -367,7 +391,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
}
}
- ast::ItemKind::Trait(ast::IsAuto::Yes, ..) => {
+ ast::ItemKind::Trait(box ast::TraitKind(ast::IsAuto::Yes, ..)) => {
gate_feature_post!(
&self,
auto_traits,
@@ -385,7 +409,9 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
gate_feature_post!(&self, decl_macro, i.span, msg);
}
- ast::ItemKind::TyAlias(_, _, _, Some(ref ty)) => self.check_impl_trait(&ty),
+ ast::ItemKind::TyAlias(box ast::TyAliasKind(_, _, _, Some(ref ty))) => {
+ self.check_impl_trait(&ty)
+ }
_ => {}
}
@@ -397,10 +423,8 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
match i.kind {
ast::ForeignItemKind::Fn(..) | ast::ForeignItemKind::Static(..) => {
let link_name = self.sess.first_attr_value_str_by_name(&i.attrs, sym::link_name);
- let links_to_llvm = match link_name {
- Some(val) => val.as_str().starts_with("llvm."),
- _ => false,
- };
+ let links_to_llvm =
+ link_name.map_or(false, |val| val.as_str().starts_with("llvm."));
if links_to_llvm {
gate_feature_post!(
&self,
@@ -529,19 +553,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
visit::walk_fn(self, fn_kind, span)
}
- fn visit_generic_param(&mut self, param: &'a GenericParam) {
- if let GenericParamKind::Const { .. } = param.kind {
- gate_feature_fn!(
- &self,
- |x: &Features| x.const_generics || x.min_const_generics,
- param.ident.span,
- sym::min_const_generics,
- "const generics are unstable"
- );
- }
- visit::walk_generic_param(self, param)
- }
-
fn visit_assoc_ty_constraint(&mut self, constraint: &'a AssocTyConstraint) {
if let AssocTyConstraintKind::Bound { .. } = constraint.kind {
gate_feature_post!(
@@ -556,13 +567,13 @@ 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(_, ref sig, _, _) => {
+ ast::AssocItemKind::Fn(box ast::FnKind(_, ref sig, _, _)) => {
if let (ast::Const::Yes(_), AssocCtxt::Trait) = (sig.header.constness, ctxt) {
gate_feature_post!(&self, const_fn, i.span, "const fn is unstable");
}
true
}
- ast::AssocItemKind::TyAlias(_, ref generics, _, ref ty) => {
+ ast::AssocItemKind::TyAlias(box ast::TyAliasKind(_, ref generics, _, ref ty)) => {
if let (Some(_), AssocCtxt::Trait) = (ty, ctxt) {
gate_feature_post!(
&self,
@@ -612,6 +623,13 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
let spans = sess.parse_sess.gated_spans.spans.borrow();
macro_rules! gate_all {
+ ($gate:ident, $msg:literal, $help:literal) => {
+ if let Some(spans) = spans.get(&sym::$gate) {
+ for span in spans {
+ gate_feature_post!(&visitor, $gate, *span, $msg, $help);
+ }
+ }
+ };
($gate:ident, $msg:literal) => {
if let Some(spans) = spans.get(&sym::$gate) {
for span in spans {
@@ -622,7 +640,11 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
}
gate_all!(if_let_guard, "`if let` guards are experimental");
gate_all!(let_chains, "`let` expressions in this position are experimental");
- gate_all!(async_closure, "async closures are unstable");
+ gate_all!(
+ async_closure,
+ "async closures are unstable",
+ "to use an async block, remove the `||`: `async {`"
+ );
gate_all!(generators, "yield syntax is experimental");
gate_all!(or_patterns, "or-patterns syntax is experimental");
gate_all!(raw_ref_op, "raw address of syntax is experimental");
@@ -634,6 +656,10 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
extended_key_value_attributes,
"arbitrary expressions in key-value attributes are unstable"
);
+ gate_all!(
+ const_generics_defaults,
+ "default values for const generic parameters are experimental"
+ );
if sess.parse_sess.span_diagnostic.err_count() == 0 {
// Errors for `destructuring_assignment` can get quite noisy, especially where `_` is
// involved, so we only emit errors where there are no other parsing errors.
diff --git a/compiler/rustc_ast_passes/src/lib.rs b/compiler/rustc_ast_passes/src/lib.rs
index 7487421e70..c9e2d202da 100644
--- a/compiler/rustc_ast_passes/src/lib.rs
+++ b/compiler/rustc_ast_passes/src/lib.rs
@@ -6,6 +6,8 @@
#![feature(bindings_after_at)]
#![feature(iter_is_partitioned)]
+#![feature(box_syntax)]
+#![feature(box_patterns)]
#![recursion_limit = "256"]
pub mod ast_validation;
diff --git a/compiler/rustc_ast_passes/src/node_count.rs b/compiler/rustc_ast_passes/src/node_count.rs
index 6efc78c884..2971fa435c 100644
--- a/compiler/rustc_ast_passes/src/node_count.rs
+++ b/compiler/rustc_ast_passes/src/node_count.rs
@@ -68,7 +68,7 @@ impl<'ast> Visitor<'ast> for NodeCounter {
self.count += 1;
walk_generics(self, g)
}
- fn visit_fn(&mut self, fk: FnKind<'_>, s: Span, _: NodeId) {
+ fn visit_fn(&mut self, fk: visit::FnKind<'_>, s: Span, _: NodeId) {
self.count += 1;
walk_fn(self, fk, s)
}
diff --git a/compiler/rustc_ast_pretty/Cargo.toml b/compiler/rustc_ast_pretty/Cargo.toml
index f447bc7f4e..6ea942a2f3 100644
--- a/compiler/rustc_ast_pretty/Cargo.toml
+++ b/compiler/rustc_ast_pretty/Cargo.toml
@@ -11,4 +11,3 @@ doctest = false
tracing = "0.1"
rustc_span = { path = "../rustc_span" }
rustc_ast = { path = "../rustc_ast" }
-rustc_target = { path = "../rustc_target" }
diff --git a/compiler/rustc_ast_pretty/src/lib.rs b/compiler/rustc_ast_pretty/src/lib.rs
index 9adc6c604e..d869baad01 100644
--- a/compiler/rustc_ast_pretty/src/lib.rs
+++ b/compiler/rustc_ast_pretty/src/lib.rs
@@ -1,6 +1,7 @@
#![feature(bool_to_option)]
#![feature(crate_visibility_modifier)]
#![feature(or_patterns)]
+#![feature(box_patterns)]
#![recursion_limit = "256"]
mod helpers;
diff --git a/compiler/rustc_ast_pretty/src/pp.rs b/compiler/rustc_ast_pretty/src/pp.rs
index 56e769ba6b..ea298d28e7 100644
--- a/compiler/rustc_ast_pretty/src/pp.rs
+++ b/compiler/rustc_ast_pretty/src/pp.rs
@@ -75,7 +75,7 @@
//! breaking inconsistently to become
//!
//! ```
-//! foo(hello, there
+//! foo(hello, there,
//! good, friends);
//! ```
//!
@@ -83,7 +83,7 @@
//!
//! ```
//! foo(hello,
-//! there
+//! there,
//! good,
//! friends);
//! ```
diff --git a/compiler/rustc_ast_pretty/src/pprust/mod.rs b/compiler/rustc_ast_pretty/src/pprust/mod.rs
index b34ea41ab5..b88699f6ee 100644
--- a/compiler/rustc_ast_pretty/src/pprust/mod.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/mod.rs
@@ -8,11 +8,6 @@ use rustc_ast as ast;
use rustc_ast::token::{Nonterminal, Token, TokenKind};
use rustc_ast::tokenstream::{TokenStream, TokenTree};
-pub fn nonterminal_to_string_no_extra_parens(nt: &Nonterminal) -> String {
- let state = State::without_insert_extra_parens();
- state.nonterminal_to_string(nt)
-}
-
pub fn nonterminal_to_string(nt: &Nonterminal) -> String {
State::new().nonterminal_to_string(nt)
}
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index dcb6e115ed..7f4775bf41 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -88,13 +88,6 @@ pub struct State<'a> {
comments: Option>,
ann: &'a (dyn PpAnn + 'a),
is_expanded: bool,
- // If `true`, additional parenthesis (separate from `ExprKind::Paren`)
- // are inserted to ensure that proper precedence is preserved
- // in the pretty-printed output.
- //
- // This is usually `true`, except when performing the pretty-print/reparse
- // check in `nt_to_tokenstream`
- insert_extra_parens: bool,
}
crate const INDENT_UNIT: usize = 4;
@@ -115,7 +108,6 @@ pub fn print_crate<'a>(
comments: Some(Comments::new(sm, filename, input)),
ann,
is_expanded,
- insert_extra_parens: true,
};
if is_expanded && !krate.attrs.iter().any(|attr| attr.has_name(sym::no_core)) {
@@ -235,7 +227,6 @@ impl std::ops::DerefMut for State<'_> {
}
pub trait PrintState<'a>: std::ops::Deref + std::ops::DerefMut {
- fn insert_extra_parens(&self) -> bool;
fn comments(&mut self) -> &mut Option>;
fn print_ident(&mut self, ident: Ident);
fn print_generic_args(&mut self, args: &ast::GenericArgs, colons_before_params: bool);
@@ -454,10 +445,11 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere
),
MacArgs::Empty | MacArgs::Eq(..) => {
self.print_path(&item.path, false, 0);
- if let MacArgs::Eq(_, tokens) = &item.args {
+ if let MacArgs::Eq(_, token) = &item.args {
self.space();
self.word_space("=");
- self.print_tts(tokens, true);
+ let token_str = self.token_to_string_ext(token, true);
+ self.word(token_str);
}
}
}
@@ -819,16 +811,12 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere
fn to_string(&self, f: impl FnOnce(&mut State<'_>)) -> String {
let mut printer = State::new();
- printer.insert_extra_parens = self.insert_extra_parens();
f(&mut printer);
printer.s.eof()
}
}
impl<'a> PrintState<'a> for State<'a> {
- fn insert_extra_parens(&self) -> bool {
- self.insert_extra_parens
- }
fn comments(&mut self) -> &mut Option> {
&mut self.comments
}
@@ -865,17 +853,7 @@ impl<'a> PrintState<'a> for State<'a> {
impl<'a> State<'a> {
pub fn new() -> State<'a> {
- State {
- s: pp::mk_printer(),
- comments: None,
- ann: &NoAnn,
- is_expanded: false,
- insert_extra_parens: true,
- }
- }
-
- pub(super) fn without_insert_extra_parens() -> State<'a> {
- State { insert_extra_parens: false, ..State::new() }
+ State { s: pp::mk_printer(), comments: None, ann: &NoAnn, is_expanded: false }
}
// Synthesizes a comment that was not textually present in the original source
@@ -1044,14 +1022,14 @@ impl<'a> State<'a> {
self.maybe_print_comment(span.lo());
self.print_outer_attributes(attrs);
match kind {
- ast::ForeignItemKind::Fn(def, sig, gen, body) => {
+ ast::ForeignItemKind::Fn(box ast::FnKind(def, sig, gen, body)) => {
self.print_fn_full(sig, ident, gen, vis, *def, body.as_deref(), attrs);
}
ast::ForeignItemKind::Static(ty, mutbl, body) => {
let def = ast::Defaultness::Final;
self.print_item_const(ident, Some(*mutbl), ty, body.as_deref(), vis, def);
}
- ast::ForeignItemKind::TyAlias(def, generics, bounds, ty) => {
+ ast::ForeignItemKind::TyAlias(box ast::TyAliasKind(def, generics, bounds, ty)) => {
self.print_associated_type(ident, generics, bounds, ty.as_deref(), vis, *def);
}
ast::ForeignItemKind::MacCall(m) => {
@@ -1156,7 +1134,7 @@ impl<'a> State<'a> {
ast::ItemKind::Const(def, ref ty, ref body) => {
self.print_item_const(item.ident, None, ty, body.as_deref(), &item.vis, def);
}
- ast::ItemKind::Fn(def, ref sig, ref gen, ref body) => {
+ ast::ItemKind::Fn(box ast::FnKind(def, ref sig, ref gen, ref body)) => {
let body = body.as_deref();
self.print_fn_full(sig, item.ident, gen, &item.vis, def, body, &item.attrs);
}
@@ -1197,7 +1175,7 @@ impl<'a> State<'a> {
self.s.word(ga.asm.to_string());
self.end();
}
- ast::ItemKind::TyAlias(def, ref generics, ref bounds, ref ty) => {
+ ast::ItemKind::TyAlias(box ast::TyAliasKind(def, ref generics, ref bounds, ref ty)) => {
let ty = ty.as_deref();
self.print_associated_type(item.ident, generics, bounds, ty, &item.vis, def);
}
@@ -1212,7 +1190,7 @@ impl<'a> State<'a> {
self.head(visibility_qualified(&item.vis, "union"));
self.print_struct(struct_def, generics, item.ident, item.span, true);
}
- ast::ItemKind::Impl {
+ ast::ItemKind::Impl(box ast::ImplKind {
unsafety,
polarity,
defaultness,
@@ -1221,7 +1199,7 @@ impl<'a> State<'a> {
ref of_trait,
ref self_ty,
ref items,
- } => {
+ }) => {
self.head("");
self.print_visibility(&item.vis);
self.print_defaultness(defaultness);
@@ -1255,7 +1233,13 @@ impl<'a> State<'a> {
}
self.bclose(item.span);
}
- ast::ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, ref trait_items) => {
+ ast::ItemKind::Trait(box ast::TraitKind(
+ is_auto,
+ unsafety,
+ ref generics,
+ ref bounds,
+ ref trait_items,
+ )) => {
self.head("");
self.print_visibility(&item.vis);
self.print_unsafety(unsafety);
@@ -1475,13 +1459,13 @@ impl<'a> State<'a> {
self.maybe_print_comment(span.lo());
self.print_outer_attributes(attrs);
match kind {
- ast::AssocItemKind::Fn(def, sig, gen, body) => {
+ ast::AssocItemKind::Fn(box ast::FnKind(def, sig, gen, body)) => {
self.print_fn_full(sig, ident, gen, vis, *def, body.as_deref(), attrs);
}
ast::AssocItemKind::Const(def, ty, body) => {
self.print_item_const(ident, None, ty, body.as_deref(), vis, *def);
}
- ast::AssocItemKind::TyAlias(def, generics, bounds, ty) => {
+ ast::AssocItemKind::TyAlias(box ast::TyAliasKind(def, generics, bounds, ty)) => {
self.print_associated_type(ident, generics, bounds, ty.as_deref(), vis, *def);
}
ast::AssocItemKind::MacCall(m) => {
@@ -1680,8 +1664,7 @@ impl<'a> State<'a> {
}
/// Prints `expr` or `(expr)` when `needs_par` holds.
- fn print_expr_cond_paren(&mut self, expr: &ast::Expr, mut needs_par: bool) {
- needs_par &= self.insert_extra_parens;
+ fn print_expr_cond_paren(&mut self, expr: &ast::Expr, needs_par: bool) {
if needs_par {
self.popen();
}
@@ -2668,13 +2651,16 @@ impl<'a> State<'a> {
s.print_type(default)
}
}
- ast::GenericParamKind::Const { ref ty, kw_span: _ } => {
+ ast::GenericParamKind::Const { ref ty, kw_span: _, ref default } => {
s.word_space("const");
s.print_ident(param.ident);
s.s.space();
s.word_space(":");
s.print_type(ty);
- s.print_type_bounds(":", ¶m.bounds)
+ s.print_type_bounds(":", ¶m.bounds);
+ if let Some(ref _default) = default {
+ // FIXME(const_generics_defaults): print the `default` value here
+ }
}
}
});
@@ -2787,7 +2773,7 @@ impl<'a> State<'a> {
self.print_explicit_self(&eself);
} else {
let invalid = if let PatKind::Ident(_, ident, _) = input.pat.kind {
- ident.name == kw::Invalid
+ ident.name == kw::Empty
} else {
false
};
diff --git a/compiler/rustc_attr/Cargo.toml b/compiler/rustc_attr/Cargo.toml
index 5f941a0a65..dc0711a5b0 100644
--- a/compiler/rustc_attr/Cargo.toml
+++ b/compiler/rustc_attr/Cargo.toml
@@ -18,4 +18,3 @@ rustc_lexer = { path = "../rustc_lexer" }
rustc_macros = { path = "../rustc_macros" }
rustc_session = { path = "../rustc_session" }
rustc_ast = { path = "../rustc_ast" }
-version_check = "0.9"
diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs
index ead90f23ce..aca3fbbca1 100644
--- a/compiler/rustc_attr/src/builtin.rs
+++ b/compiler/rustc_attr/src/builtin.rs
@@ -10,7 +10,6 @@ use rustc_session::Session;
use rustc_span::hygiene::Transparency;
use rustc_span::{symbol::sym, symbol::Symbol, Span};
use std::num::NonZeroU32;
-use version_check::Version;
pub fn is_builtin_attr(attr: &Attribute) -> bool {
attr.is_doc_comment() || attr.ident().filter(|ident| is_builtin_attr_name(ident.name)).is_some()
@@ -67,7 +66,7 @@ fn handle_errors(sess: &ParseSess, span: Span, error: AttrError) {
}
}
-#[derive(Copy, Clone, PartialEq, Encodable, Decodable)]
+#[derive(Copy, Clone, PartialEq, Encodable, Decodable, Debug)]
pub enum InlineAttr {
None,
Hint,
@@ -75,13 +74,13 @@ pub enum InlineAttr {
Never,
}
-#[derive(Clone, Encodable, Decodable)]
+#[derive(Clone, Encodable, Decodable, Debug, PartialEq, Eq)]
pub enum InstructionSetAttr {
ArmA32,
ArmT32,
}
-#[derive(Clone, Encodable, Decodable)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub enum OptimizeAttr {
None,
Speed,
@@ -526,6 +525,26 @@ fn gate_cfg(gated_cfg: &GatedCfg, cfg_span: Span, sess: &ParseSess, features: &F
}
}
+#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
+struct Version {
+ major: u16,
+ minor: u16,
+ patch: u16,
+}
+
+fn parse_version(s: &str, allow_appendix: bool) -> Option {
+ let mut components = s.split('-');
+ let d = components.next()?;
+ if !allow_appendix && components.next().is_some() {
+ return None;
+ }
+ let mut digits = d.splitn(3, '.');
+ let major = digits.next()?.parse().ok()?;
+ let minor = digits.next()?.parse().ok()?;
+ let patch = digits.next().unwrap_or("0").parse().ok()?;
+ Some(Version { major, minor, patch })
+}
+
/// Evaluate a cfg-like condition (with `any` and `all`), using `eval` to
/// evaluate individual items.
pub fn eval_condition(
@@ -555,19 +574,26 @@ pub fn eval_condition(
return false;
}
};
- let min_version = match Version::parse(&min_version.as_str()) {
+ let min_version = match parse_version(&min_version.as_str(), false) {
Some(ver) => ver,
None => {
- sess.span_diagnostic.struct_span_err(*span, "invalid version literal").emit();
+ sess.span_diagnostic
+ .struct_span_warn(
+ *span,
+ "unknown version literal format, assuming it refers to a future version",
+ )
+ .emit();
return false;
}
};
- let channel = env!("CFG_RELEASE_CHANNEL");
- let nightly = channel == "nightly" || channel == "dev";
- let rustc_version = Version::parse(env!("CFG_RELEASE")).unwrap();
+ let rustc_version = parse_version(env!("CFG_RELEASE"), true).unwrap();
- // See https://github.com/rust-lang/rust/issues/64796#issuecomment-625474439 for details
- if nightly { rustc_version > min_version } else { rustc_version >= min_version }
+ // See https://github.com/rust-lang/rust/issues/64796#issuecomment-640851454 for details
+ if sess.assume_incomplete_release {
+ rustc_version > min_version
+ } else {
+ rustc_version >= min_version
+ }
}
ast::MetaItemKind::List(ref mis) => {
for mi in mis.iter() {
diff --git a/compiler/rustc_builtin_macros/src/assert.rs b/compiler/rustc_builtin_macros/src/assert.rs
index bb6d3f6a00..93ba54da34 100644
--- a/compiler/rustc_builtin_macros/src/assert.rs
+++ b/compiler/rustc_builtin_macros/src/assert.rs
@@ -12,27 +12,43 @@ use rustc_span::{Span, DUMMY_SP};
pub fn expand_assert<'cx>(
cx: &'cx mut ExtCtxt<'_>,
- sp: Span,
+ span: Span,
tts: TokenStream,
) -> Box {
- let Assert { cond_expr, custom_message } = match parse_assert(cx, sp, tts) {
+ let Assert { cond_expr, custom_message } = match parse_assert(cx, span, tts) {
Ok(assert) => assert,
Err(mut err) => {
err.emit();
- return DummyResult::any(sp);
+ return DummyResult::any(span);
}
};
// `core::panic` and `std::panic` are different macros, so we use call-site
// context to pick up whichever is currently in scope.
- let sp = cx.with_call_site_ctxt(sp);
+ let sp = cx.with_call_site_ctxt(span);
let panic_call = if let Some(tokens) = custom_message {
+ let path = if span.rust_2021() {
+ // On edition 2021, we always call `$crate::panic::panic_2021!()`.
+ Path {
+ span: sp,
+ segments: cx
+ .std_path(&[sym::panic, sym::panic_2021])
+ .into_iter()
+ .map(|ident| PathSegment::from_ident(ident))
+ .collect(),
+ tokens: None,
+ }
+ } else {
+ // Before edition 2021, we call `panic!()` unqualified,
+ // such that it calls either `std::panic!()` or `core::panic!()`.
+ Path::from_ident(Ident::new(sym::panic, sp))
+ };
// Pass the custom message to panic!().
cx.expr(
sp,
ExprKind::MacCall(MacCall {
- path: Path::from_ident(Ident::new(sym::panic, sp)),
+ path,
args: P(MacArgs::Delimited(
DelimSpan::from_single(sp),
MacDelimiter::Parenthesis,
diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs
index 957c803539..ca1226b445 100644
--- a/compiler/rustc_builtin_macros/src/deriving/clone.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs
@@ -38,10 +38,9 @@ pub fn expand_deriving_clone(
| ItemKind::Enum(_, Generics { ref params, .. }) => {
let container_id = cx.current_expansion.id.expn_data().parent;
if cx.resolver.has_derive_copy(container_id)
- && !params.iter().any(|param| match param.kind {
- ast::GenericParamKind::Type { .. } => true,
- _ => false,
- })
+ && !params
+ .iter()
+ .any(|param| matches!(param.kind, ast::GenericParamKind::Type { .. }))
{
bounds = vec![];
is_shallow = true;
diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs
index 5c21329069..ba43be6ae9 100644
--- a/compiler/rustc_builtin_macros/src/deriving/debug.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/debug.rs
@@ -8,6 +8,10 @@ use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_span::symbol::{sym, Ident};
use rustc_span::{Span, DUMMY_SP};
+fn make_mut_borrow(cx: &mut ExtCtxt<'_>, sp: Span, expr: P) -> P {
+ cx.expr(sp, ast::ExprKind::AddrOf(ast::BorrowKind::Ref, ast::Mutability::Mut, expr))
+}
+
pub fn expand_deriving_debug(
cx: &mut ExtCtxt<'_>,
span: Span,
@@ -67,11 +71,12 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
let fmt = substr.nonself_args[0].clone();
let mut stmts = Vec::with_capacity(fields.len() + 2);
+ let fn_path_finish;
match vdata {
ast::VariantData::Tuple(..) | ast::VariantData::Unit(..) => {
// tuple struct/"normal" variant
- let expr =
- cx.expr_method_call(span, fmt, Ident::new(sym::debug_tuple, span), vec![name]);
+ let fn_path_debug_tuple = cx.std_path(&[sym::fmt, sym::Formatter, sym::debug_tuple]);
+ let expr = cx.expr_call_global(span, fn_path_debug_tuple, vec![fmt, name]);
stmts.push(cx.stmt_let(span, true, builder, expr));
for field in fields {
@@ -79,22 +84,21 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
let field = cx.expr_addr_of(field.span, field.self_.clone());
let field = cx.expr_addr_of(field.span, field);
- let expr = cx.expr_method_call(
- span,
- builder_expr.clone(),
- Ident::new(sym::field, span),
- vec![field],
- );
+ let fn_path_field = cx.std_path(&[sym::fmt, sym::DebugTuple, sym::field]);
+ let builder_recv = make_mut_borrow(cx, span, builder_expr.clone());
+ let expr = cx.expr_call_global(span, fn_path_field, vec![builder_recv, field]);
// Use `let _ = expr;` to avoid triggering the
// unused_results lint.
stmts.push(stmt_let_underscore(cx, span, expr));
}
+
+ fn_path_finish = cx.std_path(&[sym::fmt, sym::DebugTuple, sym::finish]);
}
ast::VariantData::Struct(..) => {
// normal struct/struct variant
- let expr =
- cx.expr_method_call(span, fmt, Ident::new(sym::debug_struct, span), vec![name]);
+ let fn_path_debug_struct = cx.std_path(&[sym::fmt, sym::Formatter, sym::debug_struct]);
+ let expr = cx.expr_call_global(span, fn_path_debug_struct, vec![fmt, name]);
stmts.push(cx.stmt_let(DUMMY_SP, true, builder, expr));
for field in fields {
@@ -104,20 +108,20 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
);
// Use double indirection to make sure this works for unsized types
+ let fn_path_field = cx.std_path(&[sym::fmt, sym::DebugStruct, sym::field]);
let field = cx.expr_addr_of(field.span, field.self_.clone());
let field = cx.expr_addr_of(field.span, field);
- let expr = cx.expr_method_call(
- span,
- builder_expr.clone(),
- Ident::new(sym::field, span),
- vec![name, field],
- );
+ let builder_recv = make_mut_borrow(cx, span, builder_expr.clone());
+ let expr =
+ cx.expr_call_global(span, fn_path_field, vec![builder_recv, name, field]);
stmts.push(stmt_let_underscore(cx, span, expr));
}
+ fn_path_finish = cx.std_path(&[sym::fmt, sym::DebugStruct, sym::finish]);
}
}
- let expr = cx.expr_method_call(span, builder_expr, Ident::new(sym::finish, span), vec![]);
+ let builder_recv = make_mut_borrow(cx, span, builder_expr);
+ let expr = cx.expr_call_global(span, fn_path_finish, vec![builder_recv]);
stmts.push(cx.stmt_expr(expr));
let block = cx.block(span, stmts);
diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
index 6531e68be9..d498c8e172 100644
--- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
@@ -404,12 +404,10 @@ impl<'a> TraitDef<'a> {
let has_no_type_params = match item.kind {
ast::ItemKind::Struct(_, ref generics)
| ast::ItemKind::Enum(_, ref generics)
- | ast::ItemKind::Union(_, ref generics) => {
- !generics.params.iter().any(|param| match param.kind {
- ast::GenericParamKind::Type { .. } => true,
- _ => false,
- })
- }
+ | ast::ItemKind::Union(_, ref generics) => !generics
+ .params
+ .iter()
+ .any(|param| matches!(param.kind, ast::GenericParamKind::Type { .. })),
_ => unreachable!(),
};
let container_id = cx.current_expansion.id.expn_data().parent;
@@ -529,12 +527,12 @@ impl<'a> TraitDef<'a> {
tokens: None,
},
attrs: Vec::new(),
- kind: ast::AssocItemKind::TyAlias(
+ kind: ast::AssocItemKind::TyAlias(box ast::TyAliasKind(
ast::Defaultness::Final,
Generics::default(),
Vec::new(),
Some(type_def.to_ty(cx, self.span, type_ident, generics)),
- ),
+ )),
tokens: None,
})
});
@@ -600,7 +598,7 @@ impl<'a> TraitDef<'a> {
let mut ty_params = params
.iter()
- .filter(|param| matches!(param.kind, ast::GenericParamKind::Type{..}))
+ .filter(|param| matches!(param.kind, ast::GenericParamKind::Type { .. }))
.peekable();
if ty_params.peek().is_some() {
@@ -689,7 +687,7 @@ impl<'a> TraitDef<'a> {
self.span,
Ident::invalid(),
a,
- ast::ItemKind::Impl {
+ ast::ItemKind::Impl(box ast::ImplKind {
unsafety,
polarity: ast::ImplPolarity::Positive,
defaultness: ast::Defaultness::Final,
@@ -698,7 +696,7 @@ impl<'a> TraitDef<'a> {
of_trait: opt_trait_ref,
self_ty: self_type,
items: methods.into_iter().chain(associated_types).collect(),
- },
+ }),
)
}
@@ -868,7 +866,7 @@ impl<'a> MethodDef<'a> {
Self_ if nonstatic => {
self_args.push(arg_expr);
}
- Ptr(ref ty, _) if (if let Self_ = **ty { true } else { false }) && nonstatic => {
+ Ptr(ref ty, _) if matches!(**ty, Self_) && nonstatic => {
self_args.push(cx.expr_deref(trait_.span, arg_expr))
}
_ => {
@@ -931,7 +929,7 @@ impl<'a> MethodDef<'a> {
tokens: None,
},
ident: method_ident,
- kind: ast::AssocItemKind::Fn(def, sig, fn_generics, Some(body_block)),
+ kind: ast::AssocItemKind::Fn(box ast::FnKind(def, sig, fn_generics, Some(body_block))),
tokens: None,
})
}
diff --git a/compiler/rustc_builtin_macros/src/deriving/hash.rs b/compiler/rustc_builtin_macros/src/deriving/hash.rs
index 868f863b99..7114b98768 100644
--- a/compiler/rustc_builtin_macros/src/deriving/hash.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/hash.rs
@@ -48,8 +48,8 @@ pub fn expand_deriving_hash(
}
fn hash_substructure(cx: &mut ExtCtxt<'_>, trait_span: Span, substr: &Substructure<'_>) -> P {
- let state_expr = match &substr.nonself_args {
- &[o_f] => o_f,
+ let state_expr = match substr.nonself_args {
+ [o_f] => o_f,
_ => cx.span_bug(trait_span, "incorrect number of arguments in `derive(Hash)`"),
};
let call_hash = |span, thing_expr| {
@@ -64,9 +64,9 @@ fn hash_substructure(cx: &mut ExtCtxt<'_>, trait_span: Span, substr: &Substructu
};
let mut stmts = Vec::new();
- let fields = match *substr.fields {
- Struct(_, ref fs) | EnumMatching(_, 1, .., ref fs) => fs,
- EnumMatching(.., ref fs) => {
+ let fields = match substr.fields {
+ Struct(_, fs) | EnumMatching(_, 1, .., fs) => fs,
+ EnumMatching(.., fs) => {
let variant_value = deriving::call_intrinsic(
cx,
trait_span,
diff --git a/compiler/rustc_builtin_macros/src/deriving/mod.rs b/compiler/rustc_builtin_macros/src/deriving/mod.rs
index 1651180817..7dea6099f8 100644
--- a/compiler/rustc_builtin_macros/src/deriving/mod.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/mod.rs
@@ -2,7 +2,7 @@
use rustc_ast as ast;
use rustc_ast::ptr::P;
-use rustc_ast::{ItemKind, MetaItem};
+use rustc_ast::{ImplKind, ItemKind, MetaItem};
use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, MultiItemModifier};
use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_span::Span;
@@ -145,7 +145,8 @@ fn inject_impl_of_structural_trait(
*default = None;
ast::GenericArg::Type(cx.ty_ident(span, param.ident))
}
- ast::GenericParamKind::Const { ty: _, kw_span: _ } => {
+ ast::GenericParamKind::Const { ty: _, kw_span: _, default } => {
+ *default = None;
ast::GenericArg::Const(cx.const_ident(span, param.ident))
}
})
@@ -178,7 +179,7 @@ fn inject_impl_of_structural_trait(
span,
Ident::invalid(),
attrs,
- ItemKind::Impl {
+ ItemKind::Impl(box ImplKind {
unsafety: ast::Unsafe::No,
polarity: ast::ImplPolarity::Positive,
defaultness: ast::Defaultness::Final,
@@ -187,7 +188,7 @@ fn inject_impl_of_structural_trait(
of_trait: Some(trait_ref),
self_ty: self_type,
items: Vec::new(),
- },
+ }),
);
push(Annotatable::Item(newitem));
diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs
index 550524e652..85ca1da6f1 100644
--- a/compiler/rustc_builtin_macros/src/format.rs
+++ b/compiler/rustc_builtin_macros/src/format.rs
@@ -1044,10 +1044,7 @@ pub fn expand_preparsed_format_args(
let numbered_position_args = pieces.iter().any(|arg: &parse::Piece<'_>| match *arg {
parse::String(_) => false,
- parse::NextArgument(arg) => match arg.position {
- parse::Position::ArgumentIs(_) => true,
- _ => false,
- },
+ parse::NextArgument(arg) => matches!(arg.position, parse::Position::ArgumentIs(_)),
});
cx.build_index_map();
diff --git a/compiler/rustc_builtin_macros/src/format_foreign.rs b/compiler/rustc_builtin_macros/src/format_foreign.rs
index f00dfd1241..0496c72cb0 100644
--- a/compiler/rustc_builtin_macros/src/format_foreign.rs
+++ b/compiler/rustc_builtin_macros/src/format_foreign.rs
@@ -580,10 +580,7 @@ pub mod printf {
}
fn is_flag(c: &char) -> bool {
- match c {
- '0' | '-' | '+' | ' ' | '#' | '\'' => true,
- _ => false,
- }
+ matches!(c, '0' | '-' | '+' | ' ' | '#' | '\'')
}
#[cfg(test)]
diff --git a/compiler/rustc_builtin_macros/src/global_allocator.rs b/compiler/rustc_builtin_macros/src/global_allocator.rs
index e976805d9d..9b43c11f0f 100644
--- a/compiler/rustc_builtin_macros/src/global_allocator.rs
+++ b/compiler/rustc_builtin_macros/src/global_allocator.rs
@@ -5,7 +5,7 @@ use rustc_ast::expand::allocator::{
};
use rustc_ast::ptr::P;
use rustc_ast::{self as ast, Attribute, Expr, FnHeader, FnSig, Generics, Param, StmtKind};
-use rustc_ast::{ItemKind, Mutability, Stmt, Ty, TyKind, Unsafe};
+use rustc_ast::{FnKind, ItemKind, Mutability, Stmt, Ty, TyKind, Unsafe};
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::Span;
@@ -85,7 +85,8 @@ impl AllocFnFactory<'_, '_> {
let header = FnHeader { unsafety: Unsafe::Yes(self.span), ..FnHeader::default() };
let sig = FnSig { decl, header, span: self.span };
let block = Some(self.cx.block_expr(output_expr));
- let kind = ItemKind::Fn(ast::Defaultness::Final, sig, Generics::default(), block);
+ let kind =
+ ItemKind::Fn(box FnKind(ast::Defaultness::Final, sig, Generics::default(), block));
let item = self.cx.item(
self.span,
Ident::from_str_and_span(&self.kind.fn_name(method.name), self.span),
diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs
index 97cadb913c..59844b6c69 100644
--- a/compiler/rustc_builtin_macros/src/lib.rs
+++ b/compiler/rustc_builtin_macros/src/lib.rs
@@ -2,6 +2,8 @@
//! injecting code into the crate before it is lowered to HIR.
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
+#![feature(box_patterns)]
+#![feature(box_syntax)]
#![feature(bool_to_option)]
#![feature(crate_visibility_modifier)]
#![feature(decl_macro)]
@@ -14,10 +16,9 @@ extern crate proc_macro;
use crate::deriving::*;
-use rustc_expand::base::{MacroExpanderFn, ResolverExpand, SyntaxExtension, SyntaxExtensionKind};
+use rustc_expand::base::{MacroExpanderFn, ResolverExpand, SyntaxExtensionKind};
use rustc_expand::proc_macro::BangProcMacro;
-use rustc_span::edition::Edition;
-use rustc_span::symbol::{sym, Ident};
+use rustc_span::symbol::sym;
mod asm;
mod assert;
@@ -34,6 +35,7 @@ mod global_allocator;
mod global_asm;
mod llvm_asm;
mod log_syntax;
+mod panic;
mod source_util;
mod test;
mod trace_macros;
@@ -44,13 +46,8 @@ pub mod proc_macro_harness;
pub mod standard_library_imports;
pub mod test_harness;
-pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand, edition: Edition) {
- let mut register = |name, kind| {
- resolver.register_builtin_macro(
- Ident::with_dummy_span(name),
- SyntaxExtension { is_builtin: true, ..SyntaxExtension::default(kind, edition) },
- )
- };
+pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
+ let mut register = |name, kind| resolver.register_builtin_macro(name, kind);
macro register_bang($($name:ident: $f:expr,)*) {
$(register(sym::$name, SyntaxExtensionKind::LegacyBang(Box::new($f as MacroExpanderFn)));)*
}
@@ -82,6 +79,8 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand, edition: Editi
log_syntax: log_syntax::expand_log_syntax,
module_path: source_util::expand_mod,
option_env: env::expand_option_env,
+ core_panic: panic::expand_panic,
+ std_panic: panic::expand_panic,
stringify: source_util::expand_stringify,
trace_macros: trace_macros::expand_trace_macros,
}
diff --git a/compiler/rustc_builtin_macros/src/llvm_asm.rs b/compiler/rustc_builtin_macros/src/llvm_asm.rs
index db73fdbe24..d72bfa660e 100644
--- a/compiler/rustc_builtin_macros/src/llvm_asm.rs
+++ b/compiler/rustc_builtin_macros/src/llvm_asm.rs
@@ -87,13 +87,15 @@ fn parse_inline_asm<'a>(
// parsed as `llvm_asm!(z)` with `z = "x": y` which is type ascription.
let first_colon = tts
.trees()
- .position(|tt| match tt {
- tokenstream::TokenTree::Token(Token { kind: token::Colon | token::ModSep, .. }) => true,
- _ => false,
+ .position(|tt| {
+ matches!(
+ tt,
+ tokenstream::TokenTree::Token(Token { kind: token::Colon | token::ModSep, .. })
+ )
})
.unwrap_or(tts.len());
let mut p = cx.new_parser_from_tts(tts.trees().skip(first_colon).collect());
- let mut asm = kw::Invalid;
+ let mut asm = kw::Empty;
let mut asm_str_style = None;
let mut outputs = Vec::new();
let mut inputs = Vec::new();
diff --git a/compiler/rustc_builtin_macros/src/panic.rs b/compiler/rustc_builtin_macros/src/panic.rs
new file mode 100644
index 0000000000..6f5962d435
--- /dev/null
+++ b/compiler/rustc_builtin_macros/src/panic.rs
@@ -0,0 +1,48 @@
+use rustc_ast::ptr::P;
+use rustc_ast::tokenstream::{DelimSpan, TokenStream};
+use rustc_ast::*;
+use rustc_expand::base::*;
+use rustc_span::symbol::sym;
+use rustc_span::Span;
+
+// This expands to either
+// - `$crate::panic::panic_2015!(...)` or
+// - `$crate::panic::panic_2021!(...)`
+// depending on the edition.
+//
+// This is used for both std::panic!() and core::panic!().
+//
+// `$crate` will refer to either the `std` or `core` crate depending on which
+// one we're expanding from.
+pub fn expand_panic<'cx>(
+ cx: &'cx mut ExtCtxt<'_>,
+ sp: Span,
+ tts: TokenStream,
+) -> Box {
+ let panic = if sp.rust_2021() { sym::panic_2021 } else { sym::panic_2015 };
+
+ let sp = cx.with_call_site_ctxt(sp);
+
+ MacEager::expr(
+ cx.expr(
+ sp,
+ ExprKind::MacCall(MacCall {
+ path: Path {
+ span: sp,
+ segments: cx
+ .std_path(&[sym::panic, panic])
+ .into_iter()
+ .map(|ident| PathSegment::from_ident(ident))
+ .collect(),
+ tokens: None,
+ },
+ args: P(MacArgs::Delimited(
+ DelimSpan::from_single(sp),
+ MacDelimiter::Parenthesis,
+ tts,
+ )),
+ prior_type_ascription: None,
+ }),
+ ),
+ )
+}
diff --git a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs
index 4e91436199..7582d98053 100644
--- a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs
+++ b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs
@@ -256,10 +256,7 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> {
// we're just not interested in this item.
//
// If we find one, try to locate a `#[proc_macro_derive]` attribute on it.
- let is_fn = match item.kind {
- ast::ItemKind::Fn(..) => true,
- _ => false,
- };
+ let is_fn = matches!(item.kind, ast::ItemKind::Fn(..));
let mut found_attr: Option<&'a ast::Attribute> = None;
diff --git a/compiler/rustc_builtin_macros/src/source_util.rs b/compiler/rustc_builtin_macros/src/source_util.rs
index f76bbd8381..28efd483c8 100644
--- a/compiler/rustc_builtin_macros/src/source_util.rs
+++ b/compiler/rustc_builtin_macros/src/source_util.rs
@@ -5,7 +5,8 @@ use rustc_ast::tokenstream::TokenStream;
use rustc_ast_pretty::pprust;
use rustc_expand::base::{self, *};
use rustc_expand::module::DirectoryOwnership;
-use rustc_parse::{self, new_parser_from_file, parser::Parser};
+use rustc_parse::parser::{ForceCollect, Parser};
+use rustc_parse::{self, new_parser_from_file};
use rustc_session::lint::builtin::INCOMPLETE_INCLUDE;
use rustc_span::symbol::Symbol;
use rustc_span::{self, Pos, Span};
@@ -139,7 +140,7 @@ pub fn expand_include<'cx>(
fn make_items(mut self: Box>) -> Option; 1]>> {
let mut ret = SmallVec::new();
while self.p.token != token::Eof {
- match self.p.parse_item() {
+ match self.p.parse_item(ForceCollect::No) {
Err(mut err) => {
err.emit();
break;
diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs
index 25d3f46da6..e845f9ec55 100644
--- a/compiler/rustc_builtin_macros/src/test.rs
+++ b/compiler/rustc_builtin_macros/src/test.rs
@@ -425,7 +425,7 @@ fn test_type(cx: &ExtCtxt<'_>) -> TestType {
fn has_test_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool {
let has_should_panic_attr = cx.sess.contains_name(&i.attrs, sym::should_panic);
let sd = &cx.sess.parse_sess.span_diagnostic;
- if let ast::ItemKind::Fn(_, ref sig, ref generics, _) = i.kind {
+ if let ast::ItemKind::Fn(box ast::FnKind(_, ref sig, ref generics, _)) = i.kind {
if let ast::Unsafe::Yes(span) = sig.header.unsafety {
sd.struct_span_err(i.span, "unsafe functions cannot be used for tests")
.span_label(span, "`unsafe` because of this")
@@ -474,7 +474,7 @@ fn has_test_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool {
}
fn has_bench_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool {
- let has_sig = if let ast::ItemKind::Fn(_, ref sig, _, _) = i.kind {
+ let has_sig = if let ast::ItemKind::Fn(box ast::FnKind(_, ref sig, _, _)) = i.kind {
// N.B., inadequate check, but we're running
// well before resolve, can't get too deep.
sig.decl.inputs.len() == 1
diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs
index 9976140d6b..4ac22be3c2 100644
--- a/compiler/rustc_builtin_macros/src/test_harness.rs
+++ b/compiler/rustc_builtin_macros/src/test_harness.rs
@@ -311,7 +311,8 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P {
let decl = ecx.fn_decl(vec![], ast::FnRetTy::Ty(main_ret_ty));
let sig = ast::FnSig { decl, header: ast::FnHeader::default(), span: sp };
let def = ast::Defaultness::Final;
- let main = ast::ItemKind::Fn(def, sig, ast::Generics::default(), Some(main_body));
+ let main =
+ ast::ItemKind::Fn(box ast::FnKind(def, sig, ast::Generics::default(), Some(main_body)));
// Honor the reexport_test_harness_main attribute
let main_id = match cx.reexport_test_harness_main {
diff --git a/compiler/rustc_codegen_cranelift/.github/workflows/main.yml b/compiler/rustc_codegen_cranelift/.github/workflows/main.yml
index e6d3375fb1..20c58423a0 100644
--- a/compiler/rustc_codegen_cranelift/.github/workflows/main.yml
+++ b/compiler/rustc_codegen_cranelift/.github/workflows/main.yml
@@ -12,6 +12,9 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest]
+ env:
+ - BACKEND: ""
+ - BACKEND: --oldbe
steps:
- uses: actions/checkout@v2
@@ -51,7 +54,7 @@ jobs:
export COMPILE_RUNS=2
export RUN_RUNS=2
- ./test.sh
+ ./test.sh $BACKEND
- name: Package prebuilt cg_clif
run: tar cvfJ cg_clif.tar.xz build
diff --git a/compiler/rustc_codegen_cranelift/.vscode/settings.json b/compiler/rustc_codegen_cranelift/.vscode/settings.json
index 04ab5085c1..19ea41563d 100644
--- a/compiler/rustc_codegen_cranelift/.vscode/settings.json
+++ b/compiler/rustc_codegen_cranelift/.vscode/settings.json
@@ -1,6 +1,7 @@
{
// source for rustc_* is not included in the rust-src component; disable the errors about this
"rust-analyzer.diagnostics.disabled": ["unresolved-extern-crate"],
+ "rust-analyzer.assist.importMergeBehavior": "last",
"rust-analyzer.cargo.loadOutDirsFromCheck": true,
"rust-analyzer.linkedProjects": [
"./Cargo.toml",
diff --git a/compiler/rustc_codegen_cranelift/Cargo.lock b/compiler/rustc_codegen_cranelift/Cargo.lock
index 67ed41e765..5495cfa5ea 100644
--- a/compiler/rustc_codegen_cranelift/Cargo.lock
+++ b/compiler/rustc_codegen_cranelift/Cargo.lock
@@ -2,9 +2,9 @@
# It is not intended for manual editing.
[[package]]
name = "anyhow"
-version = "1.0.34"
+version = "1.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bf8dcb5b4bbaa28653b647d8c77bd4ed40183b48882e130c1f1ffb73de069fd7"
+checksum = "afddf7f520a80dbf76e6f50a35bca42a2331ef227a28b3b6dc5c2e2338d114b1"
[[package]]
name = "ar"
@@ -25,15 +25,15 @@ checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
[[package]]
name = "byteorder"
-version = "1.3.4"
+version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
+checksum = "ae44d1a3d5a19df61dd0c8beb138458ac2a53a7ac09eba97d55592540004306b"
[[package]]
name = "cc"
-version = "1.0.62"
+version = "1.0.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f1770ced377336a88a67c473594ccc14eca6f4559217c34f64aac8f83d641b40"
+checksum = "4c0496836a84f8d0495758516b8621a622beb77c0fed418570e50764093ced48"
[[package]]
name = "cfg-if"
@@ -49,16 +49,16 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "cranelift-bforest"
-version = "0.68.0"
-source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#19640367dbf0da7093e61add3306c8d092644fb3"
+version = "0.69.0"
+source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#986b5768f9e68f1564b43f32b8a4080a6582c8ca"
dependencies = [
"cranelift-entity",
]
[[package]]
name = "cranelift-codegen"
-version = "0.68.0"
-source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#19640367dbf0da7093e61add3306c8d092644fb3"
+version = "0.69.0"
+source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#986b5768f9e68f1564b43f32b8a4080a6582c8ca"
dependencies = [
"byteorder",
"cranelift-bforest",
@@ -75,8 +75,8 @@ dependencies = [
[[package]]
name = "cranelift-codegen-meta"
-version = "0.68.0"
-source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#19640367dbf0da7093e61add3306c8d092644fb3"
+version = "0.69.0"
+source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#986b5768f9e68f1564b43f32b8a4080a6582c8ca"
dependencies = [
"cranelift-codegen-shared",
"cranelift-entity",
@@ -84,18 +84,18 @@ dependencies = [
[[package]]
name = "cranelift-codegen-shared"
-version = "0.68.0"
-source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#19640367dbf0da7093e61add3306c8d092644fb3"
+version = "0.69.0"
+source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#986b5768f9e68f1564b43f32b8a4080a6582c8ca"
[[package]]
name = "cranelift-entity"
-version = "0.68.0"
-source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#19640367dbf0da7093e61add3306c8d092644fb3"
+version = "0.69.0"
+source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#986b5768f9e68f1564b43f32b8a4080a6582c8ca"
[[package]]
name = "cranelift-frontend"
-version = "0.68.0"
-source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#19640367dbf0da7093e61add3306c8d092644fb3"
+version = "0.69.0"
+source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#986b5768f9e68f1564b43f32b8a4080a6582c8ca"
dependencies = [
"cranelift-codegen",
"log",
@@ -104,45 +104,11 @@ dependencies = [
]
[[package]]
-name = "cranelift-module"
-version = "0.68.0"
-source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#19640367dbf0da7093e61add3306c8d092644fb3"
+name = "cranelift-jit"
+version = "0.69.0"
+source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#986b5768f9e68f1564b43f32b8a4080a6582c8ca"
dependencies = [
"anyhow",
- "cranelift-codegen",
- "cranelift-entity",
- "log",
- "thiserror",
-]
-
-[[package]]
-name = "cranelift-native"
-version = "0.68.0"
-source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#19640367dbf0da7093e61add3306c8d092644fb3"
-dependencies = [
- "cranelift-codegen",
- "raw-cpuid",
- "target-lexicon",
-]
-
-[[package]]
-name = "cranelift-object"
-version = "0.68.0"
-source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#19640367dbf0da7093e61add3306c8d092644fb3"
-dependencies = [
- "anyhow",
- "cranelift-codegen",
- "cranelift-module",
- "log",
- "object",
- "target-lexicon",
-]
-
-[[package]]
-name = "cranelift-simplejit"
-version = "0.68.0"
-source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#19640367dbf0da7093e61add3306c8d092644fb3"
-dependencies = [
"cranelift-codegen",
"cranelift-entity",
"cranelift-module",
@@ -155,6 +121,41 @@ dependencies = [
"winapi",
]
+[[package]]
+name = "cranelift-module"
+version = "0.69.0"
+source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#986b5768f9e68f1564b43f32b8a4080a6582c8ca"
+dependencies = [
+ "anyhow",
+ "cranelift-codegen",
+ "cranelift-entity",
+ "log",
+ "thiserror",
+]
+
+[[package]]
+name = "cranelift-native"
+version = "0.69.0"
+source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#986b5768f9e68f1564b43f32b8a4080a6582c8ca"
+dependencies = [
+ "cranelift-codegen",
+ "raw-cpuid",
+ "target-lexicon",
+]
+
+[[package]]
+name = "cranelift-object"
+version = "0.69.0"
+source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#986b5768f9e68f1564b43f32b8a4080a6582c8ca"
+dependencies = [
+ "anyhow",
+ "cranelift-codegen",
+ "cranelift-module",
+ "log",
+ "object",
+ "target-lexicon",
+]
+
[[package]]
name = "crc32fast"
version = "1.2.1"
@@ -208,9 +209,9 @@ checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
[[package]]
name = "indexmap"
-version = "1.6.0"
+version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "55e2e4c765aa53a0424761bf9f41aa7a6ac1efa87238f59560640e27fca028f2"
+checksum = "4fb1fa934250de4de8aef298d81c729a7d33d8c239daa3a7575e6b92bfc7313b"
dependencies = [
"autocfg",
"hashbrown",
@@ -218,15 +219,15 @@ dependencies = [
[[package]]
name = "libc"
-version = "0.2.80"
+version = "0.2.82"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4d58d1b70b004888f764dfbf6a26a3b0342a1632d33968e4a179d8011c760614"
+checksum = "89203f3fba0a3795506acaad8ebce3c80c0af93f994d5a1d7a0b1eeb23271929"
[[package]]
name = "libloading"
-version = "0.6.5"
+version = "0.6.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1090080fe06ec2648d0da3881d9453d97e71a45f00eb179af7fdd7e3f686fdb0"
+checksum = "351a32417a12d5f7e82c368a66781e307834dae04c6ce0cd4456d52989229883"
dependencies = [
"cfg-if 1.0.0",
"winapi",
@@ -234,9 +235,9 @@ dependencies = [
[[package]]
name = "log"
-version = "0.4.11"
+version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b"
+checksum = "fcf3805d4480bb5b86070dcfeb9e2cb2ebc148adb753c5cca5f884d1d65a42b2"
dependencies = [
"cfg-if 0.1.10",
]
@@ -271,9 +272,9 @@ dependencies = [
[[package]]
name = "quote"
-version = "1.0.7"
+version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
+checksum = "991431c3519a3f36861882da93630ce66b52918dcf1b8e2fd66b397fc96f28df"
dependencies = [
"proc-macro2",
]
@@ -325,13 +326,14 @@ dependencies = [
"ar",
"cranelift-codegen",
"cranelift-frontend",
+ "cranelift-jit",
"cranelift-module",
"cranelift-object",
- "cranelift-simplejit",
"gimli",
"indexmap",
"libloading",
"object",
+ "smallvec",
"target-lexicon",
]
@@ -361,15 +363,15 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
[[package]]
name = "smallvec"
-version = "1.4.2"
+version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fbee7696b84bbf3d89a1c2eccff0850e3047ed46bfcd2e92c29a2d074d57e252"
+checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e"
[[package]]
name = "syn"
-version = "1.0.48"
+version = "1.0.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cc371affeffc477f42a221a1e4297aedcea33d47d19b61455588bd9d8f6b19ac"
+checksum = "cc60a3d73ea6594cd712d830cc1f0390fd71542d8c8cd24e70cc54cdfd5e05d5"
dependencies = [
"proc-macro2",
"quote",
@@ -384,18 +386,18 @@ checksum = "4ee5a98e506fb7231a304c3a1bd7c132a55016cf65001e0282480665870dfcb9"
[[package]]
name = "thiserror"
-version = "1.0.22"
+version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0e9ae34b84616eedaaf1e9dd6026dbe00dcafa92aa0c8077cb69df1fcfe5e53e"
+checksum = "76cc616c6abf8c8928e2fdcc0dbfab37175edd8fb49a4641066ad1364fdab146"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
-version = "1.0.22"
+version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9ba20f23e85b10754cd195504aebf6a27e2e6cbe28c17778a0c930724628dd56"
+checksum = "9be73a2caec27583d0046ef3796c3794f868a5bc813db689eed00c7631275cd1"
dependencies = [
"proc-macro2",
"quote",
diff --git a/compiler/rustc_codegen_cranelift/Cargo.toml b/compiler/rustc_codegen_cranelift/Cargo.toml
index cbff06749d..3820fce6d1 100644
--- a/compiler/rustc_codegen_cranelift/Cargo.toml
+++ b/compiler/rustc_codegen_cranelift/Cargo.toml
@@ -9,10 +9,10 @@ crate-type = ["dylib"]
[dependencies]
# These have to be in sync with each other
-cranelift-codegen = { git = "https://github.com/bytecodealliance/wasmtime/", branch = "main", features = ["unwind"] }
+cranelift-codegen = { git = "https://github.com/bytecodealliance/wasmtime/", branch = "main", features = ["unwind", "x86", "x64"] }
cranelift-frontend = { git = "https://github.com/bytecodealliance/wasmtime/", branch = "main" }
cranelift-module = { git = "https://github.com/bytecodealliance/wasmtime/", branch = "main" }
-cranelift-simplejit = { git = "https://github.com/bytecodealliance/wasmtime/", branch = "main", optional = true }
+cranelift-jit = { git = "https://github.com/bytecodealliance/wasmtime/", branch = "main", optional = true }
cranelift-object = { git = "https://github.com/bytecodealliance/wasmtime/", branch = "main" }
target-lexicon = "0.11.0"
gimli = { version = "0.23.0", default-features = false, features = ["write"]}
@@ -21,13 +21,14 @@ object = { version = "0.22.0", default-features = false, features = ["std", "rea
ar = { git = "https://github.com/bjorn3/rust-ar.git", branch = "do_not_remove_cg_clif_ranlib" }
indexmap = "1.0.2"
libloading = { version = "0.6.0", optional = true }
+smallvec = "1.6.1"
# Uncomment to use local checkout of cranelift
#[patch."https://github.com/bytecodealliance/wasmtime/"]
#cranelift-codegen = { path = "../wasmtime/cranelift/codegen" }
#cranelift-frontend = { path = "../wasmtime/cranelift/frontend" }
#cranelift-module = { path = "../wasmtime/cranelift/module" }
-#cranelift-simplejit = { path = "../wasmtime/cranelift/simplejit" }
+#cranelift-jit = { path = "../wasmtime/cranelift/jit" }
#cranelift-object = { path = "../wasmtime/cranelift/object" }
#[patch.crates-io]
@@ -35,8 +36,9 @@ libloading = { version = "0.6.0", optional = true }
[features]
default = ["jit", "inline_asm"]
-jit = ["cranelift-simplejit", "libloading"]
+jit = ["cranelift-jit", "libloading"]
inline_asm = []
+oldbe = []
[profile.dev]
# By compiling dependencies with optimizations, performing tests gets much faster.
diff --git a/compiler/rustc_codegen_cranelift/Readme.md b/compiler/rustc_codegen_cranelift/Readme.md
index de54bf67f4..6fa5eebdc2 100644
--- a/compiler/rustc_codegen_cranelift/Readme.md
+++ b/compiler/rustc_codegen_cranelift/Readme.md
@@ -1,8 +1,6 @@
-# WIP Cranelift codegen backend for rust
+# Cranelift codegen backend for rust
-> ⚠⚠⚠ Certain kinds of FFI don't work yet. ⚠⚠⚠
-
-The goal of this project is to create an alternative codegen backend for the rust compiler based on [Cranelift](https://github.com/bytecodealliance/wasmtime/blob/master/cranelift).
+The goal of this project is to create an alternative codegen backend for the rust compiler based on [Cranelift](https://github.com/bytecodealliance/wasmtime/blob/main/cranelift).
This has the potential to improve compilation times in debug mode.
If your project doesn't use any of the things listed under "Not yet supported", it should work fine.
If not please open an issue.
@@ -68,7 +66,15 @@ $ $cg_clif_dir/build/cargo.sh jit
or
```bash
-$ $cg_clif_dir/build/bin/cg_clif --jit my_crate.rs
+$ $cg_clif_dir/build/bin/cg_clif -Cllvm-args=mode=jit -Cprefer-dynamic my_crate.rs
+```
+
+There is also an experimental lazy jit mode. In this mode functions are only compiled once they are
+first called. It currently does not work with multi-threaded programs. When a not yet compiled
+function is called from another thread than the main thread, you will get an ICE.
+
+```bash
+$ $cg_clif_dir/build/cargo.sh lazy-jit
```
### Shell
@@ -77,7 +83,7 @@ These are a few functions that allow you to easily run rust code from the shell
```bash
function jit_naked() {
- echo "$@" | $cg_clif_dir/build/bin/cg_clif - --jit
+ echo "$@" | $cg_clif_dir/build/bin/cg_clif - -Cllvm-args=mode=jit -Cprefer-dynamic
}
function jit() {
@@ -95,8 +101,7 @@ function jit_calc() {
## Not yet supported
-* Good non-rust abi support ([several problems](https://github.com/bjorn3/rustc_codegen_cranelift/issues/10))
-* Inline assembly ([no cranelift support](https://github.com/bytecodealliance/wasmtime/issues/1041)
+* Inline assembly ([no cranelift support](https://github.com/bytecodealliance/wasmtime/issues/1041))
* On Linux there is support for invoking an external assembler for `global_asm!` and `asm!`.
`llvm_asm!` will remain unimplemented forever. `asm!` doesn't yet support reg classes. You
have to specify specific registers instead.
diff --git a/compiler/rustc_codegen_cranelift/build.sh b/compiler/rustc_codegen_cranelift/build.sh
index 26041b59cc..598ce35ece 100755
--- a/compiler/rustc_codegen_cranelift/build.sh
+++ b/compiler/rustc_codegen_cranelift/build.sh
@@ -3,23 +3,29 @@ set -e
# Settings
export CHANNEL="release"
-build_sysroot=1
+build_sysroot="clif"
target_dir='build'
+oldbe=''
while [[ $# != 0 ]]; do
case $1 in
"--debug")
export CHANNEL="debug"
;;
- "--without-sysroot")
- build_sysroot=0
+ "--sysroot")
+ build_sysroot=$2
+ shift
;;
"--target-dir")
target_dir=$2
shift
;;
+ "--oldbe")
+ oldbe='--features oldbe'
+ ;;
*)
echo "Unknown flag '$1'"
- echo "Usage: ./build.sh [--debug] [--without-sysroot] [--target-dir DIR]"
+ echo "Usage: ./build.sh [--debug] [--sysroot none|clif|llvm] [--target-dir DIR] [--oldbe]"
+ exit 1
;;
esac
shift
@@ -27,23 +33,24 @@ done
# Build cg_clif
unset CARGO_TARGET_DIR
-export RUSTFLAGS="-Zrun_dsymutil=no"
unamestr=$(uname)
if [[ "$unamestr" == 'Linux' ]]; then
export RUSTFLAGS='-Clink-arg=-Wl,-rpath=$ORIGIN/../lib '$RUSTFLAGS
elif [[ "$unamestr" == 'Darwin' ]]; then
- export RUSTFLAGS='-Clink-arg=-Wl,-rpath,@loader_path/../lib -Zosx-rpath-install-name '$RUSTFLAGS
+ export RUSTFLAGS='-Csplit-debuginfo=unpacked -Clink-arg=-Wl,-rpath,@loader_path/../lib -Zosx-rpath-install-name '$RUSTFLAGS
dylib_ext='dylib'
else
echo "Unsupported os"
exit 1
fi
if [[ "$CHANNEL" == "release" ]]; then
- cargo build --release
+ cargo build $oldbe --release
else
- cargo build
+ cargo build $oldbe
fi
+source scripts/ext_config.sh
+
rm -rf "$target_dir"
mkdir "$target_dir"
mkdir "$target_dir"/bin "$target_dir"/lib
@@ -51,10 +58,29 @@ ln target/$CHANNEL/cg_clif{,_build_sysroot} "$target_dir"/bin
ln target/$CHANNEL/*rustc_codegen_cranelift* "$target_dir"/lib
ln rust-toolchain scripts/config.sh scripts/cargo.sh "$target_dir"
-if [[ "$build_sysroot" == "1" ]]; then
- echo "[BUILD] sysroot"
- export CG_CLIF_INCR_CACHE_DISABLED=1
- dir=$(pwd)
- cd "$target_dir"
- time "$dir/build_sysroot/build_sysroot.sh"
+mkdir -p "$target_dir/lib/rustlib/$TARGET_TRIPLE/lib/"
+if [[ "$TARGET_TRIPLE" == "x86_64-pc-windows-gnu" ]]; then
+ cp $(rustc --print sysroot)/lib/rustlib/$TARGET_TRIPLE/lib/*.o "$target_dir/lib/rustlib/$TARGET_TRIPLE/lib/"
fi
+
+case "$build_sysroot" in
+ "none")
+ ;;
+ "llvm")
+ cp -r $(rustc --print sysroot)/lib/rustlib/$TARGET_TRIPLE/lib "$target_dir/lib/rustlib/$TARGET_TRIPLE/"
+ ;;
+ "clif")
+ echo "[BUILD] sysroot"
+ dir=$(pwd)
+ cd "$target_dir"
+ time "$dir/build_sysroot/build_sysroot.sh"
+ cp lib/rustlib/*/lib/libstd-* lib/
+ ;;
+ *)
+ echo "Unknown sysroot kind \`$build_sysroot\`."
+ echo "The allowed values are:"
+ echo " none A sysroot that doesn't contain the standard library"
+ echo " llvm Copy the sysroot from rustc compiled by cg_llvm"
+ echo " clif Build a new sysroot using cg_clif"
+ exit 1
+esac
diff --git a/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock b/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock
index a2b8f449f0..0da9999c17 100644
--- a/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock
+++ b/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock
@@ -2,9 +2,9 @@
# It is not intended for manual editing.
[[package]]
name = "addr2line"
-version = "0.14.0"
+version = "0.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7c0929d69e78dd9bf5408269919fcbcaeb2e35e5d43e5815517cdc6a8e11a423"
+checksum = "a55f82cfe485775d02112886f4169bde0c5894d75e79ead7eafe7e40a25e45f7"
dependencies = [
"compiler_builtins",
"gimli",
@@ -47,9 +47,9 @@ checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
[[package]]
name = "cc"
-version = "1.0.65"
+version = "1.0.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "95752358c8f7552394baf48cd82695b345628ad3f170d607de3ca03b8dacca15"
+checksum = "4c0496836a84f8d0495758516b8621a622beb77c0fed418570e50764093ced48"
[[package]]
name = "cfg-if"
@@ -63,9 +63,7 @@ dependencies = [
[[package]]
name = "compiler_builtins"
-version = "0.1.36"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7cd0782e0a7da7598164153173e5a5d4d9b1da094473c98dce0ff91406112369"
+version = "0.1.39"
dependencies = [
"rustc-std-workspace-core",
]
@@ -130,9 +128,9 @@ dependencies = [
[[package]]
name = "hermit-abi"
-version = "0.1.17"
+version = "0.1.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5aca5565f760fb5b220e499d72710ed156fdb74e631659e99377d9ebfbd13ae8"
+checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c"
dependencies = [
"compiler_builtins",
"libc",
@@ -141,9 +139,9 @@ dependencies = [
[[package]]
name = "libc"
-version = "0.2.80"
+version = "0.2.84"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4d58d1b70b004888f764dfbf6a26a3b0342a1632d33968e4a179d8011c760614"
+checksum = "1cca32fa0182e8c0989459524dc356b8f2b5c10f1b9eb521b7d182c03cf8c5ff"
dependencies = [
"rustc-std-workspace-core",
]
diff --git a/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.toml b/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.toml
index e562dedb53..82516c98af 100644
--- a/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.toml
+++ b/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.toml
@@ -5,17 +5,19 @@ version = "0.0.0"
[dependencies]
core = { path = "./sysroot_src/library/core" }
-compiler_builtins = "0.1"
alloc = { path = "./sysroot_src/library/alloc" }
std = { path = "./sysroot_src/library/std", features = ["panic_unwind", "backtrace"] }
test = { path = "./sysroot_src/library/test" }
alloc_system = { path = "./alloc_system" }
+compiler_builtins = { version = "0.1.39", default-features = false, features = ["no-asm"] }
+
[patch.crates-io]
rustc-std-workspace-core = { path = "./sysroot_src/library/rustc-std-workspace-core" }
rustc-std-workspace-alloc = { path = "./sysroot_src/library/rustc-std-workspace-alloc" }
rustc-std-workspace-std = { path = "./sysroot_src/library/rustc-std-workspace-std" }
+compiler_builtins = { path = "./compiler-builtins" }
[profile.dev]
lto = "off"
diff --git a/compiler/rustc_codegen_cranelift/build_sysroot/build_sysroot.sh b/compiler/rustc_codegen_cranelift/build_sysroot/build_sysroot.sh
index d7a72df2eb..282ce4a582 100755
--- a/compiler/rustc_codegen_cranelift/build_sysroot/build_sysroot.sh
+++ b/compiler/rustc_codegen_cranelift/build_sysroot/build_sysroot.sh
@@ -24,17 +24,16 @@ export CARGO_TARGET_DIR=target
# Build libs
export RUSTFLAGS="$RUSTFLAGS -Zforce-unstable-if-unmarked -Cpanic=abort"
+export __CARGO_DEFAULT_LIB_METADATA="cg_clif"
if [[ "$1" != "--debug" ]]; then
sysroot_channel='release'
# FIXME Enable incremental again once rust-lang/rust#74946 is fixed
- # FIXME Enable -Zmir-opt-level=2 again once it doesn't ice anymore
- CARGO_INCREMENTAL=0 RUSTFLAGS="$RUSTFLAGS" cargo build --target "$TARGET_TRIPLE" --release
+ CARGO_INCREMENTAL=0 RUSTFLAGS="$RUSTFLAGS -Zmir-opt-level=2" cargo build --target "$TARGET_TRIPLE" --release
else
sysroot_channel='debug'
cargo build --target "$TARGET_TRIPLE"
fi
# Copy files to sysroot
-mkdir -p "$dir/lib/rustlib/$TARGET_TRIPLE/lib/"
ln "target/$TARGET_TRIPLE/$sysroot_channel/deps/"* "$dir/lib/rustlib/$TARGET_TRIPLE/lib/"
rm "$dir/lib/rustlib/$TARGET_TRIPLE/lib/"*.{rmeta,d}
diff --git a/compiler/rustc_codegen_cranelift/build_sysroot/prepare_sysroot_src.sh b/compiler/rustc_codegen_cranelift/build_sysroot/prepare_sysroot_src.sh
index 40fbaf646a..d3b87e02ba 100755
--- a/compiler/rustc_codegen_cranelift/build_sysroot/prepare_sysroot_src.sh
+++ b/compiler/rustc_codegen_cranelift/build_sysroot/prepare_sysroot_src.sh
@@ -29,4 +29,11 @@ git commit --no-gpg-sign -m "Patch $file"
done
popd
-echo "Successfully prepared libcore for building"
+git clone https://github.com/rust-lang/compiler-builtins.git || echo "rust-lang/compiler-builtins has already been cloned"
+pushd compiler-builtins
+git checkout -- .
+git checkout 0.1.39
+git apply ../../crate_patches/0001-compiler-builtins-Remove-rotate_left-from-Int.patch
+popd
+
+echo "Successfully prepared sysroot source for building"
diff --git a/compiler/rustc_codegen_cranelift/clean_all.sh b/compiler/rustc_codegen_cranelift/clean_all.sh
index 5a69c862d0..b47efe72bc 100755
--- a/compiler/rustc_codegen_cranelift/clean_all.sh
+++ b/compiler/rustc_codegen_cranelift/clean_all.sh
@@ -1,5 +1,5 @@
#!/bin/bash --verbose
set -e
-rm -rf target/ build/ build_sysroot/{sysroot_src/,target/} perf.data{,.old}
+rm -rf target/ build/ build_sysroot/{sysroot_src/,target/,compiler-builtins/} perf.data{,.old}
rm -rf rand/ regex/ simple-raytracer/
diff --git a/compiler/rustc_codegen_cranelift/crate_patches/0001-compiler-builtins-Remove-rotate_left-from-Int.patch b/compiler/rustc_codegen_cranelift/crate_patches/0001-compiler-builtins-Remove-rotate_left-from-Int.patch
new file mode 100644
index 0000000000..e14768910a
--- /dev/null
+++ b/compiler/rustc_codegen_cranelift/crate_patches/0001-compiler-builtins-Remove-rotate_left-from-Int.patch
@@ -0,0 +1,35 @@
+From 7078cca3cb614e1e82da428380b4e16fc3afef46 Mon Sep 17 00:00:00 2001
+From: bjorn3
+Date: Thu, 21 Jan 2021 14:46:36 +0100
+Subject: [PATCH] Remove rotate_left from Int
+
+---
+ src/int/mod.rs | 5 -----
+ 1 file changed, 5 deletions(-)
+
+diff --git a/src/int/mod.rs b/src/int/mod.rs
+index 06054c8..3bea17b 100644
+--- a/src/int/mod.rs
++++ b/src/int/mod.rs
+@@ -85,7 +85,6 @@ pub trait Int:
+ fn wrapping_sub(self, other: Self) -> Self;
+ fn wrapping_shl(self, other: u32) -> Self;
+ fn wrapping_shr(self, other: u32) -> Self;
+- fn rotate_left(self, other: u32) -> Self;
+ fn overflowing_add(self, other: Self) -> (Self, bool);
+ fn aborting_div(self, other: Self) -> Self;
+ fn aborting_rem(self, other: Self) -> Self;
+@@ -209,10 +208,6 @@ macro_rules! int_impl_common {
+ ::wrapping_shr(self, other)
+ }
+
+- fn rotate_left(self, other: u32) -> Self {
+- ::rotate_left(self, other)
+- }
+-
+ fn overflowing_add(self, other: Self) -> (Self, bool) {
+ ::overflowing_add(self, other)
+ }
+--
+2.26.2.7.g19db9cfb68
+
diff --git a/compiler/rustc_codegen_cranelift/example/alloc_example.rs b/compiler/rustc_codegen_cranelift/example/alloc_example.rs
index dc2ad4c676..f59600ebb3 100644
--- a/compiler/rustc_codegen_cranelift/example/alloc_example.rs
+++ b/compiler/rustc_codegen_cranelift/example/alloc_example.rs
@@ -11,7 +11,8 @@ use alloc_system::System;
#[global_allocator]
static ALLOC: System = System;
-#[link(name = "c")]
+#[cfg_attr(unix, link(name = "c"))]
+#[cfg_attr(target_env = "msvc", link(name = "msvcrt"))]
extern "C" {
fn puts(s: *const u8) -> i32;
}
diff --git a/compiler/rustc_codegen_cranelift/example/mini_core.rs b/compiler/rustc_codegen_cranelift/example/mini_core.rs
index 10cba99205..002ec7e2e3 100644
--- a/compiler/rustc_codegen_cranelift/example/mini_core.rs
+++ b/compiler/rustc_codegen_cranelift/example/mini_core.rs
@@ -532,8 +532,8 @@ pub mod intrinsics {
}
pub mod libc {
- #[cfg_attr(not(windows), link(name = "c"))]
- #[cfg_attr(windows, link(name = "msvcrt"))]
+ #[cfg_attr(unix, link(name = "c"))]
+ #[cfg_attr(target_env = "msvc", link(name = "msvcrt"))]
extern "C" {
pub fn puts(s: *const i8) -> i32;
pub fn printf(format: *const i8, ...) -> i32;
diff --git a/compiler/rustc_codegen_cranelift/example/mod_bench.rs b/compiler/rustc_codegen_cranelift/example/mod_bench.rs
index bc65221362..152041aa9e 100644
--- a/compiler/rustc_codegen_cranelift/example/mod_bench.rs
+++ b/compiler/rustc_codegen_cranelift/example/mod_bench.rs
@@ -1,7 +1,8 @@
#![feature(start, box_syntax, core_intrinsics, lang_items)]
#![no_std]
-#[link(name = "c")]
+#[cfg_attr(unix, link(name = "c"))]
+#[cfg_attr(target_env = "msvc", link(name = "msvcrt"))]
extern {}
#[panic_handler]
diff --git a/compiler/rustc_codegen_cranelift/example/std_example.rs b/compiler/rustc_codegen_cranelift/example/std_example.rs
index b38e25328a..015bbdfed4 100644
--- a/compiler/rustc_codegen_cranelift/example/std_example.rs
+++ b/compiler/rustc_codegen_cranelift/example/std_example.rs
@@ -15,6 +15,8 @@ fn main() {
let stderr = ::std::io::stderr();
let mut stderr = stderr.lock();
+ // FIXME support lazy jit when multi threading
+ #[cfg(not(lazy_jit))]
std::thread::spawn(move || {
println!("Hello from another thread!");
});
diff --git a/compiler/rustc_codegen_cranelift/patches/0022-core-Disable-not-compiling-tests.patch b/compiler/rustc_codegen_cranelift/patches/0022-core-Disable-not-compiling-tests.patch
index 8cfffe580a..3eb10069ad 100644
--- a/compiler/rustc_codegen_cranelift/patches/0022-core-Disable-not-compiling-tests.patch
+++ b/compiler/rustc_codegen_cranelift/patches/0022-core-Disable-not-compiling-tests.patch
@@ -119,5 +119,21 @@ index 6609bc3..241b497 100644
#[test]
#[should_panic(expected = "index 0 greater than length of slice")]
+diff --git a/library/core/tests/num/ops.rs b/library/core/tests/num/ops.rs
+index 9979cc8..d5d1d83 100644
+--- a/library/core/tests/num/ops.rs
++++ b/library/core/tests/num/ops.rs
+@@ -238,7 +238,7 @@ macro_rules! test_shift_assign {
+ }
+ };
+ }
+-test_shift!(test_shl_defined, Shl::shl);
+-test_shift_assign!(test_shl_assign_defined, ShlAssign::shl_assign);
+-test_shift!(test_shr_defined, Shr::shr);
+-test_shift_assign!(test_shr_assign_defined, ShrAssign::shr_assign);
++//test_shift!(test_shl_defined, Shl::shl);
++//test_shift_assign!(test_shl_assign_defined, ShlAssign::shl_assign);
++//test_shift!(test_shr_defined, Shr::shr);
++//test_shift_assign!(test_shr_assign_defined, ShrAssign::shr_assign);
--
2.21.0 (Apple Git-122)
diff --git a/compiler/rustc_codegen_cranelift/rust-toolchain b/compiler/rustc_codegen_cranelift/rust-toolchain
index ed1e64f45d..a08f00d19c 100644
--- a/compiler/rustc_codegen_cranelift/rust-toolchain
+++ b/compiler/rustc_codegen_cranelift/rust-toolchain
@@ -1 +1 @@
-nightly-2020-11-27
+nightly-2021-01-30
diff --git a/compiler/rustc_codegen_cranelift/scripts/cargo.sh b/compiler/rustc_codegen_cranelift/scripts/cargo.sh
index dcd40acc02..a3d6d30305 100755
--- a/compiler/rustc_codegen_cranelift/scripts/cargo.sh
+++ b/compiler/rustc_codegen_cranelift/scripts/cargo.sh
@@ -10,7 +10,9 @@ cmd=$1
shift || true
if [[ "$cmd" = "jit" ]]; then
-cargo "+${TOOLCHAIN}" rustc "$@" -- --jit
+cargo "+${TOOLCHAIN}" rustc "$@" -- -Cllvm-args=mode=jit -Cprefer-dynamic
+elif [[ "$cmd" = "lazy-jit" ]]; then
+cargo "+${TOOLCHAIN}" rustc "$@" -- -Cllvm-args=mode=jit-lazy -Cprefer-dynamic
else
cargo "+${TOOLCHAIN}" "$cmd" "$@"
fi
diff --git a/compiler/rustc_codegen_cranelift/scripts/config.sh b/compiler/rustc_codegen_cranelift/scripts/config.sh
index dea037e2bc..834708aa9a 100644
--- a/compiler/rustc_codegen_cranelift/scripts/config.sh
+++ b/compiler/rustc_codegen_cranelift/scripts/config.sh
@@ -12,28 +12,6 @@ else
exit 1
fi
-HOST_TRIPLE=$(rustc -vV | grep host | cut -d: -f2 | tr -d " ")
-TARGET_TRIPLE=$HOST_TRIPLE
-#TARGET_TRIPLE="x86_64-pc-windows-gnu"
-#TARGET_TRIPLE="aarch64-unknown-linux-gnu"
-
-linker=''
-RUN_WRAPPER=''
-export JIT_SUPPORTED=1
-if [[ "$HOST_TRIPLE" != "$TARGET_TRIPLE" ]]; then
- export JIT_SUPPORTED=0
- if [[ "$TARGET_TRIPLE" == "aarch64-unknown-linux-gnu" ]]; then
- # We are cross-compiling for aarch64. Use the correct linker and run tests in qemu.
- linker='-Clinker=aarch64-linux-gnu-gcc'
- RUN_WRAPPER='qemu-aarch64 -L /usr/aarch64-linux-gnu'
- elif [[ "$TARGET_TRIPLE" == "x86_64-pc-windows-gnu" ]]; then
- # We are cross-compiling for Windows. Run tests in wine.
- RUN_WRAPPER='wine'
- else
- echo "Unknown non-native platform"
- fi
-fi
-
if echo "$RUSTC_WRAPPER" | grep sccache; then
echo
echo -e "\x1b[1;93m=== Warning: Unset RUSTC_WRAPPER to prevent interference with sccache ===\x1b[0m"
@@ -44,16 +22,14 @@ fi
dir=$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)
export RUSTC=$dir"/bin/cg_clif"
-export RUSTFLAGS=$linker" "$RUSTFLAGS
+
export RUSTDOCFLAGS=$linker' -Cpanic=abort -Zpanic-abort-tests '\
'-Zcodegen-backend='$dir'/lib/librustc_codegen_cranelift.'$dylib_ext' --sysroot '$dir
# FIXME remove once the atomic shim is gone
-if [[ $(uname) == 'Darwin' ]]; then
+if [[ "$unamestr" == 'Darwin' ]]; then
export RUSTFLAGS="$RUSTFLAGS -Clink-arg=-undefined -Clink-arg=dynamic_lookup"
fi
-export LD_LIBRARY_PATH="$(rustc --print sysroot)/lib"
+export LD_LIBRARY_PATH="$(rustc --print sysroot)/lib:"$dir"/lib"
export DYLD_LIBRARY_PATH=$LD_LIBRARY_PATH
-
-export CG_CLIF_DISPLAY_CG_TIME=1
diff --git a/compiler/rustc_codegen_cranelift/scripts/ext_config.sh b/compiler/rustc_codegen_cranelift/scripts/ext_config.sh
new file mode 100644
index 0000000000..7971f620df
--- /dev/null
+++ b/compiler/rustc_codegen_cranelift/scripts/ext_config.sh
@@ -0,0 +1,27 @@
+# Note to people running shellcheck: this file should only be sourced, not executed directly.
+
+# Various env vars that should only be set for the build system but not for cargo.sh
+
+set -e
+
+export CG_CLIF_DISPLAY_CG_TIME=1
+export CG_CLIF_INCR_CACHE_DISABLED=1
+
+export HOST_TRIPLE=$(rustc -vV | grep host | cut -d: -f2 | tr -d " ")
+export TARGET_TRIPLE=${TARGET_TRIPLE:-$HOST_TRIPLE}
+
+export RUN_WRAPPER=''
+export JIT_SUPPORTED=1
+if [[ "$HOST_TRIPLE" != "$TARGET_TRIPLE" ]]; then
+ export JIT_SUPPORTED=0
+ if [[ "$TARGET_TRIPLE" == "aarch64-unknown-linux-gnu" ]]; then
+ # We are cross-compiling for aarch64. Use the correct linker and run tests in qemu.
+ export RUSTFLAGS='-Clinker=aarch64-linux-gnu-gcc '$RUSTFLAGS
+ export RUN_WRAPPER='qemu-aarch64 -L /usr/aarch64-linux-gnu'
+ elif [[ "$TARGET_TRIPLE" == "x86_64-pc-windows-gnu" ]]; then
+ # We are cross-compiling for Windows. Run tests in wine.
+ export RUN_WRAPPER='wine'
+ else
+ echo "Unknown non-native platform"
+ fi
+fi
diff --git a/compiler/rustc_codegen_cranelift/scripts/filter_profile.rs b/compiler/rustc_codegen_cranelift/scripts/filter_profile.rs
index 3327c10089..15388926ec 100755
--- a/compiler/rustc_codegen_cranelift/scripts/filter_profile.rs
+++ b/compiler/rustc_codegen_cranelift/scripts/filter_profile.rs
@@ -4,7 +4,7 @@
pushd $(dirname "$0")/../
source build/config.sh
popd
-PROFILE=$1 OUTPUT=$2 exec $RUSTC $RUSTFLAGS --jit $0
+PROFILE=$1 OUTPUT=$2 exec $RUSTC $RUSTFLAGS -Cllvm-args=mode=jit -Cprefer-dynamic $0
#*/
//! This program filters away uninteresting samples and trims uninteresting frames for stackcollapse
diff --git a/compiler/rustc_codegen_cranelift/scripts/tests.sh b/compiler/rustc_codegen_cranelift/scripts/tests.sh
index 114b6f30a4..d37b57babe 100755
--- a/compiler/rustc_codegen_cranelift/scripts/tests.sh
+++ b/compiler/rustc_codegen_cranelift/scripts/tests.sh
@@ -3,7 +3,7 @@
set -e
source build/config.sh
-export CG_CLIF_INCR_CACHE_DISABLED=1
+source scripts/ext_config.sh
MY_RUSTC="$RUSTC $RUSTFLAGS -L crate=target/out --out-dir target/out -Cdebuginfo=2"
function no_sysroot_tests() {
@@ -15,7 +15,10 @@ function no_sysroot_tests() {
if [[ "$JIT_SUPPORTED" = "1" ]]; then
echo "[JIT] mini_core_hello_world"
- CG_CLIF_JIT_ARGS="abc bcd" $MY_RUSTC --jit example/mini_core_hello_world.rs --cfg jit --target "$HOST_TRIPLE"
+ CG_CLIF_JIT_ARGS="abc bcd" $MY_RUSTC -Cllvm-args=mode=jit -Cprefer-dynamic example/mini_core_hello_world.rs --cfg jit --target "$HOST_TRIPLE"
+
+ echo "[JIT-lazy] mini_core_hello_world"
+ CG_CLIF_JIT_ARGS="abc bcd" $MY_RUSTC -Cllvm-args=mode=jit-lazy -Cprefer-dynamic example/mini_core_hello_world.rs --cfg jit --target "$HOST_TRIPLE"
else
echo "[JIT] mini_core_hello_world (skipped)"
fi
@@ -37,7 +40,10 @@ function base_sysroot_tests() {
if [[ "$JIT_SUPPORTED" = "1" ]]; then
echo "[JIT] std_example"
- $MY_RUSTC --jit example/std_example.rs --target "$HOST_TRIPLE"
+ $MY_RUSTC -Cllvm-args=mode=jit -Cprefer-dynamic example/std_example.rs --target "$HOST_TRIPLE"
+
+ echo "[JIT-lazy] std_example"
+ $MY_RUSTC -Cllvm-args=mode=jit-lazy -Cprefer-dynamic example/std_example.rs --cfg lazy_jit --target "$HOST_TRIPLE"
else
echo "[JIT] std_example (skipped)"
fi
diff --git a/compiler/rustc_codegen_cranelift/src/abi/comments.rs b/compiler/rustc_codegen_cranelift/src/abi/comments.rs
index 01073d26e8..9aab45b62e 100644
--- a/compiler/rustc_codegen_cranelift/src/abi/comments.rs
+++ b/compiler/rustc_codegen_cranelift/src/abi/comments.rs
@@ -4,10 +4,10 @@
use std::borrow::Cow;
use rustc_middle::mir;
+use rustc_target::abi::call::PassMode;
use cranelift_codegen::entity::EntityRef;
-use crate::abi::pass_mode::*;
use crate::prelude::*;
pub(super) fn add_args_header_comment(fx: &mut FunctionCx<'_, '_, impl Module>) {
@@ -21,9 +21,9 @@ pub(super) fn add_arg_comment<'tcx>(
kind: &str,
local: Option,
local_field: Option,
- params: EmptySinglePair,
- pass_mode: PassMode,
- ty: Ty<'tcx>,
+ params: &[Value],
+ arg_abi_mode: PassMode,
+ arg_layout: TyAndLayout<'tcx>,
) {
let local = if let Some(local) = local {
Cow::Owned(format!("{:?}", local))
@@ -37,12 +37,20 @@ pub(super) fn add_arg_comment<'tcx>(
};
let params = match params {
- Empty => Cow::Borrowed("-"),
- Single(param) => Cow::Owned(format!("= {:?}", param)),
- Pair(param_a, param_b) => Cow::Owned(format!("= {:?}, {:?}", param_a, param_b)),
+ [] => Cow::Borrowed("-"),
+ [param] => Cow::Owned(format!("= {:?}", param)),
+ [param_a, param_b] => Cow::Owned(format!("= {:?},{:?}", param_a, param_b)),
+ params => Cow::Owned(format!(
+ "= {}",
+ params
+ .iter()
+ .map(ToString::to_string)
+ .collect::>()
+ .join(",")
+ )),
};
- let pass_mode = format!("{:?}", pass_mode);
+ let pass_mode = format!("{:?}", arg_abi_mode);
fx.add_global_comment(format!(
"{kind:5}{local:>3}{local_field:<5} {params:10} {pass_mode:36} {ty:?}",
kind = kind,
@@ -50,7 +58,7 @@ pub(super) fn add_arg_comment<'tcx>(
local_field = local_field,
params = params,
pass_mode = pass_mode,
- ty = ty,
+ ty = arg_layout.ty,
));
}
diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
index 76e1987459..b2647e6c8d 100644
--- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
@@ -6,199 +6,51 @@ mod pass_mode;
mod returning;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
+use rustc_middle::ty::layout::FnAbiExt;
+use rustc_target::abi::call::{Conv, FnAbi};
use rustc_target::spec::abi::Abi;
-use cranelift_codegen::ir::{AbiParam, ArgumentPurpose};
+use cranelift_codegen::ir::AbiParam;
+use smallvec::smallvec;
use self::pass_mode::*;
use crate::prelude::*;
pub(crate) use self::returning::{can_return_to_ssa_var, codegen_return};
-// Copied from https://github.com/rust-lang/rust/blob/f52c72948aa1dd718cc1f168d21c91c584c0a662/src/librustc_middle/ty/layout.rs#L2301
-#[rustfmt::skip]
-pub(crate) fn fn_sig_for_fn_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> ty::PolyFnSig<'tcx> {
- use rustc_middle::ty::subst::Subst;
-
- // FIXME(davidtwco,eddyb): A `ParamEnv` should be passed through to this function.
- let ty = instance.ty(tcx, ty::ParamEnv::reveal_all());
- match *ty.kind() {
- ty::FnDef(..) => {
- // HACK(davidtwco,eddyb): This is a workaround for polymorphization considering
- // parameters unused if they show up in the signature, but not in the `mir::Body`
- // (i.e. due to being inside a projection that got normalized, see
- // `src/test/ui/polymorphization/normalized_sig_types.rs`), and codegen not keeping
- // track of a polymorphization `ParamEnv` to allow normalizing later.
- let mut sig = match *ty.kind() {
- ty::FnDef(def_id, substs) => tcx
- .normalize_erasing_regions(tcx.param_env(def_id), tcx.fn_sig(def_id))
- .subst(tcx, substs),
- _ => unreachable!(),
- };
-
- if let ty::InstanceDef::VtableShim(..) = instance.def {
- // Modify `fn(self, ...)` to `fn(self: *mut Self, ...)`.
- sig = sig.map_bound(|mut sig| {
- let mut inputs_and_output = sig.inputs_and_output.to_vec();
- inputs_and_output[0] = tcx.mk_mut_ptr(inputs_and_output[0]);
- sig.inputs_and_output = tcx.intern_type_list(&inputs_and_output);
- sig
- });
- }
- sig
- }
- ty::Closure(def_id, substs) => {
- let sig = substs.as_closure().sig();
-
- let env_ty = tcx.closure_env_ty(def_id, substs).unwrap();
- sig.map_bound(|sig| {
- tcx.mk_fn_sig(
- std::iter::once(env_ty.skip_binder()).chain(sig.inputs().iter().cloned()),
- sig.output(),
- sig.c_variadic,
- sig.unsafety,
- sig.abi,
- )
- })
- }
- ty::Generator(_, substs, _) => {
- let sig = substs.as_generator().poly_sig();
-
- let env_region = ty::ReLateBound(ty::INNERMOST, ty::BoundRegion { kind: ty::BrEnv });
- let env_ty = tcx.mk_mut_ref(tcx.mk_region(env_region), ty);
-
- let pin_did = tcx.require_lang_item(rustc_hir::LangItem::Pin, None);
- let pin_adt_ref = tcx.adt_def(pin_did);
- let pin_substs = tcx.intern_substs(&[env_ty.into()]);
- let env_ty = tcx.mk_adt(pin_adt_ref, pin_substs);
-
- sig.map_bound(|sig| {
- let state_did = tcx.require_lang_item(rustc_hir::LangItem::GeneratorState, None);
- let state_adt_ref = tcx.adt_def(state_did);
- let state_substs =
- tcx.intern_substs(&[sig.yield_ty.into(), sig.return_ty.into()]);
- let ret_ty = tcx.mk_adt(state_adt_ref, state_substs);
-
- tcx.mk_fn_sig(
- [env_ty, sig.resume_ty].iter(),
- &ret_ty,
- false,
- rustc_hir::Unsafety::Normal,
- rustc_target::spec::abi::Abi::Rust,
- )
- })
- }
- _ => bug!("unexpected type {:?} in Instance::fn_sig", ty),
- }
-}
-
-fn clif_sig_from_fn_sig<'tcx>(
+fn clif_sig_from_fn_abi<'tcx>(
tcx: TyCtxt<'tcx>,
triple: &target_lexicon::Triple,
- sig: FnSig<'tcx>,
- span: Span,
- is_vtable_fn: bool,
- requires_caller_location: bool,
+ fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
) -> Signature {
- let abi = match sig.abi {
- Abi::System => Abi::C,
- abi => abi,
- };
- let (call_conv, inputs, output): (CallConv, Vec>, Ty<'tcx>) = match abi {
- Abi::Rust => (
- CallConv::triple_default(triple),
- sig.inputs().to_vec(),
- sig.output(),
- ),
- Abi::C | Abi::Unadjusted => (
- CallConv::triple_default(triple),
- sig.inputs().to_vec(),
- sig.output(),
- ),
- Abi::SysV64 => (CallConv::SystemV, sig.inputs().to_vec(), sig.output()),
- Abi::RustCall => {
- assert_eq!(sig.inputs().len(), 2);
- let extra_args = match sig.inputs().last().unwrap().kind() {
- ty::Tuple(ref tupled_arguments) => tupled_arguments,
- _ => bug!("argument to function with \"rust-call\" ABI is not a tuple"),
- };
- let mut inputs: Vec> = vec![sig.inputs()[0]];
- inputs.extend(extra_args.types());
- (CallConv::triple_default(triple), inputs, sig.output())
+ let call_conv = match fn_abi.conv {
+ Conv::Rust | Conv::C => CallConv::triple_default(triple),
+ Conv::X86_64SysV => CallConv::SystemV,
+ Conv::X86_64Win64 => CallConv::WindowsFastcall,
+ Conv::ArmAapcs
+ | Conv::CCmseNonSecureCall
+ | Conv::Msp430Intr
+ | Conv::PtxKernel
+ | Conv::X86Fastcall
+ | Conv::X86Intr
+ | Conv::X86Stdcall
+ | Conv::X86ThisCall
+ | Conv::X86VectorCall
+ | Conv::AmdGpuKernel
+ | Conv::AvrInterrupt
+ | Conv::AvrNonBlockingInterrupt => {
+ todo!("{:?}", fn_abi.conv)
}
- Abi::System => unreachable!(),
- Abi::RustIntrinsic => (
- CallConv::triple_default(triple),
- sig.inputs().to_vec(),
- sig.output(),
- ),
- _ => unimplemented!("unsupported abi {:?}", sig.abi),
};
-
- let inputs = inputs
- .into_iter()
- .enumerate()
- .map(|(i, ty)| {
- let mut layout = tcx.layout_of(ParamEnv::reveal_all().and(ty)).unwrap();
- if i == 0 && is_vtable_fn {
- // Virtual calls turn their self param into a thin pointer.
- // See https://github.com/rust-lang/rust/blob/37b6a5e5e82497caf5353d9d856e4eb5d14cbe06/src/librustc/ty/layout.rs#L2519-L2572 for more info
- layout = tcx
- .layout_of(ParamEnv::reveal_all().and(tcx.mk_mut_ptr(tcx.mk_unit())))
- .unwrap();
- }
- let pass_mode = get_pass_mode(tcx, layout);
- if abi != Abi::Rust && abi != Abi::RustCall && abi != Abi::RustIntrinsic {
- match pass_mode {
- PassMode::NoPass | PassMode::ByVal(_) => {}
- PassMode::ByRef { size: Some(size) } => {
- let purpose = ArgumentPurpose::StructArgument(u32::try_from(size.bytes()).expect("struct too big to pass on stack"));
- return EmptySinglePair::Single(AbiParam::special(pointer_ty(tcx), purpose)).into_iter();
- }
- PassMode::ByValPair(_, _) | PassMode::ByRef { size: None } => {
- tcx.sess.span_warn(
- span,
- &format!(
- "Argument of type `{:?}` with pass mode `{:?}` is not yet supported \
- for non-rust abi `{}`. Calling this function may result in a crash.",
- layout.ty,
- pass_mode,
- abi,
- ),
- );
- }
- }
- }
- pass_mode.get_param_ty(tcx).map(AbiParam::new).into_iter()
- })
+ let inputs = fn_abi
+ .args
+ .iter()
+ .map(|arg_abi| arg_abi.get_abi_param(tcx).into_iter())
.flatten();
- let (mut params, returns): (Vec<_>, Vec<_>) = match get_pass_mode(
- tcx,
- tcx.layout_of(ParamEnv::reveal_all().and(output)).unwrap(),
- ) {
- PassMode::NoPass => (inputs.collect(), vec![]),
- PassMode::ByVal(ret_ty) => (inputs.collect(), vec![AbiParam::new(ret_ty)]),
- PassMode::ByValPair(ret_ty_a, ret_ty_b) => (
- inputs.collect(),
- vec![AbiParam::new(ret_ty_a), AbiParam::new(ret_ty_b)],
- ),
- PassMode::ByRef { size: Some(_) } => {
- (
- Some(pointer_ty(tcx)) // First param is place to put return val
- .into_iter()
- .map(|ty| AbiParam::special(ty, ArgumentPurpose::StructReturn))
- .chain(inputs)
- .collect(),
- vec![],
- )
- }
- PassMode::ByRef { size: None } => todo!(),
- };
-
- if requires_caller_location {
- params.push(AbiParam::new(pointer_ty(tcx)));
- }
+ let (return_ptr, returns) = fn_abi.ret.get_abi_return(tcx);
+ // Sometimes the first param is an pointer to the place where the return value needs to be stored.
+ let params: Vec<_> = return_ptr.into_iter().chain(inputs).collect();
Signature {
params,
@@ -207,30 +59,17 @@ fn clif_sig_from_fn_sig<'tcx>(
}
}
-pub(crate) fn get_function_name_and_sig<'tcx>(
+pub(crate) fn get_function_sig<'tcx>(
tcx: TyCtxt<'tcx>,
triple: &target_lexicon::Triple,
inst: Instance<'tcx>,
- support_vararg: bool,
-) -> (String, Signature) {
+) -> Signature {
assert!(!inst.substs.needs_infer());
- let fn_sig = tcx
- .normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), fn_sig_for_fn_abi(tcx, inst));
- if fn_sig.c_variadic && !support_vararg {
- tcx.sess.span_fatal(
- tcx.def_span(inst.def_id()),
- "Variadic function definitions are not yet supported",
- );
- }
- let sig = clif_sig_from_fn_sig(
+ clif_sig_from_fn_abi(
tcx,
triple,
- fn_sig,
- tcx.def_span(inst.def_id()),
- false,
- inst.def.requires_caller_location(tcx),
- );
- (tcx.symbol_name(inst).name.to_string(), sig)
+ &FnAbi::of_instance(&RevealAllLayoutCx(tcx), inst, &[]),
+ )
}
/// Instance must be monomorphized
@@ -239,7 +78,8 @@ pub(crate) fn import_function<'tcx>(
module: &mut impl Module,
inst: Instance<'tcx>,
) -> FuncId {
- let (name, sig) = get_function_name_and_sig(tcx, module.isa().triple(), inst, true);
+ let name = tcx.symbol_name(inst).name.to_string();
+ let sig = get_function_sig(tcx, module.isa().triple(), inst);
module
.declare_function(&name, Linkage::Import, &sig)
.unwrap()
@@ -263,13 +103,13 @@ impl<'tcx, M: Module> FunctionCx<'_, 'tcx, M> {
pub(crate) fn lib_call(
&mut self,
name: &str,
- input_tys: Vec,
- output_tys: Vec,
+ params: Vec,
+ returns: Vec,
args: &[Value],
) -> &[Value] {
let sig = Signature {
- params: input_tys.iter().cloned().map(AbiParam::new).collect(),
- returns: output_tys.iter().cloned().map(AbiParam::new).collect(),
+ params,
+ returns,
call_conv: CallConv::triple_default(self.triple()),
};
let func_id = self
@@ -301,16 +141,18 @@ impl<'tcx, M: Module> FunctionCx<'_, 'tcx, M> {
.iter()
.map(|arg| {
(
- self.clif_type(arg.layout().ty).unwrap(),
+ AbiParam::new(self.clif_type(arg.layout().ty).unwrap()),
arg.load_scalar(self),
)
})
.unzip();
let return_layout = self.layout_of(return_ty);
let return_tys = if let ty::Tuple(tup) = return_ty.kind() {
- tup.types().map(|ty| self.clif_type(ty).unwrap()).collect()
+ tup.types()
+ .map(|ty| AbiParam::new(self.clif_type(ty).unwrap()))
+ .collect()
} else {
- vec![self.clif_type(return_ty).unwrap()]
+ vec![AbiParam::new(self.clif_type(return_ty).unwrap())]
};
let ret_vals = self.lib_call(name, input_tys, return_tys, &args);
match *ret_vals {
@@ -352,12 +194,25 @@ pub(crate) fn codegen_fn_prelude<'tcx>(
fx: &mut FunctionCx<'_, 'tcx, impl Module>,
start_block: Block,
) {
+ fx.bcx.append_block_params_for_function_params(start_block);
+
+ fx.bcx.switch_to_block(start_block);
+ fx.bcx.ins().nop();
+
let ssa_analyzed = crate::analyze::analyze(fx);
#[cfg(debug_assertions)]
self::comments::add_args_header_comment(fx);
- let ret_place = self::returning::codegen_return_param(fx, &ssa_analyzed, start_block);
+ let mut block_params_iter = fx
+ .bcx
+ .func
+ .dfg
+ .block_params(start_block)
+ .to_vec()
+ .into_iter();
+ let ret_place =
+ self::returning::codegen_return_param(fx, &ssa_analyzed, &mut block_params_iter);
assert_eq!(fx.local_map.push(ret_place), RETURN_PLACE);
// None means pass_mode == NoPass
@@ -366,6 +221,9 @@ pub(crate) fn codegen_fn_prelude<'tcx>(
Spread(Vec