Skip to content

Commit 5433b9d

Browse files
committed
Stabilize the #[diagnostic] namespace and #[diagnostic::on_unimplemented] attribute
This PR stabilizes the `#[diagnostic]` attribute namespace and a minimal option of the `#[diagnostic::on_unimplemented]` attribute. The `#[diagnostic]` attribute namespace is meant to provide a home for attribute that allow users to influence error messages emitted by the compiler. The compiler is not guaranteed to use any of this hints, however it should accept any (non-)existing attribute in this namespace and potentially emit lint-warnings for unused attributes and options. This is meant to allow discarding certain attributes/options in the future to allow fundamental changes to the compiler without the need to keep then non-meaningful options working. The `#[diagnostic::on_unimplemented]` attribute is allowed to appear on a trait definition. This allows crate authors to hint the compiler to emit a specific error message if a certain trait is not implemented. For the `#[diagnostic::on_unimplemented]` attribute the following options are implemented: * `message` which provides the text for the top level error message * `label` which provides the text for the label shown inline in the broken code in the error message * `note` which provides additional notes. The `note` option can appear several times, which results in several note messages being emitted. If any of the other options appears several times the first occurrence of the relevant option specifies the actually used value. Any other occurrence generates an lint warning. For any other non-existing option a lint-warning is generated. All three options accept a text as argument. This text is allowed to contain format parameters referring to generic argument or `Self` by name via the `{Self}` or `{NameOfGenericArgument}` syntax. For any non-existing argument a lint warning is generated. Tracking issue: #111996
1 parent bf2637f commit 5433b9d

33 files changed

+262
-356
lines changed

compiler/rustc_ast_passes/src/feature_gate.rs

-8
Original file line numberDiff line numberDiff line change
@@ -200,14 +200,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
200200
);
201201
}
202202
}
203-
if !attr.is_doc_comment()
204-
&& let [seg, _] = attr.get_normal_item().path.segments.as_slice()
205-
&& seg.ident.name == sym::diagnostic
206-
&& !self.features.diagnostic_namespace
207-
{
208-
let msg = "`#[diagnostic]` attribute name space is experimental";
209-
gate!(self, diagnostic_namespace, seg.ident.span, msg);
210-
}
211203

212204
// Emit errors for non-staged-api crates.
213205
if !self.features.staged_api {

compiler/rustc_feature/src/accepted.rs

+2
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,8 @@ declare_features! (
144144
(accepted, derive_default_enum, "1.62.0", Some(86985)),
145145
/// Allows the use of destructuring assignments.
146146
(accepted, destructuring_assignment, "1.59.0", Some(71126)),
147+
/// Allows using the `#[diagnostic]` attribute tool namespace
148+
(accepted, diagnostic_namespace, "CURRENT_RUSTC_VERSION", Some(111996)),
147149
/// Allows `#[doc(alias = "...")]`.
148150
(accepted, doc_alias, "1.48.0", Some(50146)),
149151
/// Allows `..` in tuple (struct) patterns.

compiler/rustc_feature/src/unstable.rs

-2
Original file line numberDiff line numberDiff line change
@@ -436,8 +436,6 @@ declare_features! (
436436
(unstable, deprecated_safe, "1.61.0", Some(94978)),
437437
/// Allows having using `suggestion` in the `#[deprecated]` attribute.
438438
(unstable, deprecated_suggestion, "1.61.0", Some(94785)),
439-
/// Allows using the `#[diagnostic]` attribute tool namespace
440-
(unstable, diagnostic_namespace, "1.73.0", Some(111996)),
441439
/// Controls errors in trait implementations.
442440
(unstable, do_not_recommend, "1.67.0", Some(51992)),
443441
/// Tells rustdoc to automatically generate `#[doc(cfg(...))]`.

library/core/src/future/future.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,13 @@ use crate::task::{Context, Poll};
2828
#[must_use = "futures do nothing unless you `.await` or poll them"]
2929
#[stable(feature = "futures_api", since = "1.36.0")]
3030
#[lang = "future_trait"]
31-
#[diagnostic::on_unimplemented(
32-
label = "`{Self}` is not a future",
33-
message = "`{Self}` is not a future",
34-
note = "{Self} must be a future or must implement `IntoFuture` to be awaited"
31+
#[cfg_attr(
32+
not(bootstrap),
33+
diagnostic::on_unimplemented(
34+
label = "`{Self}` is not a future",
35+
message = "`{Self}` is not a future",
36+
note = "{Self} must be a future or must implement `IntoFuture` to be awaited"
37+
)
3538
)]
3639
pub trait Future {
3740
/// The type of value produced on completion.

library/core/src/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,6 @@
217217
#![feature(const_trait_impl)]
218218
#![feature(decl_macro)]
219219
#![feature(deprecated_suggestion)]
220-
#![feature(diagnostic_namespace)]
221220
#![feature(doc_cfg)]
222221
#![feature(doc_cfg_hide)]
223222
#![feature(doc_notable_trait)]

library/core/src/marker.rs

+37-16
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,12 @@ macro marker_impls {
7575
/// [ub]: ../../reference/behavior-considered-undefined.html
7676
#[stable(feature = "rust1", since = "1.0.0")]
7777
#[cfg_attr(not(test), rustc_diagnostic_item = "Send")]
78-
#[diagnostic::on_unimplemented(
79-
message = "`{Self}` cannot be sent between threads safely",
80-
label = "`{Self}` cannot be sent between threads safely"
78+
#[cfg_attr(
79+
not(bootstrap),
80+
diagnostic::on_unimplemented(
81+
message = "`{Self}` cannot be sent between threads safely",
82+
label = "`{Self}` cannot be sent between threads safely"
83+
)
8184
)]
8285
pub unsafe auto trait Send {
8386
// empty.
@@ -134,9 +137,12 @@ unsafe impl<T: Sync + ?Sized> Send for &T {}
134137
#[doc(alias = "?", alias = "?Sized")]
135138
#[stable(feature = "rust1", since = "1.0.0")]
136139
#[lang = "sized"]
137-
#[diagnostic::on_unimplemented(
138-
message = "the size for values of type `{Self}` cannot be known at compilation time",
139-
label = "doesn't have a size known at compile-time"
140+
#[cfg_attr(
141+
not(bootstrap),
142+
diagnostic::on_unimplemented(
143+
message = "the size for values of type `{Self}` cannot be known at compilation time",
144+
label = "doesn't have a size known at compile-time"
145+
)
140146
)]
141147
#[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable
142148
#[rustc_specialization_trait]
@@ -205,7 +211,10 @@ pub trait Unsize<T: ?Sized> {
205211
/// [RFC1445]: https://github.com/rust-lang/rfcs/blob/master/text/1445-restrict-constants-in-patterns.md
206212
/// [issue 63438]: https://github.com/rust-lang/rust/issues/63438
207213
#[unstable(feature = "structural_match", issue = "31434")]
208-
#[diagnostic::on_unimplemented(message = "the type `{Self}` does not `#[derive(PartialEq)]`")]
214+
#[cfg_attr(
215+
not(bootstrap),
216+
diagnostic::on_unimplemented(message = "the type `{Self}` does not `#[derive(PartialEq)]`")
217+
)]
209218
#[lang = "structural_peq"]
210219
pub trait StructuralPartialEq {
211220
// Empty.
@@ -273,7 +282,10 @@ marker_impls! {
273282
/// of the two derives (`#[derive(PartialEq)]` and `#[derive(Eq)]`) and check
274283
/// that both of them are present as part of structural-match checking.
275284
#[unstable(feature = "structural_match", issue = "31434")]
276-
#[diagnostic::on_unimplemented(message = "the type `{Self}` does not `#[derive(Eq)]`")]
285+
#[cfg_attr(
286+
not(bootstrap),
287+
diagnostic::on_unimplemented(message = "the type `{Self}` does not `#[derive(Eq)]`")
288+
)]
277289
#[lang = "structural_teq"]
278290
pub trait StructuralEq {
279291
// Empty.
@@ -964,9 +976,12 @@ marker_impls! {
964976
/// [section about `Unpin`]: crate::pin#unpin "pin module docs about unpin"
965977
/// [`unsafe`]: ../../std/keyword.unsafe.html "keyword unsafe"
966978
#[stable(feature = "pin", since = "1.33.0")]
967-
#[diagnostic::on_unimplemented(
968-
note = "consider using the `pin!` macro\nconsider using `Box::pin` if you need to access the pinned value outside of the current scope",
969-
message = "`{Self}` cannot be unpinned"
979+
#[cfg_attr(
980+
not(bootstrap),
981+
diagnostic::on_unimplemented(
982+
note = "consider using the `pin!` macro\nconsider using `Box::pin` if you need to access the pinned value outside of the current scope",
983+
message = "`{Self}` cannot be unpinned"
984+
)
970985
)]
971986
#[lang = "unpin"]
972987
pub auto trait Unpin {}
@@ -1012,7 +1027,7 @@ pub trait Destruct {}
10121027
/// for any user type.
10131028
#[unstable(feature = "tuple_trait", issue = "none")]
10141029
#[lang = "tuple_trait"]
1015-
#[diagnostic::on_unimplemented(message = "`{Self}` is not a tuple")]
1030+
#[cfg_attr(not(bootstrap), diagnostic::on_unimplemented(message = "`{Self}` is not a tuple"))]
10161031
#[rustc_deny_explicit_impl(implement_via_object = false)]
10171032
pub trait Tuple {}
10181033

@@ -1022,9 +1037,12 @@ pub trait Tuple {}
10221037
/// `*const ()` automatically implement this trait.
10231038
#[unstable(feature = "pointer_like_trait", issue = "none")]
10241039
#[lang = "pointer_like"]
1025-
#[diagnostic::on_unimplemented(
1026-
message = "`{Self}` needs to have the same ABI as a pointer",
1027-
label = "`{Self}` needs to be a pointer-like type"
1040+
#[cfg_attr(
1041+
not(bootstrap),
1042+
diagnostic::on_unimplemented(
1043+
message = "`{Self}` needs to have the same ABI as a pointer",
1044+
label = "`{Self}` needs to be a pointer-like type"
1045+
)
10281046
)]
10291047
pub trait PointerLike {}
10301048

@@ -1036,7 +1054,10 @@ pub trait PointerLike {}
10361054
/// are `StructuralPartialEq`.
10371055
#[lang = "const_param_ty"]
10381056
#[unstable(feature = "adt_const_params", issue = "95174")]
1039-
#[diagnostic::on_unimplemented(message = "`{Self}` can't be used as a const parameter type")]
1057+
#[cfg_attr(
1058+
not(bootstrap),
1059+
diagnostic::on_unimplemented(message = "`{Self}` can't be used as a const parameter type")
1060+
)]
10401061
#[allow(multiple_supertrait_upcastable)]
10411062
pub trait ConstParamTy: StructuralEq + StructuralPartialEq + Eq {}
10421063

library/core/src/ops/arith.rs

+48-24
Original file line numberDiff line numberDiff line change
@@ -307,9 +307,12 @@ sub_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
307307
/// ```
308308
#[lang = "mul"]
309309
#[stable(feature = "rust1", since = "1.0.0")]
310-
#[diagnostic::on_unimplemented(
311-
message = "cannot multiply `{Self}` by `{Rhs}`",
312-
label = "no implementation for `{Self} * {Rhs}`"
310+
#[cfg_attr(
311+
not(bootstrap),
312+
diagnostic::on_unimplemented(
313+
message = "cannot multiply `{Self}` by `{Rhs}`",
314+
label = "no implementation for `{Self} * {Rhs}`"
315+
)
313316
)]
314317
#[doc(alias = "*")]
315318
pub trait Mul<Rhs = Self> {
@@ -441,9 +444,12 @@ mul_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
441444
/// ```
442445
#[lang = "div"]
443446
#[stable(feature = "rust1", since = "1.0.0")]
444-
#[diagnostic::on_unimplemented(
445-
message = "cannot divide `{Self}` by `{Rhs}`",
446-
label = "no implementation for `{Self} / {Rhs}`"
447+
#[cfg_attr(
448+
not(bootstrap),
449+
diagnostic::on_unimplemented(
450+
message = "cannot divide `{Self}` by `{Rhs}`",
451+
label = "no implementation for `{Self} / {Rhs}`"
452+
)
447453
)]
448454
#[doc(alias = "/")]
449455
pub trait Div<Rhs = Self> {
@@ -543,9 +549,12 @@ div_impl_float! { f32 f64 }
543549
/// ```
544550
#[lang = "rem"]
545551
#[stable(feature = "rust1", since = "1.0.0")]
546-
#[diagnostic::on_unimplemented(
547-
message = "cannot calculate the remainder of `{Self}` divided by `{Rhs}`",
548-
label = "no implementation for `{Self} % {Rhs}`"
552+
#[cfg_attr(
553+
not(bootstrap),
554+
diagnostic::on_unimplemented(
555+
message = "cannot calculate the remainder of `{Self}` divided by `{Rhs}`",
556+
label = "no implementation for `{Self} % {Rhs}`"
557+
)
549558
)]
550559
#[doc(alias = "%")]
551560
pub trait Rem<Rhs = Self> {
@@ -729,9 +738,12 @@ neg_impl! { isize i8 i16 i32 i64 i128 f32 f64 }
729738
/// ```
730739
#[lang = "add_assign"]
731740
#[stable(feature = "op_assign_traits", since = "1.8.0")]
732-
#[diagnostic::on_unimplemented(
733-
message = "cannot add-assign `{Rhs}` to `{Self}`",
734-
label = "no implementation for `{Self} += {Rhs}`"
741+
#[cfg_attr(
742+
not(bootstrap),
743+
diagnostic::on_unimplemented(
744+
message = "cannot add-assign `{Rhs}` to `{Self}`",
745+
label = "no implementation for `{Self} += {Rhs}`"
746+
)
735747
)]
736748
#[doc(alias = "+")]
737749
#[doc(alias = "+=")]
@@ -796,9 +808,12 @@ add_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
796808
/// ```
797809
#[lang = "sub_assign"]
798810
#[stable(feature = "op_assign_traits", since = "1.8.0")]
799-
#[diagnostic::on_unimplemented(
800-
message = "cannot subtract-assign `{Rhs}` from `{Self}`",
801-
label = "no implementation for `{Self} -= {Rhs}`"
811+
#[cfg_attr(
812+
not(bootstrap),
813+
diagnostic::on_unimplemented(
814+
message = "cannot subtract-assign `{Rhs}` from `{Self}`",
815+
label = "no implementation for `{Self} -= {Rhs}`"
816+
)
802817
)]
803818
#[doc(alias = "-")]
804819
#[doc(alias = "-=")]
@@ -854,9 +869,12 @@ sub_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
854869
/// ```
855870
#[lang = "mul_assign"]
856871
#[stable(feature = "op_assign_traits", since = "1.8.0")]
857-
#[diagnostic::on_unimplemented(
858-
message = "cannot multiply-assign `{Self}` by `{Rhs}`",
859-
label = "no implementation for `{Self} *= {Rhs}`"
872+
#[cfg_attr(
873+
not(bootstrap),
874+
diagnostic::on_unimplemented(
875+
message = "cannot multiply-assign `{Self}` by `{Rhs}`",
876+
label = "no implementation for `{Self} *= {Rhs}`"
877+
)
860878
)]
861879
#[doc(alias = "*")]
862880
#[doc(alias = "*=")]
@@ -912,9 +930,12 @@ mul_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
912930
/// ```
913931
#[lang = "div_assign"]
914932
#[stable(feature = "op_assign_traits", since = "1.8.0")]
915-
#[diagnostic::on_unimplemented(
916-
message = "cannot divide-assign `{Self}` by `{Rhs}`",
917-
label = "no implementation for `{Self} /= {Rhs}`"
933+
#[cfg_attr(
934+
not(bootstrap),
935+
diagnostic::on_unimplemented(
936+
message = "cannot divide-assign `{Self}` by `{Rhs}`",
937+
label = "no implementation for `{Self} /= {Rhs}`"
938+
)
918939
)]
919940
#[doc(alias = "/")]
920941
#[doc(alias = "/=")]
@@ -973,9 +994,12 @@ div_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
973994
/// ```
974995
#[lang = "rem_assign"]
975996
#[stable(feature = "op_assign_traits", since = "1.8.0")]
976-
#[diagnostic::on_unimplemented(
977-
message = "cannot calculate and assign the remainder of `{Self}` divided by `{Rhs}`",
978-
label = "no implementation for `{Self} %= {Rhs}`"
997+
#[cfg_attr(
998+
not(bootstrap),
999+
diagnostic::on_unimplemented(
1000+
message = "cannot calculate and assign the remainder of `{Self}` divided by `{Rhs}`",
1001+
label = "no implementation for `{Self} %= {Rhs}`"
1002+
)
9791003
)]
9801004
#[doc(alias = "%")]
9811005
#[doc(alias = "%=")]

0 commit comments

Comments
 (0)