All HIR attributes are outer

This commit is contained in:
David Tolnay
2025-06-19 23:56:23 -07:00
parent 715e02ff3c
commit 6729b667ce
10 changed files with 140 additions and 156 deletions

View File

@@ -1207,14 +1207,6 @@ pub enum Attribute {
}
impl Attribute {
pub fn style(&self) -> AttrStyle {
match &self {
Attribute::Unparsed(u) => u.style,
Attribute::Parsed(AttributeKind::DocComment { style, .. }) => *style,
_ => panic!(),
}
}
pub fn get_normal_item(&self) -> &AttrItem {
match &self {
Attribute::Unparsed(normal) => &normal,
@@ -2290,16 +2282,9 @@ pub struct Expr<'hir> {
}
impl Expr<'_> {
pub fn precedence(
&self,
for_each_attr: &dyn Fn(HirId, &mut dyn FnMut(&Attribute)),
) -> ExprPrecedence {
pub fn precedence(&self, has_attr: &dyn Fn(HirId) -> bool) -> ExprPrecedence {
let prefix_attrs_precedence = || -> ExprPrecedence {
let mut has_outer_attr = false;
for_each_attr(self.hir_id, &mut |attr: &Attribute| {
has_outer_attr |= matches!(attr.style(), AttrStyle::Outer)
});
if has_outer_attr { ExprPrecedence::Prefix } else { ExprPrecedence::Unambiguous }
if has_attr(self.hir_id) { ExprPrecedence::Prefix } else { ExprPrecedence::Unambiguous }
};
match &self.kind {
@@ -2355,7 +2340,7 @@ impl Expr<'_> {
| ExprKind::Use(..)
| ExprKind::Err(_) => prefix_attrs_precedence(),
ExprKind::DropTemps(expr, ..) => expr.precedence(for_each_attr),
ExprKind::DropTemps(expr, ..) => expr.precedence(has_attr),
}
}

View File

@@ -10,7 +10,7 @@ use std::vec;
use rustc_abi::ExternAbi;
use rustc_ast::util::parser::{self, ExprPrecedence, Fixity};
use rustc_ast::{AttrStyle, DUMMY_NODE_ID, DelimArgs};
use rustc_ast::{DUMMY_NODE_ID, DelimArgs};
use rustc_ast_pretty::pp::Breaks::{Consistent, Inconsistent};
use rustc_ast_pretty::pp::{self, BoxMarker, Breaks};
use rustc_ast_pretty::pprust::state::MacHeader;
@@ -81,32 +81,24 @@ impl<'a> State<'a> {
}
fn precedence(&self, expr: &hir::Expr<'_>) -> ExprPrecedence {
let for_each_attr = |id: HirId, callback: &mut dyn FnMut(&hir::Attribute)| {
self.attrs(id).iter().for_each(callback);
};
expr.precedence(&for_each_attr)
let has_attr = |id: HirId| !self.attrs(id).is_empty();
expr.precedence(&has_attr)
}
fn print_attrs_as_inner(&mut self, attrs: &[hir::Attribute]) {
self.print_either_attributes(attrs, ast::AttrStyle::Inner)
}
fn print_attrs_as_outer(&mut self, attrs: &[hir::Attribute]) {
self.print_either_attributes(attrs, ast::AttrStyle::Outer)
}
fn print_either_attributes(&mut self, attrs: &[hir::Attribute], style: ast::AttrStyle) {
fn print_attrs(&mut self, attrs: &[hir::Attribute]) {
if attrs.is_empty() {
return;
}
for attr in attrs {
self.print_attribute_inline(attr, style);
self.print_attribute_as_style(attr, ast::AttrStyle::Outer);
}
self.hardbreak_if_not_bol();
}
fn print_attribute_inline(&mut self, attr: &hir::Attribute, style: AttrStyle) {
/// Print a single attribute as if it has style `style`, disregarding the
/// actual style of the attribute.
fn print_attribute_as_style(&mut self, attr: &hir::Attribute, style: ast::AttrStyle) {
match &attr {
hir::Attribute::Unparsed(unparsed) => {
self.maybe_print_comment(unparsed.span.lo());
@@ -118,14 +110,17 @@ impl<'a> State<'a> {
self.word("]");
self.hardbreak()
}
hir::Attribute::Parsed(AttributeKind::DocComment { style, kind, comment, .. }) => {
hir::Attribute::Parsed(AttributeKind::DocComment { kind, comment, .. }) => {
self.word(rustc_ast_pretty::pprust::state::doc_comment_to_string(
*kind, *style, *comment,
*kind, style, *comment,
));
self.hardbreak()
}
hir::Attribute::Parsed(pa) => {
self.word("#[attr = ");
match style {
ast::AttrStyle::Inner => self.word("#![attr = "),
ast::AttrStyle::Outer => self.word("#[attr = "),
}
pa.print_attribute(self);
self.word("]");
self.hardbreak()
@@ -281,10 +276,17 @@ pub fn print_crate<'a>(
ann,
};
// Print all attributes, regardless of actual style, as inner attributes
// since this is the crate root with nothing above it to print outer
// attributes.
for attr in s.attrs(hir::CRATE_HIR_ID) {
s.print_attribute_as_style(attr, ast::AttrStyle::Inner);
}
// When printing the AST, we sometimes need to inject `#[no_std]` here.
// Since you can't compile the HIR, it's not necessary.
s.print_mod(krate, (*attrs)(hir::CRATE_HIR_ID));
s.print_mod(krate);
s.print_remaining_comments();
s.s.eof()
}
@@ -299,7 +301,7 @@ where
}
pub fn attribute_to_string(ann: &dyn PpAnn, attr: &hir::Attribute) -> String {
to_string(ann, |s| s.print_attribute_inline(attr, AttrStyle::Outer))
to_string(ann, |s| s.print_attribute_as_style(attr, ast::AttrStyle::Outer))
}
pub fn ty_to_string(ann: &dyn PpAnn, ty: &hir::Ty<'_>) -> String {
@@ -361,8 +363,7 @@ impl<'a> State<'a> {
self.commasep_cmnt(b, exprs, |s, e| s.print_expr(e), |e| e.span);
}
fn print_mod(&mut self, _mod: &hir::Mod<'_>, attrs: &[hir::Attribute]) {
self.print_attrs_as_inner(attrs);
fn print_mod(&mut self, _mod: &hir::Mod<'_>) {
for &item_id in _mod.item_ids {
self.ann.nested(self, Nested::Item(item_id));
}
@@ -479,7 +480,7 @@ impl<'a> State<'a> {
fn print_foreign_item(&mut self, item: &hir::ForeignItem<'_>) {
self.hardbreak_if_not_bol();
self.maybe_print_comment(item.span.lo());
self.print_attrs_as_outer(self.attrs(item.hir_id()));
self.print_attrs(self.attrs(item.hir_id()));
match item.kind {
hir::ForeignItemKind::Fn(sig, arg_idents, generics) => {
let (cb, ib) = self.head("");
@@ -565,7 +566,7 @@ impl<'a> State<'a> {
self.hardbreak_if_not_bol();
self.maybe_print_comment(item.span.lo());
let attrs = self.attrs(item.hir_id());
self.print_attrs_as_outer(attrs);
self.print_attrs(attrs);
self.ann.pre(self, AnnNode::Item(item));
match item.kind {
hir::ItemKind::ExternCrate(orig_name, ident) => {
@@ -647,14 +648,13 @@ impl<'a> State<'a> {
self.print_ident(ident);
self.nbsp();
self.bopen(ib);
self.print_mod(mod_, attrs);
self.print_mod(mod_);
self.bclose(item.span, cb);
}
hir::ItemKind::ForeignMod { abi, items } => {
let (cb, ib) = self.head("extern");
self.word_nbsp(abi.to_string());
self.bopen(ib);
self.print_attrs_as_inner(self.attrs(item.hir_id()));
for item in items {
self.ann.nested(self, Nested::ForeignItem(item.id));
}
@@ -731,7 +731,6 @@ impl<'a> State<'a> {
self.space();
self.bopen(ib);
self.print_attrs_as_inner(attrs);
for impl_item in items {
self.ann.nested(self, Nested::ImplItem(impl_item.id));
}
@@ -822,7 +821,7 @@ impl<'a> State<'a> {
for v in variants {
self.space_if_not_bol();
self.maybe_print_comment(v.span.lo());
self.print_attrs_as_outer(self.attrs(v.hir_id));
self.print_attrs(self.attrs(v.hir_id));
let ib = self.ibox(INDENT_UNIT);
self.print_variant(v);
self.word(",");
@@ -857,7 +856,7 @@ impl<'a> State<'a> {
self.popen();
self.commasep(Inconsistent, struct_def.fields(), |s, field| {
s.maybe_print_comment(field.span.lo());
s.print_attrs_as_outer(s.attrs(field.hir_id));
s.print_attrs(s.attrs(field.hir_id));
s.print_type(field.ty);
});
self.pclose();
@@ -878,7 +877,7 @@ impl<'a> State<'a> {
for field in struct_def.fields() {
self.hardbreak_if_not_bol();
self.maybe_print_comment(field.span.lo());
self.print_attrs_as_outer(self.attrs(field.hir_id));
self.print_attrs(self.attrs(field.hir_id));
self.print_ident(field.ident);
self.word_nbsp(":");
self.print_type(field.ty);
@@ -916,7 +915,7 @@ impl<'a> State<'a> {
self.ann.pre(self, AnnNode::SubItem(ti.hir_id()));
self.hardbreak_if_not_bol();
self.maybe_print_comment(ti.span.lo());
self.print_attrs_as_outer(self.attrs(ti.hir_id()));
self.print_attrs(self.attrs(ti.hir_id()));
match ti.kind {
hir::TraitItemKind::Const(ty, default) => {
self.print_associated_const(ti.ident, ti.generics, ty, default);
@@ -944,7 +943,7 @@ impl<'a> State<'a> {
self.ann.pre(self, AnnNode::SubItem(ii.hir_id()));
self.hardbreak_if_not_bol();
self.maybe_print_comment(ii.span.lo());
self.print_attrs_as_outer(self.attrs(ii.hir_id()));
self.print_attrs(self.attrs(ii.hir_id()));
match ii.kind {
hir::ImplItemKind::Const(ty, expr) => {
@@ -1028,27 +1027,16 @@ impl<'a> State<'a> {
}
fn print_block(&mut self, blk: &hir::Block<'_>, cb: BoxMarker, ib: BoxMarker) {
self.print_block_with_attrs(blk, &[], cb, ib)
self.print_block_maybe_unclosed(blk, Some(cb), ib)
}
fn print_block_unclosed(&mut self, blk: &hir::Block<'_>, ib: BoxMarker) {
self.print_block_maybe_unclosed(blk, &[], None, ib)
}
fn print_block_with_attrs(
&mut self,
blk: &hir::Block<'_>,
attrs: &[hir::Attribute],
cb: BoxMarker,
ib: BoxMarker,
) {
self.print_block_maybe_unclosed(blk, attrs, Some(cb), ib)
self.print_block_maybe_unclosed(blk, None, ib)
}
fn print_block_maybe_unclosed(
&mut self,
blk: &hir::Block<'_>,
attrs: &[hir::Attribute],
cb: Option<BoxMarker>,
ib: BoxMarker,
) {
@@ -1060,8 +1048,6 @@ impl<'a> State<'a> {
self.ann.pre(self, AnnNode::Block(blk));
self.bopen(ib);
self.print_attrs_as_inner(attrs);
for st in blk.stmts {
self.print_stmt(st);
}
@@ -1251,7 +1237,7 @@ impl<'a> State<'a> {
fn print_expr_field(&mut self, field: &hir::ExprField<'_>) {
let cb = self.cbox(INDENT_UNIT);
self.print_attrs_as_outer(self.attrs(field.hir_id));
self.print_attrs(self.attrs(field.hir_id));
if !field.is_shorthand {
self.print_ident(field.ident);
self.word_space(":");
@@ -1451,7 +1437,7 @@ impl<'a> State<'a> {
fn print_expr(&mut self, expr: &hir::Expr<'_>) {
self.maybe_print_comment(expr.span.lo());
self.print_attrs_as_outer(self.attrs(expr.hir_id));
self.print_attrs(self.attrs(expr.hir_id));
let ib = self.ibox(INDENT_UNIT);
self.ann.pre(self, AnnNode::Expr(expr));
match expr.kind {
@@ -2076,7 +2062,7 @@ impl<'a> State<'a> {
self.space();
}
let cb = self.cbox(INDENT_UNIT);
self.print_attrs_as_outer(self.attrs(field.hir_id));
self.print_attrs(self.attrs(field.hir_id));
if !field.is_shorthand {
self.print_ident(field.ident);
self.word_nbsp(":");
@@ -2086,7 +2072,7 @@ impl<'a> State<'a> {
}
fn print_param(&mut self, arg: &hir::Param<'_>) {
self.print_attrs_as_outer(self.attrs(arg.hir_id));
self.print_attrs(self.attrs(arg.hir_id));
self.print_pat(arg.pat);
}
@@ -2121,7 +2107,7 @@ impl<'a> State<'a> {
let cb = self.cbox(INDENT_UNIT);
self.ann.pre(self, AnnNode::Arm(arm));
let ib = self.ibox(0);
self.print_attrs_as_outer(self.attrs(arm.hir_id));
self.print_attrs(self.attrs(arm.hir_id));
self.print_pat(arm.pat);
self.space();
if let Some(ref g) = arm.guard {
@@ -2409,7 +2395,7 @@ impl<'a> State<'a> {
}
fn print_where_predicate(&mut self, predicate: &hir::WherePredicate<'_>) {
self.print_attrs_as_outer(self.attrs(predicate.hir_id));
self.print_attrs(self.attrs(predicate.hir_id));
match *predicate.kind {
hir::WherePredicateKind::BoundPredicate(hir::WhereBoundPredicate {
bound_generic_params,

View File

@@ -18,7 +18,7 @@ use rustc_errors::{
use rustc_hir::def::{CtorKind, DefKind, Res};
use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::LangItem;
use rustc_hir::{Attribute, ExprKind, HirId, QPath};
use rustc_hir::{ExprKind, HirId, QPath};
use rustc_hir_analysis::NoVariantNamed;
use rustc_hir_analysis::hir_ty_lowering::{FeedConstTy, HirTyLowerer as _};
use rustc_infer::infer;
@@ -55,7 +55,7 @@ use crate::{
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub(crate) fn precedence(&self, expr: &hir::Expr<'_>) -> ExprPrecedence {
let for_each_attr = |id: HirId, callback: &mut dyn FnMut(&Attribute)| {
let has_attr = |id: HirId| -> bool {
for attr in self.tcx.hir_attrs(id) {
// For the purpose of rendering suggestions, disregard attributes
// that originate from desugaring of any kind. For example, `x?`
@@ -71,11 +71,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// let y: u32 = (x?).try_into().unwrap();
// + +++++++++++++++++++++
if attr.span().desugaring_kind().is_none() {
callback(attr);
return true;
}
}
false
};
expr.precedence(&for_each_attr)
expr.precedence(&has_attr)
}
/// Check an expr with an expectation type, and also demand that the expr's

View File

@@ -855,14 +855,15 @@ impl<'tcx> LateContext<'tcx> {
/// rendering diagnostic. This is not the same as the precedence that would
/// be used for pretty-printing HIR by rustc_hir_pretty.
pub fn precedence(&self, expr: &hir::Expr<'_>) -> ExprPrecedence {
let for_each_attr = |id: hir::HirId, callback: &mut dyn FnMut(&hir::Attribute)| {
let has_attr = |id: hir::HirId| -> bool {
for attr in self.tcx.hir_attrs(id) {
if attr.span().desugaring_kind().is_none() {
callback(attr);
return true;
}
}
false
};
expr.precedence(&for_each_attr)
expr.precedence(&has_attr)
}
/// If the given expression is a local binding, find the initializer expression.

View File

@@ -116,6 +116,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
let mut seen = FxHashMap::default();
let attrs = self.tcx.hir_attrs(hir_id);
for attr in attrs {
let mut style = None;
match attr {
Attribute::Parsed(AttributeKind::Confusables { first_span, .. }) => {
self.check_confusables(*first_span, target);
@@ -163,10 +164,11 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
Attribute::Parsed(AttributeKind::AsPtr(attr_span)) => {
self.check_applied_to_fn_or_method(hir_id, *attr_span, span, target)
}
&Attribute::Parsed(AttributeKind::MayDangle(attr_span)) => {
self.check_may_dangle(hir_id, attr_span)
Attribute::Parsed(AttributeKind::MayDangle(attr_span)) => {
self.check_may_dangle(hir_id, *attr_span)
}
Attribute::Unparsed(_) => {
Attribute::Unparsed(attr_item) => {
style = Some(attr_item.style);
match attr.path().as_slice() {
[sym::diagnostic, sym::do_not_recommend, ..] => {
self.check_do_not_recommend(attr.span(), hir_id, target, attr, item)
@@ -189,6 +191,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}
[sym::doc, ..] => self.check_doc_attrs(
attr,
attr_item.style,
hir_id,
target,
&mut specified_inline,
@@ -350,14 +353,14 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
if let Some(BuiltinAttribute { type_: AttributeType::CrateLevel, .. }) =
attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name))
{
match attr.style() {
ast::AttrStyle::Outer => self.tcx.emit_node_span_lint(
match style {
Some(ast::AttrStyle::Outer) => self.tcx.emit_node_span_lint(
UNUSED_ATTRIBUTES,
hir_id,
attr.span(),
errors::OuterCrateLevelAttr,
),
ast::AttrStyle::Inner => self.tcx.emit_node_span_lint(
Some(ast::AttrStyle::Inner) | None => self.tcx.emit_node_span_lint(
UNUSED_ATTRIBUTES,
hir_id,
attr.span(),
@@ -371,7 +374,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
check_duplicates(self.tcx, attr, hir_id, *duplicates, &mut seen);
}
self.check_unused_attribute(hir_id, attr)
self.check_unused_attribute(hir_id, attr, style)
}
self.check_repr(attrs, span, target, item, hir_id);
@@ -1194,7 +1197,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
/// the first `inline`/`no_inline` attribute.
fn check_doc_inline(
&self,
attr: &Attribute,
style: AttrStyle,
meta: &MetaItemInner,
hir_id: HirId,
target: Target,
@@ -1224,8 +1227,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
meta.span(),
errors::DocInlineOnlyUse {
attr_span: meta.span(),
item_span: (attr.style() == AttrStyle::Outer)
.then(|| self.tcx.hir_span(hir_id)),
item_span: (style == AttrStyle::Outer).then(|| self.tcx.hir_span(hir_id)),
},
);
}
@@ -1234,7 +1236,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
fn check_doc_masked(
&self,
attr: &Attribute,
style: AttrStyle,
meta: &MetaItemInner,
hir_id: HirId,
target: Target,
@@ -1246,8 +1248,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
meta.span(),
errors::DocMaskedOnlyExternCrate {
attr_span: meta.span(),
item_span: (attr.style() == AttrStyle::Outer)
.then(|| self.tcx.hir_span(hir_id)),
item_span: (style == AttrStyle::Outer).then(|| self.tcx.hir_span(hir_id)),
},
);
return;
@@ -1260,8 +1261,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
meta.span(),
errors::DocMaskedNotExternCrateSelf {
attr_span: meta.span(),
item_span: (attr.style() == AttrStyle::Outer)
.then(|| self.tcx.hir_span(hir_id)),
item_span: (style == AttrStyle::Outer).then(|| self.tcx.hir_span(hir_id)),
},
);
}
@@ -1285,13 +1285,14 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
fn check_attr_crate_level(
&self,
attr: &Attribute,
style: AttrStyle,
meta: &MetaItemInner,
hir_id: HirId,
) -> bool {
if hir_id != CRATE_HIR_ID {
// insert a bang between `#` and `[...`
let bang_span = attr.span().lo() + BytePos(1);
let sugg = (attr.style() == AttrStyle::Outer
let sugg = (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),
@@ -1308,7 +1309,13 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}
/// Checks that `doc(test(...))` attribute contains only valid attributes and are at the right place.
fn check_test_attr(&self, attr: &Attribute, meta: &MetaItemInner, hir_id: HirId) {
fn check_test_attr(
&self,
attr: &Attribute,
style: AttrStyle,
meta: &MetaItemInner,
hir_id: HirId,
) {
if let Some(metas) = meta.meta_item_list() {
for i_meta in metas {
match (i_meta.name(), i_meta.meta_item()) {
@@ -1316,7 +1323,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
// Allowed everywhere like `#[doc]`
}
(Some(sym::no_crate_inject), _) => {
self.check_attr_crate_level(attr, meta, hir_id);
self.check_attr_crate_level(attr, style, meta, hir_id);
}
(_, Some(m)) => {
self.tcx.emit_node_span_lint(
@@ -1370,6 +1377,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
fn check_doc_attrs(
&self,
attr: &Attribute,
style: AttrStyle,
hir_id: HirId,
target: Target,
specified_inline: &mut Option<(bool, Span)>,
@@ -1404,7 +1412,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}
Some(sym::test) => {
self.check_test_attr(attr, meta, hir_id);
self.check_test_attr(attr, style, meta, hir_id);
}
Some(
@@ -1415,25 +1423,25 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
| sym::html_root_url
| sym::html_no_source,
) => {
self.check_attr_crate_level(attr, meta, hir_id);
self.check_attr_crate_level(attr, style, meta, hir_id);
}
Some(sym::cfg_hide) => {
if self.check_attr_crate_level(attr, meta, hir_id) {
if self.check_attr_crate_level(attr, style, meta, hir_id) {
self.check_doc_cfg_hide(meta, hir_id);
}
}
Some(sym::inline | sym::no_inline) => {
self.check_doc_inline(attr, meta, hir_id, target, specified_inline)
self.check_doc_inline(style, meta, hir_id, target, specified_inline)
}
Some(sym::masked) => self.check_doc_masked(attr, meta, hir_id, target),
Some(sym::masked) => self.check_doc_masked(style, meta, hir_id, target),
Some(sym::cfg | sym::hidden | sym::notable_trait) => {}
Some(sym::rust_logo) => {
if self.check_attr_crate_level(attr, meta, hir_id)
if self.check_attr_crate_level(attr, style, meta, hir_id)
&& !self.tcx.features().rustdoc_internals()
{
feature_err(
@@ -1472,7 +1480,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
errors::DocTestUnknownInclude {
path,
value: value.to_string(),
inner: match attr.style() {
inner: match style {
AttrStyle::Inner => "!",
AttrStyle::Outer => "",
},
@@ -2426,7 +2434,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}
}
fn check_unused_attribute(&self, hir_id: HirId, attr: &Attribute) {
fn check_unused_attribute(&self, hir_id: HirId, attr: &Attribute, style: Option<AttrStyle>) {
// FIXME(jdonszelmann): deduplicate these checks after more attrs are parsed. This is very
// ugly now but can 100% be removed later.
if let Attribute::Parsed(p) = attr {
@@ -2479,14 +2487,14 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
})
{
if hir_id != CRATE_HIR_ID {
match attr.style() {
ast::AttrStyle::Outer => self.tcx.emit_node_span_lint(
match style {
Some(ast::AttrStyle::Outer) => self.tcx.emit_node_span_lint(
UNUSED_ATTRIBUTES,
hir_id,
attr.span(),
errors::OuterCrateLevelAttr,
),
ast::AttrStyle::Inner => self.tcx.emit_node_span_lint(
Some(ast::AttrStyle::Inner) | None => self.tcx.emit_node_span_lint(
UNUSED_ATTRIBUTES,
hir_id,
attr.span(),

View File

@@ -1,4 +1,5 @@
use clippy_utils::diagnostics::span_lint_and_then;
use rustc_ast::attr::AttributeExt as _;
use rustc_ast::token::CommentKind;
use rustc_errors::Applicability;
use rustc_hir::{AttrStyle, Attribute};
@@ -43,13 +44,19 @@ pub fn check(cx: &LateContext<'_>, doc: &str, range: Range<usize>, fragments: &F
"looks like a footnote ref, but has no matching footnote",
|diag| {
if this_fragment.kind == DocFragmentKind::SugaredDoc {
let (doc_attr, (_, doc_attr_comment_kind)) = attrs
let (doc_attr, (_, doc_attr_comment_kind), attr_style) = attrs
.iter()
.filter(|attr| attr.span().overlaps(this_fragment.span))
.rev()
.find_map(|attr| Some((attr, attr.doc_str_and_comment_kind()?)))
.find_map(|attr| {
Some((
attr,
attr.doc_str_and_comment_kind()?,
attr.doc_resolution_scope()?,
))
})
.unwrap();
let (to_add, terminator) = match (doc_attr_comment_kind, doc_attr.style()) {
let (to_add, terminator) = match (doc_attr_comment_kind, attr_style) {
(CommentKind::Line, AttrStyle::Outer) => ("\n///\n/// ", ""),
(CommentKind::Line, AttrStyle::Inner) => ("\n//!\n//! ", ""),
(CommentKind::Block, AttrStyle::Outer) => ("\n/** ", " */"),

View File

@@ -0,0 +1,11 @@
error[E0308]: mismatched types
--> $DIR/deprecated-expr-precedence.rs:6:19
|
LL | pub fn public() {
| - help: try adding a return type: `-> i32`
LL | #[deprecated] 0
| ^ expected `()`, found integer
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0308`.

View File

@@ -12,6 +12,4 @@ extern crate std;
trait ImportantTrait<A> { }
#[diagnostic::do_not_recommend]
impl <T> ImportantTrait<T> for T where T: Clone
{#![diagnostic::do_not_recommend]
}
impl <T> ImportantTrait<T> for T where T: Clone { }

View File

@@ -26,7 +26,7 @@ mod expressions {
mod items {
/// ItemKind::GlobalAsm
mod item_global_asm {/// ItemKind::GlobalAsm
mod item_global_asm {
global_asm! (".globl my_asm_func");
}
}

View File

@@ -50,20 +50,14 @@ mod prelude {
}
}
//! inner single-line doc comment
/*!
/// inner single-line doc comment
/**
* inner multi-line doc comment
*/
#[doc = "inner doc attribute"]
#[allow(dead_code, unused_variables)]
#[no_std]
mod attributes {//! inner single-line doc comment
/*!
* inner multi-line doc comment
*/
#![doc = "inner doc attribute"]
#![allow(dead_code, unused_variables)]
#![no_std]
mod attributes {
/// outer single-line doc comment
/**
@@ -413,25 +407,25 @@ mod expressions {
}
mod items {
/// ItemKind::ExternCrate
mod item_extern_crate {/// ItemKind::ExternCrate
mod item_extern_crate {
extern crate core;
extern crate self as unpretty;
extern crate core as _;
}
/// ItemKind::Use
mod item_use {/// ItemKind::Use
mod item_use {
use ::{};
use crate::expressions;
use crate::items::item_use;
use core::*;
}
/// ItemKind::Static
mod item_static {/// ItemKind::Static
mod item_static {
static A: () = { };
static mut B: () = { };
}
/// ItemKind::Const
mod item_const {/// ItemKind::Const
mod item_const {
const A: () = { };
trait TraitItems {
const
@@ -445,7 +439,7 @@ mod items {
}
}
/// ItemKind::Fn
mod item_fn {/// ItemKind::Fn
mod item_fn {
const unsafe extern "C" fn f() { }
async unsafe extern "C" fn g()
->
@@ -460,21 +454,19 @@ mod items {
}
}
/// ItemKind::Mod
mod item_mod {/// ItemKind::Mod
}
mod item_mod { }
/// ItemKind::ForeignMod
mod item_foreign_mod {/// ItemKind::ForeignMod
mod item_foreign_mod {
extern "Rust" { }
extern "C" { }
}
/// ItemKind::GlobalAsm: see exhaustive-asm.rs
/// ItemKind::TyAlias
mod item_ty_alias {/// ItemKind::GlobalAsm: see exhaustive-asm.rs
/// ItemKind::TyAlias
mod item_ty_alias {
type Type<'a> where T: 'a = T;
}
/// ItemKind::Enum
mod item_enum {/// ItemKind::Enum
mod item_enum {
enum Void { }
enum Empty {
Unit,
@@ -490,7 +482,7 @@ mod items {
}
}
/// ItemKind::Struct
mod item_struct {/// ItemKind::Struct
mod item_struct {
struct Unit;
struct Tuple();
struct Newtype(Unit);
@@ -501,45 +493,40 @@ mod items {
}
}
/// ItemKind::Union
mod item_union {/// ItemKind::Union
mod item_union {
union Generic<'a, T> where T: 'a {
t: T,
}
}
/// ItemKind::Trait
mod item_trait {/// ItemKind::Trait
mod item_trait {
auto unsafe trait Send { }
trait Trait<'a>: Sized where Self: 'a { }
}
/// ItemKind::TraitAlias
mod item_trait_alias {/// ItemKind::TraitAlias
mod item_trait_alias {
trait Trait<T> = Sized where for<'a> T: 'a;
}
/// ItemKind::Impl
mod item_impl {/// ItemKind::Impl
mod item_impl {
impl () { }
impl <T> () { }
impl Default for () { }
impl const <T> Default for () { }
}
/// ItemKind::MacCall
mod item_mac_call {/// ItemKind::MacCall
}
mod item_mac_call { }
/// ItemKind::MacroDef
mod item_macro_def {/// ItemKind::MacroDef
mod item_macro_def {
macro_rules! mac { () => {...}; }
macro stringify { () => {} }
}
/// ItemKind::Delegation
/*! FIXME: todo */
mod item_delegation {/// ItemKind::Delegation
/*! FIXME: todo */
}
/** FIXME: todo */
mod item_delegation { }
/// ItemKind::DelegationMac
/*! FIXME: todo */
mod item_delegation_mac {/// ItemKind::DelegationMac
/*! FIXME: todo */
}
/** FIXME: todo */
mod item_delegation_mac { }
}
mod patterns {
/// PatKind::Missing
@@ -690,29 +677,29 @@ mod types {
/// TyKind::Paren
fn ty_paren() { let _: T; }
/// TyKind::Typeof
/*! unused for now */
/** unused for now */
fn ty_typeof() { }
/// TyKind::Infer
fn ty_infer() { let _: _; }
/// TyKind::ImplicitSelf
/*! there is no syntax for this */
/** there is no syntax for this */
fn ty_implicit_self() { }
/// TyKind::MacCall
#[expect(deprecated)]
fn ty_mac_call() { let _: T; let _: T; let _: T; }
/// TyKind::CVarArgs
/*! FIXME: todo */
/** FIXME: todo */
fn ty_c_var_args() { }
/// TyKind::Pat
fn ty_pat() { let _: u32 is 1..=RangeMax; }
}
mod visibilities {
/// VisibilityKind::Public
mod visibility_public {/// VisibilityKind::Public
mod visibility_public {
struct Pub;
}
/// VisibilityKind::Restricted
mod visibility_restricted {/// VisibilityKind::Restricted
mod visibility_restricted {
struct PubCrate;
struct PubSelf;
struct PubSuper;