compiler/rustc_hir_analysis/src/check/compare_impl_item.rs RUST 2,798 lines View on github.com → Search inside
File is large — showing lines 1–2,000 of 2,798.
1use core::ops::ControlFlow;2use std::borrow::Cow;3use std::cmp::Ordering;4use std::iter;56use hir::def_id::{DefId, DefIdMap, LocalDefId};7use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};8use rustc_errors::codes::*;9use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan, pluralize, struct_span_code_err};10use rustc_hir::def::{DefKind, Res};11use rustc_hir::intravisit::VisitorExt;12use rustc_hir::{self as hir, AmbigArg, GenericParamKind, ImplItemKind, intravisit};13use rustc_infer::infer::{self, BoundRegionConversionTime, InferCtxt, TyCtxtInferExt};14use rustc_infer::traits::util;15use rustc_middle::ty::error::{ExpectedFound, TypeError};16use rustc_middle::ty::{17    self, BottomUpFolder, GenericArgs, GenericParamDefKind, Generics, Ty, TyCtxt, TypeFoldable,18    TypeFolder, TypeSuperFoldable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode,19    Unnormalized, Upcast,20};21use rustc_middle::{bug, span_bug};22use rustc_span::{BytePos, DUMMY_SP, Span};23use rustc_trait_selection::error_reporting::InferCtxtErrorExt;24use rustc_trait_selection::infer::InferCtxtExt;25use rustc_trait_selection::regions::InferCtxtRegionExt;26use rustc_trait_selection::traits::{27    self, FulfillmentError, ObligationCause, ObligationCauseCode, ObligationCtxt,28};29use tracing::{debug, instrument};3031use super::potentially_plural_count;32use crate::errors::{LifetimesOrBoundsMismatchOnTrait, MethodShouldReturnFuture};3334pub(super) mod refine;3536/// Call the query `tcx.compare_impl_item()` directly instead.37pub(super) fn compare_impl_item(38    tcx: TyCtxt<'_>,39    impl_item_def_id: LocalDefId,40) -> Result<(), ErrorGuaranteed> {41    let impl_item = tcx.associated_item(impl_item_def_id);42    let trait_item = tcx.associated_item(impl_item.expect_trait_impl()?);43    let impl_trait_ref =44        tcx.impl_trait_ref(impl_item.container_id(tcx)).instantiate_identity().skip_norm_wip();45    debug!(?impl_trait_ref);4647    match impl_item.kind {48        ty::AssocKind::Fn { .. } => compare_impl_method(tcx, impl_item, trait_item, impl_trait_ref),49        ty::AssocKind::Type { .. } => compare_impl_ty(tcx, impl_item, trait_item, impl_trait_ref),50        ty::AssocKind::Const { .. } => {51            compare_impl_const(tcx, impl_item, trait_item, impl_trait_ref)52        }53    }54}5556/// Checks that a method from an impl conforms to the signature of57/// the same method as declared in the trait.58///59/// # Parameters60///61/// - `impl_m`: type of the method we are checking62/// - `trait_m`: the method in the trait63/// - `impl_trait_ref`: the TraitRef corresponding to the trait implementation64#[instrument(level = "debug", skip(tcx))]65fn compare_impl_method<'tcx>(66    tcx: TyCtxt<'tcx>,67    impl_m: ty::AssocItem,68    trait_m: ty::AssocItem,69    impl_trait_ref: ty::TraitRef<'tcx>,70) -> Result<(), ErrorGuaranteed> {71    check_method_is_structurally_compatible(tcx, impl_m, trait_m, impl_trait_ref, false)?;72    compare_method_predicate_entailment(tcx, impl_m, trait_m, impl_trait_ref)?;73    Ok(())74}7576/// Checks a bunch of different properties of the impl/trait methods for77/// compatibility, such as asyncness, number of argument, self receiver kind,78/// and number of early- and late-bound generics.79fn check_method_is_structurally_compatible<'tcx>(80    tcx: TyCtxt<'tcx>,81    impl_m: ty::AssocItem,82    trait_m: ty::AssocItem,83    impl_trait_ref: ty::TraitRef<'tcx>,84    delay: bool,85) -> Result<(), ErrorGuaranteed> {86    compare_self_type(tcx, impl_m, trait_m, impl_trait_ref, delay)?;87    compare_number_of_generics(tcx, impl_m, trait_m, delay)?;88    compare_generic_param_kinds(tcx, impl_m, trait_m, delay)?;89    compare_number_of_method_arguments(tcx, impl_m, trait_m, delay)?;90    compare_synthetic_generics(tcx, impl_m, trait_m, delay)?;91    check_region_bounds_on_impl_item(tcx, impl_m, trait_m, delay)?;92    Ok(())93}9495/// This function is best explained by example. Consider a trait with its implementation:96///97/// ```rust98/// trait Trait<'t, T> {99///     // `trait_m`100///     fn method<'a, M>(t: &'t T, m: &'a M) -> Self;101/// }102///103/// struct Foo;104///105/// impl<'i, 'j, U> Trait<'j, &'i U> for Foo {106///     // `impl_m`107///     fn method<'b, N>(t: &'j &'i U, m: &'b N) -> Foo { Foo }108/// }109/// ```110///111/// We wish to decide if those two method types are compatible.112/// For this we have to show that, assuming the bounds of the impl hold, the113/// bounds of `trait_m` imply the bounds of `impl_m`.114///115/// We start out with `trait_to_impl_args`, that maps the trait116/// type parameters to impl type parameters. This is taken from the117/// impl trait reference:118///119/// ```rust,ignore (pseudo-Rust)120/// trait_to_impl_args = {'t => 'j, T => &'i U, Self => Foo}121/// ```122///123/// We create a mapping `dummy_args` that maps from the impl type124/// parameters to fresh types and regions. For type parameters,125/// this is the identity transform, but we could as well use any126/// placeholder types. For regions, we convert from bound to free127/// regions (Note: but only early-bound regions, i.e., those128/// declared on the impl or used in type parameter bounds).129///130/// ```rust,ignore (pseudo-Rust)131/// impl_to_placeholder_args = {'i => 'i0, U => U0, N => N0 }132/// ```133///134/// Now we can apply `placeholder_args` to the type of the impl method135/// to yield a new function type in terms of our fresh, placeholder136/// types:137///138/// ```rust,ignore (pseudo-Rust)139/// <'b> fn(t: &'i0 U0, m: &'b N0) -> Foo140/// ```141///142/// We now want to extract and instantiate the type of the *trait*143/// method and compare it. To do so, we must create a compound144/// instantiation by combining `trait_to_impl_args` and145/// `impl_to_placeholder_args`, and also adding a mapping for the method146/// type parameters. We extend the mapping to also include147/// the method parameters.148///149/// ```rust,ignore (pseudo-Rust)150/// trait_to_placeholder_args = { T => &'i0 U0, Self => Foo, M => N0 }151/// ```152///153/// Applying this to the trait method type yields:154///155/// ```rust,ignore (pseudo-Rust)156/// <'a> fn(t: &'i0 U0, m: &'a N0) -> Foo157/// ```158///159/// This type is also the same but the name of the bound region (`'a`160/// vs `'b`). However, the normal subtyping rules on fn types handle161/// this kind of equivalency just fine.162///163/// We now use these generic parameters to ensure that all declared bounds164/// are satisfied by the implementation's method.165///166/// We do this by creating a parameter environment which contains a167/// generic parameter corresponding to `impl_to_placeholder_args`. We then build168/// `trait_to_placeholder_args` and use it to convert the predicates contained169/// in the `trait_m` generics to the placeholder form.170///171/// Finally we register each of these predicates as an obligation and check that172/// they hold.173#[instrument(level = "debug", skip(tcx, impl_trait_ref))]174fn compare_method_predicate_entailment<'tcx>(175    tcx: TyCtxt<'tcx>,176    impl_m: ty::AssocItem,177    trait_m: ty::AssocItem,178    impl_trait_ref: ty::TraitRef<'tcx>,179) -> Result<(), ErrorGuaranteed> {180    // This node-id should be used for the `body_id` field on each181    // `ObligationCause` (and the `FnCtxt`).182    //183    // FIXME(@lcnr): remove that after removing `cause.body_id` from184    // obligations.185    let impl_m_def_id = impl_m.def_id.expect_local();186    let impl_m_span = tcx.def_span(impl_m_def_id);187    let cause = ObligationCause::new(188        impl_m_span,189        impl_m_def_id,190        ObligationCauseCode::CompareImplItem {191            impl_item_def_id: impl_m_def_id,192            trait_item_def_id: trait_m.def_id,193            kind: impl_m.kind,194        },195    );196197    // Create mapping from trait method to impl method.198    let impl_def_id = impl_m.container_id(tcx);199    let trait_to_impl_args = GenericArgs::identity_for_item(tcx, impl_m.def_id).rebase_onto(200        tcx,201        impl_m.container_id(tcx),202        impl_trait_ref.args,203    );204    debug!(?trait_to_impl_args);205206    let impl_m_predicates = tcx.predicates_of(impl_m.def_id);207    let trait_m_predicates = tcx.predicates_of(trait_m.def_id);208209    // This is the only tricky bit of the new way we check implementation methods210    // We need to build a set of predicates where only the method-level bounds211    // are from the trait and we assume all other bounds from the implementation212    // to be previously satisfied.213    //214    // We then register the obligations from the impl_m and check to see215    // if all constraints hold.216    let impl_predicates = tcx.predicates_of(impl_m_predicates.parent.unwrap());217    let mut hybrid_preds = impl_predicates.instantiate_identity(tcx).predicates;218    hybrid_preds.extend(219        trait_m_predicates.instantiate_own(tcx, trait_to_impl_args).map(|(predicate, _)| predicate),220    );221222    let is_conditionally_const = tcx.is_conditionally_const(impl_m.def_id);223    if is_conditionally_const {224        // Augment the hybrid param-env with the const conditions225        // of the impl header and the trait method.226        hybrid_preds.extend(227            tcx.const_conditions(impl_def_id)228                .instantiate_identity(tcx)229                .into_iter()230                .chain(231                    tcx.const_conditions(trait_m.def_id).instantiate_own(tcx, trait_to_impl_args),232                )233                .map(|(trait_ref, _)| {234                    trait_ref.to_host_effect_clause(tcx, ty::BoundConstness::Maybe)235                }),236        );237    }238239    let hybrid_preds = hybrid_preds.into_iter().map(Unnormalized::skip_norm_wip);240    let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_def_id);241    let param_env = ty::ParamEnv::new(tcx.mk_clauses_from_iter(hybrid_preds));242    // FIXME(-Zhigher-ranked-assumptions): The `hybrid_preds`243    // should be well-formed. However, using them may result in244    // region errors as we currently don't track placeholder245    // assumptions.246    //247    // To avoid being backwards incompatible with the old solver,248    // we also eagerly normalize the where-bounds in the new solver249    // here while ignoring region constraints. This means we can then250    // use where-bounds whose normalization results in placeholder251    // errors further down without getting any errors.252    //253    // It should be sound to do so as the only region errors here254    // should be due to missing implied bounds.255    //256    // cc trait-system-refactor-initiative/issues/166.257    let param_env = if tcx.next_trait_solver_globally() {258        traits::deeply_normalize_param_env_ignoring_regions(tcx, param_env, normalize_cause)259    } else {260        traits::normalize_param_env_or_error(tcx, param_env, normalize_cause)261    };262    debug!(caller_bounds=?param_env.caller_bounds());263264    let infcx = &tcx.infer_ctxt().build(TypingMode::non_body_analysis());265    let ocx = ObligationCtxt::new_with_diagnostics(infcx);266267    // Create obligations for each predicate declared by the impl268    // definition in the context of the hybrid param-env. This makes269    // sure that the impl's method's where clauses are not more270    // restrictive than the trait's method (and the impl itself).271    let impl_m_own_bounds = impl_m_predicates.instantiate_own_identity();272    for (predicate, span) in impl_m_own_bounds {273        let normalize_cause = traits::ObligationCause::misc(span, impl_m_def_id);274        let predicate = ocx.normalize(&normalize_cause, param_env, predicate);275276        let cause = ObligationCause::new(277            span,278            impl_m_def_id,279            ObligationCauseCode::CompareImplItem {280                impl_item_def_id: impl_m_def_id,281                trait_item_def_id: trait_m.def_id,282                kind: impl_m.kind,283            },284        );285        ocx.register_obligation(traits::Obligation::new(tcx, cause, param_env, predicate));286    }287288    // If we're within a const implementation, we need to make sure that the method289    // does not assume stronger `[const]` bounds than the trait definition.290    //291    // This registers the `[const]` bounds of the impl method, which we will prove292    // using the hybrid param-env that we earlier augmented with the const conditions293    // from the impl header and trait method declaration.294    if is_conditionally_const {295        for (const_condition, span) in296            tcx.const_conditions(impl_m.def_id).instantiate_own_identity()297        {298            let normalize_cause = traits::ObligationCause::misc(span, impl_m_def_id);299            let const_condition = ocx.normalize(&normalize_cause, param_env, const_condition);300301            let cause = ObligationCause::new(302                span,303                impl_m_def_id,304                ObligationCauseCode::CompareImplItem {305                    impl_item_def_id: impl_m_def_id,306                    trait_item_def_id: trait_m.def_id,307                    kind: impl_m.kind,308                },309            );310            ocx.register_obligation(traits::Obligation::new(311                tcx,312                cause,313                param_env,314                const_condition.to_host_effect_clause(tcx, ty::BoundConstness::Maybe),315            ));316        }317    }318319    // We now need to check that the signature of the impl method is320    // compatible with that of the trait method. We do this by321    // checking that `impl_fty <: trait_fty`.322    //323    // FIXME: We manually instantiate the trait method here as we need324    // to manually compute its implied bounds. Otherwise this could just325    // be `ocx.sub(impl_sig, trait_sig)`.326327    let mut wf_tys = FxIndexSet::default();328329    let unnormalized_impl_sig = infcx.instantiate_binder_with_fresh_vars(330        impl_m_span,331        BoundRegionConversionTime::HigherRankedType,332        tcx.fn_sig(impl_m.def_id).instantiate_identity().skip_norm_wip(),333    );334335    let norm_cause = ObligationCause::misc(impl_m_span, impl_m_def_id);336    let impl_sig =337        ocx.normalize(&norm_cause, param_env, Unnormalized::new_wip(unnormalized_impl_sig));338    debug!(?impl_sig);339340    let trait_sig = tcx.fn_sig(trait_m.def_id).instantiate(tcx, trait_to_impl_args).skip_norm_wip();341    let trait_sig = tcx.liberate_late_bound_regions(impl_m.def_id, trait_sig);342343    // Next, add all inputs and output as well-formed tys. Importantly,344    // we have to do this before normalization, since the normalized ty may345    // not contain the input parameters. See issue #87748.346    wf_tys.extend(trait_sig.inputs_and_output.iter());347    let trait_sig = ocx.normalize(&norm_cause, param_env, Unnormalized::new_wip(trait_sig));348    // We also have to add the normalized trait signature349    // as we don't normalize during implied bounds computation.350    wf_tys.extend(trait_sig.inputs_and_output.iter());351    debug!(?trait_sig);352353    // FIXME: We'd want to keep more accurate spans than "the method signature" when354    // processing the comparison between the trait and impl fn, but we sadly lose them355    // and point at the whole signature when a trait bound or specific input or output356    // type would be more appropriate. In other places we have a `Vec<Span>`357    // corresponding to their `Vec<Predicate>`, but we don't have that here.358    // Fixing this would improve the output of test `issue-83765.rs`.359    // There's the same issue in compare_eii code.360    let result = ocx.sup(&cause, param_env, trait_sig, impl_sig);361362    if let Err(terr) = result {363        debug!(?impl_sig, ?trait_sig, ?terr, "sub_types failed");364365        let emitted = report_trait_method_mismatch(366            infcx,367            cause,368            param_env,369            terr,370            (trait_m, trait_sig),371            (impl_m, impl_sig),372            impl_trait_ref,373        );374        return Err(emitted);375    }376377    if !(impl_sig, trait_sig).references_error() {378        for ty in unnormalized_impl_sig.inputs_and_output {379            ocx.register_obligation(traits::Obligation::new(380                infcx.tcx,381                cause.clone(),382                param_env,383                ty::ClauseKind::WellFormed(ty.into()),384            ));385        }386    }387388    // Check that all obligations are satisfied by the implementation's389    // version.390    let errors = ocx.evaluate_obligations_error_on_ambiguity();391    if !errors.is_empty() {392        let reported = infcx.err_ctxt().report_fulfillment_errors(errors);393        return Err(reported);394    }395396    // Finally, resolve all regions. This catches wily misuses of397    // lifetime parameters.398    let errors = infcx.resolve_regions(impl_m_def_id, param_env, wf_tys);399    if !errors.is_empty() {400        return Err(infcx401            .tainted_by_errors()402            .unwrap_or_else(|| infcx.err_ctxt().report_region_errors(impl_m_def_id, &errors)));403    }404405    Ok(())406}407408struct RemapLateParam<'tcx> {409    tcx: TyCtxt<'tcx>,410    mapping: FxIndexMap<ty::LateParamRegionKind, ty::LateParamRegionKind>,411}412413impl<'tcx> TypeFolder<TyCtxt<'tcx>> for RemapLateParam<'tcx> {414    fn cx(&self) -> TyCtxt<'tcx> {415        self.tcx416    }417418    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {419        if let ty::ReLateParam(fr) = r.kind() {420            ty::Region::new_late_param(421                self.tcx,422                fr.scope,423                self.mapping.get(&fr.kind).copied().unwrap_or(fr.kind),424            )425        } else {426            r427        }428    }429}430431/// Given a method def-id in an impl, compare the method signature of the impl432/// against the trait that it's implementing. In doing so, infer the hidden types433/// that this method's signature provides to satisfy each return-position `impl Trait`434/// in the trait signature.435///436/// The method is also responsible for making sure that the hidden types for each437/// RPITIT actually satisfy the bounds of the `impl Trait`, i.e. that if we infer438/// `impl Trait = Foo`, that `Foo: Trait` holds.439///440/// For example, given the sample code:441///442/// ```443/// use std::ops::Deref;444///445/// trait Foo {446///     fn bar() -> impl Deref<Target = impl Sized>;447///     //          ^- RPITIT #1        ^- RPITIT #2448/// }449///450/// impl Foo for () {451///     fn bar() -> Box<String> { Box::new(String::new()) }452/// }453/// ```454///455/// The hidden types for the RPITITs in `bar` would be inferred to:456///     * `impl Deref` (RPITIT #1) = `Box<String>`457///     * `impl Sized` (RPITIT #2) = `String`458///459/// The relationship between these two types is straightforward in this case, but460/// may be more tenuously connected via other `impl`s and normalization rules for461/// cases of more complicated nested RPITITs.462#[instrument(skip(tcx), level = "debug", ret)]463pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(464    tcx: TyCtxt<'tcx>,465    impl_m_def_id: LocalDefId,466) -> Result<&'tcx DefIdMap<ty::EarlyBinder<'tcx, Ty<'tcx>>>, ErrorGuaranteed> {467    let impl_m = tcx.associated_item(impl_m_def_id.to_def_id());468    let trait_m = tcx.associated_item(impl_m.expect_trait_impl()?);469    let impl_trait_ref = tcx470        .impl_trait_ref(tcx.parent(impl_m_def_id.to_def_id()))471        .instantiate_identity()472        .skip_norm_wip();473    // First, check a few of the same things as `compare_impl_method`,474    // just so we don't ICE during instantiation later.475    check_method_is_structurally_compatible(tcx, impl_m, trait_m, impl_trait_ref, true)?;476477    let impl_m_hir_id = tcx.local_def_id_to_hir_id(impl_m_def_id);478    let return_span = tcx.hir_fn_decl_by_hir_id(impl_m_hir_id).unwrap().output.span();479    let cause = ObligationCause::new(480        return_span,481        impl_m_def_id,482        ObligationCauseCode::CompareImplItem {483            impl_item_def_id: impl_m_def_id,484            trait_item_def_id: trait_m.def_id,485            kind: impl_m.kind,486        },487    );488489    // Create mapping from trait to impl (i.e. impl trait header + impl method identity args).490    let trait_to_impl_args = GenericArgs::identity_for_item(tcx, impl_m.def_id).rebase_onto(491        tcx,492        impl_m.container_id(tcx),493        impl_trait_ref.args,494    );495496    let hybrid_preds = tcx497        .predicates_of(impl_m.container_id(tcx))498        .instantiate_identity(tcx)499        .into_iter()500        .chain(tcx.predicates_of(trait_m.def_id).instantiate_own(tcx, trait_to_impl_args))501        .map(|(clause, _)| clause.skip_norm_wip());502    let param_env = ty::ParamEnv::new(tcx.mk_clauses_from_iter(hybrid_preds));503    let param_env = traits::normalize_param_env_or_error(504        tcx,505        param_env,506        ObligationCause::misc(tcx.def_span(impl_m_def_id), impl_m_def_id),507    );508509    let infcx = &tcx.infer_ctxt().build(TypingMode::non_body_analysis());510    let ocx = ObligationCtxt::new_with_diagnostics(infcx);511512    // Check that the where clauses of the impl are satisfied by the hybrid param env.513    // You might ask -- what does this have to do with RPITIT inference? Nothing.514    // We check these because if the where clauses of the signatures do not match515    // up, then we don't want to give spurious other errors that point at the RPITITs.516    // They're not necessary to check, though, because we already check them in517    // `compare_method_predicate_entailment`.518    let impl_m_own_bounds = tcx.predicates_of(impl_m_def_id).instantiate_own_identity();519    for (predicate, span) in impl_m_own_bounds {520        let normalize_cause = traits::ObligationCause::misc(span, impl_m_def_id);521        let predicate = ocx.normalize(&normalize_cause, param_env, predicate);522523        let cause = ObligationCause::new(524            span,525            impl_m_def_id,526            ObligationCauseCode::CompareImplItem {527                impl_item_def_id: impl_m_def_id,528                trait_item_def_id: trait_m.def_id,529                kind: impl_m.kind,530            },531        );532        ocx.register_obligation(traits::Obligation::new(tcx, cause, param_env, predicate));533    }534535    // Normalize the impl signature with fresh variables for lifetime inference.536    let misc_cause = ObligationCause::misc(return_span, impl_m_def_id);537    let impl_sig = ocx.normalize(538        &misc_cause,539        param_env,540        Unnormalized::new_wip(infcx.instantiate_binder_with_fresh_vars(541            return_span,542            BoundRegionConversionTime::HigherRankedType,543            tcx.fn_sig(impl_m.def_id).instantiate_identity().skip_norm_wip(),544        )),545    );546    impl_sig.error_reported()?;547    let impl_return_ty = impl_sig.output();548549    // Normalize the trait signature with liberated bound vars, passing it through550    // the ImplTraitInTraitCollector, which gathers all of the RPITITs and replaces551    // them with inference variables.552    // We will use these inference variables to collect the hidden types of RPITITs.553    let mut collector = ImplTraitInTraitCollector::new(&ocx, return_span, param_env, impl_m_def_id);554    let unnormalized_trait_sig = tcx555        .liberate_late_bound_regions(556            impl_m.def_id,557            tcx.fn_sig(trait_m.def_id).instantiate(tcx, trait_to_impl_args).skip_norm_wip(),558        )559        .fold_with(&mut collector);560561    let trait_sig =562        ocx.normalize(&misc_cause, param_env, Unnormalized::new_wip(unnormalized_trait_sig));563    trait_sig.error_reported()?;564    let trait_return_ty = trait_sig.output();565566    // RPITITs are allowed to use the implied predicates of the method that567    // defines them. This is because we want code like:568    // ```569    // trait Foo {570    //     fn test<'a, T>(_: &'a T) -> impl Sized;571    // }572    // impl Foo for () {573    //     fn test<'a, T>(x: &'a T) -> &'a T { x }574    // }575    // ```576    // .. to compile. However, since we use both the normalized and unnormalized577    // inputs and outputs from the instantiated trait signature, we will end up578    // seeing the hidden type of an RPIT in the signature itself. Naively, this579    // means that we will use the hidden type to imply the hidden type's own580    // well-formedness.581    //582    // To avoid this, we replace the infer vars used for hidden type inference583    // with placeholders, which imply nothing about outlives bounds, and then584    // prove below that the hidden types are well formed.585    let universe = infcx.create_next_universe();586    let mut idx = ty::BoundVar::ZERO;587    let mapping: FxIndexMap<_, _> = collector588        .types589        .iter()590        .map(|(_, &(ty, _))| {591            assert!(592                infcx.resolve_vars_if_possible(ty) == ty && ty.is_ty_var(),593                "{ty:?} should not have been constrained via normalization",594                ty = infcx.resolve_vars_if_possible(ty)595            );596            idx += 1;597            (598                ty,599                Ty::new_placeholder(600                    tcx,601                    ty::PlaceholderType::new(602                        universe,603                        ty::BoundTy { var: idx, kind: ty::BoundTyKind::Anon },604                    ),605                ),606            )607        })608        .collect();609    let mut type_mapper = BottomUpFolder {610        tcx,611        ty_op: |ty| *mapping.get(&ty).unwrap_or(&ty),612        lt_op: |lt| lt,613        ct_op: |ct| ct,614    };615    let wf_tys = FxIndexSet::from_iter(616        unnormalized_trait_sig617            .inputs_and_output618            .iter()619            .chain(trait_sig.inputs_and_output.iter())620            .map(|ty| ty.fold_with(&mut type_mapper)),621    );622623    match ocx.eq(&cause, param_env, trait_return_ty, impl_return_ty) {624        Ok(()) => {}625        Err(terr) => {626            let mut diag = struct_span_code_err!(627                tcx.dcx(),628                cause.span,629                E0053,630                "method `{}` has an incompatible return type for trait",631                trait_m.name()632            );633            infcx.err_ctxt().note_type_err(634                &mut diag,635                &cause,636                tcx.hir_get_if_local(impl_m.def_id)637                    .and_then(|node| node.fn_decl())638                    .map(|decl| (decl.output.span(), Cow::from("return type in trait"), false)),639                Some(param_env.and(infer::ValuePairs::Terms(ExpectedFound {640                    expected: trait_return_ty.into(),641                    found: impl_return_ty.into(),642                }))),643                terr,644                false,645                None,646            );647            return Err(diag.emit());648        }649    }650651    debug!(?trait_sig, ?impl_sig, "equating function signatures");652653    // Unify the whole function signature. We need to do this to fully infer654    // the lifetimes of the return type, but do this after unifying just the655    // return types, since we want to avoid duplicating errors from656    // `compare_method_predicate_entailment`.657    match ocx.eq(&cause, param_env, trait_sig, impl_sig) {658        Ok(()) => {}659        Err(terr) => {660            // This function gets called during `compare_method_predicate_entailment` when normalizing a661            // signature that contains RPITIT. When the method signatures don't match, we have to662            // emit an error now because `compare_method_predicate_entailment` will not report the error663            // when normalization fails.664            let emitted = report_trait_method_mismatch(665                infcx,666                cause,667                param_env,668                terr,669                (trait_m, trait_sig),670                (impl_m, impl_sig),671                impl_trait_ref,672            );673            return Err(emitted);674        }675    }676677    if !unnormalized_trait_sig.output().references_error() && collector.types.is_empty() {678        tcx.dcx().delayed_bug(679            "expect >0 RPITITs in call to `collect_return_position_impl_trait_in_trait_tys`",680        );681    }682683    // FIXME: This has the same issue as #108544, but since this isn't breaking684    // existing code, I'm not particularly inclined to do the same hack as above685    // where we process wf obligations manually. This can be fixed in a forward-686    // compatible way later.687    let collected_types = collector.types;688    for (_, &(ty, _)) in &collected_types {689        ocx.register_obligation(traits::Obligation::new(690            tcx,691            misc_cause.clone(),692            param_env,693            ty::ClauseKind::WellFormed(ty.into()),694        ));695    }696697    // Check that all obligations are satisfied by the implementation's698    // RPITs.699    let errors = ocx.evaluate_obligations_error_on_ambiguity();700    if !errors.is_empty() {701        if let Err(guar) = try_report_async_mismatch(tcx, infcx, &errors, trait_m, impl_m, impl_sig)702        {703            return Err(guar);704        }705706        let guar = infcx.err_ctxt().report_fulfillment_errors(errors);707        return Err(guar);708    }709710    // Finally, resolve all regions. This catches wily misuses of711    // lifetime parameters.712    ocx.resolve_regions_and_report_errors(impl_m_def_id, param_env, wf_tys)?;713714    let mut remapped_types = DefIdMap::default();715    for (def_id, (ty, args)) in collected_types {716        match infcx.fully_resolve(ty) {717            Ok(ty) => {718                // `ty` contains free regions that we created earlier while liberating the719                // trait fn signature. However, projection normalization expects `ty` to720                // contains `def_id`'s early-bound regions.721                let id_args = GenericArgs::identity_for_item(tcx, def_id);722                debug!(?id_args, ?args);723                let map: FxIndexMap<_, _> = std::iter::zip(args, id_args)724                    .skip(tcx.generics_of(trait_m.def_id).count())725                    .filter_map(|(a, b)| Some((a.as_region()?, b.as_region()?)))726                    .collect();727                debug!(?map);728729                // NOTE(compiler-errors): RPITITs, like all other RPITs, have early-bound730                // region args that are synthesized during AST lowering. These are args731                // that are appended to the parent args (trait and trait method). However,732                // we're trying to infer the uninstantiated type value of the RPITIT inside733                // the *impl*, so we can later use the impl's method args to normalize734                // an RPITIT to a concrete type (`confirm_impl_trait_in_trait_candidate`).735                //736                // Due to the design of RPITITs, during AST lowering, we have no idea that737                // an impl method corresponds to a trait method with RPITITs in it. Therefore,738                // we don't have a list of early-bound region args for the RPITIT in the impl.739                // Since early region parameters are index-based, we can't just rebase these740                // (trait method) early-bound region args onto the impl, and there's no741                // guarantee that the indices from the trait args and impl args line up.742                // So to fix this, we subtract the number of trait args and add the number of743                // impl args to *renumber* these early-bound regions to their corresponding744                // indices in the impl's generic parameters list.745                //746                // Also, we only need to account for a difference in trait and impl args,747                // since we previously enforce that the trait method and impl method have the748                // same generics.749                let num_trait_args = impl_trait_ref.args.len();750                let num_impl_args = tcx.generics_of(impl_m.container_id(tcx)).own_params.len();751                let ty = match ty.try_fold_with(&mut RemapHiddenTyRegions {752                    tcx,753                    map,754                    num_trait_args,755                    num_impl_args,756                    def_id,757                    impl_m_def_id: impl_m.def_id,758                    ty,759                    return_span,760                }) {761                    Ok(ty) => ty,762                    Err(guar) => Ty::new_error(tcx, guar),763                };764                remapped_types.insert(def_id, ty::EarlyBinder::bind(ty));765            }766            Err(err) => {767                // This code path is not reached in any tests, but may be768                // reachable. If this is triggered, it should be converted to769                // `span_delayed_bug` and the triggering case turned into a770                // test.771                tcx.dcx()772                    .span_bug(return_span, format!("could not fully resolve: {ty} => {err:?}"));773            }774        }775    }776777    // We may not collect all RPITITs that we see in the HIR for a trait signature778    // because an RPITIT was located within a missing item. Like if we have a sig779    // returning `-> Missing<impl Sized>`, that gets converted to `-> {type error}`,780    // and when walking through the signature we end up never collecting the def id781    // of the `impl Sized`. Insert that here, so we don't ICE later.782    for assoc_item in tcx.associated_types_for_impl_traits_in_associated_fn(trait_m.def_id) {783        if !remapped_types.contains_key(assoc_item) {784            remapped_types.insert(785                *assoc_item,786                ty::EarlyBinder::bind(Ty::new_error_with_message(787                    tcx,788                    return_span,789                    "missing synthetic item for RPITIT",790                )),791            );792        }793    }794795    Ok(&*tcx.arena.alloc(remapped_types))796}797798struct ImplTraitInTraitCollector<'a, 'tcx, E> {799    ocx: &'a ObligationCtxt<'a, 'tcx, E>,800    types: FxIndexMap<DefId, (Ty<'tcx>, ty::GenericArgsRef<'tcx>)>,801    span: Span,802    param_env: ty::ParamEnv<'tcx>,803    body_id: LocalDefId,804}805806impl<'a, 'tcx, E> ImplTraitInTraitCollector<'a, 'tcx, E>807where808    E: 'tcx,809{810    fn new(811        ocx: &'a ObligationCtxt<'a, 'tcx, E>,812        span: Span,813        param_env: ty::ParamEnv<'tcx>,814        body_id: LocalDefId,815    ) -> Self {816        ImplTraitInTraitCollector { ocx, types: FxIndexMap::default(), span, param_env, body_id }817    }818}819820impl<'tcx, E> TypeFolder<TyCtxt<'tcx>> for ImplTraitInTraitCollector<'_, 'tcx, E>821where822    E: 'tcx,823{824    fn cx(&self) -> TyCtxt<'tcx> {825        self.ocx.infcx.tcx826    }827828    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {829        if let &ty::Alias(ty::AliasTy { kind: ty::Projection { def_id }, args: proj_args, .. }) =830            ty.kind()831            && self.cx().is_impl_trait_in_trait(def_id)832        {833            if let Some((ty, _)) = self.types.get(&def_id) {834                return *ty;835            }836            //FIXME(RPITIT): Deny nested RPITIT in args too837            if proj_args.has_escaping_bound_vars() {838                bug!("FIXME(RPITIT): error here");839            }840            // Replace with infer var841            let infer_ty = self.ocx.infcx.next_ty_var(self.span);842            self.types.insert(def_id, (infer_ty, proj_args));843            // Recurse into bounds844            for (pred, pred_span) in self845                .cx()846                .explicit_item_bounds(def_id)847                .iter_instantiated_copied(self.cx(), proj_args)848                .map(Unnormalized::skip_norm_wip)849            {850                let pred = pred.fold_with(self);851                let pred = self.ocx.normalize(852                    &ObligationCause::misc(self.span, self.body_id),853                    self.param_env,854                    Unnormalized::new_wip(pred),855                );856857                self.ocx.register_obligation(traits::Obligation::new(858                    self.cx(),859                    ObligationCause::new(860                        self.span,861                        self.body_id,862                        ObligationCauseCode::WhereClause(def_id, pred_span),863                    ),864                    self.param_env,865                    pred,866                ));867            }868            infer_ty869        } else {870            ty.super_fold_with(self)871        }872    }873}874875struct RemapHiddenTyRegions<'tcx> {876    tcx: TyCtxt<'tcx>,877    /// Map from early/late params of the impl to identity regions of the RPITIT (GAT)878    /// in the trait.879    map: FxIndexMap<ty::Region<'tcx>, ty::Region<'tcx>>,880    num_trait_args: usize,881    num_impl_args: usize,882    /// Def id of the RPITIT (GAT) in the *trait*.883    def_id: DefId,884    /// Def id of the impl method which owns the opaque hidden type we're remapping.885    impl_m_def_id: DefId,886    /// The hidden type we're remapping. Useful for diagnostics.887    ty: Ty<'tcx>,888    /// Span of the return type. Useful for diagnostics.889    return_span: Span,890}891892impl<'tcx> ty::FallibleTypeFolder<TyCtxt<'tcx>> for RemapHiddenTyRegions<'tcx> {893    type Error = ErrorGuaranteed;894895    fn cx(&self) -> TyCtxt<'tcx> {896        self.tcx897    }898899    fn try_fold_region(900        &mut self,901        region: ty::Region<'tcx>,902    ) -> Result<ty::Region<'tcx>, Self::Error> {903        match region.kind() {904            // Never remap bound regions or `'static`905            ty::ReBound(..) | ty::ReStatic | ty::ReError(_) => return Ok(region),906            // We always remap liberated late-bound regions from the function.907            ty::ReLateParam(_) => {}908            // Remap early-bound regions as long as they don't come from the `impl` itself,909            // in which case we don't really need to renumber them.910            ty::ReEarlyParam(ebr) => {911                if ebr.index as usize >= self.num_impl_args {912                    // Remap913                } else {914                    return Ok(region);915                }916            }917            ty::ReVar(_) | ty::RePlaceholder(_) | ty::ReErased => unreachable!(918                "should not have leaked vars or placeholders into hidden type of RPITIT"919            ),920        }921922        let e = if let Some(id_region) = self.map.get(&region) {923            if let ty::ReEarlyParam(e) = id_region.kind() {924                e925            } else {926                bug!(927                    "expected to map region {region} to early-bound identity region, but got {id_region}"928                );929            }930        } else {931            let guar = match region.opt_param_def_id(self.tcx, self.impl_m_def_id) {932                Some(def_id) => {933                    let return_span = if let &ty::Alias(ty::AliasTy {934                        kind: ty::Opaque { def_id: opaque_ty_def_id },935                        ..936                    }) = self.ty.kind()937                    {938                        self.tcx.def_span(opaque_ty_def_id)939                    } else {940                        self.return_span941                    };942                    self.tcx943                        .dcx()944                        .struct_span_err(945                            return_span,946                            "return type captures more lifetimes than trait definition",947                        )948                        .with_span_label(self.tcx.def_span(def_id), "this lifetime was captured")949                        .with_span_note(950                            self.tcx.def_span(self.def_id),951                            "hidden type must only reference lifetimes captured by this impl trait",952                        )953                        .with_note(format!("hidden type inferred to be `{}`", self.ty))954                        .emit()955                }956                None => {957                    // This code path is not reached in any tests, but may be958                    // reachable. If this is triggered, it should be converted959                    // to `delayed_bug` and the triggering case turned into a960                    // test.961                    self.tcx.dcx().bug("should've been able to remap region");962                }963            };964            return Err(guar);965        };966967        Ok(ty::Region::new_early_param(968            self.tcx,969            ty::EarlyParamRegion {970                name: e.name,971                index: (e.index as usize - self.num_trait_args + self.num_impl_args) as u32,972            },973        ))974    }975}976977/// Gets the string for an explicit self declaration, e.g. "self", "&self",978/// etc.979fn get_self_string<'tcx, P>(self_arg_ty: Ty<'tcx>, is_self_ty: P) -> String980where981    P: Fn(Ty<'tcx>) -> bool,982{983    if is_self_ty(self_arg_ty) {984        "self".to_owned()985    } else if let ty::Ref(_, ty, mutbl) = self_arg_ty.kind()986        && is_self_ty(*ty)987    {988        match mutbl {989            hir::Mutability::Not => "&self".to_owned(),990            hir::Mutability::Mut => "&mut self".to_owned(),991        }992    } else {993        format!("self: {self_arg_ty}")994    }995}996997fn report_trait_method_mismatch<'tcx>(998    infcx: &InferCtxt<'tcx>,999    mut cause: ObligationCause<'tcx>,1000    param_env: ty::ParamEnv<'tcx>,1001    terr: TypeError<'tcx>,1002    (trait_m, trait_sig): (ty::AssocItem, ty::FnSig<'tcx>),1003    (impl_m, impl_sig): (ty::AssocItem, ty::FnSig<'tcx>),1004    impl_trait_ref: ty::TraitRef<'tcx>,1005) -> ErrorGuaranteed {1006    let tcx = infcx.tcx;1007    let (impl_err_span, trait_err_span) =1008        extract_spans_for_error_reporting(infcx, terr, &cause, impl_m, trait_m);10091010    let mut diag = struct_span_code_err!(1011        tcx.dcx(),1012        impl_err_span,1013        E0053,1014        "method `{}` has an incompatible type for trait",1015        trait_m.name()1016    );1017    match &terr {1018        TypeError::ArgumentMutability(0) | TypeError::ArgumentSorts(_, 0)1019            if trait_m.is_method() =>1020        {1021            let ty = trait_sig.inputs()[0];1022            let sugg = get_self_string(ty, |ty| ty == impl_trait_ref.self_ty());10231024            // When the `impl` receiver is an arbitrary self type, like `self: Box<Self>`, the1025            // span points only at the type `Box<Self`>, but we want to cover the whole1026            // argument pattern and type.1027            let (sig, body) = tcx.hir_expect_impl_item(impl_m.def_id.expect_local()).expect_fn();1028            let span = tcx1029                .hir_body_param_idents(body)1030                .zip(sig.decl.inputs.iter())1031                .map(|(param_ident, ty)| {1032                    if let Some(param_ident) = param_ident {1033                        param_ident.span.to(ty.span)1034                    } else {1035                        ty.span1036                    }1037                })1038                .next()1039                .unwrap_or(impl_err_span);10401041            diag.span_suggestion_verbose(1042                span,1043                "change the self-receiver type to match the trait",1044                sugg,1045                Applicability::MachineApplicable,1046            );1047        }1048        TypeError::ArgumentMutability(i) | TypeError::ArgumentSorts(_, i) => {1049            if trait_sig.inputs().len() == *i {1050                // Suggestion to change output type. We do not suggest in `async` functions1051                // to avoid complex logic or incorrect output.1052                if let ImplItemKind::Fn(sig, _) =1053                    &tcx.hir_expect_impl_item(impl_m.def_id.expect_local()).kind1054                    && !sig.header.asyncness.is_async()1055                {1056                    let msg = "change the output type to match the trait";1057                    let ap = Applicability::MachineApplicable;1058                    match sig.decl.output {1059                        hir::FnRetTy::DefaultReturn(sp) => {1060                            let sugg = format!(" -> {}", trait_sig.output());1061                            diag.span_suggestion_verbose(sp, msg, sugg, ap);1062                        }1063                        hir::FnRetTy::Return(hir_ty) => {1064                            let sugg = trait_sig.output();1065                            diag.span_suggestion_verbose(hir_ty.span, msg, sugg, ap);1066                        }1067                    };1068                };1069            } else if let Some(trait_ty) = trait_sig.inputs().get(*i) {1070                diag.span_suggestion_verbose(1071                    impl_err_span,1072                    "change the parameter type to match the trait",1073                    trait_ty,1074                    Applicability::MachineApplicable,1075                );1076            }1077        }1078        _ => {}1079    }10801081    cause.span = impl_err_span;1082    infcx.err_ctxt().note_type_err(1083        &mut diag,1084        &cause,1085        trait_err_span.map(|sp| (sp, Cow::from("type in trait"), false)),1086        Some(param_env.and(infer::ValuePairs::PolySigs(ExpectedFound {1087            expected: ty::Binder::dummy(trait_sig),1088            found: ty::Binder::dummy(impl_sig),1089        }))),1090        terr,1091        false,1092        None,1093    );10941095    diag.emit()1096}10971098fn check_region_bounds_on_impl_item<'tcx>(1099    tcx: TyCtxt<'tcx>,1100    impl_m: ty::AssocItem,1101    trait_m: ty::AssocItem,1102    delay: bool,1103) -> Result<(), ErrorGuaranteed> {1104    let impl_generics = tcx.generics_of(impl_m.def_id);1105    let impl_params = impl_generics.own_counts().lifetimes;11061107    let trait_generics = tcx.generics_of(trait_m.def_id);1108    let trait_params = trait_generics.own_counts().lifetimes;11091110    let Err(CheckNumberOfEarlyBoundRegionsError { span, generics_span, bounds_span, where_span }) =1111        check_number_of_early_bound_regions(1112            tcx,1113            impl_m.def_id.expect_local(),1114            trait_m.def_id,1115            impl_generics,1116            impl_params,1117            trait_generics,1118            trait_params,1119        )1120    else {1121        return Ok(());1122    };11231124    if !delay && let Some(guar) = check_region_late_boundedness(tcx, impl_m, trait_m) {1125        return Err(guar);1126    }11271128    let reported = tcx1129        .dcx()1130        .create_err(LifetimesOrBoundsMismatchOnTrait {1131            span,1132            item_kind: impl_m.descr(),1133            ident: impl_m.ident(tcx),1134            generics_span,1135            bounds_span,1136            where_span,1137        })1138        .emit_unless_delay(delay);11391140    Err(reported)1141}11421143pub(super) struct CheckNumberOfEarlyBoundRegionsError {1144    pub(super) span: Span,1145    pub(super) generics_span: Span,1146    pub(super) bounds_span: Vec<Span>,1147    pub(super) where_span: Option<Span>,1148}11491150pub(super) fn check_number_of_early_bound_regions<'tcx>(1151    tcx: TyCtxt<'tcx>,1152    impl_def_id: LocalDefId,1153    trait_def_id: DefId,1154    impl_generics: &Generics,1155    impl_params: usize,1156    trait_generics: &Generics,1157    trait_params: usize,1158) -> Result<(), CheckNumberOfEarlyBoundRegionsError> {1159    debug!(?trait_generics, ?impl_generics);11601161    // Must have same number of early-bound lifetime parameters.1162    // Unfortunately, if the user screws up the bounds, then this1163    // will change classification between early and late. E.g.,1164    // if in trait we have `<'a,'b:'a>`, and in impl we just have1165    // `<'a,'b>`, then we have 2 early-bound lifetime parameters1166    // in trait but 0 in the impl. But if we report "expected 21167    // but found 0" it's confusing, because it looks like there1168    // are zero. Since I don't quite know how to phrase things at1169    // the moment, give a kind of vague error message.1170    if trait_params == impl_params {1171        return Ok(());1172    }11731174    let span = tcx1175        .hir_get_generics(impl_def_id)1176        .expect("expected impl item to have generics or else we can't compare them")1177        .span;11781179    let mut generics_span = tcx.def_span(trait_def_id);1180    let mut bounds_span = vec![];1181    let mut where_span = None;11821183    if let Some(trait_node) = tcx.hir_get_if_local(trait_def_id)1184        && let Some(trait_generics) = trait_node.generics()1185    {1186        generics_span = trait_generics.span;1187        // FIXME: we could potentially look at the impl's bounds to not point at bounds that1188        // *are* present in the impl.1189        for p in trait_generics.predicates {1190            match p.kind {1191                hir::WherePredicateKind::BoundPredicate(hir::WhereBoundPredicate {1192                    bounds,1193                    ..1194                })1195                | hir::WherePredicateKind::RegionPredicate(hir::WhereRegionPredicate {1196                    bounds,1197                    ..1198                }) => {1199                    for b in *bounds {1200                        if let hir::GenericBound::Outlives(lt) = b {1201                            bounds_span.push(lt.ident.span);1202                        }1203                    }1204                }1205                _ => {}1206            }1207        }1208        if let Some(impl_node) = tcx.hir_get_if_local(impl_def_id.into())1209            && let Some(impl_generics) = impl_node.generics()1210        {1211            let mut impl_bounds = 0;1212            for p in impl_generics.predicates {1213                match p.kind {1214                    hir::WherePredicateKind::BoundPredicate(hir::WhereBoundPredicate {1215                        bounds,1216                        ..1217                    })1218                    | hir::WherePredicateKind::RegionPredicate(hir::WhereRegionPredicate {1219                        bounds,1220                        ..1221                    }) => {1222                        for b in *bounds {1223                            if let hir::GenericBound::Outlives(_) = b {1224                                impl_bounds += 1;1225                            }1226                        }1227                    }1228                    _ => {}1229                }1230            }1231            if impl_bounds == bounds_span.len() {1232                bounds_span = vec![];1233            } else if impl_generics.has_where_clause_predicates {1234                where_span = Some(impl_generics.where_clause_span);1235            }1236        }1237    }12381239    Err(CheckNumberOfEarlyBoundRegionsError { span, generics_span, bounds_span, where_span })1240}12411242#[allow(unused)]1243enum LateEarlyMismatch<'tcx> {1244    EarlyInImpl(DefId, DefId, ty::Region<'tcx>),1245    LateInImpl(DefId, DefId, ty::Region<'tcx>),1246}12471248fn check_region_late_boundedness<'tcx>(1249    tcx: TyCtxt<'tcx>,1250    impl_m: ty::AssocItem,1251    trait_m: ty::AssocItem,1252) -> Option<ErrorGuaranteed> {1253    if !impl_m.is_fn() {1254        return None;1255    }12561257    let (infcx, param_env) = tcx1258        .infer_ctxt()1259        .build_with_typing_env(ty::TypingEnv::non_body_analysis(tcx, impl_m.def_id));12601261    let impl_m_args = infcx.fresh_args_for_item(DUMMY_SP, impl_m.def_id);1262    let impl_m_sig = tcx.fn_sig(impl_m.def_id).instantiate(tcx, impl_m_args).skip_norm_wip();1263    let impl_m_sig = tcx.liberate_late_bound_regions(impl_m.def_id, impl_m_sig);12641265    let trait_m_args = infcx.fresh_args_for_item(DUMMY_SP, trait_m.def_id);1266    let trait_m_sig = tcx.fn_sig(trait_m.def_id).instantiate(tcx, trait_m_args).skip_norm_wip();1267    let trait_m_sig = tcx.liberate_late_bound_regions(impl_m.def_id, trait_m_sig);12681269    let ocx = ObligationCtxt::new(&infcx);12701271    // Equate the signatures so that we can infer whether a late-bound param was present where1272    // an early-bound param was expected, since we replace the late-bound lifetimes with1273    // `ReLateParam`, and early-bound lifetimes with infer vars, so the early-bound args will1274    // resolve to `ReLateParam` if there is a mismatch.1275    let Ok(()) = ocx.eq(1276        &ObligationCause::dummy(),1277        param_env,1278        ty::Binder::dummy(trait_m_sig),1279        ty::Binder::dummy(impl_m_sig),1280    ) else {1281        return None;1282    };12831284    let errors = ocx.try_evaluate_obligations();1285    if !errors.is_empty() {1286        return None;1287    }12881289    let mut mismatched = vec![];12901291    let impl_generics = tcx.generics_of(impl_m.def_id);1292    for (id_arg, arg) in1293        std::iter::zip(ty::GenericArgs::identity_for_item(tcx, impl_m.def_id), impl_m_args)1294    {1295        if let ty::GenericArgKind::Lifetime(r) = arg.kind()1296            && let ty::ReVar(vid) = r.kind()1297            && let r = infcx1298                .inner1299                .borrow_mut()1300                .unwrap_region_constraints()1301                .opportunistic_resolve_var(tcx, vid)1302            && let ty::ReLateParam(ty::LateParamRegion {1303                kind: ty::LateParamRegionKind::Named(trait_param_def_id),1304                ..1305            }) = r.kind()1306            && let ty::ReEarlyParam(ebr) = id_arg.expect_region().kind()1307        {1308            mismatched.push(LateEarlyMismatch::EarlyInImpl(1309                impl_generics.region_param(ebr, tcx).def_id,1310                trait_param_def_id,1311                id_arg.expect_region(),1312            ));1313        }1314    }13151316    let trait_generics = tcx.generics_of(trait_m.def_id);1317    for (id_arg, arg) in1318        std::iter::zip(ty::GenericArgs::identity_for_item(tcx, trait_m.def_id), trait_m_args)1319    {1320        if let ty::GenericArgKind::Lifetime(r) = arg.kind()1321            && let ty::ReVar(vid) = r.kind()1322            && let r = infcx1323                .inner1324                .borrow_mut()1325                .unwrap_region_constraints()1326                .opportunistic_resolve_var(tcx, vid)1327            && let ty::ReLateParam(ty::LateParamRegion {1328                kind: ty::LateParamRegionKind::Named(impl_param_def_id),1329                ..1330            }) = r.kind()1331            && let ty::ReEarlyParam(ebr) = id_arg.expect_region().kind()1332        {1333            mismatched.push(LateEarlyMismatch::LateInImpl(1334                impl_param_def_id,1335                trait_generics.region_param(ebr, tcx).def_id,1336                id_arg.expect_region(),1337            ));1338        }1339    }13401341    if mismatched.is_empty() {1342        return None;1343    }13441345    let spans: Vec<_> = mismatched1346        .iter()1347        .map(|param| {1348            let (LateEarlyMismatch::EarlyInImpl(impl_param_def_id, ..)1349            | LateEarlyMismatch::LateInImpl(impl_param_def_id, ..)) = *param;1350            tcx.def_span(impl_param_def_id)1351        })1352        .collect();13531354    let mut diag = tcx1355        .dcx()1356        .struct_span_err(spans, "lifetime parameters do not match the trait definition")1357        .with_note("lifetime parameters differ in whether they are early- or late-bound")1358        .with_code(E0195);1359    for mismatch in mismatched {1360        match mismatch {1361            LateEarlyMismatch::EarlyInImpl(1362                impl_param_def_id,1363                trait_param_def_id,1364                early_bound_region,1365            ) => {1366                let mut multispan = MultiSpan::from_spans(vec![1367                    tcx.def_span(impl_param_def_id),1368                    tcx.def_span(trait_param_def_id),1369                ]);1370                multispan1371                    .push_span_label(tcx.def_span(tcx.parent(impl_m.def_id)), "in this impl...");1372                multispan1373                    .push_span_label(tcx.def_span(tcx.parent(trait_m.def_id)), "in this trait...");1374                multispan.push_span_label(1375                    tcx.def_span(impl_param_def_id),1376                    format!("`{}` is early-bound", tcx.item_name(impl_param_def_id)),1377                );1378                multispan.push_span_label(1379                    tcx.def_span(trait_param_def_id),1380                    format!("`{}` is late-bound", tcx.item_name(trait_param_def_id)),1381                );1382                if let Some(span) =1383                    find_region_in_predicates(tcx, impl_m.def_id, early_bound_region)1384                {1385                    multispan.push_span_label(1386                        span,1387                        format!(1388                            "this lifetime bound makes `{}` early-bound",1389                            tcx.item_name(impl_param_def_id)1390                        ),1391                    );1392                }1393                diag.span_note(1394                    multispan,1395                    format!(1396                        "`{}` differs between the trait and impl",1397                        tcx.item_name(impl_param_def_id)1398                    ),1399                );1400            }1401            LateEarlyMismatch::LateInImpl(1402                impl_param_def_id,1403                trait_param_def_id,1404                early_bound_region,1405            ) => {1406                let mut multispan = MultiSpan::from_spans(vec![1407                    tcx.def_span(impl_param_def_id),1408                    tcx.def_span(trait_param_def_id),1409                ]);1410                multispan1411                    .push_span_label(tcx.def_span(tcx.parent(impl_m.def_id)), "in this impl...");1412                multispan1413                    .push_span_label(tcx.def_span(tcx.parent(trait_m.def_id)), "in this trait...");1414                multispan.push_span_label(1415                    tcx.def_span(impl_param_def_id),1416                    format!("`{}` is late-bound", tcx.item_name(impl_param_def_id)),1417                );1418                multispan.push_span_label(1419                    tcx.def_span(trait_param_def_id),1420                    format!("`{}` is early-bound", tcx.item_name(trait_param_def_id)),1421                );1422                if let Some(span) =1423                    find_region_in_predicates(tcx, trait_m.def_id, early_bound_region)1424                {1425                    multispan.push_span_label(1426                        span,1427                        format!(1428                            "this lifetime bound makes `{}` early-bound",1429                            tcx.item_name(trait_param_def_id)1430                        ),1431                    );1432                }1433                diag.span_note(1434                    multispan,1435                    format!(1436                        "`{}` differs between the trait and impl",1437                        tcx.item_name(impl_param_def_id)1438                    ),1439                );1440            }1441        }1442    }14431444    Some(diag.emit())1445}14461447fn find_region_in_predicates<'tcx>(1448    tcx: TyCtxt<'tcx>,1449    def_id: DefId,1450    early_bound_region: ty::Region<'tcx>,1451) -> Option<Span> {1452    for (pred, span) in tcx.explicit_predicates_of(def_id).instantiate_identity(tcx) {1453        if pred.skip_norm_wip().visit_with(&mut FindRegion(early_bound_region)).is_break() {1454            return Some(span);1455        }1456    }14571458    struct FindRegion<'tcx>(ty::Region<'tcx>);1459    impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for FindRegion<'tcx> {1460        type Result = ControlFlow<()>;1461        fn visit_region(&mut self, r: ty::Region<'tcx>) -> Self::Result {1462            if r == self.0 { ControlFlow::Break(()) } else { ControlFlow::Continue(()) }1463        }1464    }14651466    None1467}14681469#[instrument(level = "debug", skip(infcx))]1470fn extract_spans_for_error_reporting<'tcx>(1471    infcx: &infer::InferCtxt<'tcx>,1472    terr: TypeError<'_>,1473    cause: &ObligationCause<'tcx>,1474    impl_m: ty::AssocItem,1475    trait_m: ty::AssocItem,1476) -> (Span, Option<Span>) {1477    let tcx = infcx.tcx;1478    let mut impl_args = {1479        let (sig, _) = tcx.hir_expect_impl_item(impl_m.def_id.expect_local()).expect_fn();1480        sig.decl.inputs.iter().map(|t| t.span).chain(iter::once(sig.decl.output.span()))1481    };14821483    let trait_args = trait_m.def_id.as_local().map(|def_id| {1484        let (sig, _) = tcx.hir_expect_trait_item(def_id).expect_fn();1485        sig.decl.inputs.iter().map(|t| t.span).chain(iter::once(sig.decl.output.span()))1486    });14871488    match terr {1489        TypeError::ArgumentMutability(i) | TypeError::ArgumentSorts(ExpectedFound { .. }, i) => {1490            (impl_args.nth(i).unwrap(), trait_args.and_then(|mut args| args.nth(i)))1491        }1492        _ => (cause.span, tcx.hir_span_if_local(trait_m.def_id)),1493    }1494}14951496fn compare_self_type<'tcx>(1497    tcx: TyCtxt<'tcx>,1498    impl_m: ty::AssocItem,1499    trait_m: ty::AssocItem,1500    impl_trait_ref: ty::TraitRef<'tcx>,1501    delay: bool,1502) -> Result<(), ErrorGuaranteed> {1503    // Try to give more informative error messages about self typing1504    // mismatches. Note that any mismatch will also be detected1505    // below, where we construct a canonical function type that1506    // includes the self parameter as a normal parameter. It's just1507    // that the error messages you get out of this code are a bit more1508    // inscrutable, particularly for cases where one method has no1509    // self.15101511    let self_string = |method: ty::AssocItem| {1512        let untransformed_self_ty = match method.container {1513            ty::AssocContainer::InherentImpl | ty::AssocContainer::TraitImpl(_) => {1514                impl_trait_ref.self_ty()1515            }1516            ty::AssocContainer::Trait => tcx.types.self_param,1517        };1518        let self_arg_ty = tcx.fn_sig(method.def_id).instantiate_identity().skip_norm_wip().input(0);1519        let (infcx, param_env) = tcx1520            .infer_ctxt()1521            .build_with_typing_env(ty::TypingEnv::non_body_analysis(tcx, method.def_id));1522        let self_arg_ty = tcx.liberate_late_bound_regions(method.def_id, self_arg_ty);1523        let can_eq_self = |ty| infcx.can_eq(param_env, untransformed_self_ty, ty);1524        get_self_string(self_arg_ty, can_eq_self)1525    };15261527    match (trait_m.is_method(), impl_m.is_method()) {1528        (false, false) | (true, true) => {}15291530        (false, true) => {1531            let self_descr = self_string(impl_m);1532            let impl_m_span = tcx.def_span(impl_m.def_id);1533            let mut err = struct_span_code_err!(1534                tcx.dcx(),1535                impl_m_span,1536                E0185,1537                "method `{}` has a `{}` declaration in the impl, but not in the trait",1538                trait_m.name(),1539                self_descr1540            );1541            err.span_label(impl_m_span, format!("`{self_descr}` used in impl"));1542            if let Some(span) = tcx.hir_span_if_local(trait_m.def_id) {1543                err.span_label(span, format!("trait method declared without `{self_descr}`"));1544            } else {1545                err.note_trait_signature(trait_m.name(), trait_m.signature(tcx));1546            }1547            return Err(err.emit_unless_delay(delay));1548        }15491550        (true, false) => {1551            let self_descr = self_string(trait_m);1552            let impl_m_span = tcx.def_span(impl_m.def_id);1553            let mut err = struct_span_code_err!(1554                tcx.dcx(),1555                impl_m_span,1556                E0186,1557                "method `{}` has a `{}` declaration in the trait, but not in the impl",1558                trait_m.name(),1559                self_descr1560            );1561            err.span_label(impl_m_span, format!("expected `{self_descr}` in impl"));1562            if let Some(span) = tcx.hir_span_if_local(trait_m.def_id) {1563                err.span_label(span, format!("`{self_descr}` used in trait"));1564            } else {1565                err.note_trait_signature(trait_m.name(), trait_m.signature(tcx));1566            }15671568            return Err(err.emit_unless_delay(delay));1569        }1570    }15711572    Ok(())1573}15741575/// Checks that the number of generics on a given assoc item in a trait impl is the same1576/// as the number of generics on the respective assoc item in the trait definition.1577///1578/// For example this code emits the errors in the following code:1579/// ```rust,compile_fail1580/// trait Trait {1581///     fn foo();1582///     type Assoc<T>;1583/// }1584///1585/// impl Trait for () {1586///     fn foo<T>() {}1587///     //~^ error1588///     type Assoc = u32;1589///     //~^ error1590/// }1591/// ```1592///1593/// Notably this does not error on `foo<T>` implemented as `foo<const N: u8>` or1594/// `foo<const N: u8>` implemented as `foo<const N: u32>`. This is handled in1595/// [`compare_generic_param_kinds`]. This function also does not handle lifetime parameters1596fn compare_number_of_generics<'tcx>(1597    tcx: TyCtxt<'tcx>,1598    impl_: ty::AssocItem,1599    trait_: ty::AssocItem,1600    delay: bool,1601) -> Result<(), ErrorGuaranteed> {1602    let trait_own_counts = tcx.generics_of(trait_.def_id).own_counts();1603    let impl_own_counts = tcx.generics_of(impl_.def_id).own_counts();16041605    // This avoids us erroring on `foo<T>` implemented as `foo<const N: u8>` as this is implemented1606    // in `compare_generic_param_kinds` which will give a nicer error message than something like:1607    // "expected 1 type parameter, found 0 type parameters"1608    if (trait_own_counts.types + trait_own_counts.consts)1609        == (impl_own_counts.types + impl_own_counts.consts)1610    {1611        return Ok(());1612    }16131614    // We never need to emit a separate error for RPITITs, since if an RPITIT1615    // has mismatched type or const generic arguments, then the method that it's1616    // inheriting the generics from will also have mismatched arguments, and1617    // we'll report an error for that instead. Delay a bug for safety, though.1618    if trait_.is_impl_trait_in_trait() {1619        // FIXME: no tests trigger this. If you find example code that does1620        // trigger this, please add it to the test suite.1621        tcx.dcx()1622            .bug("errors comparing numbers of generics of trait/impl functions were not emitted");1623    }16241625    let matchings = [1626        ("type", trait_own_counts.types, impl_own_counts.types),1627        ("const", trait_own_counts.consts, impl_own_counts.consts),1628    ];16291630    let item_kind = impl_.descr();16311632    let mut err_occurred = None;1633    for (kind, trait_count, impl_count) in matchings {1634        if impl_count != trait_count {1635            let arg_spans = |item: &ty::AssocItem, generics: &hir::Generics<'_>| {1636                let mut spans = generics1637                    .params1638                    .iter()1639                    .filter(|p| match p.kind {1640                        hir::GenericParamKind::Lifetime {1641                            kind: hir::LifetimeParamKind::Elided(_),1642                        } => {1643                            // A fn can have an arbitrary number of extra elided lifetimes for the1644                            // same signature.1645                            !item.is_fn()1646                        }1647                        _ => true,1648                    })1649                    .map(|p| p.span)1650                    .collect::<Vec<Span>>();1651                if spans.is_empty() {1652                    spans = vec![generics.span]1653                }1654                spans1655            };1656            let (trait_spans, impl_trait_spans) = if let Some(def_id) = trait_.def_id.as_local() {1657                let trait_item = tcx.hir_expect_trait_item(def_id);1658                let arg_spans: Vec<Span> = arg_spans(&trait_, trait_item.generics);1659                let impl_trait_spans: Vec<Span> = trait_item1660                    .generics1661                    .params1662                    .iter()1663                    .filter_map(|p| match p.kind {1664                        GenericParamKind::Type { synthetic: true, .. } => Some(p.span),1665                        _ => None,1666                    })1667                    .collect();1668                (Some(arg_spans), impl_trait_spans)1669            } else {1670                let trait_span = tcx.hir_span_if_local(trait_.def_id);1671                (trait_span.map(|s| vec![s]), vec![])1672            };16731674            let impl_item = tcx.hir_expect_impl_item(impl_.def_id.expect_local());1675            let impl_item_impl_trait_spans: Vec<Span> = impl_item1676                .generics1677                .params1678                .iter()1679                .filter_map(|p| match p.kind {1680                    GenericParamKind::Type { synthetic: true, .. } => Some(p.span),1681                    _ => None,1682                })1683                .collect();1684            let spans = arg_spans(&impl_, impl_item.generics);1685            let span = spans.first().copied();16861687            let mut err = tcx.dcx().struct_span_err(1688                spans,1689                format!(1690                    "{} `{}` has {} {kind} parameter{} but its trait \1691                     declaration has {} {kind} parameter{}",1692                    item_kind,1693                    trait_.name(),1694                    impl_count,1695                    pluralize!(impl_count),1696                    trait_count,1697                    pluralize!(trait_count),1698                    kind = kind,1699                ),1700            );1701            err.code(E0049);17021703            let msg =1704                format!("expected {trait_count} {kind} parameter{}", pluralize!(trait_count),);1705            if let Some(spans) = trait_spans {1706                let mut spans = spans.iter();1707                if let Some(span) = spans.next() {1708                    err.span_label(*span, msg);1709                }1710                for span in spans {1711                    err.span_label(*span, "");1712                }1713            } else {1714                err.span_label(tcx.def_span(trait_.def_id), msg);1715            }17161717            if let Some(span) = span {1718                err.span_label(1719                    span,1720                    format!("found {} {} parameter{}", impl_count, kind, pluralize!(impl_count),),1721                );1722            }17231724            for span in impl_trait_spans.iter().chain(impl_item_impl_trait_spans.iter()) {1725                err.span_label(*span, "`impl Trait` introduces an implicit type parameter");1726            }17271728            let reported = err.emit_unless_delay(delay);1729            err_occurred = Some(reported);1730        }1731    }17321733    if let Some(reported) = err_occurred { Err(reported) } else { Ok(()) }1734}17351736fn compare_number_of_method_arguments<'tcx>(1737    tcx: TyCtxt<'tcx>,1738    impl_m: ty::AssocItem,1739    trait_m: ty::AssocItem,1740    delay: bool,1741) -> Result<(), ErrorGuaranteed> {1742    let impl_m_fty = tcx.fn_sig(impl_m.def_id);1743    let trait_m_fty = tcx.fn_sig(trait_m.def_id);1744    let trait_number_args = trait_m_fty.skip_binder().inputs().skip_binder().len();1745    let impl_number_args = impl_m_fty.skip_binder().inputs().skip_binder().len();17461747    if trait_number_args != impl_number_args {1748        let trait_span = trait_m1749            .def_id1750            .as_local()1751            .and_then(|def_id| {1752                let (trait_m_sig, _) = &tcx.hir_expect_trait_item(def_id).expect_fn();1753                let pos = trait_number_args.saturating_sub(1);1754                trait_m_sig.decl.inputs.get(pos).map(|arg| {1755                    if pos == 0 {1756                        arg.span1757                    } else {1758                        arg.span.with_lo(trait_m_sig.decl.inputs[0].span.lo())1759                    }1760                })1761            })1762            .or_else(|| tcx.hir_span_if_local(trait_m.def_id));17631764        let (impl_m_sig, _) = &tcx.hir_expect_impl_item(impl_m.def_id.expect_local()).expect_fn();1765        let pos = impl_number_args.saturating_sub(1);1766        let impl_span = impl_m_sig1767            .decl1768            .inputs1769            .get(pos)1770            .map(|arg| {1771                if pos == 0 {1772                    arg.span1773                } else {1774                    arg.span.with_lo(impl_m_sig.decl.inputs[0].span.lo())1775                }1776            })1777            .unwrap_or_else(|| tcx.def_span(impl_m.def_id));17781779        let mut err = struct_span_code_err!(1780            tcx.dcx(),1781            impl_span,1782            E0050,1783            "method `{}` has {} but the declaration in trait `{}` has {}",1784            trait_m.name(),1785            potentially_plural_count(impl_number_args, "parameter"),1786            tcx.def_path_str(trait_m.def_id),1787            trait_number_args1788        );17891790        if let Some(trait_span) = trait_span {1791            err.span_label(1792                trait_span,1793                format!(1794                    "trait requires {}",1795                    potentially_plural_count(trait_number_args, "parameter")1796                ),1797            );1798        } else {1799            err.note_trait_signature(trait_m.name(), trait_m.signature(tcx));1800        }18011802        err.span_label(1803            impl_span,1804            format!(1805                "expected {}, found {}",1806                potentially_plural_count(trait_number_args, "parameter"),1807                impl_number_args1808            ),1809        );18101811        // Only emit verbose suggestions when the trait span isn’t local (e.g., cross-crate).1812        if !trait_m.def_id.is_local() {1813            let trait_sig = tcx.fn_sig(trait_m.def_id);1814            let trait_arg_idents = tcx.fn_arg_idents(trait_m.def_id);1815            let sm = tcx.sess.source_map();1816            // Find the span of the space between the parentheses in a method.1817            // fn foo(...) {}1818            //        ^^^1819            let impl_inputs_span = if let (Some(first), Some(last)) =1820                (impl_m_sig.decl.inputs.first(), impl_m_sig.decl.inputs.last())1821            {1822                // We have inputs; construct the span from those.1823                // fn foo( a: i32, b: u32 ) {}1824                //        ^^^^^^^^^^^^^^^^1825                let arg_idents = tcx.fn_arg_idents(impl_m.def_id);1826                let first_lo = arg_idents1827                    .get(0)1828                    .and_then(|id| id.map(|id| id.span.lo()))1829                    .unwrap_or(first.span.lo());1830                Some(impl_m_sig.span.with_lo(first_lo).with_hi(last.span.hi()))1831            } else {1832                // We have no inputs; construct the span to the left of the last parenthesis1833                // fn foo( ) {}1834                //        ^1835                // FIXME: Keep spans for function parentheses around to make this more robust.1836                sm.span_to_snippet(impl_m_sig.span).ok().and_then(|s| {1837                    let right_paren = s.as_bytes().iter().rposition(|&b| b == b')')?;1838                    let pos = impl_m_sig.span.lo() + BytePos(right_paren as u32);1839                    Some(impl_m_sig.span.with_lo(pos).with_hi(pos))1840                })1841            };1842            let suggestion = match trait_number_args.cmp(&impl_number_args) {1843                Ordering::Greater => {1844                    // Span is right before the end parenthesis:1845                    // fn foo(a: i32 ) {}1846                    //              ^1847                    let trait_inputs = trait_sig.skip_binder().inputs().skip_binder();1848                    let missing = trait_inputs1849                        .iter()1850                        .enumerate()1851                        .skip(impl_number_args)1852                        .map(|(idx, ty)| {1853                            let name = trait_arg_idents1854                                .get(idx)1855                                .and_then(|ident| *ident)1856                                .map(|ident| ident.to_string())1857                                .unwrap_or_else(|| "_".to_string());1858                            format!("{name}: {ty}")1859                        })1860                        .collect::<Vec<_>>();18611862                    if missing.is_empty() {1863                        None1864                    } else {1865                        impl_inputs_span.map(|s| {1866                            let span = s.shrink_to_hi();1867                            let prefix = if impl_number_args == 0 { "" } else { ", " };1868                            let replacement = format!("{prefix}{}", missing.join(", "));1869                            (1870                                span,1871                                format!(1872                                    "add the missing parameter{} from the trait",1873                                    pluralize!(trait_number_args - impl_number_args)1874                                ),1875                                replacement,1876                            )1877                        })1878                    }1879                }1880                Ordering::Less => impl_inputs_span.and_then(|full| {1881                    // Span of the arguments that there are too many of:1882                    // fn foo(a: i32, b: u32) {}1883                    //              ^^^^^^^^1884                    let lo = if trait_number_args == 0 {1885                        full.lo()1886                    } else {1887                        impl_m_sig1888                            .decl1889                            .inputs1890                            .get(trait_number_args - 1)1891                            .map(|arg| arg.span.hi())?1892                    };1893                    let span = full.with_lo(lo);1894                    Some((1895                        span,1896                        format!(1897                            "remove the extra parameter{} to match the trait",1898                            pluralize!(impl_number_args - trait_number_args)1899                        ),1900                        String::new(),1901                    ))1902                }),1903                Ordering::Equal => unreachable!(),1904            };1905            if let Some((span, msg, replacement)) = suggestion {1906                err.span_suggestion_verbose(span, msg, replacement, Applicability::MaybeIncorrect);1907            }1908        }19091910        return Err(err.emit_unless_delay(delay));1911    }19121913    Ok(())1914}19151916fn compare_synthetic_generics<'tcx>(1917    tcx: TyCtxt<'tcx>,1918    impl_m: ty::AssocItem,1919    trait_m: ty::AssocItem,1920    delay: bool,1921) -> Result<(), ErrorGuaranteed> {1922    // FIXME(chrisvittal) Clean up this function, list of FIXME items:1923    //     1. Better messages for the span labels1924    //     2. Explanation as to what is going on1925    // If we get here, we already have the same number of generics, so the zip will1926    // be okay.1927    let mut error_found = None;1928    let impl_m_generics = tcx.generics_of(impl_m.def_id);1929    let trait_m_generics = tcx.generics_of(trait_m.def_id);1930    let impl_m_type_params =1931        impl_m_generics.own_params.iter().filter_map(|param| match param.kind {1932            GenericParamDefKind::Type { synthetic, .. } => Some((param.def_id, synthetic)),1933            GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => None,1934        });1935    let trait_m_type_params =1936        trait_m_generics.own_params.iter().filter_map(|param| match param.kind {1937            GenericParamDefKind::Type { synthetic, .. } => Some((param.def_id, synthetic)),1938            GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => None,1939        });1940    for ((impl_def_id, impl_synthetic), (trait_def_id, trait_synthetic)) in1941        iter::zip(impl_m_type_params, trait_m_type_params)1942    {1943        if impl_synthetic != trait_synthetic {1944            let impl_def_id = impl_def_id.expect_local();1945            let impl_span = tcx.def_span(impl_def_id);1946            let trait_span = tcx.def_span(trait_def_id);1947            let mut err = struct_span_code_err!(1948                tcx.dcx(),1949                impl_span,1950                E0643,1951                "method `{}` has incompatible signature for trait",1952                trait_m.name()1953            );1954            err.span_label(trait_span, "declaration in trait here");1955            if impl_synthetic {1956                // The case where the impl method uses `impl Trait` but the trait method uses1957                // explicit generics1958                err.span_label(impl_span, "expected generic parameter, found `impl Trait`");1959                try {1960                    // try taking the name from the trait impl1961                    // FIXME: this is obviously suboptimal since the name can already be used1962                    // as another generic argument1963                    let new_name = tcx.opt_item_name(trait_def_id)?;1964                    let trait_m = trait_m.def_id.as_local()?;1965                    let trait_m = tcx.hir_expect_trait_item(trait_m);19661967                    let impl_m = impl_m.def_id.as_local()?;1968                    let impl_m = tcx.hir_expect_impl_item(impl_m);19691970                    // in case there are no generics, take the spot between the function name1971                    // and the opening paren of the argument list1972                    let new_generics_span = tcx.def_ident_span(impl_def_id)?.shrink_to_hi();1973                    // in case there are generics, just replace them1974                    let generics_span = impl_m.generics.span.substitute_dummy(new_generics_span);1975                    // replace with the generics from the trait1976                    let new_generics =1977                        tcx.sess.source_map().span_to_snippet(trait_m.generics.span).ok()?;19781979                    err.multipart_suggestion(1980                        "try changing the `impl Trait` argument to a generic parameter",1981                        vec![1982                            // replace `impl Trait` with `T`1983                            (impl_span, new_name.to_string()),1984                            // replace impl method generics with trait method generics1985                            // This isn't quite right, as users might have changed the names1986                            // of the generics, but it works for the common case1987                            (generics_span, new_generics),1988                        ],1989                        Applicability::MaybeIncorrect,1990                    );1991                };1992            } else {1993                // The case where the trait method uses `impl Trait`, but the impl method uses1994                // explicit generics.1995                err.span_label(impl_span, "expected `impl Trait`, found generic parameter");1996                try {1997                    let impl_m = impl_m.def_id.as_local()?;1998                    let impl_m = tcx.hir_expect_impl_item(impl_m);1999                    let (sig, _) = impl_m.expect_fn();2000                    let input_tys = sig.decl.inputs;

Findings

✓ No findings reported for this file.

Get this view in your editor

Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.