diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 22edc18d71ca3..1658c8dac6768 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -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); diff --git a/tests/ui/unpretty/deprecated-attr.rs b/tests/ui/unpretty/deprecated-attr.rs new file mode 100644 index 0000000000000..dda362a595e24 --- /dev/null +++ b/tests/ui/unpretty/deprecated-attr.rs @@ -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; diff --git a/tests/ui/unpretty/deprecated-attr.stdout b/tests/ui/unpretty/deprecated-attr.stdout new file mode 100644 index 0000000000000..60dbac1072b9f --- /dev/null +++ b/tests/ui/unpretty/deprecated-attr.stdout @@ -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; diff --git a/tests/ui/unpretty/diagnostic-attr.rs b/tests/ui/unpretty/diagnostic-attr.rs new file mode 100644 index 0000000000000..27f5b693e691c --- /dev/null +++ b/tests/ui/unpretty/diagnostic-attr.rs @@ -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 {} + +#[diagnostic::do_not_recommend] +impl ImportantTrait for T where T: Clone {} diff --git a/tests/ui/unpretty/diagnostic-attr.stdout b/tests/ui/unpretty/diagnostic-attr.stdout new file mode 100644 index 0000000000000..e8696d04d38ab --- /dev/null +++ b/tests/ui/unpretty/diagnostic-attr.stdout @@ -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 { } + +#[diagnostic::do_not_recommend] +impl ImportantTrait for T where T: Clone + {#![diagnostic::do_not_recommend] +}