Consider unfulfilled obligations in binop errors

When encountering a binop where the types would have been accepted, if
all the predicates had been fulfilled, include information about the
predicates and suggest appropriate `#[derive]`s if possible.

Point at trait(s) that needs to be `impl`emented.
This commit is contained in:
Esteban Kuber 2021-09-28 14:48:54 +00:00
parent 074f63648b
commit e8fc076f23
27 changed files with 667 additions and 108 deletions

View File

@ -2171,10 +2171,26 @@ impl fmt::Debug for TraitRefPrintOnlyTraitPath<'tcx> {
}
}
/// Wrapper type for `ty::TraitRef` which opts-in to pretty printing only
/// the trait name. That is, it will print `Trait` instead of
/// `<T as Trait<U>>`.
#[derive(Copy, Clone, TypeFoldable, Lift)]
pub struct TraitRefPrintOnlyTraitName<'tcx>(ty::TraitRef<'tcx>);
impl fmt::Debug for TraitRefPrintOnlyTraitName<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(self, f)
}
}
impl ty::TraitRef<'tcx> {
pub fn print_only_trait_path(self) -> TraitRefPrintOnlyTraitPath<'tcx> {
TraitRefPrintOnlyTraitPath(self)
}
pub fn print_only_trait_name(self) -> TraitRefPrintOnlyTraitName<'tcx> {
TraitRefPrintOnlyTraitName(self)
}
}
impl ty::Binder<'tcx, ty::TraitRef<'tcx>> {
@ -2193,6 +2209,7 @@ forward_display_to_print! {
ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>,
ty::Binder<'tcx, ty::TraitRef<'tcx>>,
ty::Binder<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
ty::Binder<'tcx, TraitRefPrintOnlyTraitName<'tcx>>,
ty::Binder<'tcx, ty::FnSig<'tcx>>,
ty::Binder<'tcx, ty::TraitPredicate<'tcx>>,
ty::Binder<'tcx, ty::SubtypePredicate<'tcx>>,
@ -2255,6 +2272,10 @@ define_print_and_forward_display! {
p!(print_def_path(self.0.def_id, self.0.substs));
}
TraitRefPrintOnlyTraitName<'tcx> {
p!(print_def_path(self.0.def_id, &[]));
}
ty::ParamTy {
p!(write("{}", self.name))
}

View File

@ -521,7 +521,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
"this error might have been caused by changes to \
Rust's type-inference algorithm (see issue #48950 \
<https://github.com/rust-lang/rust/issues/48950> \
for more information).",
for more information)",
);
err.help("did you intend to use the type `()` here instead?");
}

View File

@ -290,29 +290,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
)
}
/// `lookup_method_in_trait` is used for overloaded operators.
/// It does a very narrow slice of what the normal probe/confirm path does.
/// In particular, it doesn't really do any probing: it simply constructs
/// an obligation for a particular trait with the given self type and checks
/// whether that trait is implemented.
//
// FIXME(#18741): it seems likely that we can consolidate some of this
// code with the other method-lookup code. In particular, the second half
// of this method is basically the same as confirmation.
#[instrument(level = "debug", skip(self, span, opt_input_types))]
pub fn lookup_method_in_trait(
pub(super) fn obligation_for_method(
&self,
span: Span,
m_name: Ident,
trait_def_id: DefId,
self_ty: Ty<'tcx>,
opt_input_types: Option<&[Ty<'tcx>]>,
) -> Option<InferOk<'tcx, MethodCallee<'tcx>>> {
debug!(
"lookup_in_trait_adjusted(self_ty={:?}, m_name={}, trait_def_id={:?}, opt_input_types={:?})",
self_ty, m_name, trait_def_id, opt_input_types
);
) -> (traits::Obligation<'tcx, ty::Predicate<'tcx>>, &'tcx ty::List<ty::subst::GenericArg<'tcx>>)
{
// Construct a trait-reference `self_ty : Trait<input_tys>`
let substs = InternalSubsts::for_item(self.tcx, trait_def_id, |param, _| {
match param.kind {
@ -332,17 +317,48 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Construct an obligation
let poly_trait_ref = ty::Binder::dummy(trait_ref);
let obligation = traits::Obligation::misc(
span,
self.body_id,
self.param_env,
poly_trait_ref.without_const().to_predicate(self.tcx),
(
traits::Obligation::misc(
span,
self.body_id,
self.param_env,
poly_trait_ref.without_const().to_predicate(self.tcx),
),
substs,
)
}
/// `lookup_method_in_trait` is used for overloaded operators.
/// It does a very narrow slice of what the normal probe/confirm path does.
/// In particular, it doesn't really do any probing: it simply constructs
/// an obligation for a particular trait with the given self type and checks
/// whether that trait is implemented.
//
// FIXME(#18741): it seems likely that we can consolidate some of this
// code with the other method-lookup code. In particular, the second half
// of this method is basically the same as confirmation.
#[instrument(level = "debug", skip(self, span, opt_input_types))]
pub(super) fn lookup_method_in_trait(
&self,
span: Span,
m_name: Ident,
trait_def_id: DefId,
self_ty: Ty<'tcx>,
opt_input_types: Option<&[Ty<'tcx>]>,
) -> Option<InferOk<'tcx, MethodCallee<'tcx>>> {
debug!(
"lookup_in_trait_adjusted(self_ty={:?}, m_name={}, trait_def_id={:?}, opt_input_types={:?})",
self_ty, m_name, trait_def_id, opt_input_types
);
let (obligation, substs) =
self.obligation_for_method(span, trait_def_id, self_ty, opt_input_types);
// Now we want to know if this can be matched
if !self.predicate_may_hold(&obligation) {
debug!("--> Cannot match obligation");
return None; // Cannot be matched, no such method resolution is possible.
// Cannot be matched, no such method resolution is possible.
return None;
}
// Trait must have a method named `m_name` and it should not have
@ -416,7 +432,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ty::Binder::dummy(ty::PredicateKind::WellFormed(method_ty.into())).to_predicate(tcx),
));
let callee = MethodCallee { def_id, substs: trait_ref.substs, sig: fn_sig };
let callee = MethodCallee { def_id, substs, sig: fn_sig };
debug!("callee = {:?}", callee);

View File

@ -15,9 +15,9 @@ use rustc_middle::ty::print::with_crate_prefix;
use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
use rustc_span::lev_distance;
use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::{source_map, FileName, Span};
use rustc_span::{source_map, FileName, MultiSpan, Span};
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
use rustc_trait_selection::traits::Obligation;
use rustc_trait_selection::traits::{FulfillmentError, Obligation};
use std::cmp::Ordering;
use std::iter;
@ -969,6 +969,79 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
None
}
crate fn note_unmet_impls_on_type(
&self,
err: &mut rustc_errors::DiagnosticBuilder<'_>,
errors: Vec<FulfillmentError<'tcx>>,
) {
let all_local_types_needing_impls =
errors.iter().all(|e| match e.obligation.predicate.kind().skip_binder() {
ty::PredicateKind::Trait(pred) => match pred.self_ty().kind() {
ty::Adt(def, _) => def.did.is_local(),
_ => false,
},
_ => false,
});
let mut preds: Vec<_> = errors
.iter()
.filter_map(|e| match e.obligation.predicate.kind().skip_binder() {
ty::PredicateKind::Trait(pred) => Some(pred),
_ => None,
})
.collect();
preds.sort_by_key(|pred| (pred.def_id(), pred.self_ty()));
let def_ids = preds
.iter()
.filter_map(|pred| match pred.self_ty().kind() {
ty::Adt(def, _) => Some(def.did),
_ => None,
})
.collect::<FxHashSet<_>>();
let sm = self.tcx.sess.source_map();
let mut spans: MultiSpan = def_ids
.iter()
.filter_map(|def_id| {
let span = self.tcx.def_span(*def_id);
if span.is_dummy() { None } else { Some(sm.guess_head_span(span)) }
})
.collect::<Vec<_>>()
.into();
for pred in &preds {
match pred.self_ty().kind() {
ty::Adt(def, _) => {
spans.push_span_label(
sm.guess_head_span(self.tcx.def_span(def.did)),
format!("must implement `{}`", pred.trait_ref.print_only_trait_path()),
);
}
_ => {}
}
}
if all_local_types_needing_impls && spans.primary_span().is_some() {
let msg = if preds.len() == 1 {
format!(
"an implementation of `{}` might be missing for `{}`",
preds[0].trait_ref.print_only_trait_path(),
preds[0].self_ty()
)
} else {
format!(
"the following type{} would have to `impl` {} required trait{} for this \
operation to be valid",
pluralize!(def_ids.len()),
if def_ids.len() == 1 { "its" } else { "their" },
pluralize!(preds.len()),
)
};
err.span_note(spans, &msg);
}
let preds: Vec<_> = errors.iter().map(|e| (e.obligation.predicate, None)).collect();
self.suggest_derive(err, &preds);
}
fn suggest_derive(
&self,
err: &mut DiagnosticBuilder<'_>,
@ -1010,7 +1083,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return Some((
format!("{}", trait_ref.self_ty()),
self.tcx.def_span(adt_def.did),
format!("{}", trait_ref.print_only_trait_path()),
format!("{}", trait_ref.print_only_trait_name()),
));
}
None
@ -1033,6 +1106,48 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
acc
},
);
let mut traits: Vec<_> = unsatisfied_predicates
.iter()
.filter_map(|(pred, _)| {
let trait_pred =
if let ty::PredicateKind::Trait(trait_pred) = pred.kind().skip_binder() {
trait_pred
} else {
return None;
};
if let ty::Adt(adt_def, _) = trait_pred.trait_ref.self_ty().kind() {
if !adt_def.did.is_local() {
return None;
}
} else {
return None;
};
let did = trait_pred.def_id();
let diagnostic_items = self.tcx.diagnostic_items(did.krate);
if !derivables
.iter()
.any(|trait_derivable| diagnostic_items.get(trait_derivable) == Some(&did))
{
Some(self.tcx.def_span(did))
} else {
None
}
})
.collect();
traits.sort();
traits.dedup();
let len = traits.len();
if len > 0 {
let span: MultiSpan = traits.into();
err.span_note(
span,
&format!("the following trait{} must be implemented", pluralize!(len),),
);
}
for (self_name, self_span, traits) in &derives_grouped {
err.span_suggestion_verbose(
self_span.shrink_to_lo(),

View File

@ -18,6 +18,7 @@ use rustc_span::source_map::Spanned;
use rustc_span::symbol::{sym, Ident};
use rustc_span::Span;
use rustc_trait_selection::infer::InferCtxtExt;
use rustc_trait_selection::traits::{FulfillmentError, TraitEngine, TraitEngineExt};
use std::ops::ControlFlow;
@ -257,12 +258,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
method.sig.output()
}
// error types are considered "builtin"
Err(()) if lhs_ty.references_error() || rhs_ty.references_error() => {
self.tcx.ty_error()
}
Err(()) => {
Err(_) if lhs_ty.references_error() || rhs_ty.references_error() => self.tcx.ty_error(),
Err(errors) => {
let source_map = self.tcx.sess.source_map();
let (mut err, missing_trait, use_output, involves_fn) = match is_assign {
let (mut err, missing_trait, use_output) = match is_assign {
IsAssign::Yes => {
let mut err = struct_span_err!(
self.tcx.sess,
@ -289,7 +288,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
hir::BinOpKind::Shr => Some("std::ops::ShrAssign"),
_ => None,
};
(err, missing_trait, false, false)
self.note_unmet_impls_on_type(&mut err, errors);
(err, missing_trait, false)
}
IsAssign::No => {
let (message, missing_trait, use_output) = match op.node {
@ -376,9 +376,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
};
let mut err =
struct_span_err!(self.tcx.sess, op.span, E0369, "{}", message.as_str());
let mut involves_fn = false;
if !lhs_expr.span.eq(&rhs_expr.span) {
involves_fn |= self.add_type_neq_err_label(
self.add_type_neq_err_label(
&mut err,
lhs_expr.span,
lhs_ty,
@ -386,7 +385,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
op,
is_assign,
);
involves_fn |= self.add_type_neq_err_label(
self.add_type_neq_err_label(
&mut err,
rhs_expr.span,
rhs_ty,
@ -395,10 +394,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
is_assign,
);
}
(err, missing_trait, use_output, involves_fn)
self.note_unmet_impls_on_type(&mut err, errors);
(err, missing_trait, use_output)
}
};
let mut suggested_deref = false;
if let Ref(_, rty, _) = lhs_ty.kind() {
if {
self.infcx.type_is_copy_modulo_regions(self.param_env, rty, lhs_expr.span)
@ -423,7 +422,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
"*".to_string(),
rustc_errors::Applicability::MachineApplicable,
);
suggested_deref = true;
}
}
}
@ -474,8 +472,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} else {
bug!("type param visitor stored a non type param: {:?}", ty.kind());
}
} else if !suggested_deref && !involves_fn {
suggest_impl_missing(&mut err, lhs_ty, missing_trait);
}
}
err.emit();
@ -665,7 +661,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.write_method_call(ex.hir_id, method);
method.sig.output()
}
Err(()) => {
Err(errors) => {
let actual = self.resolve_vars_if_possible(operand_ty);
if !actual.references_error() {
let mut err = struct_span_err!(
@ -720,12 +716,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Str | Never | Char | Tuple(_) | Array(_, _) => {}
Ref(_, lty, _) if *lty.kind() == Str => {}
_ => {
let missing_trait = match op {
hir::UnOp::Neg => "std::ops::Neg",
hir::UnOp::Not => "std::ops::Not",
hir::UnOp::Deref => "std::ops::UnDerf",
};
suggest_impl_missing(&mut err, operand_ty, missing_trait);
self.note_unmet_impls_on_type(&mut err, errors);
}
}
}
@ -741,7 +732,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
lhs_ty: Ty<'tcx>,
other_tys: &[Ty<'tcx>],
op: Op,
) -> Result<MethodCallee<'tcx>, ()> {
) -> Result<MethodCallee<'tcx>, Vec<FulfillmentError<'tcx>>> {
let lang = self.tcx.lang_items();
let span = match op {
@ -820,22 +811,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Op::Unary(..) => 0,
},
) {
return Err(());
return Err(vec![]);
}
let opname = Ident::with_dummy_span(opname);
let method = trait_did.and_then(|trait_did| {
let opname = Ident::with_dummy_span(opname);
self.lookup_method_in_trait(span, opname, trait_did, lhs_ty, Some(other_tys))
});
match method {
Some(ok) => {
match (method, trait_did) {
(Some(ok), _) => {
let method = self.register_infer_ok_obligations(ok);
self.select_obligations_where_possible(false, |_| {});
Ok(method)
}
None => Err(()),
(None, None) => Err(vec![]),
(None, Some(trait_did)) => {
let (obligation, _) =
self.obligation_for_method(span, trait_did, lhs_ty, Some(other_tys));
let mut fulfill = <dyn TraitEngine<'_>>::new(self.tcx);
fulfill.register_predicate_obligation(self, obligation);
Err(match fulfill.select_where_possible(&self.infcx) {
Err(errors) => errors,
_ => vec![],
})
}
}
}
}
@ -962,18 +962,6 @@ fn is_builtin_binop<'tcx>(lhs: Ty<'tcx>, rhs: Ty<'tcx>, op: hir::BinOp) -> bool
}
}
/// If applicable, note that an implementation of `trait` for `ty` may fix the error.
fn suggest_impl_missing(err: &mut DiagnosticBuilder<'_>, ty: Ty<'_>, missing_trait: &str) {
if let Adt(def, _) = ty.peel_refs().kind() {
if def.did.is_local() {
err.note(&format!(
"an implementation of `{}` might be missing for `{}`",
missing_trait, ty
));
}
}
}
fn suggest_constraining_param(
tcx: TyCtxt<'_>,
body_id: hir::HirId,

View File

@ -6,7 +6,22 @@ LL | a += *b;
| |
| cannot use `+=` on type `Foo`
|
= note: an implementation of `std::ops::AddAssign` might be missing for `Foo`
note: an implementation of `AddAssign<_>` might be missing for `Foo`
--> $DIR/assignment-operator-unimplemented.rs:1:1
|
LL | struct Foo;
| ^^^^^^^^^^^ must implement `AddAssign<_>`
note: the following trait must be implemented
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL
|
LL | / pub trait AddAssign<Rhs = Self> {
LL | | /// Performs the `+=` operation.
LL | | ///
LL | | /// # Example
... |
LL | | fn add_assign(&mut self, rhs: Rhs);
LL | | }
| |_^
error: aborting due to previous error

View File

@ -6,7 +6,22 @@ LL | a + a;
| |
| A
|
= note: an implementation of `std::ops::Add` might be missing for `A`
note: an implementation of `Add<_>` might be missing for `A`
--> $DIR/issue-28837.rs:1:1
|
LL | struct A;
| ^^^^^^^^^ must implement `Add<_>`
note: the following trait must be implemented
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL
|
LL | / pub trait Add<Rhs = Self> {
LL | | /// The resulting type after applying the `+` operator.
LL | | #[stable(feature = "rust1", since = "1.0.0")]
LL | | type Output;
... |
LL | | fn add(self, rhs: Rhs) -> Self::Output;
LL | | }
| |_^
error[E0369]: cannot subtract `A` from `A`
--> $DIR/issue-28837.rs:8:7
@ -16,7 +31,22 @@ LL | a - a;
| |
| A
|
= note: an implementation of `std::ops::Sub` might be missing for `A`
note: an implementation of `Sub<_>` might be missing for `A`
--> $DIR/issue-28837.rs:1:1
|
LL | struct A;
| ^^^^^^^^^ must implement `Sub<_>`
note: the following trait must be implemented
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL
|
LL | / pub trait Sub<Rhs = Self> {
LL | | /// The resulting type after applying the `-` operator.
LL | | #[stable(feature = "rust1", since = "1.0.0")]
LL | | type Output;
... |
LL | | fn sub(self, rhs: Rhs) -> Self::Output;
LL | | }
| |_^
error[E0369]: cannot multiply `A` by `A`
--> $DIR/issue-28837.rs:10:7
@ -26,7 +56,22 @@ LL | a * a;
| |
| A
|
= note: an implementation of `std::ops::Mul` might be missing for `A`
note: an implementation of `Mul<_>` might be missing for `A`
--> $DIR/issue-28837.rs:1:1
|
LL | struct A;
| ^^^^^^^^^ must implement `Mul<_>`
note: the following trait must be implemented
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL
|
LL | / pub trait Mul<Rhs = Self> {
LL | | /// The resulting type after applying the `*` operator.
LL | | #[stable(feature = "rust1", since = "1.0.0")]
LL | | type Output;
... |
LL | | fn mul(self, rhs: Rhs) -> Self::Output;
LL | | }
| |_^
error[E0369]: cannot divide `A` by `A`
--> $DIR/issue-28837.rs:12:7
@ -36,7 +81,22 @@ LL | a / a;
| |
| A
|
= note: an implementation of `std::ops::Div` might be missing for `A`
note: an implementation of `Div<_>` might be missing for `A`
--> $DIR/issue-28837.rs:1:1
|
LL | struct A;
| ^^^^^^^^^ must implement `Div<_>`
note: the following trait must be implemented
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL
|
LL | / pub trait Div<Rhs = Self> {
LL | | /// The resulting type after applying the `/` operator.
LL | | #[stable(feature = "rust1", since = "1.0.0")]
LL | | type Output;
... |
LL | | fn div(self, rhs: Rhs) -> Self::Output;
LL | | }
| |_^
error[E0369]: cannot mod `A` by `A`
--> $DIR/issue-28837.rs:14:7
@ -46,7 +106,22 @@ LL | a % a;
| |
| A
|
= note: an implementation of `std::ops::Rem` might be missing for `A`
note: an implementation of `Rem<_>` might be missing for `A`
--> $DIR/issue-28837.rs:1:1
|
LL | struct A;
| ^^^^^^^^^ must implement `Rem<_>`
note: the following trait must be implemented
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL
|
LL | / pub trait Rem<Rhs = Self> {
LL | | /// The resulting type after applying the `%` operator.
LL | | #[stable(feature = "rust1", since = "1.0.0")]
LL | | type Output;
... |
LL | | fn rem(self, rhs: Rhs) -> Self::Output;
LL | | }
| |_^
error[E0369]: no implementation for `A & A`
--> $DIR/issue-28837.rs:16:7
@ -56,7 +131,22 @@ LL | a & a;
| |
| A
|
= note: an implementation of `std::ops::BitAnd` might be missing for `A`
note: an implementation of `BitAnd<_>` might be missing for `A`
--> $DIR/issue-28837.rs:1:1
|
LL | struct A;
| ^^^^^^^^^ must implement `BitAnd<_>`
note: the following trait must be implemented
--> $SRC_DIR/core/src/ops/bit.rs:LL:COL
|
LL | / pub trait BitAnd<Rhs = Self> {
LL | | /// The resulting type after applying the `&` operator.
LL | | #[stable(feature = "rust1", since = "1.0.0")]
LL | | type Output;
... |
LL | | fn bitand(self, rhs: Rhs) -> Self::Output;
LL | | }
| |_^
error[E0369]: no implementation for `A | A`
--> $DIR/issue-28837.rs:18:7
@ -66,7 +156,22 @@ LL | a | a;
| |
| A
|
= note: an implementation of `std::ops::BitOr` might be missing for `A`
note: an implementation of `BitOr<_>` might be missing for `A`
--> $DIR/issue-28837.rs:1:1
|
LL | struct A;
| ^^^^^^^^^ must implement `BitOr<_>`
note: the following trait must be implemented
--> $SRC_DIR/core/src/ops/bit.rs:LL:COL
|
LL | / pub trait BitOr<Rhs = Self> {
LL | | /// The resulting type after applying the `|` operator.
LL | | #[stable(feature = "rust1", since = "1.0.0")]
LL | | type Output;
... |
LL | | fn bitor(self, rhs: Rhs) -> Self::Output;
LL | | }
| |_^
error[E0369]: no implementation for `A << A`
--> $DIR/issue-28837.rs:20:7
@ -76,7 +181,22 @@ LL | a << a;
| |
| A
|
= note: an implementation of `std::ops::Shl` might be missing for `A`
note: an implementation of `Shl<_>` might be missing for `A`
--> $DIR/issue-28837.rs:1:1
|
LL | struct A;
| ^^^^^^^^^ must implement `Shl<_>`
note: the following trait must be implemented
--> $SRC_DIR/core/src/ops/bit.rs:LL:COL
|
LL | / pub trait Shl<Rhs = Self> {
LL | | /// The resulting type after applying the `<<` operator.
LL | | #[stable(feature = "rust1", since = "1.0.0")]
LL | | type Output;
... |
LL | | fn shl(self, rhs: Rhs) -> Self::Output;
LL | | }
| |_^
error[E0369]: no implementation for `A >> A`
--> $DIR/issue-28837.rs:22:7
@ -86,7 +206,22 @@ LL | a >> a;
| |
| A
|
= note: an implementation of `std::ops::Shr` might be missing for `A`
note: an implementation of `Shr<_>` might be missing for `A`
--> $DIR/issue-28837.rs:1:1
|
LL | struct A;
| ^^^^^^^^^ must implement `Shr<_>`
note: the following trait must be implemented
--> $SRC_DIR/core/src/ops/bit.rs:LL:COL
|
LL | / pub trait Shr<Rhs = Self> {
LL | | /// The resulting type after applying the `>>` operator.
LL | | #[stable(feature = "rust1", since = "1.0.0")]
LL | | type Output;
... |
LL | | fn shr(self, rhs: Rhs) -> Self::Output;
LL | | }
| |_^
error[E0369]: binary operation `==` cannot be applied to type `A`
--> $DIR/issue-28837.rs:24:7
@ -96,7 +231,15 @@ LL | a == a;
| |
| A
|
= note: an implementation of `std::cmp::PartialEq` might be missing for `A`
note: an implementation of `PartialEq<_>` might be missing for `A`
--> $DIR/issue-28837.rs:1:1
|
LL | struct A;
| ^^^^^^^^^ must implement `PartialEq<_>`
help: consider annotating `A` with `#[derive(PartialEq)]`
|
LL | #[derive(PartialEq)]
|
error[E0369]: binary operation `!=` cannot be applied to type `A`
--> $DIR/issue-28837.rs:26:7
@ -106,7 +249,15 @@ LL | a != a;
| |
| A
|
= note: an implementation of `std::cmp::PartialEq` might be missing for `A`
note: an implementation of `PartialEq<_>` might be missing for `A`
--> $DIR/issue-28837.rs:1:1
|
LL | struct A;
| ^^^^^^^^^ must implement `PartialEq<_>`
help: consider annotating `A` with `#[derive(PartialEq)]`
|
LL | #[derive(PartialEq)]
|
error[E0369]: binary operation `<` cannot be applied to type `A`
--> $DIR/issue-28837.rs:28:7
@ -116,7 +267,15 @@ LL | a < a;
| |
| A
|
= note: an implementation of `std::cmp::PartialOrd` might be missing for `A`
note: an implementation of `PartialOrd<_>` might be missing for `A`
--> $DIR/issue-28837.rs:1:1
|
LL | struct A;
| ^^^^^^^^^ must implement `PartialOrd<_>`
help: consider annotating `A` with `#[derive(PartialOrd)]`
|
LL | #[derive(PartialOrd)]
|
error[E0369]: binary operation `<=` cannot be applied to type `A`
--> $DIR/issue-28837.rs:30:7
@ -126,7 +285,15 @@ LL | a <= a;
| |
| A
|
= note: an implementation of `std::cmp::PartialOrd` might be missing for `A`
note: an implementation of `PartialOrd<_>` might be missing for `A`
--> $DIR/issue-28837.rs:1:1
|
LL | struct A;
| ^^^^^^^^^ must implement `PartialOrd<_>`
help: consider annotating `A` with `#[derive(PartialOrd)]`
|
LL | #[derive(PartialOrd)]
|
error[E0369]: binary operation `>` cannot be applied to type `A`
--> $DIR/issue-28837.rs:32:7
@ -136,7 +303,15 @@ LL | a > a;
| |
| A
|
= note: an implementation of `std::cmp::PartialOrd` might be missing for `A`
note: an implementation of `PartialOrd<_>` might be missing for `A`
--> $DIR/issue-28837.rs:1:1
|
LL | struct A;
| ^^^^^^^^^ must implement `PartialOrd<_>`
help: consider annotating `A` with `#[derive(PartialOrd)]`
|
LL | #[derive(PartialOrd)]
|
error[E0369]: binary operation `>=` cannot be applied to type `A`
--> $DIR/issue-28837.rs:34:7
@ -146,7 +321,15 @@ LL | a >= a;
| |
| A
|
= note: an implementation of `std::cmp::PartialOrd` might be missing for `A`
note: an implementation of `PartialOrd<_>` might be missing for `A`
--> $DIR/issue-28837.rs:1:1
|
LL | struct A;
| ^^^^^^^^^ must implement `PartialOrd<_>`
help: consider annotating `A` with `#[derive(PartialOrd)]`
|
LL | #[derive(PartialOrd)]
|
error: aborting due to 15 previous errors

View File

@ -7,8 +7,16 @@ LL | #[derive(PartialEq)]
LL | x: Error
| ^^^^^^^^
|
= note: an implementation of `std::cmp::PartialEq` might be missing for `Error`
note: an implementation of `PartialEq<_>` might be missing for `Error`
--> $DIR/derives-span-PartialEq-enum-struct-variant.rs:4:1
|
LL | struct Error;
| ^^^^^^^^^^^^^ must implement `PartialEq<_>`
= note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider annotating `Error` with `#[derive(PartialEq)]`
|
LL | #[derive(PartialEq)]
|
error[E0369]: binary operation `!=` cannot be applied to type `Error`
--> $DIR/derives-span-PartialEq-enum-struct-variant.rs:9:6
@ -19,8 +27,16 @@ LL | #[derive(PartialEq)]
LL | x: Error
| ^^^^^^^^
|
= note: an implementation of `std::cmp::PartialEq` might be missing for `Error`
note: an implementation of `PartialEq<_>` might be missing for `Error`
--> $DIR/derives-span-PartialEq-enum-struct-variant.rs:4:1
|
LL | struct Error;
| ^^^^^^^^^^^^^ must implement `PartialEq<_>`
= note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider annotating `Error` with `#[derive(PartialEq)]`
|
LL | #[derive(PartialEq)]
|
error: aborting due to 2 previous errors

View File

@ -7,8 +7,16 @@ LL | #[derive(PartialEq)]
LL | Error
| ^^^^^
|
= note: an implementation of `std::cmp::PartialEq` might be missing for `Error`
note: an implementation of `PartialEq<_>` might be missing for `Error`
--> $DIR/derives-span-PartialEq-enum.rs:4:1
|
LL | struct Error;
| ^^^^^^^^^^^^^ must implement `PartialEq<_>`
= note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider annotating `Error` with `#[derive(PartialEq)]`
|
LL | #[derive(PartialEq)]
|
error[E0369]: binary operation `!=` cannot be applied to type `Error`
--> $DIR/derives-span-PartialEq-enum.rs:9:6
@ -19,8 +27,16 @@ LL | #[derive(PartialEq)]
LL | Error
| ^^^^^
|
= note: an implementation of `std::cmp::PartialEq` might be missing for `Error`
note: an implementation of `PartialEq<_>` might be missing for `Error`
--> $DIR/derives-span-PartialEq-enum.rs:4:1
|
LL | struct Error;
| ^^^^^^^^^^^^^ must implement `PartialEq<_>`
= note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider annotating `Error` with `#[derive(PartialEq)]`
|
LL | #[derive(PartialEq)]
|
error: aborting due to 2 previous errors

View File

@ -7,8 +7,16 @@ LL | struct Struct {
LL | x: Error
| ^^^^^^^^
|
= note: an implementation of `std::cmp::PartialEq` might be missing for `Error`
note: an implementation of `PartialEq<_>` might be missing for `Error`
--> $DIR/derives-span-PartialEq-struct.rs:4:1
|
LL | struct Error;
| ^^^^^^^^^^^^^ must implement `PartialEq<_>`
= note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider annotating `Error` with `#[derive(PartialEq)]`
|
LL | #[derive(PartialEq)]
|
error[E0369]: binary operation `!=` cannot be applied to type `Error`
--> $DIR/derives-span-PartialEq-struct.rs:8:5
@ -19,8 +27,16 @@ LL | struct Struct {
LL | x: Error
| ^^^^^^^^
|
= note: an implementation of `std::cmp::PartialEq` might be missing for `Error`
note: an implementation of `PartialEq<_>` might be missing for `Error`
--> $DIR/derives-span-PartialEq-struct.rs:4:1
|
LL | struct Error;
| ^^^^^^^^^^^^^ must implement `PartialEq<_>`
= note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider annotating `Error` with `#[derive(PartialEq)]`
|
LL | #[derive(PartialEq)]
|
error: aborting due to 2 previous errors

View File

@ -7,8 +7,16 @@ LL | struct Struct(
LL | Error
| ^^^^^
|
= note: an implementation of `std::cmp::PartialEq` might be missing for `Error`
note: an implementation of `PartialEq<_>` might be missing for `Error`
--> $DIR/derives-span-PartialEq-tuple-struct.rs:4:1
|
LL | struct Error;
| ^^^^^^^^^^^^^ must implement `PartialEq<_>`
= note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider annotating `Error` with `#[derive(PartialEq)]`
|
LL | #[derive(PartialEq)]
|
error[E0369]: binary operation `!=` cannot be applied to type `Error`
--> $DIR/derives-span-PartialEq-tuple-struct.rs:8:5
@ -19,8 +27,16 @@ LL | struct Struct(
LL | Error
| ^^^^^
|
= note: an implementation of `std::cmp::PartialEq` might be missing for `Error`
note: an implementation of `PartialEq<_>` might be missing for `Error`
--> $DIR/derives-span-PartialEq-tuple-struct.rs:4:1
|
LL | struct Error;
| ^^^^^^^^^^^^^ must implement `PartialEq<_>`
= note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider annotating `Error` with `#[derive(PartialEq)]`
|
LL | #[derive(PartialEq)]
|
error: aborting due to 2 previous errors

View File

@ -7,8 +7,16 @@ LL | struct E {
LL | x: NoCloneOrEq
| ^^^^^^^^^^^^^^
|
= note: an implementation of `std::cmp::PartialEq` might be missing for `NoCloneOrEq`
note: an implementation of `PartialEq<_>` might be missing for `NoCloneOrEq`
--> $DIR/deriving-no-inner-impl-error-message.rs:1:1
|
LL | struct NoCloneOrEq;
| ^^^^^^^^^^^^^^^^^^^ must implement `PartialEq<_>`
= note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider annotating `NoCloneOrEq` with `#[derive(PartialEq)]`
|
LL | #[derive(PartialEq)]
|
error[E0369]: binary operation `!=` cannot be applied to type `NoCloneOrEq`
--> $DIR/deriving-no-inner-impl-error-message.rs:5:5
@ -19,8 +27,16 @@ LL | struct E {
LL | x: NoCloneOrEq
| ^^^^^^^^^^^^^^
|
= note: an implementation of `std::cmp::PartialEq` might be missing for `NoCloneOrEq`
note: an implementation of `PartialEq<_>` might be missing for `NoCloneOrEq`
--> $DIR/deriving-no-inner-impl-error-message.rs:1:1
|
LL | struct NoCloneOrEq;
| ^^^^^^^^^^^^^^^^^^^ must implement `PartialEq<_>`
= note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider annotating `NoCloneOrEq` with `#[derive(PartialEq)]`
|
LL | #[derive(PartialEq)]
|
error[E0277]: the trait bound `NoCloneOrEq: Clone` is not satisfied
--> $DIR/deriving-no-inner-impl-error-message.rs:10:5

View File

@ -99,7 +99,22 @@ LL | S { x: a, y: b } += s;
| |
| cannot use `+=` on type `S`
|
= note: an implementation of `std::ops::AddAssign` might be missing for `S`
note: an implementation of `AddAssign<_>` might be missing for `S`
--> $DIR/note-unsupported.rs:1:1
|
LL | struct S { x: u8, y: u8 }
| ^^^^^^^^ must implement `AddAssign<_>`
note: the following trait must be implemented
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL
|
LL | / pub trait AddAssign<Rhs = Self> {
LL | | /// Performs the `+=` operation.
LL | | ///
LL | | /// # Example
... |
LL | | fn add_assign(&mut self, rhs: Rhs);
LL | | }
| |_^
error[E0067]: invalid left-hand side of assignment
--> $DIR/note-unsupported.rs:17:22

View File

@ -36,7 +36,22 @@ error[E0600]: cannot apply unary operator `!` to type `Question`
LL | !Question::Yes;
| ^^^^^^^^^^^^^^ cannot apply unary operator `!`
|
= note: an implementation of `std::ops::Not` might be missing for `Question`
note: an implementation of `Not` might be missing for `Question`
--> $DIR/error-festival.rs:1:1
|
LL | enum Question {
| ^^^^^^^^^^^^^ must implement `Not`
note: the following trait must be implemented
--> $SRC_DIR/core/src/ops/bit.rs:LL:COL
|
LL | / pub trait Not {
LL | | /// The resulting type after applying the `!` operator.
LL | | #[stable(feature = "rust1", since = "1.0.0")]
LL | | type Output;
... |
LL | | fn not(self) -> Self::Output;
LL | | }
| |_^
error[E0604]: only `u8` can be cast as `char`, not `u32`
--> $DIR/error-festival.rs:25:5

View File

@ -4,7 +4,22 @@ error[E0600]: cannot apply unary operator `!` to type `BytePos`
LL | assert!(x, x);
| ^^^^^^^^^^^^^^ cannot apply unary operator `!`
|
= note: an implementation of `std::ops::Not` might be missing for `BytePos`
note: an implementation of `Not` might be missing for `BytePos`
--> $DIR/issue-14091-2.rs:6:1
|
LL | pub struct BytePos(pub u32);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ must implement `Not`
note: the following trait must be implemented
--> $SRC_DIR/core/src/ops/bit.rs:LL:COL
|
LL | / pub trait Not {
LL | | /// The resulting type after applying the `!` operator.
LL | | #[stable(feature = "rust1", since = "1.0.0")]
LL | | type Output;
... |
LL | | fn not(self) -> Self::Output;
LL | | }
| |_^
= note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error

View File

@ -11,7 +11,7 @@ impl Add<i32> for i32 {}
fn main() {
let x = 5 + 6;
//~^ ERROR cannot add `{integer}` to `{integer}`
//~^ ERROR cannot add `i32` to `{integer}`
let y = 5i32 + 6i32;
//~^ ERROR cannot add `i32` to `i32`
}

View File

@ -1,8 +1,8 @@
error[E0369]: cannot add `{integer}` to `{integer}`
error[E0369]: cannot add `i32` to `{integer}`
--> $DIR/issue-31076.rs:13:15
|
LL | let x = 5 + 6;
| - ^ - {integer}
| - ^ - i32
| |
| {integer}

View File

@ -6,7 +6,22 @@ LL | let w = u * 3;
| |
| Thing
|
= note: an implementation of `std::ops::Mul` might be missing for `Thing`
note: an implementation of `Mul<_>` might be missing for `Thing`
--> $DIR/issue-3820.rs:1:1
|
LL | struct Thing {
| ^^^^^^^^^^^^ must implement `Mul<_>`
note: the following trait must be implemented
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL
|
LL | / pub trait Mul<Rhs = Self> {
LL | | /// The resulting type after applying the `*` operator.
LL | | #[stable(feature = "rust1", since = "1.0.0")]
LL | | type Output;
... |
LL | | fn mul(self, rhs: Rhs) -> Self::Output;
LL | | }
| |_^
error: aborting due to previous error

View File

@ -6,7 +6,15 @@ LL | a == A::Value;
| |
| A
|
= note: an implementation of `std::cmp::PartialEq` might be missing for `A`
note: an implementation of `PartialEq<_>` might be missing for `A`
--> $DIR/issue-62375.rs:1:1
|
LL | enum A {
| ^^^^^^ must implement `PartialEq<_>`
help: consider annotating `A` with `#[derive(PartialEq)]`
|
LL | #[derive(PartialEq)]
|
error: aborting due to previous error

View File

@ -55,6 +55,17 @@ LL | .take()
= note: the following trait bounds were not satisfied:
`Foo: Iterator`
which is required by `&mut Foo: Iterator`
note: the following trait must be implemented
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
|
LL | / pub trait Iterator {
LL | | /// The type of the elements being iterated over.
LL | | #[stable(feature = "rust1", since = "1.0.0")]
LL | | type Item;
... |
LL | | }
LL | | }
| |_^
= help: items from traits can only be used if the trait is implemented and in scope
= note: the following trait defines an item `take`, perhaps you need to implement it:
candidate #1: `Iterator`

View File

@ -5,7 +5,7 @@ LL | foo(_x);
| ^^^ the trait `ImplementedForUnitButNotNever` is not implemented for `!`
|
= note: this trait is implemented for `()`
= note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 <https://github.com/rust-lang/rust/issues/48950> for more information).
= note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 <https://github.com/rust-lang/rust/issues/48950> for more information)
= help: did you intend to use the type `()` here instead?
note: required by a bound in `foo`
--> $DIR/defaulted-never-note.rs:25:11

View File

@ -5,7 +5,7 @@ LL | unconstrained_arg(return);
| ^^^^^^^^^^^^^^^^^ the trait `Test` is not implemented for `!`
|
= note: this trait is implemented for `()`
= note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 <https://github.com/rust-lang/rust/issues/48950> for more information).
= note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 <https://github.com/rust-lang/rust/issues/48950> for more information)
= help: did you intend to use the type `()` here instead?
note: required by a bound in `unconstrained_arg`
--> $DIR/diverging-fallback-no-leak.rs:12:25

View File

@ -30,7 +30,22 @@ LL | let _ = |A | B: E| ();
| |
| E
|
= note: an implementation of `std::ops::BitOr` might be missing for `E`
note: an implementation of `BitOr<_>` might be missing for `E`
--> $DIR/or-patterns-syntactic-fail.rs:6:1
|
LL | enum E { A, B }
| ^^^^^^ must implement `BitOr<_>`
note: the following trait must be implemented
--> $SRC_DIR/core/src/ops/bit.rs:LL:COL
|
LL | / pub trait BitOr<Rhs = Self> {
LL | | /// The resulting type after applying the `|` operator.
LL | | #[stable(feature = "rust1", since = "1.0.0")]
LL | | type Output;
... |
LL | | fn bitor(self, rhs: Rhs) -> Self::Output;
LL | | }
| |_^
error: aborting due to 5 previous errors

View File

@ -20,7 +20,22 @@ LL | let y = World::Hello + World::Goodbye;
| |
| World
|
= note: an implementation of `std::ops::Add` might be missing for `World`
note: an implementation of `Add<_>` might be missing for `World`
--> $DIR/issue-39018.rs:15:1
|
LL | enum World {
| ^^^^^^^^^^ must implement `Add<_>`
note: the following trait must be implemented
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL
|
LL | / pub trait Add<Rhs = Self> {
LL | | /// The resulting type after applying the `+` operator.
LL | | #[stable(feature = "rust1", since = "1.0.0")]
LL | | type Output;
... |
LL | | fn add(self, rhs: Rhs) -> Self::Output;
LL | | }
| |_^
error[E0369]: cannot add `String` to `&str`
--> $DIR/issue-39018.rs:11:22

View File

@ -22,6 +22,14 @@ LL | println!("{}", MyStruct.foo_one());
|
= note: the following trait bounds were not satisfied:
`MyStruct: Foo`
note: the following trait must be implemented
--> $DIR/specialization-trait-not-implemented.rs:7:1
|
LL | / trait Foo {
LL | | fn foo_one(&self) -> &'static str;
LL | | fn foo_two(&self) -> &'static str;
LL | | }
| |_^
= help: items from traits can only be used if the trait is implemented and in scope
note: `Foo` defines an item `foo_one`, perhaps you need to implement it
--> $DIR/specialization-trait-not-implemented.rs:7:1

View File

@ -6,7 +6,16 @@ LL | let _ = s == t;
| |
| S<T>
|
note: an implementation of `PartialEq<_>` might be missing for `S<T>`
--> $DIR/invalid-bin-op.rs:5:1
|
LL | struct S<T>(T);
| ^^^^^^^^^^^^^^^ must implement `PartialEq<_>`
= note: the trait `std::cmp::PartialEq` is not implemented for `S<T>`
help: consider annotating `S<T>` with `#[derive(PartialEq)]`
|
LL | #[derive(PartialEq)]
|
error: aborting due to previous error

View File

@ -28,7 +28,22 @@ error[E0600]: cannot apply unary operator `-` to type `Z`
LL | -(S: Z);
| ^^^^^^^ cannot apply unary operator `-`
|
= note: an implementation of `std::ops::Neg` might be missing for `Z`
note: an implementation of `std::ops::Neg` might be missing for `Z`
--> $DIR/type-ascription-precedence.rs:9:1
|
LL | struct Z;
| ^^^^^^^^^ must implement `std::ops::Neg`
note: the following trait must be implemented
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL
|
LL | / pub trait Neg {
LL | | /// The resulting type after applying the `-` operator.
LL | | #[stable(feature = "rust1", since = "1.0.0")]
LL | | type Output;
... |
LL | | fn neg(self) -> Self::Output;
LL | | }
| |_^
error[E0308]: mismatched types
--> $DIR/type-ascription-precedence.rs:45:5