Skip to content

Commit 39d2f2a

Browse files
committed
Auto merge of rust-lang#125436 - matthiaskrgr:rollup-uijo2ga, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - rust-lang#122665 (Add some tests for public-private dependencies.) - rust-lang#123623 (Fix OutsideLoop's error suggestion: adding label `'block` for `if` block.) - rust-lang#125054 (Handle `ReVar` in `note_and_explain_region`) - rust-lang#125156 (Expand `for_loops_over_fallibles` lint to lint on fallibles behind references.) - rust-lang#125222 (Migrate `run-make/issue-46239` to `rmake`) - rust-lang#125316 (Tweak `Spacing` use) - rust-lang#125392 (Wrap Context.ext in AssertUnwindSafe) - rust-lang#125417 (self-contained linker: retry linking without `-fuse-ld=lld` on CCs that don't support it) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 5293c6a + 748647f commit 39d2f2a

Some content is hidden

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

52 files changed

+931
-158
lines changed

compiler/rustc_ast/src/tokenstream.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -661,11 +661,11 @@ impl TokenStream {
661661
if attr_style == AttrStyle::Inner {
662662
vec![
663663
TokenTree::token_joint(token::Pound, span),
664-
TokenTree::token_alone(token::Not, span),
664+
TokenTree::token_joint_hidden(token::Not, span),
665665
body,
666666
]
667667
} else {
668-
vec![TokenTree::token_alone(token::Pound, span), body]
668+
vec![TokenTree::token_joint_hidden(token::Pound, span), body]
669669
}
670670
}
671671
}

compiler/rustc_ast_pretty/src/pprust/state.rs

+29-11
Original file line numberDiff line numberDiff line change
@@ -681,22 +681,40 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
681681
}
682682
}
683683

684+
// The easiest way to implement token stream pretty printing would be to
685+
// print each token followed by a single space. But that would produce ugly
686+
// output, so we go to some effort to do better.
687+
//
688+
// First, we track whether each token that appears in source code is
689+
// followed by a space, with `Spacing`, and reproduce that in the output.
690+
// This works well in a lot of cases. E.g. `stringify!(x + y)` produces
691+
// "x + y" and `stringify!(x+y)` produces "x+y".
692+
//
693+
// But this doesn't work for code produced by proc macros (which have no
694+
// original source text representation) nor for code produced by decl
695+
// macros (which are tricky because the whitespace after tokens appearing
696+
// in macro rules isn't always what you want in the produced output). For
697+
// these we mostly use `Spacing::Alone`, which is the conservative choice.
698+
//
699+
// So we have a backup mechanism for when `Spacing::Alone` occurs between a
700+
// pair of tokens: we check if that pair of tokens can obviously go
701+
// together without a space between them. E.g. token `x` followed by token
702+
// `,` is better printed as `x,` than `x ,`. (Even if the original source
703+
// code was `x ,`.)
704+
//
705+
// Finally, we must be careful about changing the output. Token pretty
706+
// printing is used by `stringify!` and `impl Display for
707+
// proc_macro::TokenStream`, and some programs rely on the output having a
708+
// particular form, even though they shouldn't. In particular, some proc
709+
// macros do `format!({stream})` on a token stream and then "parse" the
710+
// output with simple string matching that can't handle whitespace changes.
711+
// E.g. we have seen cases where a proc macro can handle `a :: b` but not
712+
// `a::b`. See #117433 for some examples.
684713
fn print_tts(&mut self, tts: &TokenStream, convert_dollar_crate: bool) {
685714
let mut iter = tts.trees().peekable();
686715
while let Some(tt) = iter.next() {
687716
let spacing = self.print_tt(tt, convert_dollar_crate);
688717
if let Some(next) = iter.peek() {
689-
// Should we print a space after `tt`? There are two guiding
690-
// factors.
691-
// - `spacing` is the more important and accurate one. Most
692-
// tokens have good spacing information, and
693-
// `Joint`/`JointHidden` get used a lot.
694-
// - `space_between` is the backup. Code produced by proc
695-
// macros has worse spacing information, with no
696-
// `JointHidden` usage and too much `Alone` usage, which
697-
// would result in over-spaced output such as
698-
// `( x () , y . z )`. `space_between` avoids some of the
699-
// excess whitespace.
700718
if spacing == Spacing::Alone && space_between(tt, next) {
701719
self.space();
702720
}

compiler/rustc_builtin_macros/src/assert/context.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
153153
fn build_panic(&self, expr_str: &str, panic_path: Path) -> P<Expr> {
154154
let escaped_expr_str = escape_to_fmt(expr_str);
155155
let initial = [
156-
TokenTree::token_joint_hidden(
156+
TokenTree::token_joint(
157157
token::Literal(token::Lit {
158158
kind: token::LitKind::Str,
159159
symbol: Symbol::intern(&if self.fmt_string.is_empty() {
@@ -172,7 +172,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
172172
];
173173
let captures = self.capture_decls.iter().flat_map(|cap| {
174174
[
175-
TokenTree::token_joint_hidden(
175+
TokenTree::token_joint(
176176
token::Ident(cap.ident.name, IdentIsRaw::No),
177177
cap.ident.span,
178178
),

compiler/rustc_builtin_macros/src/deriving/default.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::deriving::generic::*;
33
use crate::errors;
44
use core::ops::ControlFlow;
55
use rustc_ast as ast;
6-
use rustc_ast::visit::walk_list;
6+
use rustc_ast::visit::visit_opt;
77
use rustc_ast::{attr, EnumDef, VariantData};
88
use rustc_expand::base::{Annotatable, DummyResult, ExtCtxt};
99
use rustc_span::symbol::Ident;
@@ -224,7 +224,7 @@ impl<'a, 'b> rustc_ast::visit::Visitor<'a> for DetectNonVariantDefaultAttr<'a, '
224224
self.visit_ident(v.ident);
225225
self.visit_vis(&v.vis);
226226
self.visit_variant_data(&v.data);
227-
walk_list!(self, visit_anon_const, &v.disr_expr);
227+
visit_opt!(self, visit_anon_const, &v.disr_expr);
228228
for attr in &v.attrs {
229229
rustc_ast::visit::walk_attribute(self, attr);
230230
}

compiler/rustc_codegen_ssa/src/back/link.rs

+21
Original file line numberDiff line numberDiff line change
@@ -799,6 +799,27 @@ fn link_natively(
799799
continue;
800800
}
801801

802+
// Check if linking failed with an error message that indicates the driver didn't recognize
803+
// the `-fuse-ld=lld` option. If so, re-perform the link step without it. This avoids having
804+
// to spawn multiple instances on the happy path to do version checking, and ensures things
805+
// keep working on the tier 1 baseline of GLIBC 2.17+. That is generally understood as GCCs
806+
// circa RHEL/CentOS 7, 4.5 or so, whereas lld support was added in GCC 9.
807+
if matches!(flavor, LinkerFlavor::Gnu(Cc::Yes, Lld::Yes))
808+
&& unknown_arg_regex.is_match(&out)
809+
&& out.contains("-fuse-ld=lld")
810+
&& cmd.get_args().iter().any(|e| e.to_string_lossy() == "-fuse-ld=lld")
811+
{
812+
info!("linker output: {:?}", out);
813+
warn!("The linker driver does not support `-fuse-ld=lld`. Retrying without it.");
814+
for arg in cmd.take_args() {
815+
if arg.to_string_lossy() != "-fuse-ld=lld" {
816+
cmd.arg(arg);
817+
}
818+
}
819+
info!("{:?}", &cmd);
820+
continue;
821+
}
822+
802823
// Detect '-static-pie' used with an older version of gcc or clang not supporting it.
803824
// Fallback from '-static-pie' to '-static' in that case.
804825
if matches!(flavor, LinkerFlavor::Gnu(Cc::Yes, _))

compiler/rustc_expand/src/mbe.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,15 @@ pub(crate) enum KleeneOp {
6868
/// `MetaVarExpr` are "first-class" token trees. Useful for parsing macros.
6969
#[derive(Debug, PartialEq, Encodable, Decodable)]
7070
enum TokenTree {
71+
/// A token. Unlike `tokenstream::TokenTree::Token` this lacks a `Spacing`.
72+
/// See the comments about `Spacing` in the `transcribe` function.
7173
Token(Token),
7274
/// A delimited sequence, e.g. `($e:expr)` (RHS) or `{ $e }` (LHS).
7375
Delimited(DelimSpan, DelimSpacing, Delimited),
7476
/// A kleene-style repetition sequence, e.g. `$($e:expr)*` (RHS) or `$($e),*` (LHS).
7577
Sequence(DelimSpan, SequenceRepetition),
76-
/// e.g., `$var`.
78+
/// e.g., `$var`. The span covers the leading dollar and the ident. (The span within the ident
79+
/// only covers the ident, e.g. `var`.)
7780
MetaVar(Span, Ident),
7881
/// e.g., `$var:expr`. Only appears on the LHS.
7982
MetaVarDecl(Span, Ident /* name to bind */, Option<NonterminalKind>),

compiler/rustc_expand/src/mbe/quoted.rs

+19-11
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,10 @@ pub(super) fn parse(
6262
match tree {
6363
TokenTree::MetaVar(start_sp, ident) if parsing_patterns => {
6464
let span = match trees.next() {
65-
Some(&tokenstream::TokenTree::Token(Token { kind: token::Colon, span }, _)) => {
65+
Some(&tokenstream::TokenTree::Token(
66+
Token { kind: token::Colon, span: colon_span },
67+
_,
68+
)) => {
6669
match trees.next() {
6770
Some(tokenstream::TokenTree::Token(token, _)) => match token.ident() {
6871
Some((fragment, _)) => {
@@ -126,10 +129,12 @@ pub(super) fn parse(
126129
}
127130
_ => token.span,
128131
},
129-
tree => tree.map_or(span, tokenstream::TokenTree::span),
132+
Some(tree) => tree.span(),
133+
None => colon_span,
130134
}
131135
}
132-
tree => tree.map_or(start_sp, tokenstream::TokenTree::span),
136+
Some(tree) => tree.span(),
137+
None => start_sp,
133138
};
134139

135140
result.push(TokenTree::MetaVarDecl(span, ident, None));
@@ -176,7 +181,7 @@ fn parse_tree<'a>(
176181
// Depending on what `tree` is, we could be parsing different parts of a macro
177182
match tree {
178183
// `tree` is a `$` token. Look at the next token in `trees`
179-
&tokenstream::TokenTree::Token(Token { kind: token::Dollar, span }, _) => {
184+
&tokenstream::TokenTree::Token(Token { kind: token::Dollar, span: dollar_span }, _) => {
180185
// FIXME: Handle `Invisible`-delimited groups in a more systematic way
181186
// during parsing.
182187
let mut next = outer_trees.next();
@@ -209,7 +214,7 @@ fn parse_tree<'a>(
209214
err.emit();
210215
// Returns early the same read `$` to avoid spanning
211216
// unrelated diagnostics that could be performed afterwards
212-
return TokenTree::token(token::Dollar, span);
217+
return TokenTree::token(token::Dollar, dollar_span);
213218
}
214219
Ok(elem) => {
215220
maybe_emit_macro_metavar_expr_feature(
@@ -251,7 +256,7 @@ fn parse_tree<'a>(
251256
// special metavariable that names the crate of the invocation.
252257
Some(tokenstream::TokenTree::Token(token, _)) if token.is_ident() => {
253258
let (ident, is_raw) = token.ident().unwrap();
254-
let span = ident.span.with_lo(span.lo());
259+
let span = ident.span.with_lo(dollar_span.lo());
255260
if ident.name == kw::Crate && matches!(is_raw, IdentIsRaw::No) {
256261
TokenTree::token(token::Ident(kw::DollarCrate, is_raw), span)
257262
} else {
@@ -260,16 +265,19 @@ fn parse_tree<'a>(
260265
}
261266

262267
// `tree` is followed by another `$`. This is an escaped `$`.
263-
Some(&tokenstream::TokenTree::Token(Token { kind: token::Dollar, span }, _)) => {
268+
Some(&tokenstream::TokenTree::Token(
269+
Token { kind: token::Dollar, span: dollar_span2 },
270+
_,
271+
)) => {
264272
if parsing_patterns {
265273
span_dollar_dollar_or_metavar_in_the_lhs_err(
266274
sess,
267-
&Token { kind: token::Dollar, span },
275+
&Token { kind: token::Dollar, span: dollar_span2 },
268276
);
269277
} else {
270-
maybe_emit_macro_metavar_expr_feature(features, sess, span);
278+
maybe_emit_macro_metavar_expr_feature(features, sess, dollar_span2);
271279
}
272-
TokenTree::token(token::Dollar, span)
280+
TokenTree::token(token::Dollar, dollar_span2)
273281
}
274282

275283
// `tree` is followed by some other token. This is an error.
@@ -281,7 +289,7 @@ fn parse_tree<'a>(
281289
}
282290

283291
// There are no more tokens. Just return the `$` we already have.
284-
None => TokenTree::token(token::Dollar, span),
292+
None => TokenTree::token(token::Dollar, dollar_span),
285293
}
286294
}
287295

compiler/rustc_expand/src/mbe/transcribe.rs

+15
Original file line numberDiff line numberDiff line change
@@ -253,8 +253,23 @@ pub(super) fn transcribe<'a>(
253253
mbe::TokenTree::MetaVar(mut sp, mut original_ident) => {
254254
// Find the matched nonterminal from the macro invocation, and use it to replace
255255
// the meta-var.
256+
//
257+
// We use `Spacing::Alone` everywhere here, because that's the conservative choice
258+
// and spacing of declarative macros is tricky. E.g. in this macro:
259+
// ```
260+
// macro_rules! idents {
261+
// ($($a:ident,)*) => { stringify!($($a)*) }
262+
// }
263+
// ```
264+
// `$a` has no whitespace after it and will be marked `JointHidden`. If you then
265+
// call `idents!(x,y,z,)`, each of `x`, `y`, and `z` will be marked as `Joint`. So
266+
// if you choose to use `$x`'s spacing or the identifier's spacing, you'll end up
267+
// producing "xyz", which is bad because it effectively merges tokens.
268+
// `Spacing::Alone` is the safer option. Fortunately, `space_between` will avoid
269+
// some of the unnecessary whitespace.
256270
let ident = MacroRulesNormalizedIdent::new(original_ident);
257271
if let Some(cur_matched) = lookup_cur_matched(ident, interp, &repeats) {
272+
// njn: explain the use of alone here
258273
let tt = match cur_matched {
259274
MatchedSingle(ParseNtResult::Tt(tt)) => {
260275
// `tt`s are emitted into the output stream directly as "raw tokens",

compiler/rustc_expand/src/proc_macro_server.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -309,10 +309,10 @@ impl ToInternal<SmallVec<[tokenstream::TokenTree; 2]>>
309309
use rustc_ast::token::*;
310310

311311
// The code below is conservative, using `token_alone`/`Spacing::Alone`
312-
// in most places. When the resulting code is pretty-printed by
313-
// `print_tts` it ends up with spaces between most tokens, which is
314-
// safe but ugly. It's hard in general to do better when working at the
315-
// token level.
312+
// in most places. It's hard in general to do better when working at
313+
// the token level. When the resulting code is pretty-printed by
314+
// `print_tts` the `space_between` function helps avoid a lot of
315+
// unnecessary whitespace, so the results aren't too bad.
316316
let (tree, rustc) = self;
317317
match tree {
318318
TokenTree::Punct(Punct { ch, joint, span }) => {

compiler/rustc_hir_analysis/src/check/region.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
//!
77
//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/borrow_check.html
88
9-
use rustc_ast::visit::walk_list;
9+
use rustc_ast::visit::visit_opt;
1010
use rustc_data_structures::fx::FxHashSet;
1111
use rustc_hir as hir;
1212
use rustc_hir::def_id::DefId;
@@ -168,7 +168,7 @@ fn resolve_block<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, blk: &'tcx h
168168
hir::StmtKind::Expr(..) | hir::StmtKind::Semi(..) => visitor.visit_stmt(statement),
169169
}
170170
}
171-
walk_list!(visitor, visit_expr, &blk.expr);
171+
visit_opt!(visitor, visit_expr, &blk.expr);
172172
}
173173

174174
visitor.cx = prev_cx;

compiler/rustc_infer/src/infer/error_reporting/mod.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,10 @@ pub(super) fn note_and_explain_region<'tcx>(
173173

174174
ty::ReError(_) => return,
175175

176-
ty::ReVar(_) | ty::ReBound(..) | ty::ReErased => {
176+
// FIXME(#125431): `ReVar` shouldn't reach here.
177+
ty::ReVar(_) => (format!("lifetime `{region}`"), alt_span),
178+
179+
ty::ReBound(..) | ty::ReErased => {
177180
bug!("unexpected region for note_and_explain_region: {:?}", region);
178181
}
179182
};

compiler/rustc_lint/messages.ftl

+1-1
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ lint_extern_without_abi = extern declarations without an explicit ABI are deprec
263263
.help = the default ABI is {$default_abi}
264264
265265
lint_for_loops_over_fallibles =
266-
for loop over {$article} `{$ty}`. This is more readably written as an `if let` statement
266+
for loop over {$article} `{$ref_prefix}{$ty}`. This is more readably written as an `if let` statement
267267
.suggestion = consider using `if let` to clear intent
268268
.remove_next = to iterate over `{$recv_snip}` remove the call to `next`
269269
.use_while_let = to check pattern in a loop use `while let`

compiler/rustc_lint/src/for_loops_over_fallibles.rs

+15-2
Original file line numberDiff line numberDiff line change
@@ -52,14 +52,27 @@ impl<'tcx> LateLintPass<'tcx> for ForLoopsOverFallibles {
5252

5353
let ty = cx.typeck_results().expr_ty(arg);
5454

55-
let &ty::Adt(adt, args) = ty.kind() else { return };
55+
let (adt, args, ref_mutability) = match ty.kind() {
56+
&ty::Adt(adt, args) => (adt, args, None),
57+
&ty::Ref(_, ty, mutability) => match ty.kind() {
58+
&ty::Adt(adt, args) => (adt, args, Some(mutability)),
59+
_ => return,
60+
},
61+
_ => return,
62+
};
5663

5764
let (article, ty, var) = match adt.did() {
65+
did if cx.tcx.is_diagnostic_item(sym::Option, did) && ref_mutability.is_some() => ("a", "Option", "Some"),
5866
did if cx.tcx.is_diagnostic_item(sym::Option, did) => ("an", "Option", "Some"),
5967
did if cx.tcx.is_diagnostic_item(sym::Result, did) => ("a", "Result", "Ok"),
6068
_ => return,
6169
};
6270

71+
let ref_prefix = match ref_mutability {
72+
None => "",
73+
Some(ref_mutability) => ref_mutability.ref_prefix_str(),
74+
};
75+
6376
let sub = if let Some(recv) = extract_iterator_next_call(cx, arg)
6477
&& let Ok(recv_snip) = cx.sess().source_map().span_to_snippet(recv.span)
6578
{
@@ -85,7 +98,7 @@ impl<'tcx> LateLintPass<'tcx> for ForLoopsOverFallibles {
8598
cx.emit_span_lint(
8699
FOR_LOOPS_OVER_FALLIBLES,
87100
arg.span,
88-
ForLoopsOverFalliblesDiag { article, ty, sub, question_mark, suggestion },
101+
ForLoopsOverFalliblesDiag { article, ref_prefix, ty, sub, question_mark, suggestion },
89102
);
90103
}
91104
}

compiler/rustc_lint/src/lints.rs

+1
Original file line numberDiff line numberDiff line change
@@ -620,6 +620,7 @@ pub enum PtrNullChecksDiag<'a> {
620620
#[diag(lint_for_loops_over_fallibles)]
621621
pub struct ForLoopsOverFalliblesDiag<'a> {
622622
pub article: &'static str,
623+
pub ref_prefix: &'static str,
623624
pub ty: &'static str,
624625
#[subdiagnostic]
625626
pub sub: ForLoopsOverFalliblesLoopSub<'a>,

compiler/rustc_mir_build/src/build/matches/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -925,7 +925,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
925925
for subpattern in prefix.iter() {
926926
self.visit_primary_bindings(subpattern, pattern_user_ty.clone().index(), f);
927927
}
928-
for subpattern in slice {
928+
if let Some(subpattern) = slice {
929929
self.visit_primary_bindings(
930930
subpattern,
931931
pattern_user_ty.clone().subslice(from, to),

compiler/rustc_passes/src/errors.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1100,7 +1100,7 @@ pub struct BreakInsideCoroutine<'a> {
11001100
pub struct OutsideLoop<'a> {
11011101
#[primary_span]
11021102
#[label]
1103-
pub span: Span,
1103+
pub spans: Vec<Span>,
11041104
pub name: &'a str,
11051105
pub is_break: bool,
11061106
#[subdiagnostic]
@@ -1112,7 +1112,7 @@ pub struct OutsideLoopSuggestion {
11121112
#[suggestion_part(code = "'block: ")]
11131113
pub block_span: Span,
11141114
#[suggestion_part(code = " 'block")]
1115-
pub break_span: Span,
1115+
pub break_spans: Vec<Span>,
11161116
}
11171117

11181118
#[derive(Diagnostic)]

0 commit comments

Comments
 (0)