Skip to content

Migrate rustc_passes to translatable diagnostics #110816

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 27, 2023
Merged
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
43 changes: 42 additions & 1 deletion compiler/rustc_passes/messages.ftl
Original file line number Diff line number Diff line change
@@ -139,7 +139,6 @@ passes_doc_attr_not_crate_level =
passes_attr_crate_level =
this attribute can only be applied at the crate level
.suggestion = to apply to the crate, use an inner attribute
.help = to apply to the crate, use an inner attribute
.note = read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information

passes_doc_test_unknown =
@@ -724,3 +723,45 @@ passes_skipping_const_checks = skipping const checks
passes_invalid_macro_export_arguments = `{$name}` isn't a valid `#[macro_export]` argument

passes_invalid_macro_export_arguments_too_many_items = `#[macro_export]` can only take 1 or 0 arguments

passes_unreachable_due_to_uninhabited = unreachable {$descr}
.label = unreachable {$descr}
.label_orig = any code following this expression is unreachable
.note = this expression has type `{$ty}`, which is uninhabited

passes_unused_var_maybe_capture_ref = unused variable: `{$name}`
.help = did you mean to capture by reference instead?

passes_unused_capture_maybe_capture_ref = value captured by `{$name}` is never read
.help = did you mean to capture by reference instead?

passes_unused_var_remove_field = unused variable: `{$name}`
passes_unused_var_remove_field_suggestion = try removing the field

passes_unused_var_assigned_only = variable `{$name}` is assigned to, but never used
.note = consider using `_{$name}` instead

passes_unnecessary_stable_feature = the feature `{$feature}` has been stable since {$since} and no longer requires an attribute to enable

passes_unnecessary_partial_stable_feature = the feature `{$feature}` has been partially stabilized since {$since} and is succeeded by the feature `{$implies}`
.suggestion = if you are using features which are still unstable, change to using `{$implies}`
.suggestion_remove = if you are using features which are now stable, remove this line

passes_ineffective_unstable_impl = an `#[unstable]` annotation here has no effect
.note = see issue #55436 <https://github.com/rust-lang/rust/issues/55436> for more information

passes_unused_assign = value assigned to `{$name}` is never read
.help = maybe it is overwritten before being read?

passes_unused_assign_passed = value passed to `{$name}` is never read
.help = maybe it is overwritten before being read?

passes_maybe_string_interpolation = you might have meant to use string interpolation in this string literal
passes_string_interpolation_only_works = string interpolation only works in `format!` invocations

passes_unused_variable_try_prefix = unused variable: `{$name}`
.label = unused variable
.suggestion = if this is intentional, prefix it with an underscore

passes_unused_variable_try_ignore = unused variable: `{$name}`
.suggestion = try ignoring the field
32 changes: 10 additions & 22 deletions compiler/rustc_passes/src/check_attr.rs
Original file line number Diff line number Diff line change
@@ -29,7 +29,7 @@ use rustc_session::lint::builtin::{
};
use rustc_session::parse::feature_err;
use rustc_span::symbol::{kw, sym, Symbol};
use rustc_span::{Span, DUMMY_SP};
use rustc_span::{BytePos, Span, DUMMY_SP};
use rustc_target::spec::abi::Abi;
use rustc_trait_selection::infer::{TyCtxtInferExt, ValuePairs};
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
@@ -927,30 +927,18 @@ impl CheckAttrVisitor<'_> {
hir_id: HirId,
) -> bool {
if hir_id != CRATE_HIR_ID {
self.tcx.struct_span_lint_hir(
// insert a bang between `#` and `[...`
let bang_span = attr.span.lo() + BytePos(1);
let sugg = (attr.style == AttrStyle::Outer
&& self.tcx.hir().get_parent_item(hir_id) == CRATE_OWNER_ID)
.then_some(errors::AttrCrateLevelOnlySugg {
attr: attr.span.with_lo(bang_span).with_hi(bang_span),
});
self.tcx.emit_spanned_lint(
INVALID_DOC_ATTRIBUTES,
hir_id,
meta.span(),
fluent::passes_attr_crate_level,
|err| {
if attr.style == AttrStyle::Outer
&& self.tcx.hir().get_parent_item(hir_id) == CRATE_OWNER_ID
{
if let Ok(mut src) = self.tcx.sess.source_map().span_to_snippet(attr.span) {
src.insert(1, '!');
err.span_suggestion_verbose(
attr.span,
fluent::passes_suggestion,
src,
Applicability::MaybeIncorrect,
);
} else {
err.span_help(attr.span, fluent::passes_help);
}
}
err.note(fluent::passes_note);
err
},
errors::AttrCrateLevelOnly { sugg },
);
return false;
}
160 changes: 159 additions & 1 deletion compiler/rustc_passes/src/errors.rs
Original file line number Diff line number Diff line change
@@ -6,7 +6,8 @@ use std::{
use crate::fluent_generated as fluent;
use rustc_ast::Label;
use rustc_errors::{
error_code, Applicability, DiagnosticSymbolList, ErrorGuaranteed, IntoDiagnostic, MultiSpan,
error_code, AddToDiagnostic, Applicability, Diagnostic, DiagnosticSymbolList, ErrorGuaranteed,
IntoDiagnostic, MultiSpan,
};
use rustc_hir::{self as hir, ExprKind, Target};
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
@@ -1555,3 +1556,160 @@ pub struct SkippingConstChecks {
#[primary_span]
pub span: Span,
}

#[derive(LintDiagnostic)]
#[diag(passes_unreachable_due_to_uninhabited)]
pub struct UnreachableDueToUninhabited<'desc, 'tcx> {
pub descr: &'desc str,
#[label]
pub expr: Span,
#[label(passes_label_orig)]
#[note]
pub orig: Span,
pub ty: Ty<'tcx>,
}

#[derive(LintDiagnostic)]
#[diag(passes_unused_var_maybe_capture_ref)]
#[help]
pub struct UnusedVarMaybeCaptureRef {
pub name: String,
}

#[derive(LintDiagnostic)]
#[diag(passes_unused_capture_maybe_capture_ref)]
#[help]
pub struct UnusedCaptureMaybeCaptureRef {
pub name: String,
}

#[derive(LintDiagnostic)]
#[diag(passes_unused_var_remove_field)]
pub struct UnusedVarRemoveField {
pub name: String,
#[subdiagnostic]
pub sugg: UnusedVarRemoveFieldSugg,
}

#[derive(Subdiagnostic)]
#[multipart_suggestion(
passes_unused_var_remove_field_suggestion,
applicability = "machine-applicable"
)]
pub struct UnusedVarRemoveFieldSugg {
#[suggestion_part(code = "")]
pub spans: Vec<Span>,
}

#[derive(LintDiagnostic)]
#[diag(passes_unused_var_assigned_only)]
#[note]
pub struct UnusedVarAssignedOnly {
pub name: String,
}

#[derive(LintDiagnostic)]
#[diag(passes_unnecessary_stable_feature)]
pub struct UnnecessaryStableFeature {
pub feature: Symbol,
pub since: Symbol,
}

#[derive(LintDiagnostic)]
#[diag(passes_unnecessary_partial_stable_feature)]
pub struct UnnecessaryPartialStableFeature {
#[suggestion(code = "{implies}", applicability = "maybe-incorrect")]
pub span: Span,
#[suggestion(passes_suggestion_remove, code = "", applicability = "maybe-incorrect")]
pub line: Span,
pub feature: Symbol,
pub since: Symbol,
pub implies: Symbol,
}

#[derive(LintDiagnostic)]
#[diag(passes_ineffective_unstable_impl)]
#[note]
pub struct IneffectiveUnstableImpl;

#[derive(LintDiagnostic)]
#[diag(passes_unused_assign)]
#[help]
pub struct UnusedAssign {
pub name: String,
}

#[derive(LintDiagnostic)]
#[diag(passes_unused_assign_passed)]
#[help]
pub struct UnusedAssignPassed {
pub name: String,
}

#[derive(LintDiagnostic)]
#[diag(passes_unused_variable_try_prefix)]
pub struct UnusedVariableTryPrefix {
#[label]
pub label: Option<Span>,
#[subdiagnostic]
pub string_interp: Vec<UnusedVariableStringInterp>,
#[subdiagnostic]
pub sugg: UnusedVariableTryPrefixSugg,
}

#[derive(Subdiagnostic)]
#[multipart_suggestion(passes_suggestion, applicability = "machine-applicable")]
pub struct UnusedVariableTryPrefixSugg {
#[suggestion_part(code = "_{name}")]
pub spans: Vec<Span>,
pub name: String,
}

pub struct UnusedVariableStringInterp {
pub lit: Span,
pub lo: Span,
pub hi: Span,
}

impl AddToDiagnostic for UnusedVariableStringInterp {
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F) {
diag.span_label(self.lit, crate::fluent_generated::passes_maybe_string_interpolation);
diag.multipart_suggestion(
crate::fluent_generated::passes_string_interpolation_only_works,
vec![(self.lo, String::from("format!(")), (self.hi, String::from(")"))],
Applicability::MachineApplicable,
);
}
}

#[derive(LintDiagnostic)]
#[diag(passes_unused_variable_try_ignore)]
pub struct UnusedVarTryIgnore {
#[subdiagnostic]
pub sugg: UnusedVarTryIgnoreSugg,
}

#[derive(Subdiagnostic)]
#[multipart_suggestion(passes_suggestion, applicability = "machine-applicable")]
pub struct UnusedVarTryIgnoreSugg {
#[suggestion_part(code = "{name}: _")]
pub shorthands: Vec<Span>,
#[suggestion_part(code = "_")]
pub non_shorthands: Vec<Span>,
pub name: String,
}

#[derive(LintDiagnostic)]
#[diag(passes_attr_crate_level)]
#[note]
pub struct AttrCrateLevelOnly {
#[subdiagnostic]
pub sugg: Option<AttrCrateLevelOnlySugg>,
}

#[derive(Subdiagnostic)]
#[suggestion(passes_suggestion, applicability = "maybe-incorrect", code = "!", style = "verbose")]
pub struct AttrCrateLevelOnlySugg {
#[primary_span]
pub attr: Span,
}
2 changes: 2 additions & 0 deletions compiler/rustc_passes/src/lib.rs
Original file line number Diff line number Diff line change
@@ -12,6 +12,8 @@
#![feature(min_specialization)]
#![feature(try_blocks)]
#![recursion_limit = "256"]
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]

#[macro_use]
extern crate rustc_middle;
204 changes: 80 additions & 124 deletions compiler/rustc_passes/src/liveness.rs
Original file line number Diff line number Diff line change
@@ -81,13 +81,13 @@
//! We generate various special nodes for various, well, special purposes.
//! These are described in the `Liveness` struct.
use crate::errors;

use self::LiveNodeKind::*;
use self::VarKind::*;

use rustc_ast::InlineAsmOptions;
use rustc_data_structures::fx::FxIndexMap;
use rustc_errors::Applicability;
use rustc_errors::Diagnostic;
use rustc_hir as hir;
use rustc_hir::def::*;
use rustc_hir::def_id::LocalDefId;
@@ -1297,13 +1297,13 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
self.exit_ln
}

fn warn_about_unreachable(
fn warn_about_unreachable<'desc>(
&mut self,
orig_span: Span,
orig_ty: Ty<'tcx>,
expr_span: Span,
expr_id: HirId,
descr: &str,
descr: &'desc str,
) {
if !orig_ty.is_never() {
// Unreachable code warnings are already emitted during type checking.
@@ -1316,22 +1316,15 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
// that we do not emit the same warning twice if the uninhabited type
// is indeed `!`.

let msg = format!("unreachable {}", descr);
self.ir.tcx.struct_span_lint_hir(
self.ir.tcx.emit_spanned_lint(
lint::builtin::UNREACHABLE_CODE,
expr_id,
expr_span,
&msg,
|diag| {
diag.span_label(expr_span, &msg)
.span_label(orig_span, "any code following this expression is unreachable")
.span_note(
orig_span,
&format!(
"this expression has type `{}`, which is uninhabited",
orig_ty
),
)
errors::UnreachableDueToUninhabited {
expr: expr_span,
orig: orig_span,
descr,
ty: orig_ty,
},
);
}
@@ -1483,23 +1476,21 @@ impl<'tcx> Liveness<'_, 'tcx> {
if self.used_on_entry(entry_ln, var) {
if !self.live_on_entry(entry_ln, var) {
if let Some(name) = self.should_warn(var) {
self.ir.tcx.struct_span_lint_hir(
self.ir.tcx.emit_spanned_lint(
lint::builtin::UNUSED_ASSIGNMENTS,
var_hir_id,
vec![span],
format!("value captured by `{}` is never read", name),
|lint| lint.help("did you mean to capture by reference instead?"),
errors::UnusedCaptureMaybeCaptureRef { name },
);
}
}
} else {
if let Some(name) = self.should_warn(var) {
self.ir.tcx.struct_span_lint_hir(
self.ir.tcx.emit_spanned_lint(
lint::builtin::UNUSED_VARIABLES,
var_hir_id,
vec![span],
format!("unused variable: `{}`", name),
|lint| lint.help("did you mean to capture by reference instead?"),
errors::UnusedVarMaybeCaptureRef { name },
);
}
}
@@ -1514,11 +1505,14 @@ impl<'tcx> Liveness<'_, 'tcx> {
Some(entry_ln),
Some(body),
|spans, hir_id, ln, var| {
if !self.live_on_entry(ln, var) {
self.report_unused_assign(hir_id, spans, var, |name| {
format!("value passed to `{}` is never read", name)
});
}
if !self.live_on_entry(ln, var)
&& let Some(name) = self.should_warn(var) {
self.ir.tcx.emit_spanned_lint(
lint::builtin::UNUSED_ASSIGNMENTS,
hir_id,
spans,
errors::UnusedAssignPassed { name },
); }
},
);
}
@@ -1587,39 +1581,35 @@ impl<'tcx> Liveness<'_, 'tcx> {
if ln == self.exit_ln { false } else { self.assigned_on_exit(ln, var) };

if is_assigned {
self.ir.tcx.struct_span_lint_hir(
self.ir.tcx.emit_spanned_lint(
lint::builtin::UNUSED_VARIABLES,
first_hir_id,
hir_ids_and_spans
.into_iter()
.map(|(_, _, ident_span)| ident_span)
.collect::<Vec<_>>(),
format!("variable `{}` is assigned to, but never used", name),
|lint| lint.note(&format!("consider using `_{}` instead", name)),
errors::UnusedVarAssignedOnly { name },
)
} else if can_remove {
self.ir.tcx.struct_span_lint_hir(
let spans = hir_ids_and_spans
.iter()
.map(|(_, pat_span, _)| {
let span = self
.ir
.tcx
.sess
.source_map()
.span_extend_to_next_char(*pat_span, ',', true);
span.with_hi(BytePos(span.hi().0 + 1))
})
.collect();
self.ir.tcx.emit_spanned_lint(
lint::builtin::UNUSED_VARIABLES,
first_hir_id,
hir_ids_and_spans.iter().map(|(_, pat_span, _)| *pat_span).collect::<Vec<_>>(),
format!("unused variable: `{}`", name),
|lint| {
lint.multipart_suggestion(
"try removing the field",
hir_ids_and_spans
.iter()
.map(|(_, pat_span, _)| {
let span = self
.ir
.tcx
.sess
.source_map()
.span_extend_to_next_char(*pat_span, ',', true);
(span.with_hi(BytePos(span.hi().0 + 1)), String::new())
})
.collect(),
Applicability::MachineApplicable,
)
errors::UnusedVarRemoveField {
name,
sugg: errors::UnusedVarRemoveFieldSugg { spans },
},
);
} else {
@@ -1633,121 +1623,87 @@ impl<'tcx> Liveness<'_, 'tcx> {
// the field" message, and suggest `_` for the non-shorthands. If we only
// have non-shorthand, then prefix with an underscore instead.
if !shorthands.is_empty() {
let shorthands = shorthands
.into_iter()
.map(|(_, pat_span, _)| (pat_span, format!("{}: _", name)))
.chain(
non_shorthands
.into_iter()
.map(|(_, pat_span, _)| (pat_span, "_".to_string())),
)
.collect::<Vec<_>>();
let shorthands =
shorthands.into_iter().map(|(_, pat_span, _)| pat_span).collect();
let non_shorthands =
non_shorthands.into_iter().map(|(_, pat_span, _)| pat_span).collect();

self.ir.tcx.struct_span_lint_hir(
self.ir.tcx.emit_spanned_lint(
lint::builtin::UNUSED_VARIABLES,
first_hir_id,
hir_ids_and_spans
.iter()
.map(|(_, pat_span, _)| *pat_span)
.collect::<Vec<_>>(),
format!("unused variable: `{}`", name),
|lint| {
lint.multipart_suggestion(
"try ignoring the field",
errors::UnusedVarTryIgnore {
sugg: errors::UnusedVarTryIgnoreSugg {
shorthands,
Applicability::MachineApplicable,
)
non_shorthands,
name,
},
},
);
} else {
let non_shorthands = non_shorthands
.into_iter()
.map(|(_, _, ident_span)| (ident_span, format!("_{}", name)))
.map(|(_, _, ident_span)| ident_span)
.collect::<Vec<_>>();

self.ir.tcx.struct_span_lint_hir(
let suggestions = self.string_interp_suggestions(&name, opt_body);
self.ir.tcx.emit_spanned_lint(
lint::builtin::UNUSED_VARIABLES,
first_hir_id,
hir_ids_and_spans
.iter()
.map(|(_, _, ident_span)| *ident_span)
.collect::<Vec<_>>(),
format!("unused variable: `{}`", name),
|lint| {
if self.has_added_lit_match_name_span(&name, opt_body, lint) {
lint.span_label(pat.span, "unused variable");
}
lint.multipart_suggestion(
"if this is intentional, prefix it with an underscore",
non_shorthands,
Applicability::MachineApplicable,
)
errors::UnusedVariableTryPrefix {
label: if !suggestions.is_empty() { Some(pat.span) } else { None },
sugg: errors::UnusedVariableTryPrefixSugg {
spans: non_shorthands,
name,
},
string_interp: suggestions,
},
);
}
}
}
}

fn has_added_lit_match_name_span(
fn string_interp_suggestions(
&self,
name: &str,
opt_body: Option<&hir::Body<'_>>,
err: &mut Diagnostic,
) -> bool {
let mut has_litstring = false;
let Some(opt_body) = opt_body else {return false;};
) -> Vec<errors::UnusedVariableStringInterp> {
let mut suggs = Vec::new();
let Some(opt_body) = opt_body else { return suggs; };
let mut visitor = CollectLitsVisitor { lit_exprs: vec![] };
intravisit::walk_body(&mut visitor, opt_body);
for lit_expr in visitor.lit_exprs {
let hir::ExprKind::Lit(litx) = &lit_expr.kind else { continue };
let rustc_ast::LitKind::Str(syb, _) = litx.node else{ continue; };
let name_str: &str = syb.as_str();
let mut name_pa = String::from("{");
name_pa.push_str(&name);
name_pa.push('}');
let name_pa = format!("{{{name}}}");
if name_str.contains(&name_pa) {
err.span_label(
lit_expr.span,
"you might have meant to use string interpolation in this string literal",
);
err.multipart_suggestion(
"string interpolation only works in `format!` invocations",
vec![
(lit_expr.span.shrink_to_lo(), "format!(".to_string()),
(lit_expr.span.shrink_to_hi(), ")".to_string()),
],
Applicability::MachineApplicable,
);
has_litstring = true;
suggs.push(errors::UnusedVariableStringInterp {
lit: lit_expr.span,
lo: lit_expr.span.shrink_to_lo(),
hi: lit_expr.span.shrink_to_hi(),
});
}
}
has_litstring
suggs
}

fn warn_about_dead_assign(&self, spans: Vec<Span>, hir_id: HirId, ln: LiveNode, var: Variable) {
if !self.live_on_exit(ln, var) {
self.report_unused_assign(hir_id, spans, var, |name| {
format!("value assigned to `{}` is never read", name)
});
}
}

fn report_unused_assign(
&self,
hir_id: HirId,
spans: Vec<Span>,
var: Variable,
message: impl Fn(&str) -> String,
) {
if let Some(name) = self.should_warn(var) {
self.ir.tcx.struct_span_lint_hir(
lint::builtin::UNUSED_ASSIGNMENTS,
hir_id,
spans,
message(&name),
|lint| lint.help("maybe it is overwritten before being read?"),
)
}
if !self.live_on_exit(ln, var)
&& let Some(name) = self.should_warn(var) {
self.ir.tcx.emit_spanned_lint(
lint::builtin::UNUSED_ASSIGNMENTS,
hir_id,
spans,
errors::UnusedAssign { name },
);
}
}
}
42 changes: 15 additions & 27 deletions compiler/rustc_passes/src/stability.rs
Original file line number Diff line number Diff line change
@@ -7,7 +7,6 @@ use rustc_attr::{
UnstableReason, VERSION_PLACEHOLDER,
};
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
@@ -759,12 +758,11 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
// do not lint when the trait isn't resolved, since resolution error should
// be fixed first
if t.path.res != Res::Err && c.fully_stable {
self.tcx.struct_span_lint_hir(
self.tcx.emit_spanned_lint(
INEFFECTIVE_UNSTABLE_TRAIT_IMPL,
item.hir_id(),
span,
"an `#[unstable]` annotation here has no effect",
|lint| lint.note("see issue #55436 <https://github.com/rust-lang/rust/issues/55436> for more information")
errors::IneffectiveUnstableImpl,
);
}
}
@@ -1095,29 +1093,16 @@ fn unnecessary_partially_stable_feature_lint(
implies: Symbol,
since: Symbol,
) {
tcx.struct_span_lint_hir(
tcx.emit_spanned_lint(
lint::builtin::STABLE_FEATURES,
hir::CRATE_HIR_ID,
span,
format!(
"the feature `{feature}` has been partially stabilized since {since} and is succeeded \
by the feature `{implies}`"
),
|lint| {
lint.span_suggestion(
span,
&format!(
"if you are using features which are still unstable, change to using `{implies}`"
),
implies,
Applicability::MaybeIncorrect,
)
.span_suggestion(
tcx.sess.source_map().span_extend_to_line(span),
"if you are using features which are now stable, remove this line",
"",
Applicability::MaybeIncorrect,
)
errors::UnnecessaryPartialStableFeature {
span,
line: tcx.sess.source_map().span_extend_to_line(span),
feature,
since,
implies,
},
);
}
@@ -1131,7 +1116,10 @@ fn unnecessary_stable_feature_lint(
if since.as_str() == VERSION_PLACEHOLDER {
since = rust_version_symbol();
}
tcx.struct_span_lint_hir(lint::builtin::STABLE_FEATURES, hir::CRATE_HIR_ID, span, format!("the feature `{feature}` has been stable since {since} and no longer requires an attribute to enable"), |lint| {
lint
});
tcx.emit_spanned_lint(
lint::builtin::STABLE_FEATURES,
hir::CRATE_HIR_ID,
span,
errors::UnnecessaryStableFeature { feature, since },
);
}
2 changes: 1 addition & 1 deletion tests/rustdoc-ui/doc_cfg_hide.stderr
Original file line number Diff line number Diff line change
@@ -16,7 +16,7 @@ LL | #![deny(warnings)]
help: to apply to the crate, use an inner attribute
|
LL | #![doc(cfg_hide(doc))]
| ~~~~~~~~~~~~~~~~~~~~~~
| +

error: `#[doc(cfg_hide(...)]` takes a list of attributes
--> $DIR/doc_cfg_hide.rs:4:8
2 changes: 1 addition & 1 deletion tests/rustdoc-ui/invalid-doc-attr.rs
Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@
//~^ ERROR can only be applied at the crate level
//~| WARN is being phased out
//~| HELP to apply to the crate, use an inner attribute
//~| SUGGESTION #![doc(test(no_crate_inject))]
//~| SUGGESTION !
#[doc(inline)]
//~^ ERROR can only be applied to a `use` item
//~| WARN is being phased out
2 changes: 1 addition & 1 deletion tests/rustdoc-ui/invalid-doc-attr.stderr
Original file line number Diff line number Diff line change
@@ -16,7 +16,7 @@ LL | #![deny(warnings)]
help: to apply to the crate, use an inner attribute
|
LL | #![doc(test(no_crate_inject))]
|
| +

error: this attribute can only be applied to a `use` item
--> $DIR/invalid-doc-attr.rs:9:7
2 changes: 1 addition & 1 deletion tests/ui/attributes/invalid-doc-attr.rs
Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@
//~^ ERROR can only be applied at the crate level
//~| WARN is being phased out
//~| HELP to apply to the crate, use an inner attribute
//~| SUGGESTION #![doc(test(no_crate_inject))]
//~| SUGGESTION !
#[doc(inline)]
//~^ ERROR can only be applied to a `use` item
//~| WARN is being phased out
2 changes: 1 addition & 1 deletion tests/ui/attributes/invalid-doc-attr.stderr
Original file line number Diff line number Diff line change
@@ -16,7 +16,7 @@ LL | #![deny(warnings)]
help: to apply to the crate, use an inner attribute
|
LL | #![doc(test(no_crate_inject))]
|
| +

error: this attribute can only be applied to a `use` item
--> $DIR/invalid-doc-attr.rs:9:7