Skip to content
2 changes: 0 additions & 2 deletions compiler/rustc_ast/src/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -758,8 +758,6 @@ impl Token {
OpenInvisible(InvisibleOrigin::MetaVar(MetaVarKind::Ty { .. } | MetaVarKind::Path)) => {
true
}
// For anonymous structs or unions, which only appear in specific positions
// (type of struct fields or union fields), we don't consider them as regular types
_ => false,
}
}
Expand Down
30 changes: 2 additions & 28 deletions compiler/rustc_attr_parsing/src/attributes/cfg_select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use rustc_ast::{AttrStyle, NodeId, token};
use rustc_attr_ir::target::Target;
use rustc_attr_ir::{AttrPath, CfgEntry};
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::{Diagnostic, MultiSpan};
use rustc_errors::Diagnostic;
use rustc_feature::Features;
use rustc_lint_defs::builtin::UNREACHABLE_CFG_SELECT_PREDICATES;
use rustc_parse::exp;
Expand Down Expand Up @@ -87,10 +87,9 @@ pub fn parse_cfg_select(
lint_node_id: NodeId,
) -> Result<CfgSelectBranches, ErrorGuaranteed> {
let mut branches = CfgSelectBranches::default();
let mut branch_attr_error: Option<ErrorGuaranteed> = None;

while p.token != token::Eof {
reject_branch_outer_attrs(p, &mut branch_attr_error)?;
p.recover_from_outer_attributes("`cfg_select` branches").map_err(|e| e.emit())?;

if p.eat_keyword(exp!(Underscore)) {
let underscore = p.prev_token;
Expand Down Expand Up @@ -145,10 +144,6 @@ pub fn parse_cfg_select(
}
}

if let Some(guar) = branch_attr_error {
return Err(guar);
}

let it = branches
.reachable
.iter()
Expand All @@ -161,27 +156,6 @@ pub fn parse_cfg_select(
Ok(branches)
}

fn reject_branch_outer_attrs(
p: &mut Parser<'_>,
branch_attr_error: &mut Option<ErrorGuaranteed>,
) -> Result<(), ErrorGuaranteed> {
let Some(spans) = p.parse_cfg_select_branch_outer_attrs().map_err(|e| e.emit())? else {
return Ok(());
};

for (spans, msg) in [
(spans.doc_comments, "doc comments are not allowed on `cfg_select` branches"),
(spans.attrs, "attributes are not allowed on `cfg_select` branches"),
] {
if !spans.is_empty() {
branch_attr_error
.get_or_insert(p.dcx().struct_span_err(MultiSpan::from_spans(spans), msg).emit());
}
}

Ok(())
}

fn lint_unreachable(
p: &mut Parser<'_>,
predicates: impl Iterator<Item = CfgSelectPredicate>,
Expand Down
54 changes: 0 additions & 54 deletions compiler/rustc_parse/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1826,60 +1826,6 @@ pub(crate) struct ParenthesesInMatchPatSugg {
pub right: Span,
}

#[derive(Diagnostic)]
#[diag("documentation comments cannot be applied to a function parameter's type")]
pub(crate) struct DocCommentOnParamType {
#[primary_span]
#[label("doc comments are not allowed here")]
pub span: Span,
}

#[derive(Diagnostic)]
#[diag("attributes cannot be applied to a function parameter's type")]
pub(crate) struct AttributeOnParamType {
#[primary_span]
#[label("attributes are not allowed here")]
pub span: Span,
}

#[derive(Diagnostic)]
#[diag("attributes cannot be applied to types")]
pub(crate) struct AttributeOnType {
#[primary_span]
#[label("attributes are not allowed here")]
pub span: Span,
#[suggestion(
"remove attribute from here",
code = "",
applicability = "machine-applicable",
style = "tool-only"
)]
pub fix_span: Span,
}

#[derive(Diagnostic)]
#[diag("attributes cannot be applied to generic arguments")]
pub(crate) struct AttributeOnGenericArg {
#[primary_span]
#[label("attributes are not allowed here")]
pub span: Span,
#[suggestion(
"remove attribute from here",
code = "",
applicability = "machine-applicable",
style = "tool-only"
)]
pub fix_span: Span,
}

#[derive(Diagnostic)]
#[diag("attributes cannot be applied here")]
pub(crate) struct AttributeOnEmptyType {
#[primary_span]
#[label("attributes are not allowed here")]
pub span: Span,
}

#[derive(Diagnostic)]
#[diag("patterns aren't allowed in {$target}", code = E0642)]
pub(crate) struct PatternMethodParamWithoutBody {
Expand Down
38 changes: 38 additions & 0 deletions compiler/rustc_parse/src/parser/attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -507,4 +507,42 @@ impl<'a> Parser<'a> {

Err(self.dcx().create_err(err))
}

/// Recover from outer attributes in places where none were expected.
pub fn recover_from_outer_attributes(&mut self, target: &str) -> PResult<'a, ()> {
// We check the token ourselves first to prevent `#`
// from getting added to the set of expected tokens.
if !self.may_recover() || !matches!(self.token.kind, token::Pound | token::DocComment(..)) {
return Ok(());
}

let attrs = self.parse_outer_attributes()?;
if attrs.is_empty() {
return Ok(());
}

let attrs = attrs.take_for_recovery(self.psess);
let span = attrs.first().unwrap().span.to(attrs.last().unwrap().span);

let subject = if attrs.iter().all(|attr| matches!(attr.kind, ast::AttrKind::DocComment(..)))
{
"doc comments"
} else {
"attributes"
};

self.dcx()
.struct_span_err(span, format!("{subject} cannot be applied to {target}"))
.with_span_label(span, format!("{subject} are not allowed here"))
.with_span_suggestion_with_style(
span.until(self.token.span),
format!("remove these {subject}"),
String::new(),
rustc_errors::Applicability::MachineApplicable,
rustc_errors::SuggestionStyle::CompletelyHidden,
)
.emit();

Ok(())
}
}
32 changes: 1 addition & 31 deletions compiler/rustc_parse/src/parser/cfg_select.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use rustc_ast::token;
use rustc_ast::tokenstream::{TokenStream, TokenTree};
use rustc_ast::util::classify;
use rustc_ast::{AttrKind, token};
use rustc_errors::PResult;
use rustc_span::Span;

Expand Down Expand Up @@ -48,34 +48,4 @@ impl<'a> Parser<'a> {
}
Ok(TokenStream::from_ast(&expr))
}

/// Parses outer attributes before a `cfg_select!` branch for recovery.
pub fn parse_cfg_select_branch_outer_attrs(
&mut self,
) -> PResult<'a, Option<CfgSelectBranchAttrSpans>> {
let attrs = self.parse_outer_attributes()?;
if attrs.is_empty() {
return Ok(None);
}

let mut spans = CfgSelectBranchAttrSpans::default();
for attr in attrs.take_for_recovery(self.psess) {
match attr.kind {
AttrKind::Normal(..) => spans.attrs.push(attr.span),
AttrKind::Synthetic(..) => unreachable!(),
// `parse_outer_attributes` already emitted E0753 for inner doc comments before
// recovering them as outer doc-comment attributes.
AttrKind::DocComment(comment_kind, _)
if self.span_to_snippet(attr.span).ok().is_some_and(
|snippet| match comment_kind {
token::CommentKind::Line => snippet.starts_with("//!"),
token::CommentKind::Block => snippet.starts_with("/*!"),
},
) => {}
AttrKind::DocComment(..) => spans.doc_comments.push(attr.span),
}
}

Ok(Some(spans))
}
}
23 changes: 3 additions & 20 deletions compiler/rustc_parse/src/parser/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,9 @@ use super::{
SeqSep, TokenType,
};
use crate::diagnostics::{
AddParen, AmbiguousPlus, AsyncMoveBlockIn2015, AsyncUseBlockIn2015, AttributeOnParamType,
AwaitSuggestion, BadQPathStage2, BadTypePlus, BadTypePlusSub, ColonAsSemi,
ComparisonOperatorsCannotBeChained, ComparisonOperatorsCannotBeChainedSugg,
DocCommentDoesNotDocumentAnything, DocCommentOnParamType, DoubleColonInBound,
AddParen, AmbiguousPlus, AsyncMoveBlockIn2015, AsyncUseBlockIn2015, AwaitSuggestion,
BadQPathStage2, BadTypePlus, BadTypePlusSub, ColonAsSemi, ComparisonOperatorsCannotBeChained,
ComparisonOperatorsCannotBeChainedSugg, DocCommentDoesNotDocumentAnything, DoubleColonInBound,
ExpectedIdentifier, ExpectedSemi, ExpectedSemiSugg, ExprParenthesesNeeded, FoundPathInGenerics,
GenericParamsWithoutAngleBrackets, GenericParamsWithoutAngleBracketsSugg,
HelpIdentifierStartsWithNumber, HelpUseLatestEdition, InInTypo, IncorrectAwait,
Expand Down Expand Up @@ -2216,22 +2215,6 @@ impl<'a> Parser<'a> {
}
}

pub(super) fn eat_incorrect_doc_comment_for_param_type(&mut self) {
if let token::DocComment(..) = self.token.kind {
self.dcx().emit_err(DocCommentOnParamType { span: self.token.span });
self.bump();
} else if self.token == token::Pound && self.look_ahead(1, |t| *t == token::OpenBracket) {
let lo = self.token.span;
// Skip every token until next possible arg.
while self.token != token::CloseBracket {
self.bump();
}
let sp = lo.to(self.token.span);
self.bump();
self.dcx().emit_err(AttributeOnParamType { span: sp });
}
}

pub(super) fn parameter_without_type(
&mut self,
err: &mut Diag<'_>,
Expand Down
2 changes: 0 additions & 2 deletions compiler/rustc_parse/src/parser/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -778,12 +778,10 @@ impl<'a> Parser<'a> {
};
}

this.eat_incorrect_doc_comment_for_param_type();
(pat, this.parse_ty_for_param()?)
} else {
debug!("parse_param_general ident_to_pat");
let parser_snapshot_before_ty = this.create_snapshot_for_diagnostic();
this.eat_incorrect_doc_comment_for_param_type();
let mut ty = this.parse_ty_for_param();

if let Ok(t) = &ty {
Expand Down
63 changes: 7 additions & 56 deletions compiler/rustc_parse/src/parser/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,11 @@ use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
use super::{Parser, Restrictions, TokenType};
use crate::ast::{PatKind, TyKind};
use crate::diagnostics::{
self, AttributeOnEmptyType, AttributeOnGenericArg, ConstGenericWithoutBraces,
ConstGenericWithoutBracesSugg, PathFoundAttributeInParams, PathFoundCVariadicParams,
PathSingleColon, PathTripleColon,
self, ConstGenericWithoutBraces, ConstGenericWithoutBracesSugg, PathFoundAttributeInParams,
PathFoundCVariadicParams, PathSingleColon, PathTripleColon,
};
use crate::exp;
use crate::parser::{
CommaRecoveryMode, Expr, ExprKind, FnContext, FnParseMode, RecoverColon, RecoverComma,
};
use crate::parser::{CommaRecoveryMode, Expr, FnContext, FnParseMode, RecoverColon, RecoverComma};

/// Specifies how to parse a path.
#[derive(Copy, Clone, PartialEq)]
Expand Down Expand Up @@ -914,12 +911,8 @@ impl<'a> Parser<'a> {
&mut self,
ty_generics: Option<&Generics>,
) -> PResult<'a, Option<GenericArg>> {
let mut attr_span: Option<Span> = None;
if self.token == token::Pound && self.look_ahead(1, |t| *t == token::OpenBracket) {
let attrs_wrapper = self.parse_outer_attributes()?;
let raw_attrs = attrs_wrapper.take_for_recovery(self.psess);
attr_span = Some(raw_attrs[0].span.to(raw_attrs.last().unwrap().span));
}
self.recover_from_outer_attributes("generic arguments")?;

let start = self.token.span;
let arg = if self.check_lifetime() && self.look_ahead(1, |t| !t.is_like_plus()) {
// Parse lifetime argument.
Expand All @@ -939,33 +932,9 @@ impl<'a> Parser<'a> {
}

match self.parse_ty() {
Ok(ty) => {
// Since the type parser recovers from some malformed slice and array types and
// successfully returns a type, we need to look for `TyKind::Err`s in the
// type to determine if error recovery has occurred and if the input is not a
// syntactically valid type after all.
if let ast::TyKind::Slice(inner_ty) | ast::TyKind::Array(inner_ty, _) = &ty.kind
&& let ast::TyKind::Err(_) = inner_ty.kind
&& let Some(snapshot) = snapshot
&& let Some(expr) =
self.recover_unbraced_const_arg_that_can_begin_ty(snapshot)
{
return Ok(Some(
self.dummy_const_arg_needs_braces(
self.dcx()
.struct_span_err(expr.span, "invalid const generic expression"),
expr.span,
),
));
}

GenericArg::Type(ty)
}
Ok(ty) => GenericArg::Type(ty),
Err(err) => {
let stopped_at_doc_comment = matches!(self.token.kind, token::DocComment(..));

if !stopped_at_doc_comment
&& let Some(snapshot) = snapshot
if let Some(snapshot) = snapshot
&& let Some(expr) =
self.recover_unbraced_const_arg_that_can_begin_ty(snapshot)
{
Expand All @@ -977,9 +946,6 @@ impl<'a> Parser<'a> {
}
} else if self.token.is_keyword(kw::Const) {
return self.recover_const_param_declaration(ty_generics);
} else if let Some(attr_span) = attr_span {
let diag = self.dcx().create_err(AttributeOnEmptyType { span: attr_span });
return Err(diag);
} else {
// Fall back by trying to parse a const-expr expression. If we successfully do so,
// then we should report an error that it needs to be wrapped in braces.
Expand All @@ -999,21 +965,6 @@ impl<'a> Parser<'a> {
}
};

if let Some(attr_span) = attr_span {
let guar = self.dcx().emit_err(AttributeOnGenericArg {
span: attr_span,
fix_span: attr_span.until(arg.span()),
});
return Ok(Some(match arg {
GenericArg::Type(_) => GenericArg::Type(self.mk_ty(attr_span, TyKind::Err(guar))),
GenericArg::Const(_) => {
let error_expr = self.mk_expr(attr_span, ExprKind::Err(guar));
GenericArg::Const(AnonConst { id: ast::DUMMY_NODE_ID, value: error_expr })
}
GenericArg::Lifetime(lt) => GenericArg::Lifetime(lt),
}));
}

Ok(Some(arg))
}

Expand Down
Loading
Loading