Skip to content

Commit aee2255

Browse files
authored
Rollup merge of rust-lang#47613 - estebank:rustc_on_unimplemented, r=nikomatsakis
Add filtering options to `rustc_on_unimplemented` - Add filtering options to `rustc_on_unimplemented` for local traits, filtering on `Self` and type arguments. - Add a way to provide custom notes. - Tweak binops text. - Add filter to detect wether `Self` is local or belongs to another crate. - Add filter to `Iterator` diagnostic for `&str`. Partly addresses rust-lang#44755 with a different syntax, as a first approach. Fixes rust-lang#46216, fixes rust-lang#37522, CC rust-lang#34297, rust-lang#46806.
2 parents 4f93357 + fd3f231 commit aee2255

File tree

19 files changed

+234
-83
lines changed

19 files changed

+234
-83
lines changed

src/libcore/fmt/mod.rs

+11-6
Original file line numberDiff line numberDiff line change
@@ -530,9 +530,12 @@ impl<'a> Display for Arguments<'a> {
530530
/// }
531531
/// ```
532532
#[stable(feature = "rust1", since = "1.0.0")]
533-
#[rustc_on_unimplemented = "`{Self}` cannot be formatted using `:?`; if it is \
534-
defined in your crate, add `#[derive(Debug)]` or \
535-
manually implement it"]
533+
#[rustc_on_unimplemented(
534+
on(crate_local, label="`{Self}` cannot be formatted using `:?`; \
535+
add `#[derive(Debug)]` or manually implement `{Debug}`"),
536+
message="`{Self}` doesn't implement `{Debug}`",
537+
label="`{Self}` cannot be formatted using `:?` because it doesn't implement `{Debug}`",
538+
)]
536539
#[lang = "debug_trait"]
537540
pub trait Debug {
538541
/// Formats the value using the given formatter.
@@ -593,9 +596,11 @@ pub trait Debug {
593596
///
594597
/// println!("The origin is: {}", origin);
595598
/// ```
596-
#[rustc_on_unimplemented = "`{Self}` cannot be formatted with the default \
597-
formatter; try using `:?` instead if you are using \
598-
a format string"]
599+
#[rustc_on_unimplemented(
600+
message="`{Self}` doesn't implement `{Display}`",
601+
label="`{Self}` cannot be formatted with the default formatter; \
602+
try using `:?` instead if you are using a format string",
603+
)]
599604
#[stable(feature = "rust1", since = "1.0.0")]
600605
pub trait Display {
601606
/// Formats the value using the given formatter.

src/libcore/iter/iterator.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,13 @@ fn _assert_is_object_safe(_: &Iterator<Item=()>) {}
2828
/// [module-level documentation]: index.html
2929
/// [impl]: index.html#implementing-iterator
3030
#[stable(feature = "rust1", since = "1.0.0")]
31-
#[rustc_on_unimplemented = "`{Self}` is not an iterator; maybe try calling \
32-
`.iter()` or a similar method"]
31+
#[rustc_on_unimplemented(
32+
on(
33+
_Self="&str",
34+
label="`{Self}` is not an iterator; try calling `.chars()` or `.bytes()`"
35+
),
36+
label="`{Self}` is not an iterator; maybe try calling `.iter()` or a similar method"
37+
)]
3338
#[doc(spotlight)]
3439
pub trait Iterator {
3540
/// The type of the elements being iterated over.

src/libcore/ops/arith.rs

+30-10
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,18 @@
7575
/// ```
7676
#[lang = "add"]
7777
#[stable(feature = "rust1", since = "1.0.0")]
78-
#[rustc_on_unimplemented = "no implementation for `{Self} + {RHS}`"]
78+
#[rustc_on_unimplemented(
79+
on(
80+
all(_Self="{integer}", RHS="{float}"),
81+
message="cannot add a float to an integer",
82+
),
83+
on(
84+
all(_Self="{float}", RHS="{integer}"),
85+
message="cannot add an integer to a float",
86+
),
87+
message="cannot add `{RHS}` to `{Self}`",
88+
label="no implementation for `{Self} + {RHS}`",
89+
)]
7990
pub trait Add<RHS=Self> {
8091
/// The resulting type after applying the `+` operator.
8192
#[stable(feature = "rust1", since = "1.0.0")]
@@ -170,7 +181,8 @@ add_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
170181
/// ```
171182
#[lang = "sub"]
172183
#[stable(feature = "rust1", since = "1.0.0")]
173-
#[rustc_on_unimplemented = "no implementation for `{Self} - {RHS}`"]
184+
#[rustc_on_unimplemented(message="cannot substract `{RHS}` from `{Self}`",
185+
label="no implementation for `{Self} - {RHS}`")]
174186
pub trait Sub<RHS=Self> {
175187
/// The resulting type after applying the `-` operator.
176188
#[stable(feature = "rust1", since = "1.0.0")]
@@ -287,7 +299,8 @@ sub_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
287299
/// ```
288300
#[lang = "mul"]
289301
#[stable(feature = "rust1", since = "1.0.0")]
290-
#[rustc_on_unimplemented = "no implementation for `{Self} * {RHS}`"]
302+
#[rustc_on_unimplemented(message="cannot multiply `{RHS}` to `{Self}`",
303+
label="no implementation for `{Self} * {RHS}`")]
291304
pub trait Mul<RHS=Self> {
292305
/// The resulting type after applying the `*` operator.
293306
#[stable(feature = "rust1", since = "1.0.0")]
@@ -408,7 +421,8 @@ mul_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
408421
/// ```
409422
#[lang = "div"]
410423
#[stable(feature = "rust1", since = "1.0.0")]
411-
#[rustc_on_unimplemented = "no implementation for `{Self} / {RHS}`"]
424+
#[rustc_on_unimplemented(message="cannot divide `{Self}` by `{RHS}`",
425+
label="no implementation for `{Self} / {RHS}`")]
412426
pub trait Div<RHS=Self> {
413427
/// The resulting type after applying the `/` operator.
414428
#[stable(feature = "rust1", since = "1.0.0")]
@@ -490,7 +504,8 @@ div_impl_float! { f32 f64 }
490504
/// ```
491505
#[lang = "rem"]
492506
#[stable(feature = "rust1", since = "1.0.0")]
493-
#[rustc_on_unimplemented = "no implementation for `{Self} % {RHS}`"]
507+
#[rustc_on_unimplemented(message="cannot mod `{Self}` by `{RHS}`",
508+
label="no implementation for `{Self} % {RHS}`")]
494509
pub trait Rem<RHS=Self> {
495510
/// The resulting type after applying the `%` operator.
496511
#[stable(feature = "rust1", since = "1.0.0")]
@@ -647,7 +662,8 @@ neg_impl_numeric! { isize i8 i16 i32 i64 i128 f32 f64 }
647662
/// ```
648663
#[lang = "add_assign"]
649664
#[stable(feature = "op_assign_traits", since = "1.8.0")]
650-
#[rustc_on_unimplemented = "no implementation for `{Self} += {Rhs}`"]
665+
#[rustc_on_unimplemented(message="cannot add-assign `{Rhs}` to `{Self}`",
666+
label="no implementation for `{Self} += {Rhs}`")]
651667
pub trait AddAssign<Rhs=Self> {
652668
/// Performs the `+=` operation.
653669
#[stable(feature = "op_assign_traits", since = "1.8.0")]
@@ -700,7 +716,8 @@ add_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
700716
/// ```
701717
#[lang = "sub_assign"]
702718
#[stable(feature = "op_assign_traits", since = "1.8.0")]
703-
#[rustc_on_unimplemented = "no implementation for `{Self} -= {Rhs}`"]
719+
#[rustc_on_unimplemented(message="cannot substract-assign `{Rhs}` from `{Self}`",
720+
label="no implementation for `{Self} -= {Rhs}`")]
704721
pub trait SubAssign<Rhs=Self> {
705722
/// Performs the `-=` operation.
706723
#[stable(feature = "op_assign_traits", since = "1.8.0")]
@@ -744,7 +761,8 @@ sub_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
744761
/// ```
745762
#[lang = "mul_assign"]
746763
#[stable(feature = "op_assign_traits", since = "1.8.0")]
747-
#[rustc_on_unimplemented = "no implementation for `{Self} *= {Rhs}`"]
764+
#[rustc_on_unimplemented(message="cannot multiply-assign `{Rhs}` to `{Self}`",
765+
label="no implementation for `{Self} *= {Rhs}`")]
748766
pub trait MulAssign<Rhs=Self> {
749767
/// Performs the `*=` operation.
750768
#[stable(feature = "op_assign_traits", since = "1.8.0")]
@@ -788,7 +806,8 @@ mul_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
788806
/// ```
789807
#[lang = "div_assign"]
790808
#[stable(feature = "op_assign_traits", since = "1.8.0")]
791-
#[rustc_on_unimplemented = "no implementation for `{Self} /= {Rhs}`"]
809+
#[rustc_on_unimplemented(message="cannot divide-assign `{Self}` by `{Rhs}`",
810+
label="no implementation for `{Self} /= {Rhs}`")]
792811
pub trait DivAssign<Rhs=Self> {
793812
/// Performs the `/=` operation.
794813
#[stable(feature = "op_assign_traits", since = "1.8.0")]
@@ -835,7 +854,8 @@ div_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
835854
/// ```
836855
#[lang = "rem_assign"]
837856
#[stable(feature = "op_assign_traits", since = "1.8.0")]
838-
#[rustc_on_unimplemented = "no implementation for `{Self} %= {Rhs}`"]
857+
#[rustc_on_unimplemented(message="cannot mod-assign `{Self}` by `{Rhs}``",
858+
label="no implementation for `{Self} %= {Rhs}`")]
839859
pub trait RemAssign<Rhs=Self> {
840860
/// Performs the `%=` operation.
841861
#[stable(feature = "op_assign_traits", since = "1.8.0")]

src/libcore/ops/bit.rs

+20-10
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,8 @@ not_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
120120
/// ```
121121
#[lang = "bitand"]
122122
#[stable(feature = "rust1", since = "1.0.0")]
123-
#[rustc_on_unimplemented = "no implementation for `{Self} & {RHS}`"]
123+
#[rustc_on_unimplemented(message="no implementation for `{Self} & {RHS}`",
124+
label="no implementation for `{Self} & {RHS}`")]
124125
pub trait BitAnd<RHS=Self> {
125126
/// The resulting type after applying the `&` operator.
126127
#[stable(feature = "rust1", since = "1.0.0")]
@@ -201,7 +202,8 @@ bitand_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
201202
/// ```
202203
#[lang = "bitor"]
203204
#[stable(feature = "rust1", since = "1.0.0")]
204-
#[rustc_on_unimplemented = "no implementation for `{Self} | {RHS}`"]
205+
#[rustc_on_unimplemented(message="no implementation for `{Self} | {RHS}`",
206+
label="no implementation for `{Self} | {RHS}`")]
205207
pub trait BitOr<RHS=Self> {
206208
/// The resulting type after applying the `|` operator.
207209
#[stable(feature = "rust1", since = "1.0.0")]
@@ -285,7 +287,8 @@ bitor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
285287
/// ```
286288
#[lang = "bitxor"]
287289
#[stable(feature = "rust1", since = "1.0.0")]
288-
#[rustc_on_unimplemented = "no implementation for `{Self} ^ {RHS}`"]
290+
#[rustc_on_unimplemented(message="no implementation for `{Self} ^ {RHS}`",
291+
label="no implementation for `{Self} ^ {RHS}`")]
289292
pub trait BitXor<RHS=Self> {
290293
/// The resulting type after applying the `^` operator.
291294
#[stable(feature = "rust1", since = "1.0.0")]
@@ -365,7 +368,8 @@ bitxor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
365368
/// ```
366369
#[lang = "shl"]
367370
#[stable(feature = "rust1", since = "1.0.0")]
368-
#[rustc_on_unimplemented = "no implementation for `{Self} << {RHS}`"]
371+
#[rustc_on_unimplemented(message="no implementation for `{Self} << {RHS}`",
372+
label="no implementation for `{Self} << {RHS}`")]
369373
pub trait Shl<RHS> {
370374
/// The resulting type after applying the `<<` operator.
371375
#[stable(feature = "rust1", since = "1.0.0")]
@@ -466,7 +470,8 @@ shl_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 isize i128 }
466470
/// ```
467471
#[lang = "shr"]
468472
#[stable(feature = "rust1", since = "1.0.0")]
469-
#[rustc_on_unimplemented = "no implementation for `{Self} >> {RHS}`"]
473+
#[rustc_on_unimplemented(message="no implementation for `{Self} >> {RHS}`",
474+
label="no implementation for `{Self} >> {RHS}`")]
470475
pub trait Shr<RHS> {
471476
/// The resulting type after applying the `>>` operator.
472477
#[stable(feature = "rust1", since = "1.0.0")]
@@ -579,7 +584,8 @@ shr_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
579584
/// ```
580585
#[lang = "bitand_assign"]
581586
#[stable(feature = "op_assign_traits", since = "1.8.0")]
582-
#[rustc_on_unimplemented = "no implementation for `{Self} &= {Rhs}`"]
587+
#[rustc_on_unimplemented(message="no implementation for `{Self} &= {Rhs}`",
588+
label="no implementation for `{Self} &= {Rhs}`")]
583589
pub trait BitAndAssign<Rhs=Self> {
584590
/// Performs the `&=` operation.
585591
#[stable(feature = "op_assign_traits", since = "1.8.0")]
@@ -626,7 +632,8 @@ bitand_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
626632
/// ```
627633
#[lang = "bitor_assign"]
628634
#[stable(feature = "op_assign_traits", since = "1.8.0")]
629-
#[rustc_on_unimplemented = "no implementation for `{Self} |= {Rhs}`"]
635+
#[rustc_on_unimplemented(message="no implementation for `{Self} |= {Rhs}`",
636+
label="no implementation for `{Self} |= {Rhs}`")]
630637
pub trait BitOrAssign<Rhs=Self> {
631638
/// Performs the `|=` operation.
632639
#[stable(feature = "op_assign_traits", since = "1.8.0")]
@@ -673,7 +680,8 @@ bitor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
673680
/// ```
674681
#[lang = "bitxor_assign"]
675682
#[stable(feature = "op_assign_traits", since = "1.8.0")]
676-
#[rustc_on_unimplemented = "no implementation for `{Self} ^= {Rhs}`"]
683+
#[rustc_on_unimplemented(message="no implementation for `{Self} ^= {Rhs}`",
684+
label="no implementation for `{Self} ^= {Rhs}`")]
677685
pub trait BitXorAssign<Rhs=Self> {
678686
/// Performs the `^=` operation.
679687
#[stable(feature = "op_assign_traits", since = "1.8.0")]
@@ -718,7 +726,8 @@ bitxor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
718726
/// ```
719727
#[lang = "shl_assign"]
720728
#[stable(feature = "op_assign_traits", since = "1.8.0")]
721-
#[rustc_on_unimplemented = "no implementation for `{Self} <<= {Rhs}`"]
729+
#[rustc_on_unimplemented(message="no implementation for `{Self} <<= {Rhs}`",
730+
label="no implementation for `{Self} <<= {Rhs}`")]
722731
pub trait ShlAssign<Rhs> {
723732
/// Performs the `<<=` operation.
724733
#[stable(feature = "op_assign_traits", since = "1.8.0")]
@@ -784,7 +793,8 @@ shl_assign_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
784793
/// ```
785794
#[lang = "shr_assign"]
786795
#[stable(feature = "op_assign_traits", since = "1.8.0")]
787-
#[rustc_on_unimplemented = "no implementation for `{Self} >>= {Rhs}`"]
796+
#[rustc_on_unimplemented(message="no implementation for `{Self} >>= {Rhs}`",
797+
label="no implementation for `{Self} >>= {Rhs}`")]
788798
pub trait ShrAssign<Rhs=Self> {
789799
/// Performs the `>>=` operation.
790800
#[stable(feature = "op_assign_traits", since = "1.8.0")]

src/librustc/traits/error_reporting.rs

+27-7
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
348348
if direct {
349349
// this is a "direct", user-specified, rather than derived,
350350
// obligation.
351-
flags.push(("direct", None));
351+
flags.push(("direct".to_string(), None));
352352
}
353353

354354
if let ObligationCauseCode::ItemObligation(item) = obligation.cause.code {
@@ -359,21 +359,37 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
359359
// Currently I'm leaving it for what I need for `try`.
360360
if self.tcx.trait_of_item(item) == Some(trait_ref.def_id) {
361361
method = self.tcx.item_name(item);
362-
flags.push(("from_method", None));
363-
flags.push(("from_method", Some(&*method)));
362+
flags.push(("from_method".to_string(), None));
363+
flags.push(("from_method".to_string(), Some(method.to_string())));
364364
}
365365
}
366366

367367
if let Some(k) = obligation.cause.span.compiler_desugaring_kind() {
368368
desugaring = k.as_symbol().as_str();
369-
flags.push(("from_desugaring", None));
370-
flags.push(("from_desugaring", Some(&*desugaring)));
369+
flags.push(("from_desugaring".to_string(), None));
370+
flags.push(("from_desugaring".to_string(), Some(desugaring.to_string())));
371+
}
372+
let generics = self.tcx.generics_of(def_id);
373+
let self_ty = trait_ref.self_ty();
374+
let self_ty_str = self_ty.to_string();
375+
flags.push(("_Self".to_string(), Some(self_ty_str.clone())));
376+
377+
for param in generics.types.iter() {
378+
let name = param.name.as_str().to_string();
379+
let ty = trait_ref.substs.type_for_def(param);
380+
let ty_str = ty.to_string();
381+
flags.push((name.clone(),
382+
Some(ty_str.clone())));
383+
}
384+
385+
if let Some(true) = self_ty.ty_to_def_id().map(|def_id| def_id.is_local()) {
386+
flags.push(("crate_local".to_string(), None));
371387
}
372388

373389
if let Ok(Some(command)) = OnUnimplementedDirective::of_item(
374390
self.tcx, trait_ref.def_id, def_id
375391
) {
376-
command.evaluate(self.tcx, trait_ref, &flags)
392+
command.evaluate(self.tcx, trait_ref, &flags[..])
377393
} else {
378394
OnUnimplementedNote::empty()
379395
}
@@ -549,7 +565,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
549565
.map(|t| (format!(" in `{}`", t), format!("within `{}`, ", t)))
550566
.unwrap_or((String::new(), String::new()));
551567

552-
let OnUnimplementedNote { message, label }
568+
let OnUnimplementedNote { message, label, note }
553569
= self.on_unimplemented_note(trait_ref, obligation);
554570
let have_alt_message = message.is_some() || label.is_some();
555571

@@ -578,6 +594,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
578594
trait_ref,
579595
trait_ref.self_ty()));
580596
}
597+
if let Some(ref s) = note {
598+
// If it has a custom "#[rustc_on_unimplemented]" note, let's display it
599+
err.note(s.as_str());
600+
}
581601

582602
self.suggest_borrow_on_unsized_slice(&obligation.cause.code, &mut err);
583603

0 commit comments

Comments
 (0)