Change:
Essentially, if my trait has and my impl has the compiler panics. Note that the code is invalid and compilation should fail. <!-- If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions. --: Note that I'm using which is experimental. <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOT_END --
This happens for all type mismatches in the arguments (but not the arity!) A : <details<summaryWith the following backtrace: </summary</details
When not using a normal , the proper error is emitted here inside : But something gets messed up with the return position impl trait in trait desugaring that doesn't make this work (the arity check above does work). claim

Discussion:
use rustc_hir::{GenericParamKind, ImplItemKind, TraitItemKind}; use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; <del> use rustc_infer::infer::{self, TyCtxtInferExt}; </del> <ins> use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt}; </ins> use rustc_infer::traits::util; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::util::ExplicitSelf; <del> use rustc_middle::ty::InternalSubsts; </del> use rustc_middle::ty::{ <del> self, AssocItem, DefIdTree, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable, </del> <ins> self, AssocItem, DefIdTree, TraitRef, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable, </ins> }; <ins> use rustc_middle::ty::{FnSig, InternalSubsts}; </ins> use rustc_middle::ty::{GenericParamDefKind, ToPredicate, TyCtxt}; use rustc_span::Span; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;

} if let Err(terr) = result { <del> debug!("sub_types failed: impl ty {:?}, trait ty {:?}", impl_fty, trait_fty); </del> <ins> debug!(?terr, "sub_types failed: impl ty {:?}, trait ty {:?}", impl_fty, trait_fty); </ins> <del> let (impl_err_span, trait_err_span) = extract_spans_for_error_reporting(&infcx, terr, &cause, impl_m, trait_m); cause.span = impl_err_span; let mut diag = struct_span_err!( tcx.sess, cause.span(), E0053, "method `{}` has an incompatible type for trait", trait_m.name ); 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 span = match tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).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. match tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).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(); 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, "change the parameter type to match the trait", trait_ty, Applicability::MachineApplicable, ); } } _ => {} } infcx.err_ctxt().note_type_err( &mut diag, &cause, trait_err_span.map(|sp| (sp, "type in trait".to_owned())), Some(infer::ValuePairs::Terms(ExpectedFound { expected: trait_fty.into(), found: impl_fty.into(), })), </del> <ins> let emitted = report_trait_method_mismatch( tcx, &mut cause, &infcx, </ins> terr, <del> false, false, </del> <ins> (trait_m, trait_fty), (impl_m, impl_fty), &trait_sig, &impl_trait_ref, </ins> ); <del> return Err(diag.emit()); </del> <ins> return Err(emitted); </ins> } // Check that all obligations are satisfied by the implementation's

Ok(()) } <ins> #[instrument(skip(tcx), level = "debug", ret)] </ins> pub fn collect_trait_impl_trait_tys<'tcx>( tcx: TyCtxt<'tcx>, def_id: DefId,

let impl_m_hir_id = tcx.hir().local_def_id_to_hir_id(impl_m.def_id.expect_local()); let return_span = tcx.hir().fn_decl_by_hir_id(impl_m_hir_id).unwrap().output.span(); <del> let cause = ObligationCause::new( </del> <ins> let mut cause = ObligationCause::new( </ins> return_span, impl_m_hir_id, ObligationCauseCode::CompareImplItemObligation {

} } <ins> debug!(?trait_sig, ?impl_sig, "equating function signatures"); let trait_fty = tcx.mk_fn_ptr(ty::Binder::dummy(trait_sig)); let impl_fty = tcx.mk_fn_ptr(ty::Binder::dummy(impl_sig)); </ins> // Unify the whole function signature. We need to do this to fully infer // the lifetimes of the return type, but do this after unifying just the // return types, since we want to avoid duplicating errors from // `compare_predicate_entailment`. <del> match infcx .at(&cause, param_env) .eq(tcx.mk_fn_ptr(ty::Binder::dummy(trait_sig)), tcx.mk_fn_ptr(ty::Binder::dummy(impl_sig))) { </del> <ins> match infcx.at(&cause, param_env).eq(trait_fty, impl_fty) { </ins> Ok(infer::InferOk { value: (), obligations }) => { ocx.register_obligations(obligations); } Err(terr) => { <del> let guar = tcx.sess.delay_span_bug( return_span, format!("could not unify `{trait_sig}` and `{impl_sig}`: {terr:?}"), </del> <ins> // This function gets called during `compare_predicate_entailment` when normalizing a // signature that contains RPITIT. When the method signatures don't match, we have to // emit an error now because `compare_predicate_entailment` will not report the error // when normalization fails. let emitted = report_trait_method_mismatch( tcx, &mut cause, infcx, terr, (trait_m, trait_fty), (impl_m, impl_fty), &trait_sig, &impl_trait_ref, </ins> ); <del> return Err(guar); </del> <ins> return Err(emitted); </ins> } }

} } <ins> fn report_trait_method_mismatch<'tcx>( tcx: TyCtxt<'tcx>, cause: &mut ObligationCause<'tcx>, infcx: &InferCtxt<'tcx>, terr: TypeError<'tcx>, (trait_m, trait_fty): (&AssocItem, Ty<'tcx>), (impl_m, impl_fty): (&AssocItem, Ty<'tcx>), trait_sig: &FnSig<'tcx>, impl_trait_ref: &TraitRef<'tcx>, ) -> ErrorGuaranteed { let (impl_err_span, trait_err_span) = extract_spans_for_error_reporting(&infcx, terr, &cause, impl_m, trait_m); cause.span = impl_err_span; let mut diag = struct_span_err!( tcx.sess, cause.span(), E0053, "method `{}` has an incompatible type for trait", trait_m.name ); 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 span = match tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).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. match tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).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(); 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, "change the parameter type to match the trait", trait_ty, Applicability::MachineApplicable, ); } } _ => {} } infcx.err_ctxt().note_type_err( &mut diag, &cause, trait_err_span.map(|sp| (sp, "type in trait".to_owned())), Some(infer::ValuePairs::Terms(ExpectedFound { expected: trait_fty.into(), found: impl_fty.into(), })), terr, false, false, ); return diag.emit(); } </ins> fn check_region_bounds_on_impl_item<'tcx>( tcx: TyCtxt<'tcx>, impl_m: &ty::AssocItem,

<ins> // edition: 2021 #![feature(return_position_impl_trait_in_trait, async_fn_in_trait)] #![allow(incomplete_features)] trait Uwu { fn owo(x: ()) -> impl Sized; } impl Uwu for () { fn owo(_: u8) {} //~^ ERROR method `owo` has an incompatible type for trait } trait AsyncUwu { async fn owo(x: ()) {} } impl AsyncUwu for () { async fn owo(_: u8) {} //~^ ERROR method `owo` has an incompatible type for trait } trait TooMuch { fn calm_down_please() -> impl Sized; } impl TooMuch for () { fn calm_down_please(_: (), _: (), _: ()) {} //~^ ERROR method `calm_down_please` has 3 parameters but the declaration in trait `TooMuch::calm_down_please` has 0 } trait TooLittle { fn come_on_a_little_more_effort(_: (), _: (), _: ()) -> impl Sized; } impl TooLittle for () { fn come_on_a_little_more_effort() {} //~^ ERROR method `come_on_a_little_more_effort` has 0 parameters but the declaration in trait `TooLittle::come_on_a_little_more_effort` has 3 } trait Lifetimes { fn early<'early, T>(x: &'early T) -> impl Sized; } impl Lifetimes for () { fn early<'late, T>(_: &'late ()) {} //~^ ERROR method `early` has an incompatible type for trait } fn main() {} </ins>

<ins> error[E0053]: method `owo` has an incompatible type for trait --> $DIR/method-signature-matches.rs:11:15 | LL |     fn owo(_: u8) {} |               ^^ |               | |               expected `()`, found `u8` |               help: change the parameter type to match the trait: `()` | note: type in trait --> $DIR/method-signature-matches.rs:7:15 | LL |     fn owo(x: ()) -> impl Sized; |               ^^ = note: expected fn pointer `fn(())` found fn pointer `fn(u8)` error[E0053]: method `owo` has an incompatible type for trait --> $DIR/method-signature-matches.rs:20:21 | LL |     async fn owo(_: u8) {} |                     ^^ |                     | |                     expected `()`, found `u8` |                     help: change the parameter type to match the trait: `()` | note: while checking the return type of the `async fn` --> $DIR/method-signature-matches.rs:20:25 | LL |     async fn owo(_: u8) {} |                         ^ checked the `Output` of this `async fn`, expected opaque type note: while checking the return type of the `async fn` --> $DIR/method-signature-matches.rs:20:25 | LL |     async fn owo(_: u8) {} |                         ^ checked the `Output` of this `async fn`, found opaque type note: type in trait --> $DIR/method-signature-matches.rs:16:21 | LL |     async fn owo(x: ()) {} |                     ^^ = note: expected fn pointer `fn(()) -> _` found fn pointer `fn(u8) -> _` error[E0050]: method `calm_down_please` has 3 parameters but the declaration in trait `TooMuch::calm_down_please` has 0 --> $DIR/method-signature-matches.rs:29:28 | LL |     fn calm_down_please() -> impl Sized; |     ------------------------------------ trait requires 0 parameters ... LL |     fn calm_down_please(_: (), _: (), _: ()) {} |                            ^^^^^^^^^^^^^^^^ expected 0 parameters, found 3 error[E0050]: method `come_on_a_little_more_effort` has 0 parameters but the declaration in trait `TooLittle::come_on_a_little_more_effort` has 3 --> $DIR/method-signature-matches.rs:38:5 | LL |     fn come_on_a_little_more_effort(_: (), _: (), _: ()) -> impl Sized; |                                        ---------------- trait requires 3 parameters ... LL |     fn come_on_a_little_more_effort() {} |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 3 parameters, found 0 error[E0053]: method `early` has an incompatible type for trait --> $DIR/method-signature-matches.rs:47:27 | LL |     fn early<'late, T>(_: &'late ()) {} |                     -     ^^^^^^^^^ |                     |     | |                     |     expected type parameter `T`, found `()` |                     |     help: change the parameter type to match the trait: `&'early T` |                     this type parameter | note: type in trait --> $DIR/method-signature-matches.rs:43:28 | LL |     fn early<'early, T>(x: &'early T) -> impl Sized; |                            ^^^^^^^^^ = note: expected fn pointer `fn(&'early T)` found fn pointer `fn(&())` error: aborting due to 5 previous errors Some errors have detailed explanations: E0050, E0053. For more information about an error, try `rustc --explain E0050`. </ins>