Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 3811f40

Browse files
committed
Auto merge of #127957 - matthiaskrgr:rollup-1u5ivck, r=matthiaskrgr
Rollup of 6 pull requests Successful merges: - #127350 (Parser: Suggest Placing the Return Type After Function Parameters) - #127621 (Rewrite and rename `issue-22131` and `issue-26006` `run-make` tests to rmake) - #127662 (When finding item gated behind a `cfg` flag, point at it) - #127903 (`force_collect` improvements) - #127932 (rustdoc: fix `current` class on sidebar modnav) - #127943 (Don't allow unsafe statics outside of extern blocks) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 11e5724 + 6fe68f8 commit 3811f40

File tree

49 files changed

+490
-146
lines changed

Some content is hidden

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

49 files changed

+490
-146
lines changed

‎compiler/rustc_ast_passes/messages.ftl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,9 @@ ast_passes_unsafe_negative_impl = negative impls cannot be unsafe
269269
.negative = negative because of this
270270
.unsafe = unsafe because of this
271271
272+
ast_passes_unsafe_static =
273+
static items cannot be declared with `unsafe` safety qualifier outside of `extern` block
274+
272275
ast_passes_visibility_not_permitted =
273276
visibility qualifiers are not permitted here
274277
.enum_variant = enum variants and their fields always share the visibility of the enum they are in

‎compiler/rustc_ast_passes/src/ast_validation.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,11 @@ impl<'a> AstValidator<'a> {
438438
}
439439
}
440440

441+
/// This ensures that items can only be `unsafe` (or unmarked) outside of extern
442+
/// blocks.
443+
///
444+
/// This additionally ensures that within extern blocks, items can only be
445+
/// `safe`/`unsafe` inside of a `unsafe`-adorned extern block.
441446
fn check_item_safety(&self, span: Span, safety: Safety) {
442447
match self.extern_mod_safety {
443448
Some(extern_safety) => {
@@ -1177,6 +1182,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
11771182
}
11781183
ItemKind::Static(box StaticItem { expr, safety, .. }) => {
11791184
self.check_item_safety(item.span, *safety);
1185+
if matches!(safety, Safety::Unsafe(_)) {
1186+
self.dcx().emit_err(errors::UnsafeStatic { span: item.span });
1187+
}
11801188

11811189
if expr.is_none() {
11821190
self.dcx().emit_err(errors::StaticWithoutBody {

‎compiler/rustc_ast_passes/src/errors.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,13 @@ pub struct InvalidSafetyOnBareFn {
224224
pub span: Span,
225225
}
226226

227+
#[derive(Diagnostic)]
228+
#[diag(ast_passes_unsafe_static)]
229+
pub struct UnsafeStatic {
230+
#[primary_span]
231+
pub span: Span,
232+
}
233+
227234
#[derive(Diagnostic)]
228235
#[diag(ast_passes_bound_in_context)]
229236
pub struct BoundInContext<'a> {

‎compiler/rustc_builtin_macros/src/cmdline_attrs.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use crate::errors;
44
use rustc_ast::attr::mk_attr;
55
use rustc_ast::token;
66
use rustc_ast::{self as ast, AttrItem, AttrStyle};
7+
use rustc_parse::parser::ForceCollect;
78
use rustc_parse::{new_parser_from_source_str, unwrap_or_emit_fatal};
89
use rustc_session::parse::ParseSess;
910
use rustc_span::FileName;
@@ -17,13 +18,14 @@ pub fn inject(krate: &mut ast::Crate, psess: &ParseSess, attrs: &[String]) {
1718
));
1819

1920
let start_span = parser.token.span;
20-
let AttrItem { unsafety, path, args, tokens: _ } = match parser.parse_attr_item(false) {
21-
Ok(ai) => ai,
22-
Err(err) => {
23-
err.emit();
24-
continue;
25-
}
26-
};
21+
let AttrItem { unsafety, path, args, tokens: _ } =
22+
match parser.parse_attr_item(ForceCollect::No) {
23+
Ok(ai) => ai,
24+
Err(err) => {
25+
err.emit();
26+
continue;
27+
}
28+
};
2729
let end_span = parser.token.span;
2830
if parser.token != token::Eof {
2931
psess.dcx().emit_err(errors::InvalidCrateAttr { span: start_span.to(end_span) });

‎compiler/rustc_parse/messages.ftl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,8 @@ parse_mismatched_closing_delimiter = mismatched closing delimiter: `{$delimiter}
524524
.label_opening_candidate = closing delimiter possibly meant for this
525525
.label_unclosed = unclosed delimiter
526526
527+
parse_misplaced_return_type = place the return type after the function parameters
528+
527529
parse_missing_comma_after_match_arm = expected `,` following `match` arm
528530
.suggestion = missing a comma here to end this `match` arm
529531

‎compiler/rustc_parse/src/errors.rs

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1502,6 +1502,20 @@ pub(crate) struct FnPtrWithGenerics {
15021502
pub sugg: Option<FnPtrWithGenericsSugg>,
15031503
}
15041504

1505+
#[derive(Subdiagnostic)]
1506+
#[multipart_suggestion(
1507+
parse_misplaced_return_type,
1508+
style = "verbose",
1509+
applicability = "maybe-incorrect"
1510+
)]
1511+
pub(crate) struct MisplacedReturnType {
1512+
#[suggestion_part(code = " {snippet}")]
1513+
pub fn_params_end: Span,
1514+
pub snippet: String,
1515+
#[suggestion_part(code = "")]
1516+
pub ret_ty_span: Span,
1517+
}
1518+
15051519
#[derive(Subdiagnostic)]
15061520
#[multipart_suggestion(parse_suggestion, applicability = "maybe-incorrect")]
15071521
pub(crate) struct FnPtrWithGenericsSugg {
@@ -1516,7 +1530,6 @@ pub(crate) struct FnPtrWithGenericsSugg {
15161530

15171531
pub(crate) struct FnTraitMissingParen {
15181532
pub span: Span,
1519-
pub machine_applicable: bool,
15201533
}
15211534

15221535
impl Subdiagnostic for FnTraitMissingParen {
@@ -1526,16 +1539,11 @@ impl Subdiagnostic for FnTraitMissingParen {
15261539
_: &F,
15271540
) {
15281541
diag.span_label(self.span, crate::fluent_generated::parse_fn_trait_missing_paren);
1529-
let applicability = if self.machine_applicable {
1530-
Applicability::MachineApplicable
1531-
} else {
1532-
Applicability::MaybeIncorrect
1533-
};
15341542
diag.span_suggestion_short(
15351543
self.span.shrink_to_hi(),
15361544
crate::fluent_generated::parse_add_paren,
15371545
"()",
1538-
applicability,
1546+
Applicability::MachineApplicable,
15391547
);
15401548
}
15411549
}

‎compiler/rustc_parse/src/parser/attr.rs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ impl<'a> Parser<'a> {
124124
if this.eat(&token::Not) { ast::AttrStyle::Inner } else { ast::AttrStyle::Outer };
125125

126126
this.expect(&token::OpenDelim(Delimiter::Bracket))?;
127-
let item = this.parse_attr_item(false)?;
127+
let item = this.parse_attr_item(ForceCollect::No)?;
128128
this.expect(&token::CloseDelim(Delimiter::Bracket))?;
129129
let attr_sp = lo.to(this.prev_token.span);
130130

@@ -248,16 +248,15 @@ impl<'a> Parser<'a> {
248248
/// PATH
249249
/// PATH `=` UNSUFFIXED_LIT
250250
/// The delimiters or `=` are still put into the resulting token stream.
251-
pub fn parse_attr_item(&mut self, capture_tokens:bool) -> PResult<'a, ast::AttrItem> {
251+
pub fn parse_attr_item(&mut self, force_collect:ForceCollect) -> PResult<'a, ast::AttrItem> {
252252
maybe_whole!(self, NtMeta, |attr| attr.into_inner());
253253

254-
let do_parse = |this: &mut Self| {
254+
let do_parse = |this: &mut Self, _empty_attrs| {
255255
let is_unsafe = this.eat_keyword(kw::Unsafe);
256256
let unsafety = if is_unsafe {
257257
let unsafe_span = this.prev_token.span;
258258
this.psess.gated_spans.gate(sym::unsafe_attributes, unsafe_span);
259259
this.expect(&token::OpenDelim(Delimiter::Parenthesis))?;
260-
261260
ast::Safety::Unsafe(unsafe_span)
262261
} else {
263262
ast::Safety::Default
@@ -268,10 +267,10 @@ impl<'a> Parser<'a> {
268267
if is_unsafe {
269268
this.expect(&token::CloseDelim(Delimiter::Parenthesis))?;
270269
}
271-
Ok(ast::AttrItem { unsafety, path, args, tokens: None })
270+
Ok((ast::AttrItem { unsafety, path, args, tokens: None },false))
272271
};
273-
// Attr items don't have attributes
274-
if capture_tokens {self.collect_tokens_no_attrs(do_parse)}else{do_parse(self)}
272+
// Attr items don't have attributes.
273+
self.collect_tokens_trailing_token(AttrWrapper::empty(), force_collect,do_parse)
275274
}
276275

277276
/// Parses attributes that appear after the opening of an item. These should
@@ -340,7 +339,7 @@ impl<'a> Parser<'a> {
340339
let mut expanded_attrs = Vec::with_capacity(1);
341340
while self.token.kind != token::Eof {
342341
let lo = self.token.span;
343-
let item = self.parse_attr_item(true)?;
342+
let item = self.parse_attr_item(ForceCollect::Yes)?;
344343
expanded_attrs.push((item, lo.to(self.prev_token.span)));
345344
if !self.eat(&token::Comma) {
346345
break;

‎compiler/rustc_parse/src/parser/diagnostics.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,7 @@ impl<'a> Parser<'a> {
430430
&mut self,
431431
edible: &[TokenKind],
432432
inedible: &[TokenKind],
433-
) -> PResult<'a, Recovered> {
433+
) -> PResult<'a, ErrorGuaranteed> {
434434
debug!("expected_one_of_not_found(edible: {:?}, inedible: {:?})", edible, inedible);
435435
fn tokens_to_string(tokens: &[TokenType]) -> String {
436436
let mut i = tokens.iter();
@@ -533,7 +533,7 @@ impl<'a> Parser<'a> {
533533
sugg: ExpectedSemiSugg::ChangeToSemi(self.token.span),
534534
});
535535
self.bump();
536-
return Ok(Recovered::Yes(guar));
536+
return Ok(guar);
537537
} else if self.look_ahead(0, |t| {
538538
t == &token::CloseDelim(Delimiter::Brace)
539539
|| ((t.can_begin_expr() || t.can_begin_item())
@@ -557,7 +557,7 @@ impl<'a> Parser<'a> {
557557
unexpected_token_label: Some(self.token.span),
558558
sugg: ExpectedSemiSugg::AddSemi(span),
559559
});
560-
return Ok(Recovered::Yes(guar));
560+
return Ok(guar);
561561
}
562562
}
563563

@@ -712,7 +712,7 @@ impl<'a> Parser<'a> {
712712
if self.check_too_many_raw_str_terminators(&mut err) {
713713
if expected.contains(&TokenType::Token(token::Semi)) && self.eat(&token::Semi) {
714714
let guar = err.emit();
715-
return Ok(Recovered::Yes(guar));
715+
return Ok(guar);
716716
} else {
717717
return Err(err);
718718
}

‎compiler/rustc_parse/src/parser/item.rs

Lines changed: 96 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use rustc_span::edit_distance::edit_distance;
1717
use rustc_span::edition::Edition;
1818
use rustc_span::source_map;
1919
use rustc_span::symbol::{kw, sym, Ident, Symbol};
20+
use rustc_span::ErrorGuaranteed;
2021
use rustc_span::{Span, DUMMY_SP};
2122
use std::fmt::Write;
2223
use std::mem;
@@ -2332,14 +2333,106 @@ impl<'a> Parser<'a> {
23322333
}
23332334
}
23342335
};
2336+
2337+
// Store the end of function parameters to give better diagnostics
2338+
// inside `parse_fn_body()`.
2339+
let fn_params_end = self.prev_token.span.shrink_to_hi();
2340+
23352341
generics.where_clause = self.parse_where_clause()?; // `where T: Ord`
23362342

2343+
// `fn_params_end` is needed only when it's followed by a where clause.
2344+
let fn_params_end =
2345+
if generics.where_clause.has_where_token { Some(fn_params_end) } else { None };
2346+
23372347
let mut sig_hi = self.prev_token.span;
2338-
let body = self.parse_fn_body(attrs, &ident, &mut sig_hi, fn_parse_mode.req_body)?; // `;` or `{ ... }`.
2348+
// Either `;` or `{ ... }`.
2349+
let body =
2350+
self.parse_fn_body(attrs, &ident, &mut sig_hi, fn_parse_mode.req_body, fn_params_end)?;
23392351
let fn_sig_span = sig_lo.to(sig_hi);
23402352
Ok((ident, FnSig { header, decl, span: fn_sig_span }, generics, body))
23412353
}
23422354

2355+
/// Provide diagnostics when function body is not found
2356+
fn error_fn_body_not_found(
2357+
&mut self,
2358+
ident_span: Span,
2359+
req_body: bool,
2360+
fn_params_end: Option<Span>,
2361+
) -> PResult<'a, ErrorGuaranteed> {
2362+
let expected = if req_body {
2363+
&[token::OpenDelim(Delimiter::Brace)][..]
2364+
} else {
2365+
&[token::Semi, token::OpenDelim(Delimiter::Brace)]
2366+
};
2367+
match self.expected_one_of_not_found(&[], expected) {
2368+
Ok(error_guaranteed) => Ok(error_guaranteed),
2369+
Err(mut err) => {
2370+
if self.token.kind == token::CloseDelim(Delimiter::Brace) {
2371+
// The enclosing `mod`, `trait` or `impl` is being closed, so keep the `fn` in
2372+
// the AST for typechecking.
2373+
err.span_label(ident_span, "while parsing this `fn`");
2374+
Ok(err.emit())
2375+
} else if self.token.kind == token::RArrow
2376+
&& let Some(fn_params_end) = fn_params_end
2377+
{
2378+
// Instead of a function body, the parser has encountered a right arrow
2379+
// preceded by a where clause.
2380+
2381+
// Find whether token behind the right arrow is a function trait and
2382+
// store its span.
2383+
let fn_trait_span =
2384+
[sym::FnOnce, sym::FnMut, sym::Fn].into_iter().find_map(|symbol| {
2385+
if self.prev_token.is_ident_named(symbol) {
2386+
Some(self.prev_token.span)
2387+
} else {
2388+
None
2389+
}
2390+
});
2391+
2392+
// Parse the return type (along with the right arrow) and store its span.
2393+
// If there's a parse error, cancel it and return the existing error
2394+
// as we are primarily concerned with the
2395+
// expected-function-body-but-found-something-else error here.
2396+
let arrow_span = self.token.span;
2397+
let ty_span = match self.parse_ret_ty(
2398+
AllowPlus::Yes,
2399+
RecoverQPath::Yes,
2400+
RecoverReturnSign::Yes,
2401+
) {
2402+
Ok(ty_span) => ty_span.span().shrink_to_hi(),
2403+
Err(parse_error) => {
2404+
parse_error.cancel();
2405+
return Err(err);
2406+
}
2407+
};
2408+
let ret_ty_span = arrow_span.to(ty_span);
2409+
2410+
if let Some(fn_trait_span) = fn_trait_span {
2411+
// Typo'd Fn* trait bounds such as
2412+
// fn foo<F>() where F: FnOnce -> () {}
2413+
err.subdiagnostic(errors::FnTraitMissingParen { span: fn_trait_span });
2414+
} else if let Ok(snippet) = self.psess.source_map().span_to_snippet(ret_ty_span)
2415+
{
2416+
// If token behind right arrow is not a Fn* trait, the programmer
2417+
// probably misplaced the return type after the where clause like
2418+
// `fn foo<T>() where T: Default -> u8 {}`
2419+
err.primary_message(
2420+
"return type should be specified after the function parameters",
2421+
);
2422+
err.subdiagnostic(errors::MisplacedReturnType {
2423+
fn_params_end,
2424+
snippet,
2425+
ret_ty_span,
2426+
});
2427+
}
2428+
Err(err)
2429+
} else {
2430+
Err(err)
2431+
}
2432+
}
2433+
}
2434+
}
2435+
23432436
/// Parse the "body" of a function.
23442437
/// This can either be `;` when there's no body,
23452438
/// or e.g. a block when the function is a provided one.
@@ -2349,6 +2442,7 @@ impl<'a> Parser<'a> {
23492442
ident: &Ident,
23502443
sig_hi: &mut Span,
23512444
req_body: bool,
2445+
fn_params_end: Option<Span>,
23522446
) -> PResult<'a, Option<P<Block>>> {
23532447
let has_semi = if req_body {
23542448
self.token.kind == TokenKind::Semi
@@ -2377,33 +2471,7 @@ impl<'a> Parser<'a> {
23772471
});
23782472
(AttrVec::new(), Some(self.mk_block_err(span, guar)))
23792473
} else {
2380-
let expected = if req_body {
2381-
&[token::OpenDelim(Delimiter::Brace)][..]
2382-
} else {
2383-
&[token::Semi, token::OpenDelim(Delimiter::Brace)]
2384-
};
2385-
if let Err(mut err) = self.expected_one_of_not_found(&[], expected) {
2386-
if self.token.kind == token::CloseDelim(Delimiter::Brace) {
2387-
// The enclosing `mod`, `trait` or `impl` is being closed, so keep the `fn` in
2388-
// the AST for typechecking.
2389-
err.span_label(ident.span, "while parsing this `fn`");
2390-
err.emit();
2391-
} else {
2392-
// check for typo'd Fn* trait bounds such as
2393-
// fn foo<F>() where F: FnOnce -> () {}
2394-
if self.token.kind == token::RArrow {
2395-
let machine_applicable = [sym::FnOnce, sym::FnMut, sym::Fn]
2396-
.into_iter()
2397-
.any(|s| self.prev_token.is_ident_named(s));
2398-
2399-
err.subdiagnostic(errors::FnTraitMissingParen {
2400-
span: self.prev_token.span,
2401-
machine_applicable,
2402-
});
2403-
}
2404-
return Err(err);
2405-
}
2406-
}
2474+
self.error_fn_body_not_found(ident.span, req_body, fn_params_end)?;
24072475
(AttrVec::new(), None)
24082476
};
24092477
attrs.extend(inner_attrs);

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /