Skip to content

Rollup of 7 pull requests #94824

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 18 commits into from
Mar 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
b328688
Statically compile libstdc++ everywhere if asked
Mar 8, 2022
307ee94
only emit pointer-like metadata for BZST-allocator Box
compiler-errors Mar 8, 2022
8852752
Treat unstable lints as unknown
djkoloski Feb 23, 2022
2677eca
Switch the primary diagnostic to `unknown_lints`
djkoloski Feb 28, 2022
1593ce8
Fill out documentation for new lint
djkoloski Feb 28, 2022
fa10d90
Fix docs, fix incorrect lint source in note
djkoloski Mar 2, 2022
1c31a95
Update for changes to other lints
djkoloski Mar 8, 2022
8073a88
Implement macro meta-variable expressions
c410-f3r Mar 9, 2022
29d979f
enable portable-simd doctests in Miri
RalfJung Mar 10, 2022
72a25d0
Use implicit capture syntax in format_args
mahmoud-moursy Feb 12, 2022
5d830f4
Update browser-ui-test version
GuillaumeGomez Mar 10, 2022
5a7f09d
Rollup merge of #93950 - T-O-R-U-S:use-modern-formatting-for-format!-…
Dylan-DPC Mar 10, 2022
1ed2a94
Rollup merge of #94274 - djkoloski:unknown_unstable_lints, r=tmandry
Dylan-DPC Mar 10, 2022
634a6b0
Rollup merge of #94368 - c410-f3r:metaaaaaaaaaaaaaaaaaaaaaaaaaaa, r=p…
Dylan-DPC Mar 10, 2022
1cf8793
Rollup merge of #94719 - jonhoo:enable-static-lld, r=Mark-Simulacrum
Dylan-DPC Mar 10, 2022
b18b2d1
Rollup merge of #94728 - compiler-errors:box-allocator-zst-meta, r=mi…
Dylan-DPC Mar 10, 2022
3979e15
Rollup merge of #94790 - RalfJung:portable-simd-miri, r=Dylan-DPC
Dylan-DPC Mar 10, 2022
456135c
Rollup merge of #94811 - GuillaumeGomez:update-browser-ui-test, r=not…
Dylan-DPC Mar 10, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/rustc_ast/src/util/literal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pub enum LitError {

impl LitKind {
/// Converts literal token into a semantic literal.
fn from_lit_token(lit: token::Lit) -> Result<LitKind, LitError> {
pub fn from_lit_token(lit: token::Lit) -> Result<LitKind, LitError> {
let token::Lit { kind, symbol, suffix } = lit;
if suffix.is_some() && !kind.may_have_suffix() {
return Err(LitError::InvalidSuffix);
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -617,7 +617,9 @@ pub fn type_metadata<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll
ty::RawPtr(ty::TypeAndMut { ty: pointee_type, .. }) | ty::Ref(_, pointee_type, _) => {
pointer_or_reference_metadata(cx, t, pointee_type, unique_type_id)
}
ty::Adt(def, _) if def.is_box() => {
// Box<T, A> may have a non-ZST allocator A. In that case, we
// cannot treat Box<T, A> as just an owned alias of `*mut T`.
ty::Adt(def, substs) if def.is_box() && cx.layout_of(substs.type_at(1)).is_zst() => {
pointer_or_reference_metadata(cx, t, t.boxed_ty(), unique_type_id)
}
ty::FnDef(..) | ty::FnPtr(_) => subroutine_type_metadata(cx, unique_type_id),
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_errors/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1087,12 +1087,12 @@ impl HandlerInner {
let warnings = match self.deduplicated_warn_count {
0 => String::new(),
1 => "1 warning emitted".to_string(),
count => format!("{} warnings emitted", count),
count => format!("{count} warnings emitted"),
};
let errors = match self.deduplicated_err_count {
0 => String::new(),
1 => "aborting due to previous error".to_string(),
count => format!("aborting due to {} previous errors", count),
count => format!("aborting due to {count} previous errors"),
};
if self.treat_err_as_bug() {
return;
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_expand/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#![feature(crate_visibility_modifier)]
#![feature(decl_macro)]
#![feature(if_let_guard)]
#![feature(let_chains)]
#![feature(let_else)]
#![feature(proc_macro_diagnostic)]
#![feature(proc_macro_internals)]
Expand Down
16 changes: 10 additions & 6 deletions compiler/rustc_expand/src/mbe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,17 @@
crate mod macro_check;
crate mod macro_parser;
crate mod macro_rules;
crate mod metavar_expr;
crate mod quoted;
crate mod transcribe;

use metavar_expr::MetaVarExpr;
use rustc_ast::token::{self, NonterminalKind, Token, TokenKind};
use rustc_ast::tokenstream::DelimSpan;

use rustc_data_structures::sync::Lrc;
use rustc_span::symbol::Ident;
use rustc_span::Span;

use rustc_data_structures::sync::Lrc;

/// Contains the sub-token-trees of a "delimited" token tree, such as the contents of `(`. Note
/// that the delimiter itself might be `NoDelim`.
#[derive(Clone, PartialEq, Encodable, Decodable, Debug)]
Expand Down Expand Up @@ -73,8 +73,8 @@ enum KleeneOp {
ZeroOrOne,
}

/// Similar to `tokenstream::TokenTree`, except that `$i`, `$i:ident`, and `$(...)`
/// are "first-class" token trees. Useful for parsing macros.
/// Similar to `tokenstream::TokenTree`, except that `$i`, `$i:ident`, `$(...)`,
/// and `${...}` are "first-class" token trees. Useful for parsing macros.
#[derive(Debug, Clone, PartialEq, Encodable, Decodable)]
enum TokenTree {
Token(Token),
Expand All @@ -85,6 +85,8 @@ enum TokenTree {
MetaVar(Span, Ident),
/// e.g., `$var:expr`. This is only used in the left hand side of MBE macros.
MetaVarDecl(Span, Ident /* name to bind */, Option<NonterminalKind>),
/// A meta-variable expression inside `${...}`
MetaVarExpr(DelimSpan, MetaVarExpr),
}

impl TokenTree {
Expand Down Expand Up @@ -139,7 +141,9 @@ impl TokenTree {
TokenTree::Token(Token { span, .. })
| TokenTree::MetaVar(span, _)
| TokenTree::MetaVarDecl(span, _, _) => span,
TokenTree::Delimited(span, _) | TokenTree::Sequence(span, _) => span.entire(),
TokenTree::Delimited(span, _)
| TokenTree::MetaVarExpr(span, _)
| TokenTree::Sequence(span, _) => span.entire(),
}
}

Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_expand/src/mbe/macro_check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,8 @@ fn check_binders(
binders.insert(name, BinderInfo { span, ops: ops.into() });
}
}
// `MetaVarExpr` can not appear in the LHS of a macro arm
TokenTree::MetaVarExpr(..) => {}
TokenTree::Delimited(_, ref del) => {
for tt in &del.tts {
check_binders(sess, node_id, tt, macros, binders, ops, valid);
Expand Down Expand Up @@ -335,6 +337,8 @@ fn check_occurrences(
let name = MacroRulesNormalizedIdent::new(name);
check_ops_is_prefix(sess, node_id, macros, binders, ops, span, name);
}
// FIXME(c410-f3r) Check token (https://github.com/rust-lang/rust/issues/93902)
TokenTree::MetaVarExpr(..) => {}
TokenTree::Delimited(_, ref del) => {
check_nested_occurrences(sess, node_id, &del.tts, macros, binders, ops, valid);
}
Expand Down
13 changes: 9 additions & 4 deletions compiler/rustc_expand/src/mbe/macro_parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ struct MatcherPos<'root, 'tt> {

// This type is used a lot. Make sure it doesn't unintentionally get bigger.
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
rustc_data_structures::static_assert_size!(MatcherPos<'_, '_>, 192);
rustc_data_structures::static_assert_size!(MatcherPos<'_, '_>, 240);

impl<'root, 'tt> MatcherPos<'root, 'tt> {
/// Generates the top-level matcher position in which the "dot" is before the first token of
Expand Down Expand Up @@ -321,10 +321,13 @@ pub(super) fn count_names(ms: &[TokenTree]) -> usize {
ms.iter().fold(0, |count, elt| {
count
+ match *elt {
TokenTree::Sequence(_, ref seq) => seq.num_captures,
TokenTree::Delimited(_, ref delim) => count_names(&delim.tts),
TokenTree::MetaVar(..) => 0,
TokenTree::MetaVarDecl(..) => 1,
// FIXME(c410-f3r) MetaVarExpr should be handled instead of being ignored
// https://github.com/rust-lang/rust/issues/9390
TokenTree::MetaVarExpr(..) => 0,
TokenTree::Sequence(_, ref seq) => seq.num_captures,
TokenTree::Token(..) => 0,
}
})
Expand Down Expand Up @@ -436,7 +439,9 @@ fn nameize<I: Iterator<Item = NamedMatch>>(
}
Occupied(..) => return Err((sp, format!("duplicated bind name: {}", bind_name))),
},
TokenTree::MetaVar(..) | TokenTree::Token(..) => (),
// FIXME(c410-f3r) MetaVar and MetaVarExpr should be handled instead of being ignored
// https://github.com/rust-lang/rust/issues/9390
TokenTree::MetaVar(..) | TokenTree::MetaVarExpr(..) | TokenTree::Token(..) => {}
}

Ok(())
Expand Down Expand Up @@ -650,7 +655,7 @@ fn inner_parse_loop<'root, 'tt>(
// rules. NOTE that this is not necessarily an error unless _all_ items in
// `cur_items` end up doing this. There may still be some other matchers that do
// end up working out.
TokenTree::Token(..) | TokenTree::MetaVar(..) => {}
TokenTree::Token(..) | TokenTree::MetaVar(..) | TokenTree::MetaVarExpr(..) => {}
}
}
}
Expand Down
20 changes: 16 additions & 4 deletions compiler/rustc_expand/src/mbe/macro_rules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,10 @@ fn check_lhs_no_empty_seq(sess: &ParseSess, tts: &[mbe::TokenTree]) -> bool {
use mbe::TokenTree;
for tt in tts {
match *tt {
TokenTree::Token(..) | TokenTree::MetaVar(..) | TokenTree::MetaVarDecl(..) => (),
TokenTree::Token(..)
| TokenTree::MetaVar(..)
| TokenTree::MetaVarDecl(..)
| TokenTree::MetaVarExpr(..) => (),
TokenTree::Delimited(_, ref del) => {
if !check_lhs_no_empty_seq(sess, &del.tts) {
return false;
Expand Down Expand Up @@ -669,7 +672,10 @@ impl FirstSets {
let mut first = TokenSet::empty();
for tt in tts.iter().rev() {
match *tt {
TokenTree::Token(..) | TokenTree::MetaVar(..) | TokenTree::MetaVarDecl(..) => {
TokenTree::Token(..)
| TokenTree::MetaVar(..)
| TokenTree::MetaVarDecl(..)
| TokenTree::MetaVarExpr(..) => {
first.replace_with(tt.clone());
}
TokenTree::Delimited(span, ref delimited) => {
Expand Down Expand Up @@ -731,7 +737,10 @@ impl FirstSets {
for tt in tts.iter() {
assert!(first.maybe_empty);
match *tt {
TokenTree::Token(..) | TokenTree::MetaVar(..) | TokenTree::MetaVarDecl(..) => {
TokenTree::Token(..)
| TokenTree::MetaVar(..)
| TokenTree::MetaVarDecl(..)
| TokenTree::MetaVarExpr(..) => {
first.add_one(tt.clone());
return first;
}
Expand Down Expand Up @@ -907,7 +916,10 @@ fn check_matcher_core(
// First, update `last` so that it corresponds to the set
// of NT tokens that might end the sequence `... token`.
match *token {
TokenTree::Token(..) | TokenTree::MetaVar(..) | TokenTree::MetaVarDecl(..) => {
TokenTree::Token(..)
| TokenTree::MetaVar(..)
| TokenTree::MetaVarDecl(..)
| TokenTree::MetaVarExpr(..) => {
if token_can_be_followed_by_any(token) {
// don't need to track tokens that work with any,
last.replace_with_irrelevant();
Expand Down
157 changes: 157 additions & 0 deletions compiler/rustc_expand/src/mbe/metavar_expr.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
use rustc_ast::token;
use rustc_ast::tokenstream::{Cursor, TokenStream, TokenTree};
use rustc_ast::{LitIntType, LitKind};
use rustc_ast_pretty::pprust;
use rustc_errors::{Applicability, PResult};
use rustc_session::parse::ParseSess;
use rustc_span::symbol::Ident;
use rustc_span::Span;

/// A meta-variable expression, for expansions based on properties of meta-variables.
#[derive(Debug, Clone, PartialEq, Encodable, Decodable)]
crate enum MetaVarExpr {
/// The number of repetitions of an identifier, optionally limited to a number
/// of outer-most repetition depths. If the depth limit is `None` then the depth is unlimited.
Count(Ident, Option<usize>),

/// Ignore a meta-variable for repetition without expansion.
Ignore(Ident),

/// The index of the repetition at a particular depth, where 0 is the inner-most
/// repetition. The `usize` is the depth.
Index(usize),

/// The length of the repetition at a particular depth, where 0 is the inner-most
/// repetition. The `usize` is the depth.
Length(usize),
}

impl MetaVarExpr {
/// Attempt to parse a meta-variable expression from a token stream.
crate fn parse<'sess>(
input: &TokenStream,
outer_span: Span,
sess: &'sess ParseSess,
) -> PResult<'sess, MetaVarExpr> {
let mut tts = input.trees();
let ident = parse_ident(&mut tts, sess, outer_span)?;
let Some(TokenTree::Delimited(_, token::Paren, args)) = tts.next() else {
let msg = "meta-variable expression parameter must be wrapped in parentheses";
return Err(sess.span_diagnostic.struct_span_err(ident.span, msg));
};
check_trailing_token(&mut tts, sess)?;
let mut iter = args.trees();
let rslt = match &*ident.as_str() {
"count" => parse_count(&mut iter, sess, ident.span)?,
"ignore" => MetaVarExpr::Ignore(parse_ident(&mut iter, sess, ident.span)?),
"index" => MetaVarExpr::Index(parse_depth(&mut iter, sess, ident.span)?),
"length" => MetaVarExpr::Length(parse_depth(&mut iter, sess, ident.span)?),
_ => {
let err_msg = "unrecognized meta-variable expression";
let mut err = sess.span_diagnostic.struct_span_err(ident.span, err_msg);
err.span_suggestion(
ident.span,
"supported expressions are count, ignore, index and length",
String::new(),
Applicability::MachineApplicable,
);
return Err(err);
}
};
check_trailing_token(&mut iter, sess)?;
Ok(rslt)
}

crate fn ident(&self) -> Option<&Ident> {
match self {
MetaVarExpr::Count(ident, _) | MetaVarExpr::Ignore(ident) => Some(&ident),
MetaVarExpr::Index(..) | MetaVarExpr::Length(..) => None,
}
}
}

// Checks if there are any remaining tokens. For example, `${ignore(ident ... a b c ...)}`
fn check_trailing_token<'sess>(iter: &mut Cursor, sess: &'sess ParseSess) -> PResult<'sess, ()> {
if let Some(tt) = iter.next() {
let mut diag = sess.span_diagnostic.struct_span_err(
tt.span(),
&format!("unexpected token: {}", pprust::tt_to_string(&tt)),
);
diag.span_note(tt.span(), "meta-variable expression must not have trailing tokens");
Err(diag)
} else {
Ok(())
}
}

/// Parse a meta-variable `count` expression: `count(ident[, depth])`
fn parse_count<'sess>(
iter: &mut Cursor,
sess: &'sess ParseSess,
span: Span,
) -> PResult<'sess, MetaVarExpr> {
let ident = parse_ident(iter, sess, span)?;
let depth = if try_eat_comma(iter) { Some(parse_depth(iter, sess, span)?) } else { None };
Ok(MetaVarExpr::Count(ident, depth))
}

/// Parses the depth used by index(depth) and length(depth).
fn parse_depth<'sess>(
iter: &mut Cursor,
sess: &'sess ParseSess,
span: Span,
) -> PResult<'sess, usize> {
let Some(tt) = iter.next() else { return Ok(0) };
let TokenTree::Token(token::Token {
kind: token::TokenKind::Literal(lit), ..
}) = tt else {
return Err(sess.span_diagnostic.struct_span_err(
span,
"meta-variable expression depth must be a literal"
));
};
if let Ok(lit_kind) = LitKind::from_lit_token(lit)
&& let LitKind::Int(n_u128, LitIntType::Unsuffixed) = lit_kind
&& let Ok(n_usize) = usize::try_from(n_u128)
{
Ok(n_usize)
}
else {
let msg = "only unsuffixes integer literals are supported in meta-variable expressions";
Err(sess.span_diagnostic.struct_span_err(span, msg))
}
}

/// Parses an generic ident
fn parse_ident<'sess>(
iter: &mut Cursor,
sess: &'sess ParseSess,
span: Span,
) -> PResult<'sess, Ident> {
let err_fn = |msg| sess.span_diagnostic.struct_span_err(span, msg);
if let Some(tt) = iter.next() && let TokenTree::Token(token) = tt {
if let Some((elem, false)) = token.ident() {
return Ok(elem);
}
let token_str = pprust::token_to_string(&token);
let mut err = err_fn(&format!("expected identifier, found `{}`", &token_str));
err.span_suggestion(
token.span,
&format!("try removing `{}`", &token_str),
String::new(),
Applicability::MaybeIncorrect,
);
return Err(err);
}
Err(err_fn("expected identifier"))
}

/// Tries to move the iterator forward returning `true` if there is a comma. If not, then the
/// iterator is not modified and the result is `false`.
fn try_eat_comma(iter: &mut Cursor) -> bool {
if let Some(TokenTree::Token(token::Token { kind: token::Comma, .. })) = iter.look_ahead(0) {
let _ = iter.next();
return true;
}
false
}
Loading