Skip to content

Commit c1383e4

Browse files
committed
Add filtering options to rustc_on_unimplemented
- filter error on the evaluated value of `Self` - filter error on the evaluated value of the type arguments - add argument to include custom note in diagnostic - allow the parser to parse `Self` when processing attributes - add custom message to binops
1 parent 56733bc commit c1383e4

40 files changed

+312
-403
lines changed

src/libcore/ops/arith.rs

Lines changed: 105 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,93 @@
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+
any(
81+
all(_Self="i128", RHS="i64"),
82+
all(_Self="i128", RHS="i32"),
83+
all(_Self="i128", RHS="i16"),
84+
all(_Self="i128", RHS="i8"),
85+
all(_Self="i64", RHS="i32"),
86+
all(_Self="i64", RHS="i16"),
87+
all(_Self="i64", RHS="i8"),
88+
all(_Self="i32", RHS="i16"),
89+
all(_Self="i32", RHS="i8"),
90+
all(_Self="i16", RHS="i8"),
91+
all(_Self="u128", RHS="u64"),
92+
all(_Self="u128", RHS="u32"),
93+
all(_Self="u128", RHS="u16"),
94+
all(_Self="u128", RHS="u8"),
95+
all(_Self="u64", RHS="u32"),
96+
all(_Self="u64", RHS="u16"),
97+
all(_Self="u64", RHS="u8"),
98+
all(_Self="u32", RHS="u16"),
99+
all(_Self="u32", RHS="u8"),
100+
all(_Self="u16", RHS="u8"),
101+
all(_Self="f64", RHS="i32"),
102+
all(_Self="f64", RHS="i16"),
103+
all(_Self="f64", RHS="i8"),
104+
all(_Self="f64", RHS="u32"),
105+
all(_Self="f64", RHS="u16"),
106+
all(_Self="f64", RHS="u8"),
107+
all(_Self="f32", RHS="i16"),
108+
all(_Self="f32", RHS="i8"),
109+
all(_Self="f32", RHS="u16"),
110+
all(_Self="f32", RHS="u8"),
111+
),
112+
message="cannot add `{RHS}` to `{Self}`",
113+
label="no implementation for `{Self} + {RHS}`, but you can safely cast \
114+
`{RHS}` into `{Self}` using `as {Self}`",
115+
),
116+
on(
117+
any(
118+
all(RHS="i128", _Self="i64"),
119+
all(RHS="i128", _Self="i32"),
120+
all(RHS="i128", _Self="i16"),
121+
all(RHS="i128", _Self="i8"),
122+
all(RHS="i64", _Self="i32"),
123+
all(RHS="i64", _Self="i16"),
124+
all(RHS="i64", _Self="i8"),
125+
all(RHS="i32", _Self="i16"),
126+
all(RHS="i32", _Self="i8"),
127+
all(RHS="i16", _Self="i8"),
128+
all(RHS="u128", _Self="u64"),
129+
all(RHS="u128", _Self="u32"),
130+
all(RHS="u128", _Self="u16"),
131+
all(RHS="u128", _Self="u8"),
132+
all(RHS="u64", _Self="u32"),
133+
all(RHS="u64", _Self="u16"),
134+
all(RHS="u64", _Self="u8"),
135+
all(RHS="u32", _Self="u16"),
136+
all(RHS="u32", _Self="u8"),
137+
all(RHS="u16", _Self="u8"),
138+
all(RHS="f64", _Self="i32"),
139+
all(RHS="f64", _Self="i16"),
140+
all(RHS="f64", _Self="i8"),
141+
all(RHS="f64", _Self="u32"),
142+
all(RHS="f64", _Self="u16"),
143+
all(RHS="f64", _Self="u8"),
144+
all(RHS="f32", _Self="i16"),
145+
all(RHS="f32", _Self="i8"),
146+
all(RHS="f32", _Self="u16"),
147+
all(RHS="f32", _Self="u8"),
148+
),
149+
message="cannot add `{RHS}` to `{Self}`",
150+
label="no implementation for `{Self} + {RHS}`, but you can safely turn \
151+
`{Self}` into `{RHS}` using `as {RHS}`",
152+
),
153+
on(
154+
all(_Self="{integer}", RHS="{float}"),
155+
message="cannot add a float to an integer",
156+
label="no implementation for `{Self} + {RHS}`",
157+
),
158+
on(
159+
all(_Self="{float}", RHS="{integer}"),
160+
message="cannot add an integer to a float",
161+
label="no implementation for `{Self} + {RHS}`",
162+
),
163+
message="cannot add `{RHS}` to `{Self}`",
164+
label="no implementation for `{Self} + {RHS}`")]
79165
pub trait Add<RHS=Self> {
80166
/// The resulting type after applying the `+` operator.
81167
#[stable(feature = "rust1", since = "1.0.0")]
@@ -170,7 +256,8 @@ add_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
170256
/// ```
171257
#[lang = "sub"]
172258
#[stable(feature = "rust1", since = "1.0.0")]
173-
#[rustc_on_unimplemented = "no implementation for `{Self} - {RHS}`"]
259+
#[rustc_on_unimplemented(message="cannot substract `{RHS}` from `{Self}`",
260+
label="no implementation for `{Self} - {RHS}`")]
174261
pub trait Sub<RHS=Self> {
175262
/// The resulting type after applying the `-` operator.
176263
#[stable(feature = "rust1", since = "1.0.0")]
@@ -287,7 +374,8 @@ sub_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
287374
/// ```
288375
#[lang = "mul"]
289376
#[stable(feature = "rust1", since = "1.0.0")]
290-
#[rustc_on_unimplemented = "no implementation for `{Self} * {RHS}`"]
377+
#[rustc_on_unimplemented(message="cannot multiply `{RHS}` to `{Self}`",
378+
label="no implementation for `{Self} * {RHS}`")]
291379
pub trait Mul<RHS=Self> {
292380
/// The resulting type after applying the `*` operator.
293381
#[stable(feature = "rust1", since = "1.0.0")]
@@ -408,7 +496,8 @@ mul_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
408496
/// ```
409497
#[lang = "div"]
410498
#[stable(feature = "rust1", since = "1.0.0")]
411-
#[rustc_on_unimplemented = "no implementation for `{Self} / {RHS}`"]
499+
#[rustc_on_unimplemented(message="cannot divide `{Self}` by `{RHS}`",
500+
label="no implementation for `{Self} / {RHS}`")]
412501
pub trait Div<RHS=Self> {
413502
/// The resulting type after applying the `/` operator.
414503
#[stable(feature = "rust1", since = "1.0.0")]
@@ -490,7 +579,8 @@ div_impl_float! { f32 f64 }
490579
/// ```
491580
#[lang = "rem"]
492581
#[stable(feature = "rust1", since = "1.0.0")]
493-
#[rustc_on_unimplemented = "no implementation for `{Self} % {RHS}`"]
582+
#[rustc_on_unimplemented(message="cannot mod `{Self}` by `{RHS}`",
583+
label="no implementation for `{Self} % {RHS}`")]
494584
pub trait Rem<RHS=Self> {
495585
/// The resulting type after applying the `%` operator.
496586
#[stable(feature = "rust1", since = "1.0.0")]
@@ -647,7 +737,8 @@ neg_impl_numeric! { isize i8 i16 i32 i64 i128 f32 f64 }
647737
/// ```
648738
#[lang = "add_assign"]
649739
#[stable(feature = "op_assign_traits", since = "1.8.0")]
650-
#[rustc_on_unimplemented = "no implementation for `{Self} += {Rhs}`"]
740+
#[rustc_on_unimplemented(message="cannot add-assign `{Rhs}` to `{Self}`",
741+
label="no implementation for `{Self} += {Rhs}`")]
651742
pub trait AddAssign<Rhs=Self> {
652743
/// Performs the `+=` operation.
653744
#[stable(feature = "op_assign_traits", since = "1.8.0")]
@@ -700,7 +791,8 @@ add_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
700791
/// ```
701792
#[lang = "sub_assign"]
702793
#[stable(feature = "op_assign_traits", since = "1.8.0")]
703-
#[rustc_on_unimplemented = "no implementation for `{Self} -= {Rhs}`"]
794+
#[rustc_on_unimplemented(message="cannot substract-assign `{Rhs}` from `{Self}`",
795+
label="no implementation for `{Self} -= {Rhs}`")]
704796
pub trait SubAssign<Rhs=Self> {
705797
/// Performs the `-=` operation.
706798
#[stable(feature = "op_assign_traits", since = "1.8.0")]
@@ -744,7 +836,8 @@ sub_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
744836
/// ```
745837
#[lang = "mul_assign"]
746838
#[stable(feature = "op_assign_traits", since = "1.8.0")]
747-
#[rustc_on_unimplemented = "no implementation for `{Self} *= {Rhs}`"]
839+
#[rustc_on_unimplemented(message="cannot multiply-assign `{Rhs}` to `{Self}`",
840+
label="no implementation for `{Self} *= {Rhs}`")]
748841
pub trait MulAssign<Rhs=Self> {
749842
/// Performs the `*=` operation.
750843
#[stable(feature = "op_assign_traits", since = "1.8.0")]
@@ -788,7 +881,8 @@ mul_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
788881
/// ```
789882
#[lang = "div_assign"]
790883
#[stable(feature = "op_assign_traits", since = "1.8.0")]
791-
#[rustc_on_unimplemented = "no implementation for `{Self} /= {Rhs}`"]
884+
#[rustc_on_unimplemented(message="cannot divide-assign `{Self}` by `{Rhs}`",
885+
label="no implementation for `{Self} /= {Rhs}`")]
792886
pub trait DivAssign<Rhs=Self> {
793887
/// Performs the `/=` operation.
794888
#[stable(feature = "op_assign_traits", since = "1.8.0")]
@@ -835,7 +929,8 @@ div_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
835929
/// ```
836930
#[lang = "rem_assign"]
837931
#[stable(feature = "op_assign_traits", since = "1.8.0")]
838-
#[rustc_on_unimplemented = "no implementation for `{Self} %= {Rhs}`"]
932+
#[rustc_on_unimplemented(message="cannot mod-assign `{Self}` by `{Rhs}``",
933+
label="no implementation for `{Self} %= {Rhs}`")]
839934
pub trait RemAssign<Rhs=Self> {
840935
/// Performs the `%=` operation.
841936
#[stable(feature = "op_assign_traits", since = "1.8.0")]

src/libcore/ops/bit.rs

Lines changed: 20 additions & 10 deletions
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

Lines changed: 25 additions & 7 deletions
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,35 @@ 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+
// FIXME: remove once `Self` is accepted by the compiler
376+
flags.push(("_Self".to_string(), Some(self_ty_str.clone())));
377+
flags.push(("Self".to_string(), Some(self_ty_str.clone())));
378+
379+
for param in generics.types.iter() {
380+
let name = param.name.as_str().to_string();
381+
let ty = trait_ref.substs.type_for_def(param);
382+
let ty_str = ty.to_string();
383+
flags.push((name.clone(),
384+
Some(ty_str.clone())));
371385
}
372386

373387
if let Ok(Some(command)) = OnUnimplementedDirective::of_item(
374388
self.tcx, trait_ref.def_id, def_id
375389
) {
376-
command.evaluate(self.tcx, trait_ref, &flags)
390+
command.evaluate(self.tcx, trait_ref, &flags[..])
377391
} else {
378392
OnUnimplementedNote::empty()
379393
}
@@ -549,7 +563,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
549563
.map(|t| (format!(" in `{}`", t), format!("within `{}`, ", t)))
550564
.unwrap_or((String::new(), String::new()));
551565

552-
let OnUnimplementedNote { message, label }
566+
let OnUnimplementedNote { message, label, note }
553567
= self.on_unimplemented_note(trait_ref, obligation);
554568
let have_alt_message = message.is_some() || label.is_some();
555569

@@ -578,6 +592,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
578592
trait_ref,
579593
trait_ref.self_ty()));
580594
}
595+
if let Some(ref s) = note {
596+
// If it has a custom "#[rustc_on_unimplemented]" note, let's display it
597+
err.note(s.as_str());
598+
}
581599

582600
self.suggest_borrow_on_unsized_slice(&obligation.cause.code, &mut err);
583601

0 commit comments

Comments
 (0)