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