Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
100 changes: 83 additions & 17 deletions compiler/rustc_attr_parsing/src/attributes/doc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,42 @@ fn check_attr_crate_level<S: Stage>(cx: &mut AcceptContext<'_, '_, S>, span: Spa
true
}

// FIXME: To be removed once merged and replace with `cx.expected_name_value(span, _name)`.
fn expected_name_value<S: Stage>(
cx: &mut AcceptContext<'_, '_, S>,
span: Span,
_name: Option<Symbol>,
) {
cx.emit_lint(
rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
AttributeLintKind::ExpectedNameValue,
span,
);
}

// FIXME: remove this method once merged and use `cx.expected_no_args(span)` instead.
fn expected_no_args<S: Stage>(cx: &mut AcceptContext<'_, '_, S>, span: Span) {
cx.emit_lint(
rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
AttributeLintKind::ExpectedNoArgs,
span,
);
}

// FIXME: remove this method once merged and use `cx.expected_no_args(span)` instead.
// cx.expected_string_literal(span, _actual_literal);
fn expected_string_literal<S: Stage>(
cx: &mut AcceptContext<'_, '_, S>,
span: Span,
_actual_literal: Option<&MetaItemLit>,
) {
cx.emit_lint(
rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
AttributeLintKind::MalformedDoc,
span,
);
}

fn parse_keyword_and_attribute<S: Stage>(
cx: &mut AcceptContext<'_, '_, S>,
path: &OwnedPathParser,
Expand All @@ -78,12 +114,12 @@ fn parse_keyword_and_attribute<S: Stage>(
attr_name: Symbol,
) {
let Some(nv) = args.name_value() else {
cx.expected_name_value(args.span().unwrap_or(path.span()), path.word_sym());
expected_name_value(cx, args.span().unwrap_or(path.span()), path.word_sym());
return;
};

let Some(value) = nv.value_as_str() else {
cx.expected_string_literal(nv.value_span, Some(nv.value_as_lit()));
expected_string_literal(cx, nv.value_span, Some(nv.value_as_lit()));
return;
};

Expand Down Expand Up @@ -127,12 +163,21 @@ impl DocParser {
match path.word_sym() {
Some(sym::no_crate_inject) => {
if let Err(span) = args.no_args() {
cx.expected_no_args(span);
expected_no_args(cx, span);
return;
}

if self.attribute.no_crate_inject.is_some() {
cx.duplicate_key(path.span(), sym::no_crate_inject);
if let Some(used_span) = self.attribute.no_crate_inject {
let unused_span = path.span();
cx.emit_lint(
rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
AttributeLintKind::UnusedDuplicate {
this: unused_span,
other: used_span,
warning: true,
},
unused_span,
);
return;
}

Expand All @@ -144,7 +189,14 @@ impl DocParser {
}
Some(sym::attr) => {
let Some(list) = args.list() else {
cx.expected_list(cx.attr_span, args);
// FIXME: remove this method once merged and uncomment the line below instead.
// cx.expected_list(cx.attr_span, args);
let span = cx.attr_span;
cx.emit_lint(
rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
AttributeLintKind::MalformedDoc,
span,
);
return;
};

Expand Down Expand Up @@ -246,7 +298,7 @@ impl DocParser {
inline: DocInline,
) {
if let Err(span) = args.no_args() {
cx.expected_no_args(span);
expected_no_args(cx, span);
return;
}

Expand Down Expand Up @@ -328,7 +380,14 @@ impl DocParser {
match sub_item.args() {
a @ (ArgParser::NoArgs | ArgParser::NameValue(_)) => {
let Some(name) = sub_item.path().word_sym() else {
cx.expected_identifier(sub_item.path().span());
// FIXME: remove this method once merged and uncomment the line
// below instead.
// cx.expected_identifier(sub_item.path().span());
cx.emit_lint(
rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
AttributeLintKind::MalformedDoc,
sub_item.path().span(),
);
continue;
};
if let Ok(CfgEntry::NameValue { name, value, .. }) =
Expand Down Expand Up @@ -391,7 +450,7 @@ impl DocParser {
macro_rules! no_args {
($ident: ident) => {{
if let Err(span) = args.no_args() {
cx.expected_no_args(span);
expected_no_args(cx, span);
return;
}

Expand All @@ -410,7 +469,7 @@ impl DocParser {
macro_rules! no_args_and_not_crate_level {
($ident: ident) => {{
if let Err(span) = args.no_args() {
cx.expected_no_args(span);
expected_no_args(cx, span);
return;
}
let span = path.span();
Expand All @@ -423,7 +482,7 @@ impl DocParser {
macro_rules! no_args_and_crate_level {
($ident: ident) => {{
if let Err(span) = args.no_args() {
cx.expected_no_args(span);
expected_no_args(cx, span);
return;
}
let span = path.span();
Expand All @@ -436,12 +495,12 @@ impl DocParser {
macro_rules! string_arg_and_crate_level {
($ident: ident) => {{
let Some(nv) = args.name_value() else {
cx.expected_name_value(args.span().unwrap_or(path.span()), path.word_sym());
expected_name_value(cx, args.span().unwrap_or(path.span()), path.word_sym());
return;
};

let Some(s) = nv.value_as_str() else {
cx.expected_string_literal(nv.value_span, Some(nv.value_as_lit()));
expected_string_literal(cx, nv.value_span, Some(nv.value_as_lit()));
return;
};

Expand Down Expand Up @@ -512,7 +571,14 @@ impl DocParser {
self.parse_single_test_doc_attr_item(cx, mip);
}
MetaItemOrLitParser::Lit(lit) => {
cx.unexpected_literal(lit.span);
// FIXME: remove this method once merged and uncomment the line
// below instead.
// cx.unexpected_literal(lit.span);
cx.emit_lint(
rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
AttributeLintKind::MalformedDoc,
lit.span,
);
}
}
}
Expand Down Expand Up @@ -582,7 +648,7 @@ impl DocParser {
let suggestions = cx.suggestions();
let span = cx.attr_span;
cx.emit_lint(
rustc_session::lint::builtin::ILL_FORMED_ATTRIBUTE_INPUT,
rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
AttributeLintKind::IllFormedAttributeInput { suggestions, docs: None },
span,
);
Expand All @@ -595,14 +661,14 @@ impl DocParser {
self.parse_single_doc_attr_item(cx, mip);
}
MetaItemOrLitParser::Lit(lit) => {
cx.expected_name_value(lit.span, None);
expected_name_value(cx, lit.span, None);
}
}
}
}
ArgParser::NameValue(nv) => {
if nv.value_as_str().is_none() {
cx.expected_string_literal(nv.value_span, Some(nv.value_as_lit()));
expected_string_literal(cx, nv.value_span, Some(nv.value_as_lit()));
} else {
unreachable!(
"Should have been handled at the same time as sugar-syntaxed doc comments"
Expand Down
12 changes: 12 additions & 0 deletions compiler/rustc_lint/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,14 @@ lint_expectation = this lint expectation is unfulfilled
.note = the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message
.rationale = {$rationale}

lint_expected_name_value =
expected this to be of the form `... = "..."`
.warn = {-lint_previously_accepted}

lint_expected_no_args =
didn't expect any arguments here
.warn = {-lint_previously_accepted}

lint_for_loops_over_fallibles =
for loop over {$article} `{$ref_prefix}{$ty}`. This is more readably written as an `if let` statement
.suggestion = consider using `if let` to clear intent
Expand Down Expand Up @@ -558,6 +566,10 @@ lint_macro_expr_fragment_specifier_2024_migration =

lint_malformed_attribute = malformed lint attribute input

lint_malformed_doc =
malformed `doc` attribute input
.warn = {-lint_previously_accepted}

lint_map_unit_fn = `Iterator::map` call that discard the iterator's values
.note = `Iterator::map`, like many of the methods on `Iterator`, gets executed lazily, meaning that its effects won't be visible until it is iterated
.function_label = this function returns `()`, which is likely not what you wanted
Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_lint/src/early/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -423,5 +423,11 @@ pub fn decorate_attribute_lint(
&AttributeLintKind::DoNotRecommendDoesNotExpectArgs => {
lints::DoNotRecommendDoesNotExpectArgs.decorate_lint(diag)
}

&AttributeLintKind::MalformedDoc => lints::MalformedDoc.decorate_lint(diag),

&AttributeLintKind::ExpectedNoArgs => lints::ExpectedNoArgs.decorate_lint(diag),

&AttributeLintKind::ExpectedNameValue => lints::ExpectedNameValue.decorate_lint(diag),
}
}
15 changes: 15 additions & 0 deletions compiler/rustc_lint/src/lints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3196,6 +3196,21 @@ pub(crate) struct UnusedDuplicate {
pub warning: bool,
}

#[derive(LintDiagnostic)]
#[diag(lint_malformed_doc)]
#[warning]
pub(crate) struct MalformedDoc;

#[derive(LintDiagnostic)]
#[diag(lint_expected_no_args)]
#[warning]
pub(crate) struct ExpectedNoArgs;

#[derive(LintDiagnostic)]
#[diag(lint_expected_name_value)]
#[warning]
pub(crate) struct ExpectedNameValue;

#[derive(LintDiagnostic)]
#[diag(lint_unsafe_attr_outside_unsafe)]
pub(crate) struct UnsafeAttrOutsideUnsafeLint {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_lint_defs/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3456,7 +3456,7 @@ declare_lint! {
/// but this lint was introduced to avoid breaking any existing
/// crates which included them.
pub INVALID_DOC_ATTRIBUTES,
Deny,
Warn,
"detects invalid `#[doc(...)]` attributes",
}

Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_lint_defs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -822,6 +822,9 @@ pub enum AttributeLintKind {
DocTestLiteral,
AttrCrateLevelOnly,
DoNotRecommendDoesNotExpectArgs,
MalformedDoc,
ExpectedNoArgs,
ExpectedNameValue,
}

pub type RegisteredTools = FxIndexSet<Ident>;
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_parse/src/parser/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2264,7 +2264,7 @@ impl<'a> Parser<'a> {
&& self.look_ahead(1, |t| *t == token::Comma || *t == token::CloseParen)
{
// `fn foo(String s) {}`
let ident = self.parse_ident().unwrap();
let ident = self.parse_ident_common(true).unwrap();
let span = pat.span.with_hi(ident.span.hi());

err.span_suggestion(
Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_parse/src/parser/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -408,12 +408,11 @@ impl<'a> Parser<'a> {
let insert_span = ident_span.shrink_to_lo();

let ident = if self.token.is_ident()
&& self.token.is_non_reserved_ident()
&& (!is_const || self.look_ahead(1, |t| *t == token::OpenParen))
&& self.look_ahead(1, |t| {
matches!(t.kind, token::Lt | token::OpenBrace | token::OpenParen)
}) {
self.parse_ident().unwrap()
self.parse_ident_common(true).unwrap()
} else {
return Ok(());
};
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_parse/src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -469,7 +469,7 @@ impl<'a> Parser<'a> {
self.parse_ident_common(self.may_recover())
}

fn parse_ident_common(&mut self, recover: bool) -> PResult<'a, Ident> {
pub(crate) fn parse_ident_common(&mut self, recover: bool) -> PResult<'a, Ident> {
let (ident, is_raw) = self.ident_or_err(recover)?;

if is_raw == IdentIsRaw::No && ident.is_reserved() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pub(crate) fn target() -> Target {
max_atomic_width: Some(128),
// As documented in https://developer.android.com/ndk/guides/cpu-features.html
// the neon (ASIMD) and FP must exist on all android aarch64 targets.
features: "+v8a,+neon,+outline-atomics".into(),
features: "+v8a,+neon".into(),
// the AAPCS64 expects use of non-leaf frame pointers per
// https://github.com/ARM-software/abi-aa/blob/4492d1570eb70c8fd146623e0db65b2d241f12e7/aapcs64/aapcs64.rst#the-frame-pointer
// and we tend to encounter interesting bugs in AArch64 unwinding code if we do not
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::spec::{Arch, Cc, FramePointer, LinkerFlavor, Lld, Target, TargetMetad
pub(crate) fn target() -> Target {
let mut base = base::windows_gnullvm::opts();
base.max_atomic_width = Some(128);
base.features = "+v8a,+neon,+outline-atomics".into();
base.features = "+v8a,+neon".into();
base.linker = Some("aarch64-w64-mingw32-clang".into());
base.add_pre_link_args(LinkerFlavor::Gnu(Cc::No, Lld::No), &["-m", "arm64pe"]);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::spec::{Arch, FramePointer, Target, TargetMetadata, base};
pub(crate) fn target() -> Target {
let mut base = base::windows_msvc::opts();
base.max_atomic_width = Some(128);
base.features = "+v8a,+neon,+outline-atomics".into();
base.features = "+v8a,+neon".into();

// Microsoft recommends enabling frame pointers on Arm64 Windows.
// From https://learn.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions?view=msvc-170#integer-registers
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub(crate) fn target() -> Target {
data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(),
arch: Arch::AArch64,
options: TargetOptions {
features: "+v8a,+outline-atomics".into(),
features: "+v8a".into(),
max_atomic_width: Some(128),
stack_probes: StackProbeType::Inline,
supported_sanitizers: SanitizerSet::ADDRESS
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::spec::{
pub(crate) fn target() -> Target {
let mut base = base::fuchsia::opts();
base.cpu = "generic".into();
base.features = "+v8a,+crc,+aes,+sha2,+neon,+outline-atomics".into();
base.features = "+v8a,+crc,+aes,+sha2,+neon".into();
base.max_atomic_width = Some(128);
base.stack_probes = StackProbeType::Inline;
base.supported_sanitizers = SanitizerSet::ADDRESS
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ pub(crate) fn target() -> Target {
data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(),
arch: Arch::AArch64,
options: TargetOptions {
features: "+v8a,+outline-atomics".into(),
features: "+v8a".into(),
max_atomic_width: Some(128),
stack_probes: StackProbeType::Inline,
..base::openbsd::opts()
Expand Down
Loading
Loading