mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-05 03:23:25 +00:00
Rollup merge of #84014 - estebank:cool-bears-hot-tip, r=varkor
Improve trait/impl method discrepancy errors * Use more accurate spans * Clean up some code by removing previous hack * Provide structured suggestions Structured suggestions are particularly useful for cases where arbitrary self types are used, like in custom `Future`s, because the way to write `self: Pin<&mut Self>` is not necessarily self-evident when first encountered.
This commit is contained in:
commit
c905e9d0ca
@ -36,6 +36,7 @@ pub enum TypeError<'tcx> {
|
||||
UnsafetyMismatch(ExpectedFound<hir::Unsafety>),
|
||||
AbiMismatch(ExpectedFound<abi::Abi>),
|
||||
Mutability,
|
||||
ArgumentMutability(usize),
|
||||
TupleSize(ExpectedFound<usize>),
|
||||
FixedArraySize(ExpectedFound<u64>),
|
||||
ArgCount,
|
||||
@ -46,6 +47,7 @@ pub enum TypeError<'tcx> {
|
||||
RegionsPlaceholderMismatch,
|
||||
|
||||
Sorts(ExpectedFound<Ty<'tcx>>),
|
||||
ArgumentSorts(ExpectedFound<Ty<'tcx>>, usize),
|
||||
IntMismatch(ExpectedFound<ty::IntVarValue>),
|
||||
FloatMismatch(ExpectedFound<ty::FloatTy>),
|
||||
Traits(ExpectedFound<DefId>),
|
||||
@ -110,7 +112,7 @@ impl<'tcx> fmt::Display for TypeError<'tcx> {
|
||||
AbiMismatch(values) => {
|
||||
write!(f, "expected {} fn, found {} fn", values.expected, values.found)
|
||||
}
|
||||
Mutability => write!(f, "types differ in mutability"),
|
||||
ArgumentMutability(_) | Mutability => write!(f, "types differ in mutability"),
|
||||
TupleSize(values) => write!(
|
||||
f,
|
||||
"expected a tuple with {} element{}, \
|
||||
@ -142,7 +144,7 @@ impl<'tcx> fmt::Display for TypeError<'tcx> {
|
||||
br_string(br)
|
||||
),
|
||||
RegionsPlaceholderMismatch => write!(f, "one type is more general than the other"),
|
||||
Sorts(values) => ty::tls::with(|tcx| {
|
||||
ArgumentSorts(values, _) | Sorts(values) => ty::tls::with(|tcx| {
|
||||
report_maybe_different(
|
||||
f,
|
||||
&values.expected.sort_string(tcx),
|
||||
@ -199,10 +201,11 @@ impl<'tcx> TypeError<'tcx> {
|
||||
use self::TypeError::*;
|
||||
match self {
|
||||
CyclicTy(_) | CyclicConst(_) | UnsafetyMismatch(_) | Mismatch | AbiMismatch(_)
|
||||
| FixedArraySize(_) | Sorts(_) | IntMismatch(_) | FloatMismatch(_)
|
||||
| VariadicMismatch(_) | TargetFeatureCast(_) => false,
|
||||
| FixedArraySize(_) | ArgumentSorts(..) | Sorts(_) | IntMismatch(_)
|
||||
| FloatMismatch(_) | VariadicMismatch(_) | TargetFeatureCast(_) => false,
|
||||
|
||||
Mutability
|
||||
| ArgumentMutability(_)
|
||||
| TupleSize(_)
|
||||
| ArgCount
|
||||
| RegionsDoesNotOutlive(..)
|
||||
@ -339,7 +342,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
use self::TypeError::*;
|
||||
debug!("note_and_explain_type_err err={:?} cause={:?}", err, cause);
|
||||
match err {
|
||||
Sorts(values) => {
|
||||
ArgumentSorts(values, _) | Sorts(values) => {
|
||||
match (values.expected.kind(), values.found.kind()) {
|
||||
(ty::Closure(..), ty::Closure(..)) => {
|
||||
db.note("no two closures, even if identical, have the same type");
|
||||
|
@ -179,6 +179,12 @@ impl<'tcx> Relate<'tcx> for ty::FnSig<'tcx> {
|
||||
} else {
|
||||
relation.relate_with_variance(ty::Contravariant, a, b)
|
||||
}
|
||||
})
|
||||
.enumerate()
|
||||
.map(|(i, r)| match r {
|
||||
Err(TypeError::Sorts(exp_found)) => Err(TypeError::ArgumentSorts(exp_found, i)),
|
||||
Err(TypeError::Mutability) => Err(TypeError::ArgumentMutability(i)),
|
||||
r => r,
|
||||
});
|
||||
Ok(ty::FnSig {
|
||||
inputs_and_output: tcx.mk_type_list(inputs_and_output)?,
|
||||
|
@ -587,6 +587,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::error::TypeError<'a> {
|
||||
UnsafetyMismatch(x) => UnsafetyMismatch(x),
|
||||
AbiMismatch(x) => AbiMismatch(x),
|
||||
Mutability => Mutability,
|
||||
ArgumentMutability(i) => ArgumentMutability(i),
|
||||
TupleSize(x) => TupleSize(x),
|
||||
FixedArraySize(x) => FixedArraySize(x),
|
||||
ArgCount => ArgCount,
|
||||
@ -607,6 +608,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::error::TypeError<'a> {
|
||||
CyclicTy(t) => return tcx.lift(t).map(|t| CyclicTy(t)),
|
||||
CyclicConst(ct) => return tcx.lift(ct).map(|ct| CyclicConst(ct)),
|
||||
ProjectionMismatched(x) => ProjectionMismatched(x),
|
||||
ArgumentSorts(x, i) => return tcx.lift(x).map(|x| ArgumentSorts(x, i)),
|
||||
Sorts(x) => return tcx.lift(x).map(Sorts),
|
||||
ExistentialMismatch(x) => return tcx.lift(x).map(ExistentialMismatch),
|
||||
ConstMismatch(x) => return tcx.lift(x).map(ConstMismatch),
|
||||
|
@ -278,9 +278,8 @@ fn compare_predicate_entailment<'tcx>(
|
||||
if let Err(terr) = sub_result {
|
||||
debug!("sub_types failed: impl ty {:?}, trait ty {:?}", impl_fty, trait_fty);
|
||||
|
||||
let (impl_err_span, trait_err_span) = extract_spans_for_error_reporting(
|
||||
&infcx, param_env, &terr, &cause, impl_m, impl_sig, trait_m, trait_sig,
|
||||
);
|
||||
let (impl_err_span, trait_err_span) =
|
||||
extract_spans_for_error_reporting(&infcx, &terr, &cause, impl_m, trait_m);
|
||||
|
||||
cause.make_mut().span = impl_err_span;
|
||||
|
||||
@ -291,18 +290,79 @@ fn compare_predicate_entailment<'tcx>(
|
||||
"method `{}` has an incompatible type for trait",
|
||||
trait_m.ident
|
||||
);
|
||||
if let TypeError::Mutability = terr {
|
||||
if let Some(trait_err_span) = trait_err_span {
|
||||
if let Ok(trait_err_str) = tcx.sess.source_map().span_to_snippet(trait_err_span)
|
||||
match &terr {
|
||||
TypeError::ArgumentMutability(0) | TypeError::ArgumentSorts(_, 0)
|
||||
if trait_m.fn_has_self_parameter =>
|
||||
{
|
||||
let ty = trait_sig.inputs()[0];
|
||||
let sugg = match ExplicitSelf::determine(ty, |_| ty == impl_trait_ref.self_ty())
|
||||
{
|
||||
ExplicitSelf::ByValue => "self".to_owned(),
|
||||
ExplicitSelf::ByReference(_, hir::Mutability::Not) => "&self".to_owned(),
|
||||
ExplicitSelf::ByReference(_, hir::Mutability::Mut) => {
|
||||
"&mut self".to_owned()
|
||||
}
|
||||
_ => format!("self: {}", ty),
|
||||
};
|
||||
|
||||
// When the `impl` receiver is an arbitrary self type, like `self: Box<Self>`, the
|
||||
// span points only at the type `Box<Self`>, but we want to cover the whole
|
||||
// argument pattern and type.
|
||||
let impl_m_hir_id =
|
||||
tcx.hir().local_def_id_to_hir_id(impl_m.def_id.expect_local());
|
||||
let span = match tcx.hir().expect_impl_item(impl_m_hir_id).kind {
|
||||
ImplItemKind::Fn(ref sig, body) => tcx
|
||||
.hir()
|
||||
.body_param_names(body)
|
||||
.zip(sig.decl.inputs.iter())
|
||||
.map(|(param, ty)| param.span.to(ty.span))
|
||||
.next()
|
||||
.unwrap_or(impl_err_span),
|
||||
_ => bug!("{:?} is not a method", impl_m),
|
||||
};
|
||||
|
||||
diag.span_suggestion(
|
||||
span,
|
||||
"change the self-receiver type to match the trait",
|
||||
sugg,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
TypeError::ArgumentMutability(i) | TypeError::ArgumentSorts(_, i) => {
|
||||
if trait_sig.inputs().len() == *i {
|
||||
// Suggestion to change output type. We do not suggest in `async` functions
|
||||
// to avoid complex logic or incorrect output.
|
||||
let impl_m_hir_id =
|
||||
tcx.hir().local_def_id_to_hir_id(impl_m.def_id.expect_local());
|
||||
match tcx.hir().expect_impl_item(impl_m_hir_id).kind {
|
||||
ImplItemKind::Fn(ref sig, _)
|
||||
if sig.header.asyncness == hir::IsAsync::NotAsync =>
|
||||
{
|
||||
let msg = "change the output type to match the trait";
|
||||
let ap = Applicability::MachineApplicable;
|
||||
match sig.decl.output {
|
||||
hir::FnRetTy::DefaultReturn(sp) => {
|
||||
let sugg = format!("-> {} ", trait_sig.output());
|
||||
diag.span_suggestion_verbose(sp, msg, sugg, ap);
|
||||
}
|
||||
hir::FnRetTy::Return(hir_ty) => {
|
||||
let sugg = trait_sig.output().to_string();
|
||||
diag.span_suggestion(hir_ty.span, msg, sugg, ap);
|
||||
}
|
||||
};
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
} else if let Some(trait_ty) = trait_sig.inputs().get(*i) {
|
||||
diag.span_suggestion(
|
||||
impl_err_span,
|
||||
"consider changing the mutability to match the trait",
|
||||
trait_err_str,
|
||||
"change the parameter type to match the trait",
|
||||
trait_ty.to_string(),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
infcx.note_type_err(
|
||||
@ -385,86 +445,35 @@ fn check_region_bounds_on_impl_item<'tcx>(
|
||||
|
||||
fn extract_spans_for_error_reporting<'a, 'tcx>(
|
||||
infcx: &infer::InferCtxt<'a, 'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
terr: &TypeError<'_>,
|
||||
cause: &ObligationCause<'tcx>,
|
||||
impl_m: &ty::AssocItem,
|
||||
impl_sig: ty::FnSig<'tcx>,
|
||||
trait_m: &ty::AssocItem,
|
||||
trait_sig: ty::FnSig<'tcx>,
|
||||
) -> (Span, Option<Span>) {
|
||||
let tcx = infcx.tcx;
|
||||
let impl_m_hir_id = tcx.hir().local_def_id_to_hir_id(impl_m.def_id.expect_local());
|
||||
let (impl_m_output, impl_m_iter) = match tcx.hir().expect_impl_item(impl_m_hir_id).kind {
|
||||
ImplItemKind::Fn(ref impl_m_sig, _) => {
|
||||
(&impl_m_sig.decl.output, impl_m_sig.decl.inputs.iter())
|
||||
let mut impl_args = match tcx.hir().expect_impl_item(impl_m_hir_id).kind {
|
||||
ImplItemKind::Fn(ref sig, _) => {
|
||||
sig.decl.inputs.iter().map(|t| t.span).chain(iter::once(sig.decl.output.span()))
|
||||
}
|
||||
_ => bug!("{:?} is not a method", impl_m),
|
||||
};
|
||||
let trait_args = trait_m.def_id.as_local().map(|def_id| {
|
||||
let trait_m_hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
|
||||
match tcx.hir().expect_trait_item(trait_m_hir_id).kind {
|
||||
TraitItemKind::Fn(ref sig, _) => {
|
||||
sig.decl.inputs.iter().map(|t| t.span).chain(iter::once(sig.decl.output.span()))
|
||||
}
|
||||
_ => bug!("{:?} is not a TraitItemKind::Fn", trait_m),
|
||||
}
|
||||
});
|
||||
|
||||
match *terr {
|
||||
TypeError::Mutability => {
|
||||
if let Some(def_id) = trait_m.def_id.as_local() {
|
||||
let trait_m_hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
|
||||
let trait_m_iter = match tcx.hir().expect_trait_item(trait_m_hir_id).kind {
|
||||
TraitItemKind::Fn(ref trait_m_sig, _) => trait_m_sig.decl.inputs.iter(),
|
||||
_ => bug!("{:?} is not a TraitItemKind::Fn", trait_m),
|
||||
};
|
||||
|
||||
iter::zip(impl_m_iter, trait_m_iter)
|
||||
.find(|&(ref impl_arg, ref trait_arg)| {
|
||||
match (&impl_arg.kind, &trait_arg.kind) {
|
||||
(
|
||||
&hir::TyKind::Rptr(_, ref impl_mt),
|
||||
&hir::TyKind::Rptr(_, ref trait_mt),
|
||||
)
|
||||
| (&hir::TyKind::Ptr(ref impl_mt), &hir::TyKind::Ptr(ref trait_mt)) => {
|
||||
impl_mt.mutbl != trait_mt.mutbl
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
})
|
||||
.map(|(ref impl_arg, ref trait_arg)| (impl_arg.span, Some(trait_arg.span)))
|
||||
.unwrap_or_else(|| (cause.span(tcx), tcx.hir().span_if_local(trait_m.def_id)))
|
||||
} else {
|
||||
(cause.span(tcx), tcx.hir().span_if_local(trait_m.def_id))
|
||||
}
|
||||
TypeError::ArgumentMutability(i) => {
|
||||
(impl_args.nth(i).unwrap(), trait_args.and_then(|mut args| args.nth(i)))
|
||||
}
|
||||
TypeError::Sorts(ExpectedFound { .. }) => {
|
||||
if let Some(def_id) = trait_m.def_id.as_local() {
|
||||
let trait_m_hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
|
||||
let (trait_m_output, trait_m_iter) =
|
||||
match tcx.hir().expect_trait_item(trait_m_hir_id).kind {
|
||||
TraitItemKind::Fn(ref trait_m_sig, _) => {
|
||||
(&trait_m_sig.decl.output, trait_m_sig.decl.inputs.iter())
|
||||
}
|
||||
_ => bug!("{:?} is not a TraitItemKind::Fn", trait_m),
|
||||
};
|
||||
|
||||
let impl_iter = impl_sig.inputs().iter();
|
||||
let trait_iter = trait_sig.inputs().iter();
|
||||
iter::zip(iter::zip(impl_iter, trait_iter), iter::zip(impl_m_iter, trait_m_iter))
|
||||
.find_map(|((&impl_arg_ty, &trait_arg_ty), (impl_arg, trait_arg))| match infcx
|
||||
.at(&cause, param_env)
|
||||
.sub(trait_arg_ty, impl_arg_ty)
|
||||
{
|
||||
Ok(_) => None,
|
||||
Err(_) => Some((impl_arg.span, Some(trait_arg.span))),
|
||||
})
|
||||
.unwrap_or_else(|| {
|
||||
if infcx
|
||||
.at(&cause, param_env)
|
||||
.sup(trait_sig.output(), impl_sig.output())
|
||||
.is_err()
|
||||
{
|
||||
(impl_m_output.span(), Some(trait_m_output.span()))
|
||||
} else {
|
||||
(cause.span(tcx), tcx.hir().span_if_local(trait_m.def_id))
|
||||
}
|
||||
})
|
||||
} else {
|
||||
(cause.span(tcx), tcx.hir().span_if_local(trait_m.def_id))
|
||||
}
|
||||
TypeError::ArgumentSorts(ExpectedFound { .. }, i) => {
|
||||
(impl_args.nth(i).unwrap(), trait_args.and_then(|mut args| args.nth(i)))
|
||||
}
|
||||
_ => (cause.span(tcx), tcx.hir().span_if_local(trait_m.def_id)),
|
||||
}
|
||||
@ -514,8 +523,7 @@ fn compare_self_type<'tcx>(
|
||||
tcx.sess,
|
||||
impl_m_span,
|
||||
E0185,
|
||||
"method `{}` has a `{}` declaration in the impl, but \
|
||||
not in the trait",
|
||||
"method `{}` has a `{}` declaration in the impl, but not in the trait",
|
||||
trait_m.ident,
|
||||
self_descr
|
||||
);
|
||||
@ -535,8 +543,7 @@ fn compare_self_type<'tcx>(
|
||||
tcx.sess,
|
||||
impl_m_span,
|
||||
E0186,
|
||||
"method `{}` has a `{}` declaration in the trait, but \
|
||||
not in the impl",
|
||||
"method `{}` has a `{}` declaration in the trait, but not in the impl",
|
||||
trait_m.ident,
|
||||
self_descr
|
||||
);
|
||||
@ -993,8 +1000,7 @@ crate fn compare_const_impl<'tcx>(
|
||||
tcx.sess,
|
||||
cause.span,
|
||||
E0326,
|
||||
"implemented const `{}` has an incompatible type for \
|
||||
trait",
|
||||
"implemented const `{}` has an incompatible type for trait",
|
||||
trait_c.ident
|
||||
);
|
||||
|
||||
|
@ -15,7 +15,10 @@ LL | fn make() -> Self::Ty {
|
||||
| -------- type in trait
|
||||
...
|
||||
LL | fn make() -> u8 { 0 }
|
||||
| ^^ expected associated type, found `u8`
|
||||
| ^^
|
||||
| |
|
||||
| expected associated type, found `u8`
|
||||
| help: change the output type to match the trait: `<A<T> as Tr>::Ty`
|
||||
|
|
||||
= note: expected fn pointer `fn() -> <A<T> as Tr>::Ty`
|
||||
found fn pointer `fn() -> u8`
|
||||
@ -30,7 +33,10 @@ LL | default type Ty = bool;
|
||||
| ----------------------- expected this associated type
|
||||
LL |
|
||||
LL | fn make() -> bool { true }
|
||||
| ^^^^ expected associated type, found `bool`
|
||||
| ^^^^
|
||||
| |
|
||||
| expected associated type, found `bool`
|
||||
| help: change the output type to match the trait: `<B<T> as Tr>::Ty`
|
||||
|
|
||||
= note: expected fn pointer `fn() -> <B<T> as Tr>::Ty`
|
||||
found fn pointer `fn() -> bool`
|
||||
|
26
src/test/ui/compare-method/bad-self-type.rs
Normal file
26
src/test/ui/compare-method/bad-self-type.rs
Normal file
@ -0,0 +1,26 @@
|
||||
use std::future::Future;
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
fn main() {}
|
||||
|
||||
struct MyFuture {}
|
||||
|
||||
impl Future for MyFuture {
|
||||
type Output = ();
|
||||
fn poll(self, _: &mut Context<'_>) -> Poll<()> {
|
||||
//~^ ERROR method `poll` has an incompatible type for trait
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
trait T {
|
||||
fn foo(self);
|
||||
fn bar(self) -> Option<()>;
|
||||
}
|
||||
|
||||
impl T for MyFuture {
|
||||
fn foo(self: Box<Self>) {}
|
||||
//~^ ERROR method `foo` has an incompatible type for trait
|
||||
fn bar(self) {}
|
||||
//~^ ERROR method `bar` has an incompatible type for trait
|
||||
}
|
46
src/test/ui/compare-method/bad-self-type.stderr
Normal file
46
src/test/ui/compare-method/bad-self-type.stderr
Normal file
@ -0,0 +1,46 @@
|
||||
error[E0053]: method `poll` has an incompatible type for trait
|
||||
--> $DIR/bad-self-type.rs:10:13
|
||||
|
|
||||
LL | fn poll(self, _: &mut Context<'_>) -> Poll<()> {
|
||||
| ^^^^
|
||||
| |
|
||||
| expected struct `Pin`, found struct `MyFuture`
|
||||
| help: change the self-receiver type to match the trait: `self: Pin<&mut MyFuture>`
|
||||
|
|
||||
= note: expected fn pointer `fn(Pin<&mut MyFuture>, &mut Context<'_>) -> Poll<_>`
|
||||
found fn pointer `fn(MyFuture, &mut Context<'_>) -> Poll<_>`
|
||||
|
||||
error[E0053]: method `foo` has an incompatible type for trait
|
||||
--> $DIR/bad-self-type.rs:22:18
|
||||
|
|
||||
LL | fn foo(self);
|
||||
| ---- type in trait
|
||||
...
|
||||
LL | fn foo(self: Box<Self>) {}
|
||||
| ------^^^^^^^^^
|
||||
| | |
|
||||
| | expected struct `MyFuture`, found struct `Box`
|
||||
| help: change the self-receiver type to match the trait: `self`
|
||||
|
|
||||
= note: expected fn pointer `fn(MyFuture)`
|
||||
found fn pointer `fn(Box<MyFuture>)`
|
||||
|
||||
error[E0053]: method `bar` has an incompatible type for trait
|
||||
--> $DIR/bad-self-type.rs:24:18
|
||||
|
|
||||
LL | fn bar(self) -> Option<()>;
|
||||
| ---------- type in trait
|
||||
...
|
||||
LL | fn bar(self) {}
|
||||
| ^ expected enum `Option`, found `()`
|
||||
|
|
||||
= note: expected fn pointer `fn(MyFuture) -> Option<()>`
|
||||
found fn pointer `fn(MyFuture)`
|
||||
help: change the output type to match the trait
|
||||
|
|
||||
LL | fn bar(self) -> Option<()> {}
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0053`.
|
@ -5,8 +5,10 @@ LL | fn b<C:Clone,D>(&self, x: C) -> C;
|
||||
| - type in trait
|
||||
...
|
||||
LL | fn b<F:Clone,G>(&self, _x: G) -> G { panic!() }
|
||||
| - - ^ expected type parameter `F`, found type parameter `G`
|
||||
| | |
|
||||
| - - ^
|
||||
| | | |
|
||||
| | | expected type parameter `F`, found type parameter `G`
|
||||
| | | help: change the parameter type to match the trait: `F`
|
||||
| | found type parameter
|
||||
| expected type parameter
|
||||
|
|
||||
|
@ -5,8 +5,10 @@ LL | fn foo<A: Debug>(&self, a: &A, b: &impl Debug);
|
||||
| -- type in trait
|
||||
...
|
||||
LL | fn foo<B: Debug>(&self, a: &impl Debug, b: &B) { }
|
||||
| - ^^^^^^^^^^^ expected type parameter `B`, found type parameter `impl Debug`
|
||||
| |
|
||||
| - ^^^^^^^^^^^
|
||||
| | |
|
||||
| | expected type parameter `B`, found type parameter `impl Debug`
|
||||
| | help: change the parameter type to match the trait: `&B`
|
||||
| expected type parameter
|
||||
|
|
||||
= note: expected fn pointer `fn(&(), &B, &impl Debug)`
|
||||
|
@ -1,8 +1,11 @@
|
||||
error[E0053]: method `fmt` has an incompatible type for trait
|
||||
--> $DIR/trait_type.rs:7:4
|
||||
--> $DIR/trait_type.rs:7:21
|
||||
|
|
||||
LL | fn fmt(&self, x: &str) -> () { }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ in mutability
|
||||
| ^^^^
|
||||
| |
|
||||
| types differ in mutability
|
||||
| help: change the parameter type to match the trait: `&mut Formatter<'_>`
|
||||
|
|
||||
= note: expected fn pointer `fn(&MyType, &mut Formatter<'_>) -> Result<(), std::fmt::Error>`
|
||||
found fn pointer `fn(&MyType, &str)`
|
||||
|
@ -8,7 +8,7 @@ LL | fn bar(&mut self, other: &dyn Foo) {}
|
||||
| ^^^^^^^^
|
||||
| |
|
||||
| types differ in mutability
|
||||
| help: consider changing the mutability to match the trait: `&mut dyn Foo`
|
||||
| help: change the parameter type to match the trait: `&mut dyn Foo`
|
||||
|
|
||||
= note: expected fn pointer `fn(&mut Baz, &mut dyn Foo)`
|
||||
found fn pointer `fn(&mut Baz, &dyn Foo)`
|
||||
|
@ -1,33 +1,42 @@
|
||||
error[E0053]: method `call` has an incompatible type for trait
|
||||
--> $DIR/issue-20225.rs:6:3
|
||||
--> $DIR/issue-20225.rs:6:43
|
||||
|
|
||||
LL | impl<'a, T> Fn<(&'a T,)> for Foo {
|
||||
| - this type parameter
|
||||
LL | extern "rust-call" fn call(&self, (_,): (T,)) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&T`, found type parameter `T`
|
||||
| ^^^^
|
||||
| |
|
||||
| expected `&T`, found type parameter `T`
|
||||
| help: change the parameter type to match the trait: `(&'a T,)`
|
||||
|
|
||||
= note: expected fn pointer `extern "rust-call" fn(&Foo, (&'a T,))`
|
||||
found fn pointer `extern "rust-call" fn(&Foo, (T,))`
|
||||
|
||||
error[E0053]: method `call_mut` has an incompatible type for trait
|
||||
--> $DIR/issue-20225.rs:11:3
|
||||
--> $DIR/issue-20225.rs:11:51
|
||||
|
|
||||
LL | impl<'a, T> FnMut<(&'a T,)> for Foo {
|
||||
| - this type parameter
|
||||
LL | extern "rust-call" fn call_mut(&mut self, (_,): (T,)) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&T`, found type parameter `T`
|
||||
| ^^^^
|
||||
| |
|
||||
| expected `&T`, found type parameter `T`
|
||||
| help: change the parameter type to match the trait: `(&'a T,)`
|
||||
|
|
||||
= note: expected fn pointer `extern "rust-call" fn(&mut Foo, (&'a T,))`
|
||||
found fn pointer `extern "rust-call" fn(&mut Foo, (T,))`
|
||||
|
||||
error[E0053]: method `call_once` has an incompatible type for trait
|
||||
--> $DIR/issue-20225.rs:18:3
|
||||
--> $DIR/issue-20225.rs:18:47
|
||||
|
|
||||
LL | impl<'a, T> FnOnce<(&'a T,)> for Foo {
|
||||
| - this type parameter
|
||||
...
|
||||
LL | extern "rust-call" fn call_once(self, (_,): (T,)) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&T`, found type parameter `T`
|
||||
| ^^^^
|
||||
| |
|
||||
| expected `&T`, found type parameter `T`
|
||||
| help: change the parameter type to match the trait: `(&'a T,)`
|
||||
|
|
||||
= note: expected fn pointer `extern "rust-call" fn(Foo, (&'a T,))`
|
||||
found fn pointer `extern "rust-call" fn(Foo, (T,))`
|
||||
|
@ -1,8 +1,11 @@
|
||||
error[E0053]: method `next` has an incompatible type for trait
|
||||
--> $DIR/issue-21332.rs:5:5
|
||||
--> $DIR/issue-21332.rs:5:27
|
||||
|
|
||||
LL | fn next(&mut self) -> Result<i32, i32> { Ok(7) }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `Option`, found enum `Result`
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| expected enum `Option`, found enum `Result`
|
||||
| help: change the output type to match the trait: `Option<i32>`
|
||||
|
|
||||
= note: expected fn pointer `fn(&mut S) -> Option<i32>`
|
||||
found fn pointer `fn(&mut S) -> Result<i32, i32>`
|
||||
|
@ -5,7 +5,10 @@ LL | fn foo(_: fn(u8) -> ());
|
||||
| ------------ type in trait
|
||||
...
|
||||
LL | fn foo(_: fn(u16) -> ()) {}
|
||||
| ^^^^^^^^^^^^^ expected `u8`, found `u16`
|
||||
| ^^^^^^^^^^^^^
|
||||
| |
|
||||
| expected `u8`, found `u16`
|
||||
| help: change the parameter type to match the trait: `fn(u8)`
|
||||
|
|
||||
= note: expected fn pointer `fn(fn(u8))`
|
||||
found fn pointer `fn(fn(u16))`
|
||||
@ -17,7 +20,10 @@ LL | fn bar(_: Option<u8>);
|
||||
| ---------- type in trait
|
||||
...
|
||||
LL | fn bar(_: Option<u16>) {}
|
||||
| ^^^^^^^^^^^ expected `u8`, found `u16`
|
||||
| ^^^^^^^^^^^
|
||||
| |
|
||||
| expected `u8`, found `u16`
|
||||
| help: change the parameter type to match the trait: `Option<u8>`
|
||||
|
|
||||
= note: expected fn pointer `fn(Option<u8>)`
|
||||
found fn pointer `fn(Option<u16>)`
|
||||
@ -29,7 +35,10 @@ LL | fn baz(_: (u8, u16));
|
||||
| --------- type in trait
|
||||
...
|
||||
LL | fn baz(_: (u16, u16)) {}
|
||||
| ^^^^^^^^^^ expected `u8`, found `u16`
|
||||
| ^^^^^^^^^^
|
||||
| |
|
||||
| expected `u8`, found `u16`
|
||||
| help: change the parameter type to match the trait: `(u8, u16)`
|
||||
|
|
||||
= note: expected fn pointer `fn((u8, _))`
|
||||
found fn pointer `fn((u16, _))`
|
||||
@ -41,7 +50,10 @@ LL | fn qux() -> u8;
|
||||
| -- type in trait
|
||||
...
|
||||
LL | fn qux() -> u16 { 5u16 }
|
||||
| ^^^ expected `u8`, found `u16`
|
||||
| ^^^
|
||||
| |
|
||||
| expected `u8`, found `u16`
|
||||
| help: change the output type to match the trait: `u8`
|
||||
|
|
||||
= note: expected fn pointer `fn() -> u8`
|
||||
found fn pointer `fn() -> u16`
|
||||
|
@ -5,7 +5,10 @@ LL | fn foo(x: u16);
|
||||
| --- type in trait
|
||||
...
|
||||
LL | fn foo(x: i16) { }
|
||||
| ^^^ expected `u16`, found `i16`
|
||||
| ^^^
|
||||
| |
|
||||
| expected `u16`, found `i16`
|
||||
| help: change the parameter type to match the trait: `u16`
|
||||
|
|
||||
= note: expected fn pointer `fn(u16)`
|
||||
found fn pointer `fn(i16)`
|
||||
@ -20,7 +23,7 @@ LL | fn bar(&mut self) { }
|
||||
| ^^^^^^^^^
|
||||
| |
|
||||
| types differ in mutability
|
||||
| help: consider changing the mutability to match the trait: `&self`
|
||||
| help: change the self-receiver type to match the trait: `self: &Bar`
|
||||
|
|
||||
= note: expected fn pointer `fn(&Bar)`
|
||||
found fn pointer `fn(&mut Bar)`
|
||||
|
@ -5,7 +5,10 @@ LL | fn foo(x: u16);
|
||||
| --- type in trait
|
||||
...
|
||||
LL | fn foo(x: i16) { }
|
||||
| ^^^ expected `u16`, found `i16`
|
||||
| ^^^
|
||||
| |
|
||||
| expected `u16`, found `i16`
|
||||
| help: change the parameter type to match the trait: `u16`
|
||||
|
|
||||
= note: expected fn pointer `fn(u16)`
|
||||
found fn pointer `fn(i16)`
|
||||
@ -20,7 +23,7 @@ LL | fn bar(&mut self, bar: &Bar) { }
|
||||
| ^^^^
|
||||
| |
|
||||
| types differ in mutability
|
||||
| help: consider changing the mutability to match the trait: `&mut Bar`
|
||||
| help: change the parameter type to match the trait: `&mut Bar`
|
||||
|
|
||||
= note: expected fn pointer `fn(&mut Bar, &mut Bar)`
|
||||
found fn pointer `fn(&mut Bar, &Bar)`
|
||||
|
@ -1,26 +1,35 @@
|
||||
error[E0053]: method `mul` has an incompatible type for trait
|
||||
--> $DIR/wrong-mul-method-signature.rs:16:5
|
||||
--> $DIR/wrong-mul-method-signature.rs:16:21
|
||||
|
|
||||
LL | fn mul(self, s: &f64) -> Vec1 {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `f64`, found `&f64`
|
||||
| ^^^^
|
||||
| |
|
||||
| expected `f64`, found `&f64`
|
||||
| help: change the parameter type to match the trait: `f64`
|
||||
|
|
||||
= note: expected fn pointer `fn(Vec1, f64) -> Vec1`
|
||||
found fn pointer `fn(Vec1, &f64) -> Vec1`
|
||||
|
||||
error[E0053]: method `mul` has an incompatible type for trait
|
||||
--> $DIR/wrong-mul-method-signature.rs:33:5
|
||||
--> $DIR/wrong-mul-method-signature.rs:33:21
|
||||
|
|
||||
LL | fn mul(self, s: f64) -> Vec2 {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `Vec2`, found `f64`
|
||||
| ^^^
|
||||
| |
|
||||
| expected struct `Vec2`, found `f64`
|
||||
| help: change the parameter type to match the trait: `Vec2`
|
||||
|
|
||||
= note: expected fn pointer `fn(Vec2, Vec2) -> f64`
|
||||
found fn pointer `fn(Vec2, f64) -> Vec2`
|
||||
|
||||
error[E0053]: method `mul` has an incompatible type for trait
|
||||
--> $DIR/wrong-mul-method-signature.rs:52:5
|
||||
--> $DIR/wrong-mul-method-signature.rs:52:29
|
||||
|
|
||||
LL | fn mul(self, s: f64) -> f64 {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `f64`
|
||||
| ^^^
|
||||
| |
|
||||
| expected `i32`, found `f64`
|
||||
| help: change the output type to match the trait: `i32`
|
||||
|
|
||||
= note: expected fn pointer `fn(Vec3, _) -> i32`
|
||||
found fn pointer `fn(Vec3, _) -> f64`
|
||||
|
Loading…
Reference in New Issue
Block a user