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