Skip to content

Commit ca00683

Browse files
committed
Auto merge of #143840 - matthiaskrgr:rollup-fun509q, r=matthiaskrgr
Rollup of 9 pull requests Successful merges: - #143213 (de-duplicate condition scoping logic between AST→HIR lowering and `ScopeTree` construction) - #143461 (make `cfg_select` a builtin macro) - #143519 (Check assoc consts and tys later like assoc fns) - #143554 (slice: Mark `rotate_left`, `rotate_right` unstably const) - #143704 (Be a bit more careful around exotic cycles in in the inliner) - #143774 (constify `From` and `Into`) - #143786 (Fix fallback for CI_JOB_NAME) - #143796 (Fix ICE for parsed attributes with longer path not handled by CheckAttribute) - #143798 (Remove format short command trait) r? `@ghost` `@rustbot` modify labels: rollup
2 parents bfc046a + 76c1c6c commit ca00683

File tree

59 files changed

+778
-321
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+778
-321
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4349,6 +4349,7 @@ dependencies = [
43494349
"rustc_ast_lowering",
43504350
"rustc_ast_pretty",
43514351
"rustc_attr_data_structures",
4352+
"rustc_attr_parsing",
43524353
"rustc_data_structures",
43534354
"rustc_errors",
43544355
"rustc_expand",

compiler/rustc_ast_lowering/src/expr.rs

Lines changed: 4 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -528,7 +528,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
528528
then: &Block,
529529
else_opt: Option<&Expr>,
530530
) -> hir::ExprKind<'hir> {
531-
let lowered_cond = self.lower_cond(cond);
531+
let lowered_cond = self.lower_expr(cond);
532532
let then_expr = self.lower_block_expr(then);
533533
if let Some(rslt) = else_opt {
534534
hir::ExprKind::If(
@@ -541,44 +541,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
541541
}
542542
}
543543

544-
// Lowers a condition (i.e. `cond` in `if cond` or `while cond`), wrapping it in a terminating scope
545-
// so that temporaries created in the condition don't live beyond it.
546-
fn lower_cond(&mut self, cond: &Expr) -> &'hir hir::Expr<'hir> {
547-
fn has_let_expr(expr: &Expr) -> bool {
548-
match &expr.kind {
549-
ExprKind::Binary(_, lhs, rhs) => has_let_expr(lhs) || has_let_expr(rhs),
550-
ExprKind::Let(..) => true,
551-
_ => false,
552-
}
553-
}
554-
555-
// We have to take special care for `let` exprs in the condition, e.g. in
556-
// `if let pat = val` or `if foo && let pat = val`, as we _do_ want `val` to live beyond the
557-
// condition in this case.
558-
//
559-
// In order to maintain the drop behavior for the non `let` parts of the condition,
560-
// we still wrap them in terminating scopes, e.g. `if foo && let pat = val` essentially
561-
// gets transformed into `if { let _t = foo; _t } && let pat = val`
562-
match &cond.kind {
563-
ExprKind::Binary(op @ Spanned { node: ast::BinOpKind::And, .. }, lhs, rhs)
564-
if has_let_expr(cond) =>
565-
{
566-
let op = self.lower_binop(*op);
567-
let lhs = self.lower_cond(lhs);
568-
let rhs = self.lower_cond(rhs);
569-
570-
self.arena.alloc(self.expr(cond.span, hir::ExprKind::Binary(op, lhs, rhs)))
571-
}
572-
ExprKind::Let(..) => self.lower_expr(cond),
573-
_ => {
574-
let cond = self.lower_expr(cond);
575-
let reason = DesugaringKind::CondTemporary;
576-
let span_block = self.mark_span_with_reason(reason, cond.span, None);
577-
self.expr_drop_temps(span_block, cond)
578-
}
579-
}
580-
}
581-
582544
// We desugar: `'label: while $cond $body` into:
583545
//
584546
// ```
@@ -602,7 +564,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
602564
body: &Block,
603565
opt_label: Option<Label>,
604566
) -> hir::ExprKind<'hir> {
605-
let lowered_cond = self.with_loop_condition_scope(|t| t.lower_cond(cond));
567+
let lowered_cond = self.with_loop_condition_scope(|t| t.lower_expr(cond));
606568
let then = self.lower_block_expr(body);
607569
let expr_break = self.expr_break(span);
608570
let stmt_break = self.stmt_expr(span, expr_break);
@@ -2091,7 +2053,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
20912053
/// In terms of drop order, it has the same effect as wrapping `expr` in
20922054
/// `{ let _t = $expr; _t }` but should provide better compile-time performance.
20932055
///
2094-
/// The drop order can be important in e.g. `if expr { .. }`.
2056+
/// The drop order can be important, e.g. to drop temporaries from an `async fn`
2057+
/// body before its parameters.
20952058
pub(super) fn expr_drop_temps(
20962059
&mut self,
20972060
span: Span,

compiler/rustc_attr_parsing/src/context.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -735,6 +735,11 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
735735
attributes
736736
}
737737

738+
/// Returns whether there is a parser for an attribute with this name
739+
pub fn is_parsed_attribute(path: &[Symbol]) -> bool {
740+
Late::parsers().0.contains_key(path)
741+
}
742+
738743
fn lower_attr_args(&self, args: &ast::AttrArgs, lower_span: impl Fn(Span) -> Span) -> AttrArgs {
739744
match args {
740745
ast::AttrArgs::Empty => AttrArgs::Empty,

compiler/rustc_builtin_macros/messages.ftl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,12 @@ builtin_macros_cfg_accessible_literal_path = `cfg_accessible` path cannot be a l
8181
builtin_macros_cfg_accessible_multiple_paths = multiple `cfg_accessible` paths are specified
8282
builtin_macros_cfg_accessible_unspecified_path = `cfg_accessible` path is not specified
8383
84+
builtin_macros_cfg_select_no_matches = none of the rules in this `cfg_select` evaluated to true
85+
86+
builtin_macros_cfg_select_unreachable = unreachable rule
87+
.label = always matches
88+
.label2 = this rules is never reached
89+
8490
builtin_macros_coerce_pointee_requires_maybe_sized = `derive(CoercePointee)` requires `{$name}` to be marked `?Sized`
8591
8692
builtin_macros_coerce_pointee_requires_one_field = `CoercePointee` can only be derived on `struct`s with at least one field
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
use rustc_ast::tokenstream::TokenStream;
2+
use rustc_attr_parsing as attr;
3+
use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacroExpanderResult};
4+
use rustc_parse::parser::cfg_select::{CfgSelectBranches, CfgSelectRule, parse_cfg_select};
5+
use rustc_span::{Ident, Span, sym};
6+
7+
use crate::errors::{CfgSelectNoMatches, CfgSelectUnreachable};
8+
9+
/// Selects the first arm whose rule evaluates to true.
10+
fn select_arm(ecx: &ExtCtxt<'_>, branches: CfgSelectBranches) -> Option<(TokenStream, Span)> {
11+
for (cfg, tt, arm_span) in branches.reachable {
12+
if attr::cfg_matches(
13+
&cfg,
14+
&ecx.sess,
15+
ecx.current_expansion.lint_node_id,
16+
Some(ecx.ecfg.features),
17+
) {
18+
return Some((tt, arm_span));
19+
}
20+
}
21+
22+
branches.wildcard.map(|(_, tt, span)| (tt, span))
23+
}
24+
25+
pub(super) fn expand_cfg_select<'cx>(
26+
ecx: &'cx mut ExtCtxt<'_>,
27+
sp: Span,
28+
tts: TokenStream,
29+
) -> MacroExpanderResult<'cx> {
30+
ExpandResult::Ready(match parse_cfg_select(&mut ecx.new_parser_from_tts(tts)) {
31+
Ok(branches) => {
32+
if let Some((underscore, _, _)) = branches.wildcard {
33+
// Warn for every unreachable rule. We store the fully parsed branch for rustfmt.
34+
for (rule, _, _) in &branches.unreachable {
35+
let span = match rule {
36+
CfgSelectRule::Wildcard(underscore) => underscore.span,
37+
CfgSelectRule::Cfg(cfg) => cfg.span(),
38+
};
39+
let err = CfgSelectUnreachable { span, wildcard_span: underscore.span };
40+
ecx.dcx().emit_warn(err);
41+
}
42+
}
43+
44+
if let Some((tts, arm_span)) = select_arm(ecx, branches) {
45+
return ExpandResult::from_tts(
46+
ecx,
47+
tts,
48+
sp,
49+
arm_span,
50+
Ident::with_dummy_span(sym::cfg_select),
51+
);
52+
} else {
53+
// Emit a compiler error when none of the rules matched.
54+
let guar = ecx.dcx().emit_err(CfgSelectNoMatches { span: sp });
55+
DummyResult::any(sp, guar)
56+
}
57+
}
58+
Err(err) => {
59+
let guar = err.emit();
60+
DummyResult::any(sp, guar)
61+
}
62+
})
63+
}

compiler/rustc_builtin_macros/src/errors.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -954,3 +954,21 @@ pub(crate) struct AsmExpectedOther {
954954
pub(crate) span: Span,
955955
pub(crate) is_inline_asm: bool,
956956
}
957+
958+
#[derive(Diagnostic)]
959+
#[diag(builtin_macros_cfg_select_no_matches)]
960+
pub(crate) struct CfgSelectNoMatches {
961+
#[primary_span]
962+
pub span: Span,
963+
}
964+
965+
#[derive(Diagnostic)]
966+
#[diag(builtin_macros_cfg_select_unreachable)]
967+
pub(crate) struct CfgSelectUnreachable {
968+
#[primary_span]
969+
#[label(builtin_macros_label2)]
970+
pub span: Span,
971+
972+
#[label]
973+
pub wildcard_span: Span,
974+
}

compiler/rustc_builtin_macros/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ mod autodiff;
3333
mod cfg;
3434
mod cfg_accessible;
3535
mod cfg_eval;
36+
mod cfg_select;
3637
mod compile_error;
3738
mod concat;
3839
mod concat_bytes;
@@ -79,6 +80,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
7980
asm: asm::expand_asm,
8081
assert: assert::expand_assert,
8182
cfg: cfg::expand_cfg,
83+
cfg_select: cfg_select::expand_cfg_select,
8284
column: source_util::expand_column,
8385
compile_error: compile_error::expand_compile_error,
8486
concat: concat::expand_concat,

compiler/rustc_expand/src/base.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ use thin_vec::ThinVec;
3434
use crate::base::ast::MetaItemInner;
3535
use crate::errors;
3636
use crate::expand::{self, AstFragment, Invocation};
37+
use crate::mbe::macro_rules::ParserAnyMacro;
3738
use crate::module::DirOwnership;
3839
use crate::stats::MacroStat;
3940

@@ -262,6 +263,25 @@ impl<T, U> ExpandResult<T, U> {
262263
}
263264
}
264265

266+
impl<'cx> MacroExpanderResult<'cx> {
267+
/// Creates a [`MacroExpanderResult::Ready`] from a [`TokenStream`].
268+
///
269+
/// The `TokenStream` is forwarded without any expansion.
270+
pub fn from_tts(
271+
cx: &'cx mut ExtCtxt<'_>,
272+
tts: TokenStream,
273+
site_span: Span,
274+
arm_span: Span,
275+
macro_ident: Ident,
276+
) -> Self {
277+
// Emit the SEMICOLON_IN_EXPRESSIONS_FROM_MACROS deprecation lint.
278+
let is_local = true;
279+
280+
let parser = ParserAnyMacro::from_tts(cx, tts, site_span, arm_span, is_local, macro_ident);
281+
ExpandResult::Ready(Box::new(parser))
282+
}
283+
}
284+
265285
pub trait MultiItemModifier {
266286
/// `meta_item` is the attribute, and `item` is the item being modified.
267287
fn expand(

compiler/rustc_expand/src/mbe/macro_rules.rs

Lines changed: 38 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,30 @@ impl<'a> ParserAnyMacro<'a> {
9696
ensure_complete_parse(parser, &path, kind.name(), site_span);
9797
fragment
9898
}
99+
100+
#[instrument(skip(cx, tts))]
101+
pub(crate) fn from_tts<'cx>(
102+
cx: &'cx mut ExtCtxt<'a>,
103+
tts: TokenStream,
104+
site_span: Span,
105+
arm_span: Span,
106+
is_local: bool,
107+
macro_ident: Ident,
108+
) -> Self {
109+
Self {
110+
parser: Parser::new(&cx.sess.psess, tts, None),
111+
112+
// Pass along the original expansion site and the name of the macro
113+
// so we can print a useful error message if the parse of the expanded
114+
// macro leaves unparsed tokens.
115+
site_span,
116+
macro_ident,
117+
lint_node_id: cx.current_expansion.lint_node_id,
118+
is_trailing_mac: cx.current_expansion.is_trailing_mac,
119+
arm_span,
120+
is_local,
121+
}
122+
}
99123
}
100124

101125
pub(super) struct MacroRule {
@@ -207,9 +231,6 @@ fn expand_macro<'cx>(
207231
rules: &[MacroRule],
208232
) -> Box<dyn MacResult + 'cx> {
209233
let psess = &cx.sess.psess;
210-
// Macros defined in the current crate have a real node id,
211-
// whereas macros from an external crate have a dummy id.
212-
let is_local = node_id != DUMMY_NODE_ID;
213234

214235
if cx.trace_macros() {
215236
let msg = format!("expanding `{}! {{ {} }}`", name, pprust::tts_to_string(&arg));
@@ -220,7 +241,7 @@ fn expand_macro<'cx>(
220241
let try_success_result = try_match_macro(psess, name, &arg, rules, &mut NoopTracker);
221242

222243
match try_success_result {
223-
Ok((i, rule, named_matches)) => {
244+
Ok((rule_index, rule, named_matches)) => {
224245
let mbe::TokenTree::Delimited(rhs_span, _, ref rhs) = rule.rhs else {
225246
cx.dcx().span_bug(sp, "malformed macro rhs");
226247
};
@@ -241,27 +262,13 @@ fn expand_macro<'cx>(
241262
trace_macros_note(&mut cx.expansions, sp, msg);
242263
}
243264

244-
let p = Parser::new(psess, tts, None);
245-
265+
let is_local = is_defined_in_current_crate(node_id);
246266
if is_local {
247-
cx.resolver.record_macro_rule_usage(node_id, i);
267+
cx.resolver.record_macro_rule_usage(node_id, rule_index);
248268
}
249269

250-
// Let the context choose how to interpret the result.
251-
// Weird, but useful for X-macros.
252-
Box::new(ParserAnyMacro {
253-
parser: p,
254-
255-
// Pass along the original expansion site and the name of the macro
256-
// so we can print a useful error message if the parse of the expanded
257-
// macro leaves unparsed tokens.
258-
site_span: sp,
259-
macro_ident: name,
260-
lint_node_id: cx.current_expansion.lint_node_id,
261-
is_trailing_mac: cx.current_expansion.is_trailing_mac,
262-
arm_span,
263-
is_local,
264-
})
270+
// Let the context choose how to interpret the result. Weird, but useful for X-macros.
271+
Box::new(ParserAnyMacro::from_tts(cx, tts, sp, arm_span, is_local, name))
265272
}
266273
Err(CanRetry::No(guar)) => {
267274
debug!("Will not retry matching as an error was emitted already");
@@ -373,9 +380,9 @@ pub fn compile_declarative_macro(
373380
node_id: NodeId,
374381
edition: Edition,
375382
) -> (SyntaxExtension, usize) {
376-
let is_local = node_id != DUMMY_NODE_ID;
377383
let mk_syn_ext = |expander| {
378384
let kind = SyntaxExtensionKind::LegacyBang(expander);
385+
let is_local = is_defined_in_current_crate(node_id);
379386
SyntaxExtension::new(sess, kind, span, Vec::new(), edition, ident.name, attrs, is_local)
380387
};
381388
let dummy_syn_ext = |guar| (mk_syn_ext(Arc::new(DummyExpander(guar))), 0);
@@ -439,7 +446,7 @@ pub fn compile_declarative_macro(
439446
}
440447

441448
// Return the number of rules for unused rule linting, if this is a local macro.
442-
let nrules = if is_local { rules.len() } else { 0 };
449+
let nrules = if is_defined_in_current_crate(node_id) { rules.len() } else { 0 };
443450

444451
let expander =
445452
Arc::new(MacroRulesMacroExpander { name: ident, span, node_id, transparency, rules });
@@ -1034,9 +1041,7 @@ fn check_matcher_core<'tt>(
10341041
// definition of this macro_rules, not while (re)parsing
10351042
// the macro when compiling another crate that is using the
10361043
// macro. (See #86567.)
1037-
// Macros defined in the current crate have a real node id,
1038-
// whereas macros from an external crate have a dummy id.
1039-
if node_id != DUMMY_NODE_ID
1044+
if is_defined_in_current_crate(node_id)
10401045
&& matches!(kind, NonterminalKind::Pat(PatParam { inferred: true }))
10411046
&& matches!(
10421047
next_token,
@@ -1296,6 +1301,12 @@ fn quoted_tt_to_string(tt: &mbe::TokenTree) -> String {
12961301
}
12971302
}
12981303

1304+
fn is_defined_in_current_crate(node_id: NodeId) -> bool {
1305+
// Macros defined in the current crate have a real node id,
1306+
// whereas macros from an external crate have a dummy id.
1307+
node_id != DUMMY_NODE_ID
1308+
}
1309+
12991310
pub(super) fn parser_from_cx(
13001311
psess: &ParseSess,
13011312
mut tts: TokenStream,

0 commit comments

Comments
 (0)