rustc_hir_analysis/check/
compare_impl_item.rs

1use core::ops::ControlFlow;
2use std::borrow::Cow;
3use std::iter;
4
5use hir::def_id::{DefId, DefIdMap, LocalDefId};
6use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
7use rustc_errors::codes::*;
8use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan, pluralize, struct_span_code_err};
9use rustc_hir::def::{DefKind, Res};
10use rustc_hir::intravisit::VisitorExt;
11use rustc_hir::{self as hir, AmbigArg, GenericParamKind, ImplItemKind, intravisit};
12use rustc_infer::infer::{self, BoundRegionConversionTime, InferCtxt, TyCtxtInferExt};
13use rustc_infer::traits::util;
14use rustc_middle::ty::error::{ExpectedFound, TypeError};
15use rustc_middle::ty::{
16    self, BottomUpFolder, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeFoldable, TypeFolder,
17    TypeSuperFoldable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, Upcast,
18};
19use rustc_middle::{bug, span_bug};
20use rustc_span::{DUMMY_SP, Span};
21use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
22use rustc_trait_selection::infer::InferCtxtExt;
23use rustc_trait_selection::regions::InferCtxtRegionExt;
24use rustc_trait_selection::traits::{
25    self, FulfillmentError, ObligationCause, ObligationCauseCode, ObligationCtxt,
26};
27use tracing::{debug, instrument};
28
29use super::potentially_plural_count;
30use crate::errors::{LifetimesOrBoundsMismatchOnTrait, MethodShouldReturnFuture};
31
32pub(super) mod refine;
33
34/// Call the query `tcx.compare_impl_item()` directly instead.
35pub(super) fn compare_impl_item(
36    tcx: TyCtxt<'_>,
37    impl_item_def_id: LocalDefId,
38) -> Result<(), ErrorGuaranteed> {
39    let impl_item = tcx.associated_item(impl_item_def_id);
40    let trait_item = tcx.associated_item(impl_item.expect_trait_impl()?);
41    let impl_trait_ref =
42        tcx.impl_trait_ref(impl_item.container_id(tcx)).unwrap().instantiate_identity();
43    debug!(?impl_trait_ref);
44
45    match impl_item.kind {
46        ty::AssocKind::Fn { .. } => compare_impl_method(tcx, impl_item, trait_item, impl_trait_ref),
47        ty::AssocKind::Type { .. } => compare_impl_ty(tcx, impl_item, trait_item, impl_trait_ref),
48        ty::AssocKind::Const { .. } => {
49            compare_impl_const(tcx, impl_item, trait_item, impl_trait_ref)
50        }
51    }
52}
53
54/// Checks that a method from an impl conforms to the signature of
55/// the same method as declared in the trait.
56///
57/// # Parameters
58///
59/// - `impl_m`: type of the method we are checking
60/// - `trait_m`: the method in the trait
61/// - `impl_trait_ref`: the TraitRef corresponding to the trait implementation
62#[instrument(level = "debug", skip(tcx))]
63fn compare_impl_method<'tcx>(
64    tcx: TyCtxt<'tcx>,
65    impl_m: ty::AssocItem,
66    trait_m: ty::AssocItem,
67    impl_trait_ref: ty::TraitRef<'tcx>,
68) -> Result<(), ErrorGuaranteed> {
69    check_method_is_structurally_compatible(tcx, impl_m, trait_m, impl_trait_ref, false)?;
70    compare_method_predicate_entailment(tcx, impl_m, trait_m, impl_trait_ref)?;
71    Ok(())
72}
73
74/// Checks a bunch of different properties of the impl/trait methods for
75/// compatibility, such as asyncness, number of argument, self receiver kind,
76/// and number of early- and late-bound generics.
77fn check_method_is_structurally_compatible<'tcx>(
78    tcx: TyCtxt<'tcx>,
79    impl_m: ty::AssocItem,
80    trait_m: ty::AssocItem,
81    impl_trait_ref: ty::TraitRef<'tcx>,
82    delay: bool,
83) -> Result<(), ErrorGuaranteed> {
84    compare_self_type(tcx, impl_m, trait_m, impl_trait_ref, delay)?;
85    compare_number_of_generics(tcx, impl_m, trait_m, delay)?;
86    compare_generic_param_kinds(tcx, impl_m, trait_m, delay)?;
87    compare_number_of_method_arguments(tcx, impl_m, trait_m, delay)?;
88    compare_synthetic_generics(tcx, impl_m, trait_m, delay)?;
89    check_region_bounds_on_impl_item(tcx, impl_m, trait_m, delay)?;
90    Ok(())
91}
92
93/// This function is best explained by example. Consider a trait with its implementation:
94///
95/// ```rust
96/// trait Trait<'t, T> {
97///     // `trait_m`
98///     fn method<'a, M>(t: &'t T, m: &'a M) -> Self;
99/// }
100///
101/// struct Foo;
102///
103/// impl<'i, 'j, U> Trait<'j, &'i U> for Foo {
104///     // `impl_m`
105///     fn method<'b, N>(t: &'j &'i U, m: &'b N) -> Foo { Foo }
106/// }
107/// ```
108///
109/// We wish to decide if those two method types are compatible.
110/// For this we have to show that, assuming the bounds of the impl hold, the
111/// bounds of `trait_m` imply the bounds of `impl_m`.
112///
113/// We start out with `trait_to_impl_args`, that maps the trait
114/// type parameters to impl type parameters. This is taken from the
115/// impl trait reference:
116///
117/// ```rust,ignore (pseudo-Rust)
118/// trait_to_impl_args = {'t => 'j, T => &'i U, Self => Foo}
119/// ```
120///
121/// We create a mapping `dummy_args` that maps from the impl type
122/// parameters to fresh types and regions. For type parameters,
123/// this is the identity transform, but we could as well use any
124/// placeholder types. For regions, we convert from bound to free
125/// regions (Note: but only early-bound regions, i.e., those
126/// declared on the impl or used in type parameter bounds).
127///
128/// ```rust,ignore (pseudo-Rust)
129/// impl_to_placeholder_args = {'i => 'i0, U => U0, N => N0 }
130/// ```
131///
132/// Now we can apply `placeholder_args` to the type of the impl method
133/// to yield a new function type in terms of our fresh, placeholder
134/// types:
135///
136/// ```rust,ignore (pseudo-Rust)
137/// <'b> fn(t: &'i0 U0, m: &'b N0) -> Foo
138/// ```
139///
140/// We now want to extract and instantiate the type of the *trait*
141/// method and compare it. To do so, we must create a compound
142/// instantiation by combining `trait_to_impl_args` and
143/// `impl_to_placeholder_args`, and also adding a mapping for the method
144/// type parameters. We extend the mapping to also include
145/// the method parameters.
146///
147/// ```rust,ignore (pseudo-Rust)
148/// trait_to_placeholder_args = { T => &'i0 U0, Self => Foo, M => N0 }
149/// ```
150///
151/// Applying this to the trait method type yields:
152///
153/// ```rust,ignore (pseudo-Rust)
154/// <'a> fn(t: &'i0 U0, m: &'a N0) -> Foo
155/// ```
156///
157/// This type is also the same but the name of the bound region (`'a`
158/// vs `'b`). However, the normal subtyping rules on fn types handle
159/// this kind of equivalency just fine.
160///
161/// We now use these generic parameters to ensure that all declared bounds
162/// are satisfied by the implementation's method.
163///
164/// We do this by creating a parameter environment which contains a
165/// generic parameter corresponding to `impl_to_placeholder_args`. We then build
166/// `trait_to_placeholder_args` and use it to convert the predicates contained
167/// in the `trait_m` generics to the placeholder form.
168///
169/// Finally we register each of these predicates as an obligation and check that
170/// they hold.
171#[instrument(level = "debug", skip(tcx, impl_trait_ref))]
172fn compare_method_predicate_entailment<'tcx>(
173    tcx: TyCtxt<'tcx>,
174    impl_m: ty::AssocItem,
175    trait_m: ty::AssocItem,
176    impl_trait_ref: ty::TraitRef<'tcx>,
177) -> Result<(), ErrorGuaranteed> {
178    // This node-id should be used for the `body_id` field on each
179    // `ObligationCause` (and the `FnCtxt`).
180    //
181    // FIXME(@lcnr): remove that after removing `cause.body_id` from
182    // obligations.
183    let impl_m_def_id = impl_m.def_id.expect_local();
184    let impl_m_span = tcx.def_span(impl_m_def_id);
185    let cause = ObligationCause::new(
186        impl_m_span,
187        impl_m_def_id,
188        ObligationCauseCode::CompareImplItem {
189            impl_item_def_id: impl_m_def_id,
190            trait_item_def_id: trait_m.def_id,
191            kind: impl_m.kind,
192        },
193    );
194
195    // Create mapping from trait method to impl method.
196    let impl_def_id = impl_m.container_id(tcx);
197    let trait_to_impl_args = GenericArgs::identity_for_item(tcx, impl_m.def_id).rebase_onto(
198        tcx,
199        impl_m.container_id(tcx),
200        impl_trait_ref.args,
201    );
202    debug!(?trait_to_impl_args);
203
204    let impl_m_predicates = tcx.predicates_of(impl_m.def_id);
205    let trait_m_predicates = tcx.predicates_of(trait_m.def_id);
206
207    // This is the only tricky bit of the new way we check implementation methods
208    // We need to build a set of predicates where only the method-level bounds
209    // are from the trait and we assume all other bounds from the implementation
210    // to be previously satisfied.
211    //
212    // We then register the obligations from the impl_m and check to see
213    // if all constraints hold.
214    let impl_predicates = tcx.predicates_of(impl_m_predicates.parent.unwrap());
215    let mut hybrid_preds = impl_predicates.instantiate_identity(tcx).predicates;
216    hybrid_preds.extend(
217        trait_m_predicates.instantiate_own(tcx, trait_to_impl_args).map(|(predicate, _)| predicate),
218    );
219
220    let is_conditionally_const = tcx.is_conditionally_const(impl_def_id);
221    if is_conditionally_const {
222        // Augment the hybrid param-env with the const conditions
223        // of the impl header and the trait method.
224        hybrid_preds.extend(
225            tcx.const_conditions(impl_def_id)
226                .instantiate_identity(tcx)
227                .into_iter()
228                .chain(
229                    tcx.const_conditions(trait_m.def_id).instantiate_own(tcx, trait_to_impl_args),
230                )
231                .map(|(trait_ref, _)| {
232                    trait_ref.to_host_effect_clause(tcx, ty::BoundConstness::Maybe)
233                }),
234        );
235    }
236
237    let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_def_id);
238    let param_env = ty::ParamEnv::new(tcx.mk_clauses(&hybrid_preds));
239    let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause);
240    debug!(caller_bounds=?param_env.caller_bounds());
241
242    let infcx = &tcx.infer_ctxt().build(TypingMode::non_body_analysis());
243    let ocx = ObligationCtxt::new_with_diagnostics(infcx);
244
245    // Create obligations for each predicate declared by the impl
246    // definition in the context of the hybrid param-env. This makes
247    // sure that the impl's method's where clauses are not more
248    // restrictive than the trait's method (and the impl itself).
249    let impl_m_own_bounds = impl_m_predicates.instantiate_own_identity();
250    for (predicate, span) in impl_m_own_bounds {
251        let normalize_cause = traits::ObligationCause::misc(span, impl_m_def_id);
252        let predicate = ocx.normalize(&normalize_cause, param_env, predicate);
253
254        let cause = ObligationCause::new(
255            span,
256            impl_m_def_id,
257            ObligationCauseCode::CompareImplItem {
258                impl_item_def_id: impl_m_def_id,
259                trait_item_def_id: trait_m.def_id,
260                kind: impl_m.kind,
261            },
262        );
263        ocx.register_obligation(traits::Obligation::new(tcx, cause, param_env, predicate));
264    }
265
266    // If we're within a const implementation, we need to make sure that the method
267    // does not assume stronger `[const]` bounds than the trait definition.
268    //
269    // This registers the `[const]` bounds of the impl method, which we will prove
270    // using the hybrid param-env that we earlier augmented with the const conditions
271    // from the impl header and trait method declaration.
272    if is_conditionally_const {
273        for (const_condition, span) in
274            tcx.const_conditions(impl_m.def_id).instantiate_own_identity()
275        {
276            let normalize_cause = traits::ObligationCause::misc(span, impl_m_def_id);
277            let const_condition = ocx.normalize(&normalize_cause, param_env, const_condition);
278
279            let cause = ObligationCause::new(
280                span,
281                impl_m_def_id,
282                ObligationCauseCode::CompareImplItem {
283                    impl_item_def_id: impl_m_def_id,
284                    trait_item_def_id: trait_m.def_id,
285                    kind: impl_m.kind,
286                },
287            );
288            ocx.register_obligation(traits::Obligation::new(
289                tcx,
290                cause,
291                param_env,
292                const_condition.to_host_effect_clause(tcx, ty::BoundConstness::Maybe),
293            ));
294        }
295    }
296
297    // We now need to check that the signature of the impl method is
298    // compatible with that of the trait method. We do this by
299    // checking that `impl_fty <: trait_fty`.
300    //
301    // FIXME: We manually instantiate the trait method here as we need
302    // to manually compute its implied bounds. Otherwise this could just
303    // be `ocx.sub(impl_sig, trait_sig)`.
304
305    let mut wf_tys = FxIndexSet::default();
306
307    let unnormalized_impl_sig = infcx.instantiate_binder_with_fresh_vars(
308        impl_m_span,
309        BoundRegionConversionTime::HigherRankedType,
310        tcx.fn_sig(impl_m.def_id).instantiate_identity(),
311    );
312
313    let norm_cause = ObligationCause::misc(impl_m_span, impl_m_def_id);
314    let impl_sig = ocx.normalize(&norm_cause, param_env, unnormalized_impl_sig);
315    debug!(?impl_sig);
316
317    let trait_sig = tcx.fn_sig(trait_m.def_id).instantiate(tcx, trait_to_impl_args);
318    let trait_sig = tcx.liberate_late_bound_regions(impl_m.def_id, trait_sig);
319
320    // Next, add all inputs and output as well-formed tys. Importantly,
321    // we have to do this before normalization, since the normalized ty may
322    // not contain the input parameters. See issue #87748.
323    wf_tys.extend(trait_sig.inputs_and_output.iter());
324    let trait_sig = ocx.normalize(&norm_cause, param_env, trait_sig);
325    // We also have to add the normalized trait signature
326    // as we don't normalize during implied bounds computation.
327    wf_tys.extend(trait_sig.inputs_and_output.iter());
328    debug!(?trait_sig);
329
330    // FIXME: We'd want to keep more accurate spans than "the method signature" when
331    // processing the comparison between the trait and impl fn, but we sadly lose them
332    // and point at the whole signature when a trait bound or specific input or output
333    // type would be more appropriate. In other places we have a `Vec<Span>`
334    // corresponding to their `Vec<Predicate>`, but we don't have that here.
335    // Fixing this would improve the output of test `issue-83765.rs`.
336    let result = ocx.sup(&cause, param_env, trait_sig, impl_sig);
337
338    if let Err(terr) = result {
339        debug!(?impl_sig, ?trait_sig, ?terr, "sub_types failed");
340
341        let emitted = report_trait_method_mismatch(
342            infcx,
343            cause,
344            param_env,
345            terr,
346            (trait_m, trait_sig),
347            (impl_m, impl_sig),
348            impl_trait_ref,
349        );
350        return Err(emitted);
351    }
352
353    if !(impl_sig, trait_sig).references_error() {
354        for ty in unnormalized_impl_sig.inputs_and_output {
355            ocx.register_obligation(traits::Obligation::new(
356                infcx.tcx,
357                cause.clone(),
358                param_env,
359                ty::ClauseKind::WellFormed(ty.into()),
360            ));
361        }
362    }
363
364    // Check that all obligations are satisfied by the implementation's
365    // version.
366    let errors = ocx.select_all_or_error();
367    if !errors.is_empty() {
368        let reported = infcx.err_ctxt().report_fulfillment_errors(errors);
369        return Err(reported);
370    }
371
372    // Finally, resolve all regions. This catches wily misuses of
373    // lifetime parameters.
374    let errors = infcx.resolve_regions(impl_m_def_id, param_env, wf_tys);
375    if !errors.is_empty() {
376        return Err(infcx
377            .tainted_by_errors()
378            .unwrap_or_else(|| infcx.err_ctxt().report_region_errors(impl_m_def_id, &errors)));
379    }
380
381    Ok(())
382}
383
384struct RemapLateParam<'tcx> {
385    tcx: TyCtxt<'tcx>,
386    mapping: FxIndexMap<ty::LateParamRegionKind, ty::LateParamRegionKind>,
387}
388
389impl<'tcx> TypeFolder<TyCtxt<'tcx>> for RemapLateParam<'tcx> {
390    fn cx(&self) -> TyCtxt<'tcx> {
391        self.tcx
392    }
393
394    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
395        if let ty::ReLateParam(fr) = r.kind() {
396            ty::Region::new_late_param(
397                self.tcx,
398                fr.scope,
399                self.mapping.get(&fr.kind).copied().unwrap_or(fr.kind),
400            )
401        } else {
402            r
403        }
404    }
405}
406
407/// Given a method def-id in an impl, compare the method signature of the impl
408/// against the trait that it's implementing. In doing so, infer the hidden types
409/// that this method's signature provides to satisfy each return-position `impl Trait`
410/// in the trait signature.
411///
412/// The method is also responsible for making sure that the hidden types for each
413/// RPITIT actually satisfy the bounds of the `impl Trait`, i.e. that if we infer
414/// `impl Trait = Foo`, that `Foo: Trait` holds.
415///
416/// For example, given the sample code:
417///
418/// ```
419/// use std::ops::Deref;
420///
421/// trait Foo {
422///     fn bar() -> impl Deref<Target = impl Sized>;
423///     //          ^- RPITIT #1        ^- RPITIT #2
424/// }
425///
426/// impl Foo for () {
427///     fn bar() -> Box<String> { Box::new(String::new()) }
428/// }
429/// ```
430///
431/// The hidden types for the RPITITs in `bar` would be inferred to:
432///     * `impl Deref` (RPITIT #1) = `Box<String>`
433///     * `impl Sized` (RPITIT #2) = `String`
434///
435/// The relationship between these two types is straightforward in this case, but
436/// may be more tenuously connected via other `impl`s and normalization rules for
437/// cases of more complicated nested RPITITs.
438#[instrument(skip(tcx), level = "debug", ret)]
439pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
440    tcx: TyCtxt<'tcx>,
441    impl_m_def_id: LocalDefId,
442) -> Result<&'tcx DefIdMap<ty::EarlyBinder<'tcx, Ty<'tcx>>>, ErrorGuaranteed> {
443    let impl_m = tcx.associated_item(impl_m_def_id.to_def_id());
444    let trait_m = tcx.associated_item(impl_m.expect_trait_impl()?);
445    let impl_trait_ref =
446        tcx.impl_trait_ref(tcx.parent(impl_m_def_id.to_def_id())).unwrap().instantiate_identity();
447    // First, check a few of the same things as `compare_impl_method`,
448    // just so we don't ICE during instantiation later.
449    check_method_is_structurally_compatible(tcx, impl_m, trait_m, impl_trait_ref, true)?;
450
451    let impl_m_hir_id = tcx.local_def_id_to_hir_id(impl_m_def_id);
452    let return_span = tcx.hir_fn_decl_by_hir_id(impl_m_hir_id).unwrap().output.span();
453    let cause = ObligationCause::new(
454        return_span,
455        impl_m_def_id,
456        ObligationCauseCode::CompareImplItem {
457            impl_item_def_id: impl_m_def_id,
458            trait_item_def_id: trait_m.def_id,
459            kind: impl_m.kind,
460        },
461    );
462
463    // Create mapping from trait to impl (i.e. impl trait header + impl method identity args).
464    let trait_to_impl_args = GenericArgs::identity_for_item(tcx, impl_m.def_id).rebase_onto(
465        tcx,
466        impl_m.container_id(tcx),
467        impl_trait_ref.args,
468    );
469
470    let hybrid_preds = tcx
471        .predicates_of(impl_m.container_id(tcx))
472        .instantiate_identity(tcx)
473        .into_iter()
474        .chain(tcx.predicates_of(trait_m.def_id).instantiate_own(tcx, trait_to_impl_args))
475        .map(|(clause, _)| clause);
476    let param_env = ty::ParamEnv::new(tcx.mk_clauses_from_iter(hybrid_preds));
477    let param_env = traits::normalize_param_env_or_error(
478        tcx,
479        param_env,
480        ObligationCause::misc(tcx.def_span(impl_m_def_id), impl_m_def_id),
481    );
482
483    let infcx = &tcx.infer_ctxt().build(TypingMode::non_body_analysis());
484    let ocx = ObligationCtxt::new_with_diagnostics(infcx);
485
486    // Check that the where clauses of the impl are satisfied by the hybrid param env.
487    // You might ask -- what does this have to do with RPITIT inference? Nothing.
488    // We check these because if the where clauses of the signatures do not match
489    // up, then we don't want to give spurious other errors that point at the RPITITs.
490    // They're not necessary to check, though, because we already check them in
491    // `compare_method_predicate_entailment`.
492    let impl_m_own_bounds = tcx.predicates_of(impl_m_def_id).instantiate_own_identity();
493    for (predicate, span) in impl_m_own_bounds {
494        let normalize_cause = traits::ObligationCause::misc(span, impl_m_def_id);
495        let predicate = ocx.normalize(&normalize_cause, param_env, predicate);
496
497        let cause = ObligationCause::new(
498            span,
499            impl_m_def_id,
500            ObligationCauseCode::CompareImplItem {
501                impl_item_def_id: impl_m_def_id,
502                trait_item_def_id: trait_m.def_id,
503                kind: impl_m.kind,
504            },
505        );
506        ocx.register_obligation(traits::Obligation::new(tcx, cause, param_env, predicate));
507    }
508
509    // Normalize the impl signature with fresh variables for lifetime inference.
510    let misc_cause = ObligationCause::misc(return_span, impl_m_def_id);
511    let impl_sig = ocx.normalize(
512        &misc_cause,
513        param_env,
514        infcx.instantiate_binder_with_fresh_vars(
515            return_span,
516            BoundRegionConversionTime::HigherRankedType,
517            tcx.fn_sig(impl_m.def_id).instantiate_identity(),
518        ),
519    );
520    impl_sig.error_reported()?;
521    let impl_return_ty = impl_sig.output();
522
523    // Normalize the trait signature with liberated bound vars, passing it through
524    // the ImplTraitInTraitCollector, which gathers all of the RPITITs and replaces
525    // them with inference variables.
526    // We will use these inference variables to collect the hidden types of RPITITs.
527    let mut collector = ImplTraitInTraitCollector::new(&ocx, return_span, param_env, impl_m_def_id);
528    let unnormalized_trait_sig = tcx
529        .liberate_late_bound_regions(
530            impl_m.def_id,
531            tcx.fn_sig(trait_m.def_id).instantiate(tcx, trait_to_impl_args),
532        )
533        .fold_with(&mut collector);
534
535    let trait_sig = ocx.normalize(&misc_cause, param_env, unnormalized_trait_sig);
536    trait_sig.error_reported()?;
537    let trait_return_ty = trait_sig.output();
538
539    // RPITITs are allowed to use the implied predicates of the method that
540    // defines them. This is because we want code like:
541    // ```
542    // trait Foo {
543    //     fn test<'a, T>(_: &'a T) -> impl Sized;
544    // }
545    // impl Foo for () {
546    //     fn test<'a, T>(x: &'a T) -> &'a T { x }
547    // }
548    // ```
549    // .. to compile. However, since we use both the normalized and unnormalized
550    // inputs and outputs from the instantiated trait signature, we will end up
551    // seeing the hidden type of an RPIT in the signature itself. Naively, this
552    // means that we will use the hidden type to imply the hidden type's own
553    // well-formedness.
554    //
555    // To avoid this, we replace the infer vars used for hidden type inference
556    // with placeholders, which imply nothing about outlives bounds, and then
557    // prove below that the hidden types are well formed.
558    let universe = infcx.create_next_universe();
559    let mut idx = ty::BoundVar::ZERO;
560    let mapping: FxIndexMap<_, _> = collector
561        .types
562        .iter()
563        .map(|(_, &(ty, _))| {
564            assert!(
565                infcx.resolve_vars_if_possible(ty) == ty && ty.is_ty_var(),
566                "{ty:?} should not have been constrained via normalization",
567                ty = infcx.resolve_vars_if_possible(ty)
568            );
569            idx += 1;
570            (
571                ty,
572                Ty::new_placeholder(
573                    tcx,
574                    ty::Placeholder {
575                        universe,
576                        bound: ty::BoundTy { var: idx, kind: ty::BoundTyKind::Anon },
577                    },
578                ),
579            )
580        })
581        .collect();
582    let mut type_mapper = BottomUpFolder {
583        tcx,
584        ty_op: |ty| *mapping.get(&ty).unwrap_or(&ty),
585        lt_op: |lt| lt,
586        ct_op: |ct| ct,
587    };
588    let wf_tys = FxIndexSet::from_iter(
589        unnormalized_trait_sig
590            .inputs_and_output
591            .iter()
592            .chain(trait_sig.inputs_and_output.iter())
593            .map(|ty| ty.fold_with(&mut type_mapper)),
594    );
595
596    match ocx.eq(&cause, param_env, trait_return_ty, impl_return_ty) {
597        Ok(()) => {}
598        Err(terr) => {
599            let mut diag = struct_span_code_err!(
600                tcx.dcx(),
601                cause.span,
602                E0053,
603                "method `{}` has an incompatible return type for trait",
604                trait_m.name()
605            );
606            infcx.err_ctxt().note_type_err(
607                &mut diag,
608                &cause,
609                tcx.hir_get_if_local(impl_m.def_id)
610                    .and_then(|node| node.fn_decl())
611                    .map(|decl| (decl.output.span(), Cow::from("return type in trait"), false)),
612                Some(param_env.and(infer::ValuePairs::Terms(ExpectedFound {
613                    expected: trait_return_ty.into(),
614                    found: impl_return_ty.into(),
615                }))),
616                terr,
617                false,
618                None,
619            );
620            return Err(diag.emit());
621        }
622    }
623
624    debug!(?trait_sig, ?impl_sig, "equating function signatures");
625
626    // Unify the whole function signature. We need to do this to fully infer
627    // the lifetimes of the return type, but do this after unifying just the
628    // return types, since we want to avoid duplicating errors from
629    // `compare_method_predicate_entailment`.
630    match ocx.eq(&cause, param_env, trait_sig, impl_sig) {
631        Ok(()) => {}
632        Err(terr) => {
633            // This function gets called during `compare_method_predicate_entailment` when normalizing a
634            // signature that contains RPITIT. When the method signatures don't match, we have to
635            // emit an error now because `compare_method_predicate_entailment` will not report the error
636            // when normalization fails.
637            let emitted = report_trait_method_mismatch(
638                infcx,
639                cause,
640                param_env,
641                terr,
642                (trait_m, trait_sig),
643                (impl_m, impl_sig),
644                impl_trait_ref,
645            );
646            return Err(emitted);
647        }
648    }
649
650    if !unnormalized_trait_sig.output().references_error() && collector.types.is_empty() {
651        tcx.dcx().delayed_bug(
652            "expect >0 RPITITs in call to `collect_return_position_impl_trait_in_trait_tys`",
653        );
654    }
655
656    // FIXME: This has the same issue as #108544, but since this isn't breaking
657    // existing code, I'm not particularly inclined to do the same hack as above
658    // where we process wf obligations manually. This can be fixed in a forward-
659    // compatible way later.
660    let collected_types = collector.types;
661    for (_, &(ty, _)) in &collected_types {
662        ocx.register_obligation(traits::Obligation::new(
663            tcx,
664            misc_cause.clone(),
665            param_env,
666            ty::ClauseKind::WellFormed(ty.into()),
667        ));
668    }
669
670    // Check that all obligations are satisfied by the implementation's
671    // RPITs.
672    let errors = ocx.select_all_or_error();
673    if !errors.is_empty() {
674        if let Err(guar) = try_report_async_mismatch(tcx, infcx, &errors, trait_m, impl_m, impl_sig)
675        {
676            return Err(guar);
677        }
678
679        let guar = infcx.err_ctxt().report_fulfillment_errors(errors);
680        return Err(guar);
681    }
682
683    // Finally, resolve all regions. This catches wily misuses of
684    // lifetime parameters.
685    ocx.resolve_regions_and_report_errors(impl_m_def_id, param_env, wf_tys)?;
686
687    let mut remapped_types = DefIdMap::default();
688    for (def_id, (ty, args)) in collected_types {
689        match infcx.fully_resolve(ty) {
690            Ok(ty) => {
691                // `ty` contains free regions that we created earlier while liberating the
692                // trait fn signature. However, projection normalization expects `ty` to
693                // contains `def_id`'s early-bound regions.
694                let id_args = GenericArgs::identity_for_item(tcx, def_id);
695                debug!(?id_args, ?args);
696                let map: FxIndexMap<_, _> = std::iter::zip(args, id_args)
697                    .skip(tcx.generics_of(trait_m.def_id).count())
698                    .filter_map(|(a, b)| Some((a.as_region()?, b.as_region()?)))
699                    .collect();
700                debug!(?map);
701
702                // NOTE(compiler-errors): RPITITs, like all other RPITs, have early-bound
703                // region args that are synthesized during AST lowering. These are args
704                // that are appended to the parent args (trait and trait method). However,
705                // we're trying to infer the uninstantiated type value of the RPITIT inside
706                // the *impl*, so we can later use the impl's method args to normalize
707                // an RPITIT to a concrete type (`confirm_impl_trait_in_trait_candidate`).
708                //
709                // Due to the design of RPITITs, during AST lowering, we have no idea that
710                // an impl method corresponds to a trait method with RPITITs in it. Therefore,
711                // we don't have a list of early-bound region args for the RPITIT in the impl.
712                // Since early region parameters are index-based, we can't just rebase these
713                // (trait method) early-bound region args onto the impl, and there's no
714                // guarantee that the indices from the trait args and impl args line up.
715                // So to fix this, we subtract the number of trait args and add the number of
716                // impl args to *renumber* these early-bound regions to their corresponding
717                // indices in the impl's generic parameters list.
718                //
719                // Also, we only need to account for a difference in trait and impl args,
720                // since we previously enforce that the trait method and impl method have the
721                // same generics.
722                let num_trait_args = impl_trait_ref.args.len();
723                let num_impl_args = tcx.generics_of(impl_m.container_id(tcx)).own_params.len();
724                let ty = match ty.try_fold_with(&mut RemapHiddenTyRegions {
725                    tcx,
726                    map,
727                    num_trait_args,
728                    num_impl_args,
729                    def_id,
730                    impl_m_def_id: impl_m.def_id,
731                    ty,
732                    return_span,
733                }) {
734                    Ok(ty) => ty,
735                    Err(guar) => Ty::new_error(tcx, guar),
736                };
737                remapped_types.insert(def_id, ty::EarlyBinder::bind(ty));
738            }
739            Err(err) => {
740                // This code path is not reached in any tests, but may be
741                // reachable. If this is triggered, it should be converted to
742                // `span_delayed_bug` and the triggering case turned into a
743                // test.
744                tcx.dcx()
745                    .span_bug(return_span, format!("could not fully resolve: {ty} => {err:?}"));
746            }
747        }
748    }
749
750    // We may not collect all RPITITs that we see in the HIR for a trait signature
751    // because an RPITIT was located within a missing item. Like if we have a sig
752    // returning `-> Missing<impl Sized>`, that gets converted to `-> {type error}`,
753    // and when walking through the signature we end up never collecting the def id
754    // of the `impl Sized`. Insert that here, so we don't ICE later.
755    for assoc_item in tcx.associated_types_for_impl_traits_in_associated_fn(trait_m.def_id) {
756        if !remapped_types.contains_key(assoc_item) {
757            remapped_types.insert(
758                *assoc_item,
759                ty::EarlyBinder::bind(Ty::new_error_with_message(
760                    tcx,
761                    return_span,
762                    "missing synthetic item for RPITIT",
763                )),
764            );
765        }
766    }
767
768    Ok(&*tcx.arena.alloc(remapped_types))
769}
770
771struct ImplTraitInTraitCollector<'a, 'tcx, E> {
772    ocx: &'a ObligationCtxt<'a, 'tcx, E>,
773    types: FxIndexMap<DefId, (Ty<'tcx>, ty::GenericArgsRef<'tcx>)>,
774    span: Span,
775    param_env: ty::ParamEnv<'tcx>,
776    body_id: LocalDefId,
777}
778
779impl<'a, 'tcx, E> ImplTraitInTraitCollector<'a, 'tcx, E>
780where
781    E: 'tcx,
782{
783    fn new(
784        ocx: &'a ObligationCtxt<'a, 'tcx, E>,
785        span: Span,
786        param_env: ty::ParamEnv<'tcx>,
787        body_id: LocalDefId,
788    ) -> Self {
789        ImplTraitInTraitCollector { ocx, types: FxIndexMap::default(), span, param_env, body_id }
790    }
791}
792
793impl<'tcx, E> TypeFolder<TyCtxt<'tcx>> for ImplTraitInTraitCollector<'_, 'tcx, E>
794where
795    E: 'tcx,
796{
797    fn cx(&self) -> TyCtxt<'tcx> {
798        self.ocx.infcx.tcx
799    }
800
801    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
802        if let ty::Alias(ty::Projection, proj) = ty.kind()
803            && self.cx().is_impl_trait_in_trait(proj.def_id)
804        {
805            if let Some((ty, _)) = self.types.get(&proj.def_id) {
806                return *ty;
807            }
808            //FIXME(RPITIT): Deny nested RPITIT in args too
809            if proj.args.has_escaping_bound_vars() {
810                bug!("FIXME(RPITIT): error here");
811            }
812            // Replace with infer var
813            let infer_ty = self.ocx.infcx.next_ty_var(self.span);
814            self.types.insert(proj.def_id, (infer_ty, proj.args));
815            // Recurse into bounds
816            for (pred, pred_span) in self
817                .cx()
818                .explicit_item_bounds(proj.def_id)
819                .iter_instantiated_copied(self.cx(), proj.args)
820            {
821                let pred = pred.fold_with(self);
822                let pred = self.ocx.normalize(
823                    &ObligationCause::misc(self.span, self.body_id),
824                    self.param_env,
825                    pred,
826                );
827
828                self.ocx.register_obligation(traits::Obligation::new(
829                    self.cx(),
830                    ObligationCause::new(
831                        self.span,
832                        self.body_id,
833                        ObligationCauseCode::WhereClause(proj.def_id, pred_span),
834                    ),
835                    self.param_env,
836                    pred,
837                ));
838            }
839            infer_ty
840        } else {
841            ty.super_fold_with(self)
842        }
843    }
844}
845
846struct RemapHiddenTyRegions<'tcx> {
847    tcx: TyCtxt<'tcx>,
848    /// Map from early/late params of the impl to identity regions of the RPITIT (GAT)
849    /// in the trait.
850    map: FxIndexMap<ty::Region<'tcx>, ty::Region<'tcx>>,
851    num_trait_args: usize,
852    num_impl_args: usize,
853    /// Def id of the RPITIT (GAT) in the *trait*.
854    def_id: DefId,
855    /// Def id of the impl method which owns the opaque hidden type we're remapping.
856    impl_m_def_id: DefId,
857    /// The hidden type we're remapping. Useful for diagnostics.
858    ty: Ty<'tcx>,
859    /// Span of the return type. Useful for diagnostics.
860    return_span: Span,
861}
862
863impl<'tcx> ty::FallibleTypeFolder<TyCtxt<'tcx>> for RemapHiddenTyRegions<'tcx> {
864    type Error = ErrorGuaranteed;
865
866    fn cx(&self) -> TyCtxt<'tcx> {
867        self.tcx
868    }
869
870    fn try_fold_region(
871        &mut self,
872        region: ty::Region<'tcx>,
873    ) -> Result<ty::Region<'tcx>, Self::Error> {
874        match region.kind() {
875            // Never remap bound regions or `'static`
876            ty::ReBound(..) | ty::ReStatic | ty::ReError(_) => return Ok(region),
877            // We always remap liberated late-bound regions from the function.
878            ty::ReLateParam(_) => {}
879            // Remap early-bound regions as long as they don't come from the `impl` itself,
880            // in which case we don't really need to renumber them.
881            ty::ReEarlyParam(ebr) => {
882                if ebr.index as usize >= self.num_impl_args {
883                    // Remap
884                } else {
885                    return Ok(region);
886                }
887            }
888            ty::ReVar(_) | ty::RePlaceholder(_) | ty::ReErased => unreachable!(
889                "should not have leaked vars or placeholders into hidden type of RPITIT"
890            ),
891        }
892
893        let e = if let Some(id_region) = self.map.get(&region) {
894            if let ty::ReEarlyParam(e) = id_region.kind() {
895                e
896            } else {
897                bug!(
898                    "expected to map region {region} to early-bound identity region, but got {id_region}"
899                );
900            }
901        } else {
902            let guar = match region.opt_param_def_id(self.tcx, self.impl_m_def_id) {
903                Some(def_id) => {
904                    let return_span = if let ty::Alias(ty::Opaque, opaque_ty) = self.ty.kind() {
905                        self.tcx.def_span(opaque_ty.def_id)
906                    } else {
907                        self.return_span
908                    };
909                    self.tcx
910                        .dcx()
911                        .struct_span_err(
912                            return_span,
913                            "return type captures more lifetimes than trait definition",
914                        )
915                        .with_span_label(self.tcx.def_span(def_id), "this lifetime was captured")
916                        .with_span_note(
917                            self.tcx.def_span(self.def_id),
918                            "hidden type must only reference lifetimes captured by this impl trait",
919                        )
920                        .with_note(format!("hidden type inferred to be `{}`", self.ty))
921                        .emit()
922                }
923                None => {
924                    // This code path is not reached in any tests, but may be
925                    // reachable. If this is triggered, it should be converted
926                    // to `delayed_bug` and the triggering case turned into a
927                    // test.
928                    self.tcx.dcx().bug("should've been able to remap region");
929                }
930            };
931            return Err(guar);
932        };
933
934        Ok(ty::Region::new_early_param(
935            self.tcx,
936            ty::EarlyParamRegion {
937                name: e.name,
938                index: (e.index as usize - self.num_trait_args + self.num_impl_args) as u32,
939            },
940        ))
941    }
942}
943
944/// Gets the string for an explicit self declaration, e.g. "self", "&self",
945/// etc.
946fn get_self_string<'tcx, P>(self_arg_ty: Ty<'tcx>, is_self_ty: P) -> String
947where
948    P: Fn(Ty<'tcx>) -> bool,
949{
950    if is_self_ty(self_arg_ty) {
951        "self".to_owned()
952    } else if let ty::Ref(_, ty, mutbl) = self_arg_ty.kind()
953        && is_self_ty(*ty)
954    {
955        match mutbl {
956            hir::Mutability::Not => "&self".to_owned(),
957            hir::Mutability::Mut => "&mut self".to_owned(),
958        }
959    } else {
960        format!("self: {self_arg_ty}")
961    }
962}
963
964fn report_trait_method_mismatch<'tcx>(
965    infcx: &InferCtxt<'tcx>,
966    mut cause: ObligationCause<'tcx>,
967    param_env: ty::ParamEnv<'tcx>,
968    terr: TypeError<'tcx>,
969    (trait_m, trait_sig): (ty::AssocItem, ty::FnSig<'tcx>),
970    (impl_m, impl_sig): (ty::AssocItem, ty::FnSig<'tcx>),
971    impl_trait_ref: ty::TraitRef<'tcx>,
972) -> ErrorGuaranteed {
973    let tcx = infcx.tcx;
974    let (impl_err_span, trait_err_span) =
975        extract_spans_for_error_reporting(infcx, terr, &cause, impl_m, trait_m);
976
977    let mut diag = struct_span_code_err!(
978        tcx.dcx(),
979        impl_err_span,
980        E0053,
981        "method `{}` has an incompatible type for trait",
982        trait_m.name()
983    );
984    match &terr {
985        TypeError::ArgumentMutability(0) | TypeError::ArgumentSorts(_, 0)
986            if trait_m.is_method() =>
987        {
988            let ty = trait_sig.inputs()[0];
989            let sugg = get_self_string(ty, |ty| ty == impl_trait_ref.self_ty());
990
991            // When the `impl` receiver is an arbitrary self type, like `self: Box<Self>`, the
992            // span points only at the type `Box<Self`>, but we want to cover the whole
993            // argument pattern and type.
994            let (sig, body) = tcx.hir_expect_impl_item(impl_m.def_id.expect_local()).expect_fn();
995            let span = tcx
996                .hir_body_param_idents(body)
997                .zip(sig.decl.inputs.iter())
998                .map(|(param_ident, ty)| {
999                    if let Some(param_ident) = param_ident {
1000                        param_ident.span.to(ty.span)
1001                    } else {
1002                        ty.span
1003                    }
1004                })
1005                .next()
1006                .unwrap_or(impl_err_span);
1007
1008            diag.span_suggestion_verbose(
1009                span,
1010                "change the self-receiver type to match the trait",
1011                sugg,
1012                Applicability::MachineApplicable,
1013            );
1014        }
1015        TypeError::ArgumentMutability(i) | TypeError::ArgumentSorts(_, i) => {
1016            if trait_sig.inputs().len() == *i {
1017                // Suggestion to change output type. We do not suggest in `async` functions
1018                // to avoid complex logic or incorrect output.
1019                if let ImplItemKind::Fn(sig, _) =
1020                    &tcx.hir_expect_impl_item(impl_m.def_id.expect_local()).kind
1021                    && !sig.header.asyncness.is_async()
1022                {
1023                    let msg = "change the output type to match the trait";
1024                    let ap = Applicability::MachineApplicable;
1025                    match sig.decl.output {
1026                        hir::FnRetTy::DefaultReturn(sp) => {
1027                            let sugg = format!(" -> {}", trait_sig.output());
1028                            diag.span_suggestion_verbose(sp, msg, sugg, ap);
1029                        }
1030                        hir::FnRetTy::Return(hir_ty) => {
1031                            let sugg = trait_sig.output();
1032                            diag.span_suggestion_verbose(hir_ty.span, msg, sugg, ap);
1033                        }
1034                    };
1035                };
1036            } else if let Some(trait_ty) = trait_sig.inputs().get(*i) {
1037                diag.span_suggestion_verbose(
1038                    impl_err_span,
1039                    "change the parameter type to match the trait",
1040                    trait_ty,
1041                    Applicability::MachineApplicable,
1042                );
1043            }
1044        }
1045        _ => {}
1046    }
1047
1048    cause.span = impl_err_span;
1049    infcx.err_ctxt().note_type_err(
1050        &mut diag,
1051        &cause,
1052        trait_err_span.map(|sp| (sp, Cow::from("type in trait"), false)),
1053        Some(param_env.and(infer::ValuePairs::PolySigs(ExpectedFound {
1054            expected: ty::Binder::dummy(trait_sig),
1055            found: ty::Binder::dummy(impl_sig),
1056        }))),
1057        terr,
1058        false,
1059        None,
1060    );
1061
1062    diag.emit()
1063}
1064
1065fn check_region_bounds_on_impl_item<'tcx>(
1066    tcx: TyCtxt<'tcx>,
1067    impl_m: ty::AssocItem,
1068    trait_m: ty::AssocItem,
1069    delay: bool,
1070) -> Result<(), ErrorGuaranteed> {
1071    let impl_generics = tcx.generics_of(impl_m.def_id);
1072    let impl_params = impl_generics.own_counts().lifetimes;
1073
1074    let trait_generics = tcx.generics_of(trait_m.def_id);
1075    let trait_params = trait_generics.own_counts().lifetimes;
1076
1077    debug!(?trait_generics, ?impl_generics);
1078
1079    // Must have same number of early-bound lifetime parameters.
1080    // Unfortunately, if the user screws up the bounds, then this
1081    // will change classification between early and late. E.g.,
1082    // if in trait we have `<'a,'b:'a>`, and in impl we just have
1083    // `<'a,'b>`, then we have 2 early-bound lifetime parameters
1084    // in trait but 0 in the impl. But if we report "expected 2
1085    // but found 0" it's confusing, because it looks like there
1086    // are zero. Since I don't quite know how to phrase things at
1087    // the moment, give a kind of vague error message.
1088    if trait_params == impl_params {
1089        return Ok(());
1090    }
1091
1092    if !delay && let Some(guar) = check_region_late_boundedness(tcx, impl_m, trait_m) {
1093        return Err(guar);
1094    }
1095
1096    let span = tcx
1097        .hir_get_generics(impl_m.def_id.expect_local())
1098        .expect("expected impl item to have generics or else we can't compare them")
1099        .span;
1100
1101    let mut generics_span = None;
1102    let mut bounds_span = vec![];
1103    let mut where_span = None;
1104
1105    if let Some(trait_node) = tcx.hir_get_if_local(trait_m.def_id)
1106        && let Some(trait_generics) = trait_node.generics()
1107    {
1108        generics_span = Some(trait_generics.span);
1109        // FIXME: we could potentially look at the impl's bounds to not point at bounds that
1110        // *are* present in the impl.
1111        for p in trait_generics.predicates {
1112            match p.kind {
1113                hir::WherePredicateKind::BoundPredicate(hir::WhereBoundPredicate {
1114                    bounds,
1115                    ..
1116                })
1117                | hir::WherePredicateKind::RegionPredicate(hir::WhereRegionPredicate {
1118                    bounds,
1119                    ..
1120                }) => {
1121                    for b in *bounds {
1122                        if let hir::GenericBound::Outlives(lt) = b {
1123                            bounds_span.push(lt.ident.span);
1124                        }
1125                    }
1126                }
1127                _ => {}
1128            }
1129        }
1130        if let Some(impl_node) = tcx.hir_get_if_local(impl_m.def_id)
1131            && let Some(impl_generics) = impl_node.generics()
1132        {
1133            let mut impl_bounds = 0;
1134            for p in impl_generics.predicates {
1135                match p.kind {
1136                    hir::WherePredicateKind::BoundPredicate(hir::WhereBoundPredicate {
1137                        bounds,
1138                        ..
1139                    })
1140                    | hir::WherePredicateKind::RegionPredicate(hir::WhereRegionPredicate {
1141                        bounds,
1142                        ..
1143                    }) => {
1144                        for b in *bounds {
1145                            if let hir::GenericBound::Outlives(_) = b {
1146                                impl_bounds += 1;
1147                            }
1148                        }
1149                    }
1150                    _ => {}
1151                }
1152            }
1153            if impl_bounds == bounds_span.len() {
1154                bounds_span = vec![];
1155            } else if impl_generics.has_where_clause_predicates {
1156                where_span = Some(impl_generics.where_clause_span);
1157            }
1158        }
1159    }
1160
1161    let reported = tcx
1162        .dcx()
1163        .create_err(LifetimesOrBoundsMismatchOnTrait {
1164            span,
1165            item_kind: impl_m.descr(),
1166            ident: impl_m.ident(tcx),
1167            generics_span,
1168            bounds_span,
1169            where_span,
1170        })
1171        .emit_unless_delay(delay);
1172
1173    Err(reported)
1174}
1175
1176#[allow(unused)]
1177enum LateEarlyMismatch<'tcx> {
1178    EarlyInImpl(DefId, DefId, ty::Region<'tcx>),
1179    LateInImpl(DefId, DefId, ty::Region<'tcx>),
1180}
1181
1182fn check_region_late_boundedness<'tcx>(
1183    tcx: TyCtxt<'tcx>,
1184    impl_m: ty::AssocItem,
1185    trait_m: ty::AssocItem,
1186) -> Option<ErrorGuaranteed> {
1187    if !impl_m.is_fn() {
1188        return None;
1189    }
1190
1191    let (infcx, param_env) = tcx
1192        .infer_ctxt()
1193        .build_with_typing_env(ty::TypingEnv::non_body_analysis(tcx, impl_m.def_id));
1194
1195    let impl_m_args = infcx.fresh_args_for_item(DUMMY_SP, impl_m.def_id);
1196    let impl_m_sig = tcx.fn_sig(impl_m.def_id).instantiate(tcx, impl_m_args);
1197    let impl_m_sig = tcx.liberate_late_bound_regions(impl_m.def_id, impl_m_sig);
1198
1199    let trait_m_args = infcx.fresh_args_for_item(DUMMY_SP, trait_m.def_id);
1200    let trait_m_sig = tcx.fn_sig(trait_m.def_id).instantiate(tcx, trait_m_args);
1201    let trait_m_sig = tcx.liberate_late_bound_regions(impl_m.def_id, trait_m_sig);
1202
1203    let ocx = ObligationCtxt::new(&infcx);
1204
1205    // Equate the signatures so that we can infer whether a late-bound param was present where
1206    // an early-bound param was expected, since we replace the late-bound lifetimes with
1207    // `ReLateParam`, and early-bound lifetimes with infer vars, so the early-bound args will
1208    // resolve to `ReLateParam` if there is a mismatch.
1209    let Ok(()) = ocx.eq(
1210        &ObligationCause::dummy(),
1211        param_env,
1212        ty::Binder::dummy(trait_m_sig),
1213        ty::Binder::dummy(impl_m_sig),
1214    ) else {
1215        return None;
1216    };
1217
1218    let errors = ocx.select_where_possible();
1219    if !errors.is_empty() {
1220        return None;
1221    }
1222
1223    let mut mismatched = vec![];
1224
1225    let impl_generics = tcx.generics_of(impl_m.def_id);
1226    for (id_arg, arg) in
1227        std::iter::zip(ty::GenericArgs::identity_for_item(tcx, impl_m.def_id), impl_m_args)
1228    {
1229        if let ty::GenericArgKind::Lifetime(r) = arg.kind()
1230            && let ty::ReVar(vid) = r.kind()
1231            && let r = infcx
1232                .inner
1233                .borrow_mut()
1234                .unwrap_region_constraints()
1235                .opportunistic_resolve_var(tcx, vid)
1236            && let ty::ReLateParam(ty::LateParamRegion {
1237                kind: ty::LateParamRegionKind::Named(trait_param_def_id),
1238                ..
1239            }) = r.kind()
1240            && let ty::ReEarlyParam(ebr) = id_arg.expect_region().kind()
1241        {
1242            mismatched.push(LateEarlyMismatch::EarlyInImpl(
1243                impl_generics.region_param(ebr, tcx).def_id,
1244                trait_param_def_id,
1245                id_arg.expect_region(),
1246            ));
1247        }
1248    }
1249
1250    let trait_generics = tcx.generics_of(trait_m.def_id);
1251    for (id_arg, arg) in
1252        std::iter::zip(ty::GenericArgs::identity_for_item(tcx, trait_m.def_id), trait_m_args)
1253    {
1254        if let ty::GenericArgKind::Lifetime(r) = arg.kind()
1255            && let ty::ReVar(vid) = r.kind()
1256            && let r = infcx
1257                .inner
1258                .borrow_mut()
1259                .unwrap_region_constraints()
1260                .opportunistic_resolve_var(tcx, vid)
1261            && let ty::ReLateParam(ty::LateParamRegion {
1262                kind: ty::LateParamRegionKind::Named(impl_param_def_id),
1263                ..
1264            }) = r.kind()
1265            && let ty::ReEarlyParam(ebr) = id_arg.expect_region().kind()
1266        {
1267            mismatched.push(LateEarlyMismatch::LateInImpl(
1268                impl_param_def_id,
1269                trait_generics.region_param(ebr, tcx).def_id,
1270                id_arg.expect_region(),
1271            ));
1272        }
1273    }
1274
1275    if mismatched.is_empty() {
1276        return None;
1277    }
1278
1279    let spans: Vec<_> = mismatched
1280        .iter()
1281        .map(|param| {
1282            let (LateEarlyMismatch::EarlyInImpl(impl_param_def_id, ..)
1283            | LateEarlyMismatch::LateInImpl(impl_param_def_id, ..)) = param;
1284            tcx.def_span(impl_param_def_id)
1285        })
1286        .collect();
1287
1288    let mut diag = tcx
1289        .dcx()
1290        .struct_span_err(spans, "lifetime parameters do not match the trait definition")
1291        .with_note("lifetime parameters differ in whether they are early- or late-bound")
1292        .with_code(E0195);
1293    for mismatch in mismatched {
1294        match mismatch {
1295            LateEarlyMismatch::EarlyInImpl(
1296                impl_param_def_id,
1297                trait_param_def_id,
1298                early_bound_region,
1299            ) => {
1300                let mut multispan = MultiSpan::from_spans(vec![
1301                    tcx.def_span(impl_param_def_id),
1302                    tcx.def_span(trait_param_def_id),
1303                ]);
1304                multispan
1305                    .push_span_label(tcx.def_span(tcx.parent(impl_m.def_id)), "in this impl...");
1306                multispan
1307                    .push_span_label(tcx.def_span(tcx.parent(trait_m.def_id)), "in this trait...");
1308                multispan.push_span_label(
1309                    tcx.def_span(impl_param_def_id),
1310                    format!("`{}` is early-bound", tcx.item_name(impl_param_def_id)),
1311                );
1312                multispan.push_span_label(
1313                    tcx.def_span(trait_param_def_id),
1314                    format!("`{}` is late-bound", tcx.item_name(trait_param_def_id)),
1315                );
1316                if let Some(span) =
1317                    find_region_in_predicates(tcx, impl_m.def_id, early_bound_region)
1318                {
1319                    multispan.push_span_label(
1320                        span,
1321                        format!(
1322                            "this lifetime bound makes `{}` early-bound",
1323                            tcx.item_name(impl_param_def_id)
1324                        ),
1325                    );
1326                }
1327                diag.span_note(
1328                    multispan,
1329                    format!(
1330                        "`{}` differs between the trait and impl",
1331                        tcx.item_name(impl_param_def_id)
1332                    ),
1333                );
1334            }
1335            LateEarlyMismatch::LateInImpl(
1336                impl_param_def_id,
1337                trait_param_def_id,
1338                early_bound_region,
1339            ) => {
1340                let mut multispan = MultiSpan::from_spans(vec![
1341                    tcx.def_span(impl_param_def_id),
1342                    tcx.def_span(trait_param_def_id),
1343                ]);
1344                multispan
1345                    .push_span_label(tcx.def_span(tcx.parent(impl_m.def_id)), "in this impl...");
1346                multispan
1347                    .push_span_label(tcx.def_span(tcx.parent(trait_m.def_id)), "in this trait...");
1348                multispan.push_span_label(
1349                    tcx.def_span(impl_param_def_id),
1350                    format!("`{}` is late-bound", tcx.item_name(impl_param_def_id)),
1351                );
1352                multispan.push_span_label(
1353                    tcx.def_span(trait_param_def_id),
1354                    format!("`{}` is early-bound", tcx.item_name(trait_param_def_id)),
1355                );
1356                if let Some(span) =
1357                    find_region_in_predicates(tcx, trait_m.def_id, early_bound_region)
1358                {
1359                    multispan.push_span_label(
1360                        span,
1361                        format!(
1362                            "this lifetime bound makes `{}` early-bound",
1363                            tcx.item_name(trait_param_def_id)
1364                        ),
1365                    );
1366                }
1367                diag.span_note(
1368                    multispan,
1369                    format!(
1370                        "`{}` differs between the trait and impl",
1371                        tcx.item_name(impl_param_def_id)
1372                    ),
1373                );
1374            }
1375        }
1376    }
1377
1378    Some(diag.emit())
1379}
1380
1381fn find_region_in_predicates<'tcx>(
1382    tcx: TyCtxt<'tcx>,
1383    def_id: DefId,
1384    early_bound_region: ty::Region<'tcx>,
1385) -> Option<Span> {
1386    for (pred, span) in tcx.explicit_predicates_of(def_id).instantiate_identity(tcx) {
1387        if pred.visit_with(&mut FindRegion(early_bound_region)).is_break() {
1388            return Some(span);
1389        }
1390    }
1391
1392    struct FindRegion<'tcx>(ty::Region<'tcx>);
1393    impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for FindRegion<'tcx> {
1394        type Result = ControlFlow<()>;
1395        fn visit_region(&mut self, r: ty::Region<'tcx>) -> Self::Result {
1396            if r == self.0 { ControlFlow::Break(()) } else { ControlFlow::Continue(()) }
1397        }
1398    }
1399
1400    None
1401}
1402
1403#[instrument(level = "debug", skip(infcx))]
1404fn extract_spans_for_error_reporting<'tcx>(
1405    infcx: &infer::InferCtxt<'tcx>,
1406    terr: TypeError<'_>,
1407    cause: &ObligationCause<'tcx>,
1408    impl_m: ty::AssocItem,
1409    trait_m: ty::AssocItem,
1410) -> (Span, Option<Span>) {
1411    let tcx = infcx.tcx;
1412    let mut impl_args = {
1413        let (sig, _) = tcx.hir_expect_impl_item(impl_m.def_id.expect_local()).expect_fn();
1414        sig.decl.inputs.iter().map(|t| t.span).chain(iter::once(sig.decl.output.span()))
1415    };
1416
1417    let trait_args = trait_m.def_id.as_local().map(|def_id| {
1418        let (sig, _) = tcx.hir_expect_trait_item(def_id).expect_fn();
1419        sig.decl.inputs.iter().map(|t| t.span).chain(iter::once(sig.decl.output.span()))
1420    });
1421
1422    match terr {
1423        TypeError::ArgumentMutability(i) | TypeError::ArgumentSorts(ExpectedFound { .. }, i) => {
1424            (impl_args.nth(i).unwrap(), trait_args.and_then(|mut args| args.nth(i)))
1425        }
1426        _ => (cause.span, tcx.hir_span_if_local(trait_m.def_id)),
1427    }
1428}
1429
1430fn compare_self_type<'tcx>(
1431    tcx: TyCtxt<'tcx>,
1432    impl_m: ty::AssocItem,
1433    trait_m: ty::AssocItem,
1434    impl_trait_ref: ty::TraitRef<'tcx>,
1435    delay: bool,
1436) -> Result<(), ErrorGuaranteed> {
1437    // Try to give more informative error messages about self typing
1438    // mismatches. Note that any mismatch will also be detected
1439    // below, where we construct a canonical function type that
1440    // includes the self parameter as a normal parameter. It's just
1441    // that the error messages you get out of this code are a bit more
1442    // inscrutable, particularly for cases where one method has no
1443    // self.
1444
1445    let self_string = |method: ty::AssocItem| {
1446        let untransformed_self_ty = match method.container {
1447            ty::AssocContainer::InherentImpl | ty::AssocContainer::TraitImpl(_) => {
1448                impl_trait_ref.self_ty()
1449            }
1450            ty::AssocContainer::Trait => tcx.types.self_param,
1451        };
1452        let self_arg_ty = tcx.fn_sig(method.def_id).instantiate_identity().input(0);
1453        let (infcx, param_env) = tcx
1454            .infer_ctxt()
1455            .build_with_typing_env(ty::TypingEnv::non_body_analysis(tcx, method.def_id));
1456        let self_arg_ty = tcx.liberate_late_bound_regions(method.def_id, self_arg_ty);
1457        let can_eq_self = |ty| infcx.can_eq(param_env, untransformed_self_ty, ty);
1458        get_self_string(self_arg_ty, can_eq_self)
1459    };
1460
1461    match (trait_m.is_method(), impl_m.is_method()) {
1462        (false, false) | (true, true) => {}
1463
1464        (false, true) => {
1465            let self_descr = self_string(impl_m);
1466            let impl_m_span = tcx.def_span(impl_m.def_id);
1467            let mut err = struct_span_code_err!(
1468                tcx.dcx(),
1469                impl_m_span,
1470                E0185,
1471                "method `{}` has a `{}` declaration in the impl, but not in the trait",
1472                trait_m.name(),
1473                self_descr
1474            );
1475            err.span_label(impl_m_span, format!("`{self_descr}` used in impl"));
1476            if let Some(span) = tcx.hir_span_if_local(trait_m.def_id) {
1477                err.span_label(span, format!("trait method declared without `{self_descr}`"));
1478            } else {
1479                err.note_trait_signature(trait_m.name(), trait_m.signature(tcx));
1480            }
1481            return Err(err.emit_unless_delay(delay));
1482        }
1483
1484        (true, false) => {
1485            let self_descr = self_string(trait_m);
1486            let impl_m_span = tcx.def_span(impl_m.def_id);
1487            let mut err = struct_span_code_err!(
1488                tcx.dcx(),
1489                impl_m_span,
1490                E0186,
1491                "method `{}` has a `{}` declaration in the trait, but not in the impl",
1492                trait_m.name(),
1493                self_descr
1494            );
1495            err.span_label(impl_m_span, format!("expected `{self_descr}` in impl"));
1496            if let Some(span) = tcx.hir_span_if_local(trait_m.def_id) {
1497                err.span_label(span, format!("`{self_descr}` used in trait"));
1498            } else {
1499                err.note_trait_signature(trait_m.name(), trait_m.signature(tcx));
1500            }
1501
1502            return Err(err.emit_unless_delay(delay));
1503        }
1504    }
1505
1506    Ok(())
1507}
1508
1509/// Checks that the number of generics on a given assoc item in a trait impl is the same
1510/// as the number of generics on the respective assoc item in the trait definition.
1511///
1512/// For example this code emits the errors in the following code:
1513/// ```rust,compile_fail
1514/// trait Trait {
1515///     fn foo();
1516///     type Assoc<T>;
1517/// }
1518///
1519/// impl Trait for () {
1520///     fn foo<T>() {}
1521///     //~^ error
1522///     type Assoc = u32;
1523///     //~^ error
1524/// }
1525/// ```
1526///
1527/// Notably this does not error on `foo<T>` implemented as `foo<const N: u8>` or
1528/// `foo<const N: u8>` implemented as `foo<const N: u32>`. This is handled in
1529/// [`compare_generic_param_kinds`]. This function also does not handle lifetime parameters
1530fn compare_number_of_generics<'tcx>(
1531    tcx: TyCtxt<'tcx>,
1532    impl_: ty::AssocItem,
1533    trait_: ty::AssocItem,
1534    delay: bool,
1535) -> Result<(), ErrorGuaranteed> {
1536    let trait_own_counts = tcx.generics_of(trait_.def_id).own_counts();
1537    let impl_own_counts = tcx.generics_of(impl_.def_id).own_counts();
1538
1539    // This avoids us erroring on `foo<T>` implemented as `foo<const N: u8>` as this is implemented
1540    // in `compare_generic_param_kinds` which will give a nicer error message than something like:
1541    // "expected 1 type parameter, found 0 type parameters"
1542    if (trait_own_counts.types + trait_own_counts.consts)
1543        == (impl_own_counts.types + impl_own_counts.consts)
1544    {
1545        return Ok(());
1546    }
1547
1548    // We never need to emit a separate error for RPITITs, since if an RPITIT
1549    // has mismatched type or const generic arguments, then the method that it's
1550    // inheriting the generics from will also have mismatched arguments, and
1551    // we'll report an error for that instead. Delay a bug for safety, though.
1552    if trait_.is_impl_trait_in_trait() {
1553        // FIXME: no tests trigger this. If you find example code that does
1554        // trigger this, please add it to the test suite.
1555        tcx.dcx()
1556            .bug("errors comparing numbers of generics of trait/impl functions were not emitted");
1557    }
1558
1559    let matchings = [
1560        ("type", trait_own_counts.types, impl_own_counts.types),
1561        ("const", trait_own_counts.consts, impl_own_counts.consts),
1562    ];
1563
1564    let item_kind = impl_.descr();
1565
1566    let mut err_occurred = None;
1567    for (kind, trait_count, impl_count) in matchings {
1568        if impl_count != trait_count {
1569            let arg_spans = |item: &ty::AssocItem, generics: &hir::Generics<'_>| {
1570                let mut spans = generics
1571                    .params
1572                    .iter()
1573                    .filter(|p| match p.kind {
1574                        hir::GenericParamKind::Lifetime {
1575                            kind: hir::LifetimeParamKind::Elided(_),
1576                        } => {
1577                            // A fn can have an arbitrary number of extra elided lifetimes for the
1578                            // same signature.
1579                            !item.is_fn()
1580                        }
1581                        _ => true,
1582                    })
1583                    .map(|p| p.span)
1584                    .collect::<Vec<Span>>();
1585                if spans.is_empty() {
1586                    spans = vec![generics.span]
1587                }
1588                spans
1589            };
1590            let (trait_spans, impl_trait_spans) = if let Some(def_id) = trait_.def_id.as_local() {
1591                let trait_item = tcx.hir_expect_trait_item(def_id);
1592                let arg_spans: Vec<Span> = arg_spans(&trait_, trait_item.generics);
1593                let impl_trait_spans: Vec<Span> = trait_item
1594                    .generics
1595                    .params
1596                    .iter()
1597                    .filter_map(|p| match p.kind {
1598                        GenericParamKind::Type { synthetic: true, .. } => Some(p.span),
1599                        _ => None,
1600                    })
1601                    .collect();
1602                (Some(arg_spans), impl_trait_spans)
1603            } else {
1604                let trait_span = tcx.hir_span_if_local(trait_.def_id);
1605                (trait_span.map(|s| vec![s]), vec![])
1606            };
1607
1608            let impl_item = tcx.hir_expect_impl_item(impl_.def_id.expect_local());
1609            let impl_item_impl_trait_spans: Vec<Span> = impl_item
1610                .generics
1611                .params
1612                .iter()
1613                .filter_map(|p| match p.kind {
1614                    GenericParamKind::Type { synthetic: true, .. } => Some(p.span),
1615                    _ => None,
1616                })
1617                .collect();
1618            let spans = arg_spans(&impl_, impl_item.generics);
1619            let span = spans.first().copied();
1620
1621            let mut err = tcx.dcx().struct_span_err(
1622                spans,
1623                format!(
1624                    "{} `{}` has {} {kind} parameter{} but its trait \
1625                     declaration has {} {kind} parameter{}",
1626                    item_kind,
1627                    trait_.name(),
1628                    impl_count,
1629                    pluralize!(impl_count),
1630                    trait_count,
1631                    pluralize!(trait_count),
1632                    kind = kind,
1633                ),
1634            );
1635            err.code(E0049);
1636
1637            let msg =
1638                format!("expected {trait_count} {kind} parameter{}", pluralize!(trait_count),);
1639            if let Some(spans) = trait_spans {
1640                let mut spans = spans.iter();
1641                if let Some(span) = spans.next() {
1642                    err.span_label(*span, msg);
1643                }
1644                for span in spans {
1645                    err.span_label(*span, "");
1646                }
1647            } else {
1648                err.span_label(tcx.def_span(trait_.def_id), msg);
1649            }
1650
1651            if let Some(span) = span {
1652                err.span_label(
1653                    span,
1654                    format!("found {} {} parameter{}", impl_count, kind, pluralize!(impl_count),),
1655                );
1656            }
1657
1658            for span in impl_trait_spans.iter().chain(impl_item_impl_trait_spans.iter()) {
1659                err.span_label(*span, "`impl Trait` introduces an implicit type parameter");
1660            }
1661
1662            let reported = err.emit_unless_delay(delay);
1663            err_occurred = Some(reported);
1664        }
1665    }
1666
1667    if let Some(reported) = err_occurred { Err(reported) } else { Ok(()) }
1668}
1669
1670fn compare_number_of_method_arguments<'tcx>(
1671    tcx: TyCtxt<'tcx>,
1672    impl_m: ty::AssocItem,
1673    trait_m: ty::AssocItem,
1674    delay: bool,
1675) -> Result<(), ErrorGuaranteed> {
1676    let impl_m_fty = tcx.fn_sig(impl_m.def_id);
1677    let trait_m_fty = tcx.fn_sig(trait_m.def_id);
1678    let trait_number_args = trait_m_fty.skip_binder().inputs().skip_binder().len();
1679    let impl_number_args = impl_m_fty.skip_binder().inputs().skip_binder().len();
1680
1681    if trait_number_args != impl_number_args {
1682        let trait_span = trait_m
1683            .def_id
1684            .as_local()
1685            .and_then(|def_id| {
1686                let (trait_m_sig, _) = &tcx.hir_expect_trait_item(def_id).expect_fn();
1687                let pos = trait_number_args.saturating_sub(1);
1688                trait_m_sig.decl.inputs.get(pos).map(|arg| {
1689                    if pos == 0 {
1690                        arg.span
1691                    } else {
1692                        arg.span.with_lo(trait_m_sig.decl.inputs[0].span.lo())
1693                    }
1694                })
1695            })
1696            .or_else(|| tcx.hir_span_if_local(trait_m.def_id));
1697
1698        let (impl_m_sig, _) = &tcx.hir_expect_impl_item(impl_m.def_id.expect_local()).expect_fn();
1699        let pos = impl_number_args.saturating_sub(1);
1700        let impl_span = impl_m_sig
1701            .decl
1702            .inputs
1703            .get(pos)
1704            .map(|arg| {
1705                if pos == 0 {
1706                    arg.span
1707                } else {
1708                    arg.span.with_lo(impl_m_sig.decl.inputs[0].span.lo())
1709                }
1710            })
1711            .unwrap_or_else(|| tcx.def_span(impl_m.def_id));
1712
1713        let mut err = struct_span_code_err!(
1714            tcx.dcx(),
1715            impl_span,
1716            E0050,
1717            "method `{}` has {} but the declaration in trait `{}` has {}",
1718            trait_m.name(),
1719            potentially_plural_count(impl_number_args, "parameter"),
1720            tcx.def_path_str(trait_m.def_id),
1721            trait_number_args
1722        );
1723
1724        if let Some(trait_span) = trait_span {
1725            err.span_label(
1726                trait_span,
1727                format!(
1728                    "trait requires {}",
1729                    potentially_plural_count(trait_number_args, "parameter")
1730                ),
1731            );
1732        } else {
1733            err.note_trait_signature(trait_m.name(), trait_m.signature(tcx));
1734        }
1735
1736        err.span_label(
1737            impl_span,
1738            format!(
1739                "expected {}, found {}",
1740                potentially_plural_count(trait_number_args, "parameter"),
1741                impl_number_args
1742            ),
1743        );
1744
1745        return Err(err.emit_unless_delay(delay));
1746    }
1747
1748    Ok(())
1749}
1750
1751fn compare_synthetic_generics<'tcx>(
1752    tcx: TyCtxt<'tcx>,
1753    impl_m: ty::AssocItem,
1754    trait_m: ty::AssocItem,
1755    delay: bool,
1756) -> Result<(), ErrorGuaranteed> {
1757    // FIXME(chrisvittal) Clean up this function, list of FIXME items:
1758    //     1. Better messages for the span labels
1759    //     2. Explanation as to what is going on
1760    // If we get here, we already have the same number of generics, so the zip will
1761    // be okay.
1762    let mut error_found = None;
1763    let impl_m_generics = tcx.generics_of(impl_m.def_id);
1764    let trait_m_generics = tcx.generics_of(trait_m.def_id);
1765    let impl_m_type_params =
1766        impl_m_generics.own_params.iter().filter_map(|param| match param.kind {
1767            GenericParamDefKind::Type { synthetic, .. } => Some((param.def_id, synthetic)),
1768            GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => None,
1769        });
1770    let trait_m_type_params =
1771        trait_m_generics.own_params.iter().filter_map(|param| match param.kind {
1772            GenericParamDefKind::Type { synthetic, .. } => Some((param.def_id, synthetic)),
1773            GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => None,
1774        });
1775    for ((impl_def_id, impl_synthetic), (trait_def_id, trait_synthetic)) in
1776        iter::zip(impl_m_type_params, trait_m_type_params)
1777    {
1778        if impl_synthetic != trait_synthetic {
1779            let impl_def_id = impl_def_id.expect_local();
1780            let impl_span = tcx.def_span(impl_def_id);
1781            let trait_span = tcx.def_span(trait_def_id);
1782            let mut err = struct_span_code_err!(
1783                tcx.dcx(),
1784                impl_span,
1785                E0643,
1786                "method `{}` has incompatible signature for trait",
1787                trait_m.name()
1788            );
1789            err.span_label(trait_span, "declaration in trait here");
1790            if impl_synthetic {
1791                // The case where the impl method uses `impl Trait` but the trait method uses
1792                // explicit generics
1793                err.span_label(impl_span, "expected generic parameter, found `impl Trait`");
1794                let _: Option<_> = try {
1795                    // try taking the name from the trait impl
1796                    // FIXME: this is obviously suboptimal since the name can already be used
1797                    // as another generic argument
1798                    let new_name = tcx.opt_item_name(trait_def_id)?;
1799                    let trait_m = trait_m.def_id.as_local()?;
1800                    let trait_m = tcx.hir_expect_trait_item(trait_m);
1801
1802                    let impl_m = impl_m.def_id.as_local()?;
1803                    let impl_m = tcx.hir_expect_impl_item(impl_m);
1804
1805                    // in case there are no generics, take the spot between the function name
1806                    // and the opening paren of the argument list
1807                    let new_generics_span = tcx.def_ident_span(impl_def_id)?.shrink_to_hi();
1808                    // in case there are generics, just replace them
1809                    let generics_span = impl_m.generics.span.substitute_dummy(new_generics_span);
1810                    // replace with the generics from the trait
1811                    let new_generics =
1812                        tcx.sess.source_map().span_to_snippet(trait_m.generics.span).ok()?;
1813
1814                    err.multipart_suggestion(
1815                        "try changing the `impl Trait` argument to a generic parameter",
1816                        vec![
1817                            // replace `impl Trait` with `T`
1818                            (impl_span, new_name.to_string()),
1819                            // replace impl method generics with trait method generics
1820                            // This isn't quite right, as users might have changed the names
1821                            // of the generics, but it works for the common case
1822                            (generics_span, new_generics),
1823                        ],
1824                        Applicability::MaybeIncorrect,
1825                    );
1826                };
1827            } else {
1828                // The case where the trait method uses `impl Trait`, but the impl method uses
1829                // explicit generics.
1830                err.span_label(impl_span, "expected `impl Trait`, found generic parameter");
1831                let _: Option<_> = try {
1832                    let impl_m = impl_m.def_id.as_local()?;
1833                    let impl_m = tcx.hir_expect_impl_item(impl_m);
1834                    let (sig, _) = impl_m.expect_fn();
1835                    let input_tys = sig.decl.inputs;
1836
1837                    struct Visitor(hir::def_id::LocalDefId);
1838                    impl<'v> intravisit::Visitor<'v> for Visitor {
1839                        type Result = ControlFlow<Span>;
1840                        fn visit_ty(&mut self, ty: &'v hir::Ty<'v, AmbigArg>) -> Self::Result {
1841                            if let hir::TyKind::Path(hir::QPath::Resolved(None, path)) = ty.kind
1842                                && let Res::Def(DefKind::TyParam, def_id) = path.res
1843                                && def_id == self.0.to_def_id()
1844                            {
1845                                ControlFlow::Break(ty.span)
1846                            } else {
1847                                intravisit::walk_ty(self, ty)
1848                            }
1849                        }
1850                    }
1851
1852                    let span = input_tys
1853                        .iter()
1854                        .find_map(|ty| Visitor(impl_def_id).visit_ty_unambig(ty).break_value())?;
1855
1856                    let bounds = impl_m.generics.bounds_for_param(impl_def_id).next()?.bounds;
1857                    let bounds = bounds.first()?.span().to(bounds.last()?.span());
1858                    let bounds = tcx.sess.source_map().span_to_snippet(bounds).ok()?;
1859
1860                    err.multipart_suggestion(
1861                        "try removing the generic parameter and using `impl Trait` instead",
1862                        vec![
1863                            // delete generic parameters
1864                            (impl_m.generics.span, String::new()),
1865                            // replace param usage with `impl Trait`
1866                            (span, format!("impl {bounds}")),
1867                        ],
1868                        Applicability::MaybeIncorrect,
1869                    );
1870                };
1871            }
1872            error_found = Some(err.emit_unless_delay(delay));
1873        }
1874    }
1875    if let Some(reported) = error_found { Err(reported) } else { Ok(()) }
1876}
1877
1878/// Checks that all parameters in the generics of a given assoc item in a trait impl have
1879/// the same kind as the respective generic parameter in the trait def.
1880///
1881/// For example all 4 errors in the following code are emitted here:
1882/// ```rust,ignore (pseudo-Rust)
1883/// trait Foo {
1884///     fn foo<const N: u8>();
1885///     type Bar<const N: u8>;
1886///     fn baz<const N: u32>();
1887///     type Blah<T>;
1888/// }
1889///
1890/// impl Foo for () {
1891///     fn foo<const N: u64>() {}
1892///     //~^ error
1893///     type Bar<const N: u64> = ();
1894///     //~^ error
1895///     fn baz<T>() {}
1896///     //~^ error
1897///     type Blah<const N: i64> = u32;
1898///     //~^ error
1899/// }
1900/// ```
1901///
1902/// This function does not handle lifetime parameters
1903fn compare_generic_param_kinds<'tcx>(
1904    tcx: TyCtxt<'tcx>,
1905    impl_item: ty::AssocItem,
1906    trait_item: ty::AssocItem,
1907    delay: bool,
1908) -> Result<(), ErrorGuaranteed> {
1909    assert_eq!(impl_item.as_tag(), trait_item.as_tag());
1910
1911    let ty_const_params_of = |def_id| {
1912        tcx.generics_of(def_id).own_params.iter().filter(|param| {
1913            matches!(
1914                param.kind,
1915                GenericParamDefKind::Const { .. } | GenericParamDefKind::Type { .. }
1916            )
1917        })
1918    };
1919
1920    for (param_impl, param_trait) in
1921        iter::zip(ty_const_params_of(impl_item.def_id), ty_const_params_of(trait_item.def_id))
1922    {
1923        use GenericParamDefKind::*;
1924        if match (&param_impl.kind, &param_trait.kind) {
1925            (Const { .. }, Const { .. })
1926                if tcx.type_of(param_impl.def_id) != tcx.type_of(param_trait.def_id) =>
1927            {
1928                true
1929            }
1930            (Const { .. }, Type { .. }) | (Type { .. }, Const { .. }) => true,
1931            // this is exhaustive so that anyone adding new generic param kinds knows
1932            // to make sure this error is reported for them.
1933            (Const { .. }, Const { .. }) | (Type { .. }, Type { .. }) => false,
1934            (Lifetime { .. }, _) | (_, Lifetime { .. }) => {
1935                bug!("lifetime params are expected to be filtered by `ty_const_params_of`")
1936            }
1937        } {
1938            let param_impl_span = tcx.def_span(param_impl.def_id);
1939            let param_trait_span = tcx.def_span(param_trait.def_id);
1940
1941            let mut err = struct_span_code_err!(
1942                tcx.dcx(),
1943                param_impl_span,
1944                E0053,
1945                "{} `{}` has an incompatible generic parameter for trait `{}`",
1946                impl_item.descr(),
1947                trait_item.name(),
1948                &tcx.def_path_str(tcx.parent(trait_item.def_id))
1949            );
1950
1951            let make_param_message = |prefix: &str, param: &ty::GenericParamDef| match param.kind {
1952                Const { .. } => {
1953                    format!(
1954                        "{} const parameter of type `{}`",
1955                        prefix,
1956                        tcx.type_of(param.def_id).instantiate_identity()
1957                    )
1958                }
1959                Type { .. } => format!("{prefix} type parameter"),
1960                Lifetime { .. } => span_bug!(
1961                    tcx.def_span(param.def_id),
1962                    "lifetime params are expected to be filtered by `ty_const_params_of`"
1963                ),
1964            };
1965
1966            let trait_header_span = tcx.def_ident_span(tcx.parent(trait_item.def_id)).unwrap();
1967            err.span_label(trait_header_span, "");
1968            err.span_label(param_trait_span, make_param_message("expected", param_trait));
1969
1970            let impl_header_span = tcx.def_span(tcx.parent(impl_item.def_id));
1971            err.span_label(impl_header_span, "");
1972            err.span_label(param_impl_span, make_param_message("found", param_impl));
1973
1974            let reported = err.emit_unless_delay(delay);
1975            return Err(reported);
1976        }
1977    }
1978
1979    Ok(())
1980}
1981
1982fn compare_impl_const<'tcx>(
1983    tcx: TyCtxt<'tcx>,
1984    impl_const_item: ty::AssocItem,
1985    trait_const_item: ty::AssocItem,
1986    impl_trait_ref: ty::TraitRef<'tcx>,
1987) -> Result<(), ErrorGuaranteed> {
1988    compare_number_of_generics(tcx, impl_const_item, trait_const_item, false)?;
1989    compare_generic_param_kinds(tcx, impl_const_item, trait_const_item, false)?;
1990    check_region_bounds_on_impl_item(tcx, impl_const_item, trait_const_item, false)?;
1991    compare_const_predicate_entailment(tcx, impl_const_item, trait_const_item, impl_trait_ref)
1992}
1993
1994/// The equivalent of [compare_method_predicate_entailment], but for associated constants
1995/// instead of associated functions.
1996// FIXME(generic_const_items): If possible extract the common parts of `compare_{type,const}_predicate_entailment`.
1997#[instrument(level = "debug", skip(tcx))]
1998fn compare_const_predicate_entailment<'tcx>(
1999    tcx: TyCtxt<'tcx>,
2000    impl_ct: ty::AssocItem,
2001    trait_ct: ty::AssocItem,
2002    impl_trait_ref: ty::TraitRef<'tcx>,
2003) -> Result<(), ErrorGuaranteed> {
2004    let impl_ct_def_id = impl_ct.def_id.expect_local();
2005    let impl_ct_span = tcx.def_span(impl_ct_def_id);
2006
2007    // The below is for the most part highly similar to the procedure
2008    // for methods above. It is simpler in many respects, especially
2009    // because we shouldn't really have to deal with lifetimes or
2010    // predicates. In fact some of this should probably be put into
2011    // shared functions because of DRY violations...
2012    let trait_to_impl_args = GenericArgs::identity_for_item(tcx, impl_ct.def_id).rebase_onto(
2013        tcx,
2014        impl_ct.container_id(tcx),
2015        impl_trait_ref.args,
2016    );
2017
2018    // Create a parameter environment that represents the implementation's
2019    // associated const.
2020    let impl_ty = tcx.type_of(impl_ct_def_id).instantiate_identity();
2021
2022    let trait_ty = tcx.type_of(trait_ct.def_id).instantiate(tcx, trait_to_impl_args);
2023    let code = ObligationCauseCode::CompareImplItem {
2024        impl_item_def_id: impl_ct_def_id,
2025        trait_item_def_id: trait_ct.def_id,
2026        kind: impl_ct.kind,
2027    };
2028    let mut cause = ObligationCause::new(impl_ct_span, impl_ct_def_id, code.clone());
2029
2030    let impl_ct_predicates = tcx.predicates_of(impl_ct.def_id);
2031    let trait_ct_predicates = tcx.predicates_of(trait_ct.def_id);
2032
2033    // The predicates declared by the impl definition, the trait and the
2034    // associated const in the trait are assumed.
2035    let impl_predicates = tcx.predicates_of(impl_ct_predicates.parent.unwrap());
2036    let mut hybrid_preds = impl_predicates.instantiate_identity(tcx).predicates;
2037    hybrid_preds.extend(
2038        trait_ct_predicates
2039            .instantiate_own(tcx, trait_to_impl_args)
2040            .map(|(predicate, _)| predicate),
2041    );
2042
2043    let param_env = ty::ParamEnv::new(tcx.mk_clauses(&hybrid_preds));
2044    let param_env = traits::normalize_param_env_or_error(
2045        tcx,
2046        param_env,
2047        ObligationCause::misc(impl_ct_span, impl_ct_def_id),
2048    );
2049
2050    let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
2051    let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
2052
2053    let impl_ct_own_bounds = impl_ct_predicates.instantiate_own_identity();
2054    for (predicate, span) in impl_ct_own_bounds {
2055        let cause = ObligationCause::misc(span, impl_ct_def_id);
2056        let predicate = ocx.normalize(&cause, param_env, predicate);
2057
2058        let cause = ObligationCause::new(span, impl_ct_def_id, code.clone());
2059        ocx.register_obligation(traits::Obligation::new(tcx, cause, param_env, predicate));
2060    }
2061
2062    // There is no "body" here, so just pass dummy id.
2063    let impl_ty = ocx.normalize(&cause, param_env, impl_ty);
2064    debug!(?impl_ty);
2065
2066    let trait_ty = ocx.normalize(&cause, param_env, trait_ty);
2067    debug!(?trait_ty);
2068
2069    let err = ocx.sup(&cause, param_env, trait_ty, impl_ty);
2070
2071    if let Err(terr) = err {
2072        debug!(?impl_ty, ?trait_ty);
2073
2074        // Locate the Span containing just the type of the offending impl
2075        let (ty, _) = tcx.hir_expect_impl_item(impl_ct_def_id).expect_const();
2076        cause.span = ty.span;
2077
2078        let mut diag = struct_span_code_err!(
2079            tcx.dcx(),
2080            cause.span,
2081            E0326,
2082            "implemented const `{}` has an incompatible type for trait",
2083            trait_ct.name()
2084        );
2085
2086        let trait_c_span = trait_ct.def_id.as_local().map(|trait_ct_def_id| {
2087            // Add a label to the Span containing just the type of the const
2088            let (ty, _) = tcx.hir_expect_trait_item(trait_ct_def_id).expect_const();
2089            ty.span
2090        });
2091
2092        infcx.err_ctxt().note_type_err(
2093            &mut diag,
2094            &cause,
2095            trait_c_span.map(|span| (span, Cow::from("type in trait"), false)),
2096            Some(param_env.and(infer::ValuePairs::Terms(ExpectedFound {
2097                expected: trait_ty.into(),
2098                found: impl_ty.into(),
2099            }))),
2100            terr,
2101            false,
2102            None,
2103        );
2104        return Err(diag.emit());
2105    };
2106
2107    // Check that all obligations are satisfied by the implementation's
2108    // version.
2109    let errors = ocx.select_all_or_error();
2110    if !errors.is_empty() {
2111        return Err(infcx.err_ctxt().report_fulfillment_errors(errors));
2112    }
2113
2114    ocx.resolve_regions_and_report_errors(impl_ct_def_id, param_env, [])
2115}
2116
2117#[instrument(level = "debug", skip(tcx))]
2118fn compare_impl_ty<'tcx>(
2119    tcx: TyCtxt<'tcx>,
2120    impl_ty: ty::AssocItem,
2121    trait_ty: ty::AssocItem,
2122    impl_trait_ref: ty::TraitRef<'tcx>,
2123) -> Result<(), ErrorGuaranteed> {
2124    compare_number_of_generics(tcx, impl_ty, trait_ty, false)?;
2125    compare_generic_param_kinds(tcx, impl_ty, trait_ty, false)?;
2126    check_region_bounds_on_impl_item(tcx, impl_ty, trait_ty, false)?;
2127    compare_type_predicate_entailment(tcx, impl_ty, trait_ty, impl_trait_ref)?;
2128    check_type_bounds(tcx, trait_ty, impl_ty, impl_trait_ref)
2129}
2130
2131/// The equivalent of [compare_method_predicate_entailment], but for associated types
2132/// instead of associated functions.
2133#[instrument(level = "debug", skip(tcx))]
2134fn compare_type_predicate_entailment<'tcx>(
2135    tcx: TyCtxt<'tcx>,
2136    impl_ty: ty::AssocItem,
2137    trait_ty: ty::AssocItem,
2138    impl_trait_ref: ty::TraitRef<'tcx>,
2139) -> Result<(), ErrorGuaranteed> {
2140    let impl_def_id = impl_ty.container_id(tcx);
2141    let trait_to_impl_args = GenericArgs::identity_for_item(tcx, impl_ty.def_id).rebase_onto(
2142        tcx,
2143        impl_def_id,
2144        impl_trait_ref.args,
2145    );
2146
2147    let impl_ty_predicates = tcx.predicates_of(impl_ty.def_id);
2148    let trait_ty_predicates = tcx.predicates_of(trait_ty.def_id);
2149
2150    let impl_ty_own_bounds = impl_ty_predicates.instantiate_own_identity();
2151    // If there are no bounds, then there are no const conditions, so no need to check that here.
2152    if impl_ty_own_bounds.len() == 0 {
2153        // Nothing to check.
2154        return Ok(());
2155    }
2156
2157    // This `DefId` should be used for the `body_id` field on each
2158    // `ObligationCause` (and the `FnCtxt`). This is what
2159    // `regionck_item` expects.
2160    let impl_ty_def_id = impl_ty.def_id.expect_local();
2161    debug!(?trait_to_impl_args);
2162
2163    // The predicates declared by the impl definition, the trait and the
2164    // associated type in the trait are assumed.
2165    let impl_predicates = tcx.predicates_of(impl_ty_predicates.parent.unwrap());
2166    let mut hybrid_preds = impl_predicates.instantiate_identity(tcx).predicates;
2167    hybrid_preds.extend(
2168        trait_ty_predicates
2169            .instantiate_own(tcx, trait_to_impl_args)
2170            .map(|(predicate, _)| predicate),
2171    );
2172    debug!(?hybrid_preds);
2173
2174    let impl_ty_span = tcx.def_span(impl_ty_def_id);
2175    let normalize_cause = ObligationCause::misc(impl_ty_span, impl_ty_def_id);
2176
2177    let is_conditionally_const = tcx.is_conditionally_const(impl_ty.def_id);
2178    if is_conditionally_const {
2179        // Augment the hybrid param-env with the const conditions
2180        // of the impl header and the trait assoc type.
2181        hybrid_preds.extend(
2182            tcx.const_conditions(impl_ty_predicates.parent.unwrap())
2183                .instantiate_identity(tcx)
2184                .into_iter()
2185                .chain(
2186                    tcx.const_conditions(trait_ty.def_id).instantiate_own(tcx, trait_to_impl_args),
2187                )
2188                .map(|(trait_ref, _)| {
2189                    trait_ref.to_host_effect_clause(tcx, ty::BoundConstness::Maybe)
2190                }),
2191        );
2192    }
2193
2194    let param_env = ty::ParamEnv::new(tcx.mk_clauses(&hybrid_preds));
2195    let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause);
2196    debug!(caller_bounds=?param_env.caller_bounds());
2197
2198    let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
2199    let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
2200
2201    for (predicate, span) in impl_ty_own_bounds {
2202        let cause = ObligationCause::misc(span, impl_ty_def_id);
2203        let predicate = ocx.normalize(&cause, param_env, predicate);
2204
2205        let cause = ObligationCause::new(
2206            span,
2207            impl_ty_def_id,
2208            ObligationCauseCode::CompareImplItem {
2209                impl_item_def_id: impl_ty.def_id.expect_local(),
2210                trait_item_def_id: trait_ty.def_id,
2211                kind: impl_ty.kind,
2212            },
2213        );
2214        ocx.register_obligation(traits::Obligation::new(tcx, cause, param_env, predicate));
2215    }
2216
2217    if is_conditionally_const {
2218        // Validate the const conditions of the impl associated type.
2219        let impl_ty_own_const_conditions =
2220            tcx.const_conditions(impl_ty.def_id).instantiate_own_identity();
2221        for (const_condition, span) in impl_ty_own_const_conditions {
2222            let normalize_cause = traits::ObligationCause::misc(span, impl_ty_def_id);
2223            let const_condition = ocx.normalize(&normalize_cause, param_env, const_condition);
2224
2225            let cause = ObligationCause::new(
2226                span,
2227                impl_ty_def_id,
2228                ObligationCauseCode::CompareImplItem {
2229                    impl_item_def_id: impl_ty_def_id,
2230                    trait_item_def_id: trait_ty.def_id,
2231                    kind: impl_ty.kind,
2232                },
2233            );
2234            ocx.register_obligation(traits::Obligation::new(
2235                tcx,
2236                cause,
2237                param_env,
2238                const_condition.to_host_effect_clause(tcx, ty::BoundConstness::Maybe),
2239            ));
2240        }
2241    }
2242
2243    // Check that all obligations are satisfied by the implementation's
2244    // version.
2245    let errors = ocx.select_all_or_error();
2246    if !errors.is_empty() {
2247        let reported = infcx.err_ctxt().report_fulfillment_errors(errors);
2248        return Err(reported);
2249    }
2250
2251    // Finally, resolve all regions. This catches wily misuses of
2252    // lifetime parameters.
2253    ocx.resolve_regions_and_report_errors(impl_ty_def_id, param_env, [])
2254}
2255
2256/// Validate that `ProjectionCandidate`s created for this associated type will
2257/// be valid.
2258///
2259/// Usually given
2260///
2261/// trait X { type Y: Copy } impl X for T { type Y = S; }
2262///
2263/// We are able to normalize `<T as X>::Y` to `S`, and so when we check the
2264/// impl is well-formed we have to prove `S: Copy`.
2265///
2266/// For default associated types the normalization is not possible (the value
2267/// from the impl could be overridden). We also can't normalize generic
2268/// associated types (yet) because they contain bound parameters.
2269#[instrument(level = "debug", skip(tcx))]
2270pub(super) fn check_type_bounds<'tcx>(
2271    tcx: TyCtxt<'tcx>,
2272    trait_ty: ty::AssocItem,
2273    impl_ty: ty::AssocItem,
2274    impl_trait_ref: ty::TraitRef<'tcx>,
2275) -> Result<(), ErrorGuaranteed> {
2276    // Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case
2277    // other `Foo` impls are incoherent.
2278    tcx.ensure_ok().coherent_trait(impl_trait_ref.def_id)?;
2279
2280    let param_env = tcx.param_env(impl_ty.def_id);
2281    debug!(?param_env);
2282
2283    let container_id = impl_ty.container_id(tcx);
2284    let impl_ty_def_id = impl_ty.def_id.expect_local();
2285    let impl_ty_args = GenericArgs::identity_for_item(tcx, impl_ty.def_id);
2286    let rebased_args = impl_ty_args.rebase_onto(tcx, container_id, impl_trait_ref.args);
2287
2288    let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
2289    let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
2290
2291    // A synthetic impl Trait for RPITIT desugaring or assoc type for effects desugaring has no HIR,
2292    // which we currently use to get the span for an impl's associated type. Instead, for these,
2293    // use the def_span for the synthesized  associated type.
2294    let impl_ty_span = if impl_ty.is_impl_trait_in_trait() {
2295        tcx.def_span(impl_ty_def_id)
2296    } else {
2297        match tcx.hir_node_by_def_id(impl_ty_def_id) {
2298            hir::Node::TraitItem(hir::TraitItem {
2299                kind: hir::TraitItemKind::Type(_, Some(ty)),
2300                ..
2301            }) => ty.span,
2302            hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Type(ty), .. }) => ty.span,
2303            item => span_bug!(
2304                tcx.def_span(impl_ty_def_id),
2305                "cannot call `check_type_bounds` on item: {item:?}",
2306            ),
2307        }
2308    };
2309    let assumed_wf_types = ocx.assumed_wf_types_and_report_errors(param_env, impl_ty_def_id)?;
2310
2311    let normalize_cause = ObligationCause::new(
2312        impl_ty_span,
2313        impl_ty_def_id,
2314        ObligationCauseCode::CheckAssociatedTypeBounds {
2315            impl_item_def_id: impl_ty.def_id.expect_local(),
2316            trait_item_def_id: trait_ty.def_id,
2317        },
2318    );
2319    let mk_cause = |span: Span| {
2320        let code = ObligationCauseCode::WhereClause(trait_ty.def_id, span);
2321        ObligationCause::new(impl_ty_span, impl_ty_def_id, code)
2322    };
2323
2324    let mut obligations: Vec<_> = util::elaborate(
2325        tcx,
2326        tcx.explicit_item_bounds(trait_ty.def_id).iter_instantiated_copied(tcx, rebased_args).map(
2327            |(concrete_ty_bound, span)| {
2328                debug!(?concrete_ty_bound);
2329                traits::Obligation::new(tcx, mk_cause(span), param_env, concrete_ty_bound)
2330            },
2331        ),
2332    )
2333    .collect();
2334
2335    // Only in a const implementation do we need to check that the `[const]` item bounds hold.
2336    if tcx.is_conditionally_const(impl_ty_def_id) {
2337        obligations.extend(util::elaborate(
2338            tcx,
2339            tcx.explicit_implied_const_bounds(trait_ty.def_id)
2340                .iter_instantiated_copied(tcx, rebased_args)
2341                .map(|(c, span)| {
2342                    traits::Obligation::new(
2343                        tcx,
2344                        mk_cause(span),
2345                        param_env,
2346                        c.to_host_effect_clause(tcx, ty::BoundConstness::Maybe),
2347                    )
2348                }),
2349        ));
2350    }
2351    debug!(item_bounds=?obligations);
2352
2353    // Normalize predicates with the assumption that the GAT may always normalize
2354    // to its definition type. This should be the param-env we use to *prove* the
2355    // predicate too, but we don't do that because of performance issues.
2356    // See <https://github.com/rust-lang/rust/pull/117542#issue-1976337685>.
2357    let normalize_param_env = param_env_with_gat_bounds(tcx, impl_ty, impl_trait_ref);
2358    for obligation in &mut obligations {
2359        match ocx.deeply_normalize(&normalize_cause, normalize_param_env, obligation.predicate) {
2360            Ok(pred) => obligation.predicate = pred,
2361            Err(e) => {
2362                return Err(infcx.err_ctxt().report_fulfillment_errors(e));
2363            }
2364        }
2365    }
2366
2367    // Check that all obligations are satisfied by the implementation's
2368    // version.
2369    ocx.register_obligations(obligations);
2370    let errors = ocx.select_all_or_error();
2371    if !errors.is_empty() {
2372        let reported = infcx.err_ctxt().report_fulfillment_errors(errors);
2373        return Err(reported);
2374    }
2375
2376    // Finally, resolve all regions. This catches wily misuses of
2377    // lifetime parameters.
2378    ocx.resolve_regions_and_report_errors(impl_ty_def_id, param_env, assumed_wf_types)
2379}
2380
2381/// Install projection predicates that allow GATs to project to their own
2382/// definition types. This is not allowed in general in cases of default
2383/// associated types in trait definitions, or when specialization is involved,
2384/// but is needed when checking these definition types actually satisfy the
2385/// trait bounds of the GAT.
2386///
2387/// # How it works
2388///
2389/// ```ignore (example)
2390/// impl<A, B> Foo<u32> for (A, B) {
2391///     type Bar<C> = Wrapper<A, B, C>
2392/// }
2393/// ```
2394///
2395/// - `impl_trait_ref` would be `<(A, B) as Foo<u32>>`
2396/// - `normalize_impl_ty_args` would be `[A, B, ^0.0]` (`^0.0` here is the bound var with db 0 and index 0)
2397/// - `normalize_impl_ty` would be `Wrapper<A, B, ^0.0>`
2398/// - `rebased_args` would be `[(A, B), u32, ^0.0]`, combining the args from
2399///    the *trait* with the generic associated type parameters (as bound vars).
2400///
2401/// A note regarding the use of bound vars here:
2402/// Imagine as an example
2403/// ```
2404/// trait Family {
2405///     type Member<C: Eq>;
2406/// }
2407///
2408/// impl Family for VecFamily {
2409///     type Member<C: Eq> = i32;
2410/// }
2411/// ```
2412/// Here, we would generate
2413/// ```ignore (pseudo-rust)
2414/// forall<C> { Normalize(<VecFamily as Family>::Member<C> => i32) }
2415/// ```
2416///
2417/// when we really would like to generate
2418/// ```ignore (pseudo-rust)
2419/// forall<C> { Normalize(<VecFamily as Family>::Member<C> => i32) :- Implemented(C: Eq) }
2420/// ```
2421///
2422/// But, this is probably fine, because although the first clause can be used with types `C` that
2423/// do not implement `Eq`, for it to cause some kind of problem, there would have to be a
2424/// `VecFamily::Member<X>` for some type `X` where `!(X: Eq)`, that appears in the value of type
2425/// `Member<C: Eq> = ....` That type would fail a well-formedness check that we ought to be doing
2426/// elsewhere, which would check that any `<T as Family>::Member<X>` meets the bounds declared in
2427/// the trait (notably, that `X: Eq` and `T: Family`).
2428fn param_env_with_gat_bounds<'tcx>(
2429    tcx: TyCtxt<'tcx>,
2430    impl_ty: ty::AssocItem,
2431    impl_trait_ref: ty::TraitRef<'tcx>,
2432) -> ty::ParamEnv<'tcx> {
2433    let param_env = tcx.param_env(impl_ty.def_id);
2434    let container_id = impl_ty.container_id(tcx);
2435    let mut predicates = param_env.caller_bounds().to_vec();
2436
2437    // for RPITITs, we should install predicates that allow us to project all
2438    // of the RPITITs associated with the same body. This is because checking
2439    // the item bounds of RPITITs often involves nested RPITITs having to prove
2440    // bounds about themselves.
2441    let impl_tys_to_install = match impl_ty.kind {
2442        ty::AssocKind::Type {
2443            data:
2444                ty::AssocTypeData::Rpitit(
2445                    ty::ImplTraitInTraitData::Impl { fn_def_id }
2446                    | ty::ImplTraitInTraitData::Trait { fn_def_id, .. },
2447                ),
2448        } => tcx
2449            .associated_types_for_impl_traits_in_associated_fn(fn_def_id)
2450            .iter()
2451            .map(|def_id| tcx.associated_item(*def_id))
2452            .collect(),
2453        _ => vec![impl_ty],
2454    };
2455
2456    for impl_ty in impl_tys_to_install {
2457        let trait_ty = match impl_ty.container {
2458            ty::AssocContainer::InherentImpl => bug!(),
2459            ty::AssocContainer::Trait => impl_ty,
2460            ty::AssocContainer::TraitImpl(Err(_)) => continue,
2461            ty::AssocContainer::TraitImpl(Ok(trait_item_def_id)) => {
2462                tcx.associated_item(trait_item_def_id)
2463            }
2464        };
2465
2466        let mut bound_vars: smallvec::SmallVec<[ty::BoundVariableKind; 8]> =
2467            smallvec::SmallVec::with_capacity(tcx.generics_of(impl_ty.def_id).own_params.len());
2468        // Extend the impl's identity args with late-bound GAT vars
2469        let normalize_impl_ty_args = ty::GenericArgs::identity_for_item(tcx, container_id)
2470            .extend_to(tcx, impl_ty.def_id, |param, _| match param.kind {
2471                GenericParamDefKind::Type { .. } => {
2472                    let kind = ty::BoundTyKind::Param(param.def_id);
2473                    let bound_var = ty::BoundVariableKind::Ty(kind);
2474                    bound_vars.push(bound_var);
2475                    Ty::new_bound(
2476                        tcx,
2477                        ty::INNERMOST,
2478                        ty::BoundTy { var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind },
2479                    )
2480                    .into()
2481                }
2482                GenericParamDefKind::Lifetime => {
2483                    let kind = ty::BoundRegionKind::Named(param.def_id);
2484                    let bound_var = ty::BoundVariableKind::Region(kind);
2485                    bound_vars.push(bound_var);
2486                    ty::Region::new_bound(
2487                        tcx,
2488                        ty::INNERMOST,
2489                        ty::BoundRegion {
2490                            var: ty::BoundVar::from_usize(bound_vars.len() - 1),
2491                            kind,
2492                        },
2493                    )
2494                    .into()
2495                }
2496                GenericParamDefKind::Const { .. } => {
2497                    let bound_var = ty::BoundVariableKind::Const;
2498                    bound_vars.push(bound_var);
2499                    ty::Const::new_bound(
2500                        tcx,
2501                        ty::INNERMOST,
2502                        ty::BoundConst { var: ty::BoundVar::from_usize(bound_vars.len() - 1) },
2503                    )
2504                    .into()
2505                }
2506            });
2507        // When checking something like
2508        //
2509        // trait X { type Y: PartialEq<<Self as X>::Y> }
2510        // impl X for T { default type Y = S; }
2511        //
2512        // We will have to prove the bound S: PartialEq<<T as X>::Y>. In this case
2513        // we want <T as X>::Y to normalize to S. This is valid because we are
2514        // checking the default value specifically here. Add this equality to the
2515        // ParamEnv for normalization specifically.
2516        let normalize_impl_ty =
2517            tcx.type_of(impl_ty.def_id).instantiate(tcx, normalize_impl_ty_args);
2518        let rebased_args =
2519            normalize_impl_ty_args.rebase_onto(tcx, container_id, impl_trait_ref.args);
2520        let bound_vars = tcx.mk_bound_variable_kinds(&bound_vars);
2521
2522        match normalize_impl_ty.kind() {
2523            ty::Alias(ty::Projection, proj)
2524                if proj.def_id == trait_ty.def_id && proj.args == rebased_args =>
2525            {
2526                // Don't include this predicate if the projected type is
2527                // exactly the same as the projection. This can occur in
2528                // (somewhat dubious) code like this:
2529                //
2530                // impl<T> X for T where T: X { type Y = <T as X>::Y; }
2531            }
2532            _ => predicates.push(
2533                ty::Binder::bind_with_vars(
2534                    ty::ProjectionPredicate {
2535                        projection_term: ty::AliasTerm::new_from_args(
2536                            tcx,
2537                            trait_ty.def_id,
2538                            rebased_args,
2539                        ),
2540                        term: normalize_impl_ty.into(),
2541                    },
2542                    bound_vars,
2543                )
2544                .upcast(tcx),
2545            ),
2546        };
2547    }
2548
2549    ty::ParamEnv::new(tcx.mk_clauses(&predicates))
2550}
2551
2552/// Manually check here that `async fn foo()` wasn't matched against `fn foo()`,
2553/// and extract a better error if so.
2554fn try_report_async_mismatch<'tcx>(
2555    tcx: TyCtxt<'tcx>,
2556    infcx: &InferCtxt<'tcx>,
2557    errors: &[FulfillmentError<'tcx>],
2558    trait_m: ty::AssocItem,
2559    impl_m: ty::AssocItem,
2560    impl_sig: ty::FnSig<'tcx>,
2561) -> Result<(), ErrorGuaranteed> {
2562    if !tcx.asyncness(trait_m.def_id).is_async() {
2563        return Ok(());
2564    }
2565
2566    let ty::Alias(ty::Projection, ty::AliasTy { def_id: async_future_def_id, .. }) =
2567        *tcx.fn_sig(trait_m.def_id).skip_binder().skip_binder().output().kind()
2568    else {
2569        bug!("expected `async fn` to return an RPITIT");
2570    };
2571
2572    for error in errors {
2573        if let ObligationCauseCode::WhereClause(def_id, _) = *error.root_obligation.cause.code()
2574            && def_id == async_future_def_id
2575            && let Some(proj) = error.root_obligation.predicate.as_projection_clause()
2576            && let Some(proj) = proj.no_bound_vars()
2577            && infcx.can_eq(
2578                error.root_obligation.param_env,
2579                proj.term.expect_type(),
2580                impl_sig.output(),
2581            )
2582        {
2583            // FIXME: We should suggest making the fn `async`, but extracting
2584            // the right span is a bit difficult.
2585            return Err(tcx.sess.dcx().emit_err(MethodShouldReturnFuture {
2586                span: tcx.def_span(impl_m.def_id),
2587                method_name: tcx.item_ident(impl_m.def_id),
2588                trait_item_span: tcx.hir_span_if_local(trait_m.def_id),
2589            }));
2590        }
2591    }
2592
2593    Ok(())
2594}