Rollup merge of #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 #44755 with a different syntax, as a first approach. Fixes #46216, fixes #37522, CC #34297, #46806.
This commit is contained in:
Manish Goregaokar 2018-02-07 08:30:47 -08:00 committed by GitHub
commit aee22556a9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 234 additions and 83 deletions

View File

@ -530,9 +530,12 @@ impl<'a> Display for Arguments<'a> {
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_on_unimplemented = "`{Self}` cannot be formatted using `:?`; if it is \
defined in your crate, add `#[derive(Debug)]` or \
manually implement it"]
#[rustc_on_unimplemented(
on(crate_local, label="`{Self}` cannot be formatted using `:?`; \
add `#[derive(Debug)]` or manually implement `{Debug}`"),
message="`{Self}` doesn't implement `{Debug}`",
label="`{Self}` cannot be formatted using `:?` because it doesn't implement `{Debug}`",
)]
#[lang = "debug_trait"]
pub trait Debug {
/// Formats the value using the given formatter.
@ -593,9 +596,11 @@ pub trait Debug {
///
/// println!("The origin is: {}", origin);
/// ```
#[rustc_on_unimplemented = "`{Self}` cannot be formatted with the default \
formatter; try using `:?` instead if you are using \
a format string"]
#[rustc_on_unimplemented(
message="`{Self}` doesn't implement `{Display}`",
label="`{Self}` cannot be formatted with the default formatter; \
try using `:?` instead if you are using a format string",
)]
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Display {
/// Formats the value using the given formatter.

View File

@ -28,8 +28,13 @@ fn _assert_is_object_safe(_: &Iterator<Item=()>) {}
/// [module-level documentation]: index.html
/// [impl]: index.html#implementing-iterator
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_on_unimplemented = "`{Self}` is not an iterator; maybe try calling \
`.iter()` or a similar method"]
#[rustc_on_unimplemented(
on(
_Self="&str",
label="`{Self}` is not an iterator; try calling `.chars()` or `.bytes()`"
),
label="`{Self}` is not an iterator; maybe try calling `.iter()` or a similar method"
)]
#[doc(spotlight)]
pub trait Iterator {
/// The type of the elements being iterated over.

View File

@ -75,7 +75,18 @@
/// ```
#[lang = "add"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_on_unimplemented = "no implementation for `{Self} + {RHS}`"]
#[rustc_on_unimplemented(
on(
all(_Self="{integer}", RHS="{float}"),
message="cannot add a float to an integer",
),
on(
all(_Self="{float}", RHS="{integer}"),
message="cannot add an integer to a float",
),
message="cannot add `{RHS}` to `{Self}`",
label="no implementation for `{Self} + {RHS}`",
)]
pub trait Add<RHS=Self> {
/// The resulting type after applying the `+` operator.
#[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 }
/// ```
#[lang = "sub"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_on_unimplemented = "no implementation for `{Self} - {RHS}`"]
#[rustc_on_unimplemented(message="cannot substract `{RHS}` from `{Self}`",
label="no implementation for `{Self} - {RHS}`")]
pub trait Sub<RHS=Self> {
/// The resulting type after applying the `-` operator.
#[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 }
/// ```
#[lang = "mul"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_on_unimplemented = "no implementation for `{Self} * {RHS}`"]
#[rustc_on_unimplemented(message="cannot multiply `{RHS}` to `{Self}`",
label="no implementation for `{Self} * {RHS}`")]
pub trait Mul<RHS=Self> {
/// The resulting type after applying the `*` operator.
#[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 }
/// ```
#[lang = "div"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_on_unimplemented = "no implementation for `{Self} / {RHS}`"]
#[rustc_on_unimplemented(message="cannot divide `{Self}` by `{RHS}`",
label="no implementation for `{Self} / {RHS}`")]
pub trait Div<RHS=Self> {
/// The resulting type after applying the `/` operator.
#[stable(feature = "rust1", since = "1.0.0")]
@ -490,7 +504,8 @@ div_impl_float! { f32 f64 }
/// ```
#[lang = "rem"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_on_unimplemented = "no implementation for `{Self} % {RHS}`"]
#[rustc_on_unimplemented(message="cannot mod `{Self}` by `{RHS}`",
label="no implementation for `{Self} % {RHS}`")]
pub trait Rem<RHS=Self> {
/// The resulting type after applying the `%` operator.
#[stable(feature = "rust1", since = "1.0.0")]
@ -647,7 +662,8 @@ neg_impl_numeric! { isize i8 i16 i32 i64 i128 f32 f64 }
/// ```
#[lang = "add_assign"]
#[stable(feature = "op_assign_traits", since = "1.8.0")]
#[rustc_on_unimplemented = "no implementation for `{Self} += {Rhs}`"]
#[rustc_on_unimplemented(message="cannot add-assign `{Rhs}` to `{Self}`",
label="no implementation for `{Self} += {Rhs}`")]
pub trait AddAssign<Rhs=Self> {
/// Performs the `+=` operation.
#[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 }
/// ```
#[lang = "sub_assign"]
#[stable(feature = "op_assign_traits", since = "1.8.0")]
#[rustc_on_unimplemented = "no implementation for `{Self} -= {Rhs}`"]
#[rustc_on_unimplemented(message="cannot substract-assign `{Rhs}` from `{Self}`",
label="no implementation for `{Self} -= {Rhs}`")]
pub trait SubAssign<Rhs=Self> {
/// Performs the `-=` operation.
#[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 }
/// ```
#[lang = "mul_assign"]
#[stable(feature = "op_assign_traits", since = "1.8.0")]
#[rustc_on_unimplemented = "no implementation for `{Self} *= {Rhs}`"]
#[rustc_on_unimplemented(message="cannot multiply-assign `{Rhs}` to `{Self}`",
label="no implementation for `{Self} *= {Rhs}`")]
pub trait MulAssign<Rhs=Self> {
/// Performs the `*=` operation.
#[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 }
/// ```
#[lang = "div_assign"]
#[stable(feature = "op_assign_traits", since = "1.8.0")]
#[rustc_on_unimplemented = "no implementation for `{Self} /= {Rhs}`"]
#[rustc_on_unimplemented(message="cannot divide-assign `{Self}` by `{Rhs}`",
label="no implementation for `{Self} /= {Rhs}`")]
pub trait DivAssign<Rhs=Self> {
/// Performs the `/=` operation.
#[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 }
/// ```
#[lang = "rem_assign"]
#[stable(feature = "op_assign_traits", since = "1.8.0")]
#[rustc_on_unimplemented = "no implementation for `{Self} %= {Rhs}`"]
#[rustc_on_unimplemented(message="cannot mod-assign `{Self}` by `{Rhs}``",
label="no implementation for `{Self} %= {Rhs}`")]
pub trait RemAssign<Rhs=Self> {
/// Performs the `%=` operation.
#[stable(feature = "op_assign_traits", since = "1.8.0")]

View File

@ -120,7 +120,8 @@ not_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
/// ```
#[lang = "bitand"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_on_unimplemented = "no implementation for `{Self} & {RHS}`"]
#[rustc_on_unimplemented(message="no implementation for `{Self} & {RHS}`",
label="no implementation for `{Self} & {RHS}`")]
pub trait BitAnd<RHS=Self> {
/// The resulting type after applying the `&` operator.
#[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 }
/// ```
#[lang = "bitor"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_on_unimplemented = "no implementation for `{Self} | {RHS}`"]
#[rustc_on_unimplemented(message="no implementation for `{Self} | {RHS}`",
label="no implementation for `{Self} | {RHS}`")]
pub trait BitOr<RHS=Self> {
/// The resulting type after applying the `|` operator.
#[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 }
/// ```
#[lang = "bitxor"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_on_unimplemented = "no implementation for `{Self} ^ {RHS}`"]
#[rustc_on_unimplemented(message="no implementation for `{Self} ^ {RHS}`",
label="no implementation for `{Self} ^ {RHS}`")]
pub trait BitXor<RHS=Self> {
/// The resulting type after applying the `^` operator.
#[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 }
/// ```
#[lang = "shl"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_on_unimplemented = "no implementation for `{Self} << {RHS}`"]
#[rustc_on_unimplemented(message="no implementation for `{Self} << {RHS}`",
label="no implementation for `{Self} << {RHS}`")]
pub trait Shl<RHS> {
/// The resulting type after applying the `<<` operator.
#[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 }
/// ```
#[lang = "shr"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_on_unimplemented = "no implementation for `{Self} >> {RHS}`"]
#[rustc_on_unimplemented(message="no implementation for `{Self} >> {RHS}`",
label="no implementation for `{Self} >> {RHS}`")]
pub trait Shr<RHS> {
/// The resulting type after applying the `>>` operator.
#[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 }
/// ```
#[lang = "bitand_assign"]
#[stable(feature = "op_assign_traits", since = "1.8.0")]
#[rustc_on_unimplemented = "no implementation for `{Self} &= {Rhs}`"]
#[rustc_on_unimplemented(message="no implementation for `{Self} &= {Rhs}`",
label="no implementation for `{Self} &= {Rhs}`")]
pub trait BitAndAssign<Rhs=Self> {
/// Performs the `&=` operation.
#[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 }
/// ```
#[lang = "bitor_assign"]
#[stable(feature = "op_assign_traits", since = "1.8.0")]
#[rustc_on_unimplemented = "no implementation for `{Self} |= {Rhs}`"]
#[rustc_on_unimplemented(message="no implementation for `{Self} |= {Rhs}`",
label="no implementation for `{Self} |= {Rhs}`")]
pub trait BitOrAssign<Rhs=Self> {
/// Performs the `|=` operation.
#[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 }
/// ```
#[lang = "bitxor_assign"]
#[stable(feature = "op_assign_traits", since = "1.8.0")]
#[rustc_on_unimplemented = "no implementation for `{Self} ^= {Rhs}`"]
#[rustc_on_unimplemented(message="no implementation for `{Self} ^= {Rhs}`",
label="no implementation for `{Self} ^= {Rhs}`")]
pub trait BitXorAssign<Rhs=Self> {
/// Performs the `^=` operation.
#[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 }
/// ```
#[lang = "shl_assign"]
#[stable(feature = "op_assign_traits", since = "1.8.0")]
#[rustc_on_unimplemented = "no implementation for `{Self} <<= {Rhs}`"]
#[rustc_on_unimplemented(message="no implementation for `{Self} <<= {Rhs}`",
label="no implementation for `{Self} <<= {Rhs}`")]
pub trait ShlAssign<Rhs> {
/// Performs the `<<=` operation.
#[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 }
/// ```
#[lang = "shr_assign"]
#[stable(feature = "op_assign_traits", since = "1.8.0")]
#[rustc_on_unimplemented = "no implementation for `{Self} >>= {Rhs}`"]
#[rustc_on_unimplemented(message="no implementation for `{Self} >>= {Rhs}`",
label="no implementation for `{Self} >>= {Rhs}`")]
pub trait ShrAssign<Rhs=Self> {
/// Performs the `>>=` operation.
#[stable(feature = "op_assign_traits", since = "1.8.0")]

View File

@ -348,7 +348,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
if direct {
// this is a "direct", user-specified, rather than derived,
// obligation.
flags.push(("direct", None));
flags.push(("direct".to_string(), None));
}
if let ObligationCauseCode::ItemObligation(item) = obligation.cause.code {
@ -359,21 +359,37 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
// Currently I'm leaving it for what I need for `try`.
if self.tcx.trait_of_item(item) == Some(trait_ref.def_id) {
method = self.tcx.item_name(item);
flags.push(("from_method", None));
flags.push(("from_method", Some(&*method)));
flags.push(("from_method".to_string(), None));
flags.push(("from_method".to_string(), Some(method.to_string())));
}
}
if let Some(k) = obligation.cause.span.compiler_desugaring_kind() {
desugaring = k.as_symbol().as_str();
flags.push(("from_desugaring", None));
flags.push(("from_desugaring", Some(&*desugaring)));
flags.push(("from_desugaring".to_string(), None));
flags.push(("from_desugaring".to_string(), Some(desugaring.to_string())));
}
let generics = self.tcx.generics_of(def_id);
let self_ty = trait_ref.self_ty();
let self_ty_str = self_ty.to_string();
flags.push(("_Self".to_string(), Some(self_ty_str.clone())));
for param in generics.types.iter() {
let name = param.name.as_str().to_string();
let ty = trait_ref.substs.type_for_def(param);
let ty_str = ty.to_string();
flags.push((name.clone(),
Some(ty_str.clone())));
}
if let Some(true) = self_ty.ty_to_def_id().map(|def_id| def_id.is_local()) {
flags.push(("crate_local".to_string(), None));
}
if let Ok(Some(command)) = OnUnimplementedDirective::of_item(
self.tcx, trait_ref.def_id, def_id
) {
command.evaluate(self.tcx, trait_ref, &flags)
command.evaluate(self.tcx, trait_ref, &flags[..])
} else {
OnUnimplementedNote::empty()
}
@ -549,7 +565,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
.map(|t| (format!(" in `{}`", t), format!("within `{}`, ", t)))
.unwrap_or((String::new(), String::new()));
let OnUnimplementedNote { message, label }
let OnUnimplementedNote { message, label, note }
= self.on_unimplemented_note(trait_ref, obligation);
let have_alt_message = message.is_some() || label.is_some();
@ -578,6 +594,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
trait_ref,
trait_ref.self_ty()));
}
if let Some(ref s) = note {
// If it has a custom "#[rustc_on_unimplemented]" note, let's display it
err.note(s.as_str());
}
self.suggest_borrow_on_unsized_slice(&obligation.cause.code, &mut err);

View File

@ -29,16 +29,18 @@ pub struct OnUnimplementedDirective {
pub subcommands: Vec<OnUnimplementedDirective>,
pub message: Option<OnUnimplementedFormatString>,
pub label: Option<OnUnimplementedFormatString>,
pub note: Option<OnUnimplementedFormatString>,
}
pub struct OnUnimplementedNote {
pub message: Option<String>,
pub label: Option<String>,
pub note: Option<String>,
}
impl OnUnimplementedNote {
pub fn empty() -> Self {
OnUnimplementedNote { message: None, label: None }
OnUnimplementedNote { message: None, label: None, note: None }
}
}
@ -89,6 +91,7 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedDirective {
let mut message = None;
let mut label = None;
let mut note = None;
let mut subcommands = vec![];
for item in item_iter {
if item.check_name("message") && message.is_none() {
@ -103,8 +106,14 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedDirective {
tcx, trait_def_id, label_.as_str(), span)?);
continue;
}
} else if item.check_name("note") && note.is_none() {
if let Some(note_) = item.value_str() {
note = Some(OnUnimplementedFormatString::try_parse(
tcx, trait_def_id, note_.as_str(), span)?);
continue;
}
} else if item.check_name("on") && is_root &&
message.is_none() && label.is_none()
message.is_none() && label.is_none() && note.is_none()
{
if let Some(items) = item.meta_item_list() {
if let Ok(subcommand) =
@ -128,7 +137,7 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedDirective {
if errored {
Err(ErrorReported)
} else {
Ok(OnUnimplementedDirective { condition, message, label, subcommands })
Ok(OnUnimplementedDirective { condition, message, label, subcommands, note })
}
}
@ -154,7 +163,8 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedDirective {
message: None,
subcommands: vec![],
label: Some(OnUnimplementedFormatString::try_parse(
tcx, trait_def_id, value.as_str(), attr.span)?)
tcx, trait_def_id, value.as_str(), attr.span)?),
note: None,
}))
} else {
return Err(parse_error(tcx, attr.span,
@ -169,20 +179,20 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedDirective {
pub fn evaluate(&self,
tcx: TyCtxt<'a, 'gcx, 'tcx>,
trait_ref: ty::TraitRef<'tcx>,
options: &[(&str, Option<&str>)])
options: &[(String, Option<String>)])
-> OnUnimplementedNote
{
let mut message = None;
let mut label = None;
info!("evaluate({:?}, trait_ref={:?}, options={:?})",
self, trait_ref, options);
let mut note = None;
info!("evaluate({:?}, trait_ref={:?}, options={:?})", self, trait_ref, options);
for command in self.subcommands.iter().chain(Some(self)).rev() {
if let Some(ref condition) = command.condition {
if !attr::eval_condition(condition, &tcx.sess.parse_sess, &mut |c| {
options.contains(&(&c.name().as_str(),
match c.value_str().map(|s| s.as_str()) {
Some(ref s) => Some(s),
options.contains(&(c.name().as_str().to_string(),
match c.value_str().map(|s| s.as_str().to_string()) {
Some(s) => Some(s),
None => None
}))
}) {
@ -198,11 +208,16 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedDirective {
if let Some(ref label_) = command.label {
label = Some(label_.clone());
}
if let Some(ref note_) = command.note {
note = Some(note_.clone());
}
}
OnUnimplementedNote {
label: label.map(|l| l.format(tcx, trait_ref)),
message: message.map(|m| m.format(tcx, trait_ref))
message: message.map(|m| m.format(tcx, trait_ref)),
note: note.map(|n| n.format(tcx, trait_ref)),
}
}
}

View File

@ -761,6 +761,18 @@ impl<'a> Parser<'a> {
})
}
fn expected_ident_found(&self) -> DiagnosticBuilder<'a> {
let mut err = self.struct_span_err(self.span,
&format!("expected identifier, found {}",
self.this_token_descr()));
if let Some(token_descr) = self.token_descr() {
err.span_label(self.span, format!("expected identifier, found {}", token_descr));
} else {
err.span_label(self.span, "expected identifier");
}
err
}
pub fn parse_ident(&mut self) -> PResult<'a, ast::Ident> {
self.parse_ident_common(true)
}
@ -769,15 +781,7 @@ impl<'a> Parser<'a> {
match self.token {
token::Ident(i) => {
if self.token.is_reserved_ident() {
let mut err = self.struct_span_err(self.span,
&format!("expected identifier, found {}",
self.this_token_descr()));
if let Some(token_descr) = self.token_descr() {
err.span_label(self.span, format!("expected identifier, found {}",
token_descr));
} else {
err.span_label(self.span, "expected identifier");
}
let mut err = self.expected_ident_found();
if recover {
err.emit();
} else {
@ -791,14 +795,7 @@ impl<'a> Parser<'a> {
Err(if self.prev_token_kind == PrevTokenKind::DocComment {
self.span_fatal_err(self.prev_span, Error::UselessDocComment)
} else {
let mut err = self.fatal(&format!("expected identifier, found `{}`",
self.this_token_to_string()));
if let Some(token_descr) = self.token_descr() {
err.span_label(self.span, format!("expected identifier, found {}",
token_descr));
} else {
err.span_label(self.span, "expected identifier");
}
let mut err = self.expected_ident_found();
if self.token == token::Underscore {
err.note("`_` is a wildcard pattern, not an identifier");
}

View File

@ -22,7 +22,7 @@ const A_I8_T
: [u32; (i8::MAX as i8 + 1u8) as usize]
//~^ ERROR mismatched types
//~| expected i8, found u8
//~| ERROR the trait bound `i8: std::ops::Add<u8>` is not satisfied
//~| ERROR cannot add `u8` to `i8`
= [0; (i8::MAX as usize) + 1];

View File

@ -12,7 +12,7 @@ use std::ops::Add;
fn main() {
<i32 as Add<u32>>::add(1, 2);
//~^ ERROR `i32: std::ops::Add<u32>` is not satisfied
//~^ ERROR cannot add `u32` to `i32`
<i32 as Add<i32>>::add(1u32, 2);
//~^ ERROR mismatched types
<i32 as Add<i32>>::add(1, 2u32);

View File

@ -32,7 +32,7 @@ fn sum_to(n: u32) -> impl Foo {
0
} else {
n + sum_to(n - 1)
//~^ ERROR the trait bound `u32: std::ops::Add<impl Foo>` is not satisfied
//~^ ERROR cannot add `impl Foo` to `u32`
}
}

View File

@ -7,7 +7,7 @@ error[E0308]: mismatched types
= note: expected type `i32`
found type `u32`
error[E0277]: the trait bound `u32: std::ops::Add<impl Foo>` is not satisfied
error[E0277]: cannot add `impl Foo` to `u32`
--> $DIR/equality.rs:34:11
|
34 | n + sum_to(n - 1)

View File

@ -9,10 +9,10 @@
// except according to those terms.
fn main() {
1 + Some(1); //~ ERROR is not satisfied
2 as usize - Some(1); //~ ERROR is not satisfied
3 * (); //~ ERROR is not satisfied
4 / ""; //~ ERROR is not satisfied
1 + Some(1); //~ ERROR cannot add `std::option::Option<{integer}>` to `{integer}`
2 as usize - Some(1); //~ ERROR cannot substract `std::option::Option<{integer}>` from `usize`
3 * (); //~ ERROR cannot multiply `()` to `{integer}`
4 / ""; //~ ERROR cannot divide `{integer}` by `&str`
5 < String::new(); //~ ERROR is not satisfied
6 == Ok(1); //~ ERROR is not satisfied
}

View File

@ -1,31 +1,31 @@
error[E0277]: the trait bound `{integer}: std::ops::Add<std::option::Option<{integer}>>` is not satisfied
error[E0277]: cannot add `std::option::Option<{integer}>` to `{integer}`
--> $DIR/binops.rs:12:7
|
12 | 1 + Some(1); //~ ERROR is not satisfied
12 | 1 + Some(1); //~ ERROR cannot add `std::option::Option<{integer}>` to `{integer}`
| ^ no implementation for `{integer} + std::option::Option<{integer}>`
|
= help: the trait `std::ops::Add<std::option::Option<{integer}>>` is not implemented for `{integer}`
error[E0277]: the trait bound `usize: std::ops::Sub<std::option::Option<{integer}>>` is not satisfied
error[E0277]: cannot substract `std::option::Option<{integer}>` from `usize`
--> $DIR/binops.rs:13:16
|
13 | 2 as usize - Some(1); //~ ERROR is not satisfied
13 | 2 as usize - Some(1); //~ ERROR cannot substract `std::option::Option<{integer}>` from `usize`
| ^ no implementation for `usize - std::option::Option<{integer}>`
|
= help: the trait `std::ops::Sub<std::option::Option<{integer}>>` is not implemented for `usize`
error[E0277]: the trait bound `{integer}: std::ops::Mul<()>` is not satisfied
error[E0277]: cannot multiply `()` to `{integer}`
--> $DIR/binops.rs:14:7
|
14 | 3 * (); //~ ERROR is not satisfied
14 | 3 * (); //~ ERROR cannot multiply `()` to `{integer}`
| ^ no implementation for `{integer} * ()`
|
= help: the trait `std::ops::Mul<()>` is not implemented for `{integer}`
error[E0277]: the trait bound `{integer}: std::ops::Div<&str>` is not satisfied
error[E0277]: cannot divide `{integer}` by `&str`
--> $DIR/binops.rs:15:7
|
15 | 4 / ""; //~ ERROR is not satisfied
15 | 4 / ""; //~ ERROR cannot divide `{integer}` by `&str`
| ^ no implementation for `{integer} / &str`
|
= help: the trait `std::ops::Div<&str>` is not implemented for `{integer}`

View File

@ -0,0 +1,14 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// ignore-tidy-linelength
#![crate_type = "lib"]
pub struct Bar;

View File

@ -0,0 +1,27 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// aux-build:no_debug.rs
extern crate no_debug;
use no_debug::Bar;
struct Foo;
fn main() {
println!("{:?} {:?}", Foo, Bar);
println!("{} {}", Foo, Bar);
}
//~^^^ ERROR `Foo` doesn't implement `std::fmt::Debug`
//~| ERROR `no_debug::Bar` doesn't implement `std::fmt::Debug`
//~^^^^ ERROR `Foo` doesn't implement `std::fmt::Display`
//~| ERROR `no_debug::Bar` doesn't implement `std::fmt::Display`

View File

@ -0,0 +1,38 @@
error[E0277]: `Foo` doesn't implement `std::fmt::Debug`
--> $DIR/no-debug.rs:20:27
|
20 | println!("{:?} {:?}", Foo, Bar);
| ^^^ `Foo` cannot be formatted using `:?`; add `#[derive(Debug)]` or manually implement `std::fmt::Debug`
|
= help: the trait `std::fmt::Debug` is not implemented for `Foo`
= note: required by `std::fmt::Debug::fmt`
error[E0277]: `no_debug::Bar` doesn't implement `std::fmt::Debug`
--> $DIR/no-debug.rs:20:32
|
20 | println!("{:?} {:?}", Foo, Bar);
| ^^^ `no_debug::Bar` cannot be formatted using `:?` because it doesn't implement `std::fmt::Debug`
|
= help: the trait `std::fmt::Debug` is not implemented for `no_debug::Bar`
= note: required by `std::fmt::Debug::fmt`
error[E0277]: `Foo` doesn't implement `std::fmt::Display`
--> $DIR/no-debug.rs:21:23
|
21 | println!("{} {}", Foo, Bar);
| ^^^ `Foo` cannot be formatted with the default formatter; try using `:?` instead if you are using a format string
|
= help: the trait `std::fmt::Display` is not implemented for `Foo`
= note: required by `std::fmt::Display::fmt`
error[E0277]: `no_debug::Bar` doesn't implement `std::fmt::Display`
--> $DIR/no-debug.rs:21:28
|
21 | println!("{} {}", Foo, Bar);
| ^^^ `no_debug::Bar` cannot be formatted with the default formatter; try using `:?` instead if you are using a format string
|
= help: the trait `std::fmt::Display` is not implemented for `no_debug::Bar`
= note: required by `std::fmt::Display::fmt`
error: aborting due to 4 previous errors

View File

@ -20,7 +20,7 @@ fn main() {
let x = 1;
let y = 2;
let z = 3;
foo(1 as u32 + //~ ERROR not satisfied
foo(1 as u32 + //~ ERROR cannot add `()` to `u32`
bar(x,

View File

@ -1,7 +1,7 @@
error[E0277]: the trait bound `u32: std::ops::Add<()>` is not satisfied
error[E0277]: cannot add `()` to `u32`
--> $DIR/multiline-span-simple.rs:23:18
|
23 | foo(1 as u32 + //~ ERROR not satisfied
23 | foo(1 as u32 + //~ ERROR cannot add `()` to `u32`
| ^ no implementation for `u32 + ()`
|
= help: the trait `std::ops::Add<()>` is not implemented for `u32`

View File

@ -2,7 +2,7 @@ error[E0277]: the trait bound `&str: std::iter::Iterator` is not satisfied
--> $DIR/for-c-in-str.rs:14:14
|
14 | for c in "asdf" {
| ^^^^^^ `&str` is not an iterator; maybe try calling `.iter()` or a similar method
| ^^^^^^ `&str` is not an iterator; try calling `.chars()` or `.bytes()`
|
= help: the trait `std::iter::Iterator` is not implemented for `&str`
= note: required by `std::iter::IntoIterator::into_iter`