Rollup merge of #138019 - obi1kenobi:pg/pretty-print-more-attrs, r=compiler-errors

Pretty-print `#[deprecated]` attribute in HIR.

Pretty-print `#[deprecated]` attribute in a form closer to how it might appear in Rust source code, rather than using a `Debug`-like representation.

Consider the following Rust code:
```rust
#[deprecated]
pub struct PlainDeprecated;

#[deprecated = "here's why this is deprecated"]
pub struct DirectNote;

#[deprecated(since = "1.2.3", note = "here's why this is deprecated")]
pub struct SinceAndNote;
```

Here's the previous output:
```
#[attr="Deprecation{deprecation: Deprecation{since: Unspecifiednote:
suggestion: }span: }")]
struct PlainDeprecated;

#[attr="Deprecation{deprecation: Deprecation{since: Unspecifiednote:
here's why this is deprecatedsuggestion: }span: }")]
struct DirectNote;

#[attr="Deprecation{deprecation: Deprecation{since: NonStandard(1.2.3)note:
here's why this is deprecatedsuggestion: }span: }")]
struct SinceAndNote;
```

Here's the new output:
```rust
#[deprecated]
struct PlainDeprecated;

#[deprecated = "here's why this is deprecated"]
struct DirectNote;

#[deprecated(since = "1.2.3", note = "here's why this is deprecated"]
struct SinceAndNote;
```

Also includes a test for `#[diagnostic::(..)]` attributes, though their behavior is not changed here. I already wrote the test, so I figured it probably won't hurt to have it.

Related to discussion in #137645.

r? `@jdonszelmann`
This commit is contained in:
Jubilee 2025-03-04 19:37:07 -08:00 committed by GitHub
commit a69982e00a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 141 additions and 0 deletions

View File

@ -117,6 +117,80 @@ impl<'a> State<'a> {
));
self.hardbreak()
}
hir::Attribute::Parsed(AttributeKind::Deprecation { deprecation, .. }) => {
self.word("#[deprecated");
// There are three possible forms here:
// 1. a form with explicit components like
// `#[deprecated(since = "1.2.3", note = "some note", suggestion = "something")]`
// where each component may be present or absent.
// 2. `#[deprecated = "message"]`
// 3. `#[deprecated]`
//
// Let's figure out which we need.
// If there's a `since` or `suggestion` value, we're definitely in form 1.
if matches!(
deprecation.since,
rustc_attr_parsing::DeprecatedSince::RustcVersion(..)
| rustc_attr_parsing::DeprecatedSince::Future
| rustc_attr_parsing::DeprecatedSince::NonStandard(..)
) || deprecation.suggestion.is_some()
{
self.word("(");
let mut use_comma = false;
match &deprecation.since {
rustc_attr_parsing::DeprecatedSince::RustcVersion(rustc_version) => {
self.word("since = \"");
self.word(format!(
"{}.{}.{}",
rustc_version.major, rustc_version.minor, rustc_version.patch
));
self.word("\"");
use_comma = true;
}
rustc_attr_parsing::DeprecatedSince::Future => {
self.word("since = \"future\"");
use_comma = true;
}
rustc_attr_parsing::DeprecatedSince::NonStandard(symbol) => {
self.word("since = \"");
self.word(symbol.to_ident_string());
self.word("\"");
use_comma = true;
}
_ => {}
}
if let Some(note) = &deprecation.note {
if use_comma {
self.word(", ");
}
self.word("note = \"");
self.word(note.to_ident_string());
self.word("\"");
use_comma = true;
}
if let Some(suggestion) = &deprecation.suggestion {
if use_comma {
self.word(", ");
}
self.word("suggestion = \"");
self.word(suggestion.to_ident_string());
self.word("\"");
}
} else if let Some(note) = &deprecation.note {
// We're in form 2: `#[deprecated = "message"]`.
self.word(" = \"");
self.word(note.to_ident_string());
self.word("\"");
} else {
// We're in form 3: `#[deprecated]`. Nothing to do here.
}
self.word("]");
}
hir::Attribute::Parsed(pa) => {
self.word("#[attr=\"");
pa.print_attribute(self);

View File

@ -0,0 +1,17 @@
//@ compile-flags: -Zunpretty=hir
//@ check-pass
#[deprecated]
pub struct PlainDeprecated;
#[deprecated = "here's why this is deprecated"]
pub struct DirectNote;
#[deprecated(note = "here's why this is deprecated")]
pub struct ExplicitNote;
#[deprecated(since = "1.2.3", note = "here's why this is deprecated")]
pub struct SinceAndNote;
#[deprecated(note = "here's why this is deprecated", since = "1.2.3")]
pub struct FlippedOrder;

View File

@ -0,0 +1,21 @@
#[prelude_import]
use ::std::prelude::rust_2015::*;
#[macro_use]
extern crate std;
//@ compile-flags: -Zunpretty=hir
//@ check-pass
#[deprecated]
struct PlainDeprecated;
#[deprecated = "here's why this is deprecated"]
struct DirectNote;
#[deprecated = "here's why this is deprecated"]
struct ExplicitNote;
#[deprecated(since = "1.2.3", note = "here's why this is deprecated"]
struct SinceAndNote;
#[deprecated(since = "1.2.3", note = "here's why this is deprecated"]
struct FlippedOrder;

View File

@ -0,0 +1,13 @@
//@ compile-flags: -Zunpretty=hir
//@ check-pass
#[diagnostic::on_unimplemented(
message = "My Message for `ImportantTrait<{A}>` implemented for `{Self}`",
label = "My Label",
note = "Note 1",
note = "Note 2"
)]
pub trait ImportantTrait<A> {}
#[diagnostic::do_not_recommend]
impl<T> ImportantTrait<T> for T where T: Clone {}

View File

@ -0,0 +1,16 @@
#[prelude_import]
use ::std::prelude::rust_2015::*;
#[macro_use]
extern crate std;
//@ compile-flags: -Zunpretty=hir
//@ check-pass
#[diagnostic::on_unimplemented(message =
"My Message for `ImportantTrait<{A}>` implemented for `{Self}`", label =
"My Label", note = "Note 1", note = "Note 2")]
trait ImportantTrait<A> { }
#[diagnostic::do_not_recommend]
impl <T> ImportantTrait<T> for T where T: Clone
{#![diagnostic::do_not_recommend]
}