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, 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::fold::BottomUpFolder;
16use rustc_middle::ty::util::ExplicitSelf;
17use rustc_middle::ty::{
18 self, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeFoldable, TypeFolder,
19 TypeSuperFoldable, TypeVisitableExt, TypingMode, Upcast,
20};
21use rustc_middle::{bug, span_bug};
22use rustc_span::Span;
23use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
24use rustc_trait_selection::infer::InferCtxtExt;
25use rustc_trait_selection::regions::InferCtxtRegionExt;
26use rustc_trait_selection::traits::{
27 self, FulfillmentError, ObligationCause, ObligationCauseCode, ObligationCtxt,
28};
29use tracing::{debug, instrument};
30
31use super::potentially_plural_count;
32use crate::errors::{LifetimesOrBoundsMismatchOnTrait, MethodShouldReturnFuture};
33
34pub(super) mod refine;
35
36pub(super) fn compare_impl_item(
38 tcx: TyCtxt<'_>,
39 impl_item_def_id: LocalDefId,
40) -> Result<(), ErrorGuaranteed> {
41 let impl_item = tcx.associated_item(impl_item_def_id);
42 let trait_item = tcx.associated_item(impl_item.trait_item_def_id.unwrap());
43 let impl_trait_ref =
44 tcx.impl_trait_ref(impl_item.container_id(tcx)).unwrap().instantiate_identity();
45 debug!(?impl_trait_ref);
46
47 match impl_item.kind {
48 ty::AssocKind::Fn => compare_impl_method(tcx, impl_item, trait_item, impl_trait_ref),
49 ty::AssocKind::Type => compare_impl_ty(tcx, impl_item, trait_item, impl_trait_ref),
50 ty::AssocKind::Const => compare_impl_const(tcx, impl_item, trait_item, impl_trait_ref),
51 }
52}
53
54#[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
74fn 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#[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 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 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 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 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 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 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 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 wf_tys.extend(trait_sig.inputs_and_output.iter());
329 let trait_sig = ocx.normalize(&norm_cause, param_env, trait_sig);
330 wf_tys.extend(trait_sig.inputs_and_output.iter());
333 debug!(?trait_sig);
334
335 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 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 let mut wf_args: smallvec::SmallVec<[_; 4]> =
378 unnormalized_impl_sig.inputs_and_output.iter().map(|ty| ty.into()).collect();
379 let mut wf_args_seen: FxHashSet<_> = wf_args.iter().copied().collect();
382 while let Some(arg) = 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 arg,
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 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(arg)) => {
406 if wf_args_seen.insert(arg) {
407 wf_args.push(arg)
408 }
409 }
410 _ => {}
411 }
412 }
413 }
414 }
415
416 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 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 {
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#[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 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 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 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 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 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 let universe = infcx.create_next_universe();
611 let mut idx = 0;
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 {
629 var: ty::BoundVar::from_usize(idx),
630 kind: ty::BoundTyKind::Anon,
631 },
632 },
633 ),
634 )
635 })
636 .collect();
637 let mut type_mapper = BottomUpFolder {
638 tcx,
639 ty_op: |ty| *mapping.get(&ty).unwrap_or(&ty),
640 lt_op: |lt| lt,
641 ct_op: |ct| ct,
642 };
643 let wf_tys = FxIndexSet::from_iter(
644 unnormalized_trait_sig
645 .inputs_and_output
646 .iter()
647 .chain(trait_sig.inputs_and_output.iter())
648 .map(|ty| ty.fold_with(&mut type_mapper)),
649 );
650
651 match ocx.eq(&cause, param_env, trait_return_ty, impl_return_ty) {
652 Ok(()) => {}
653 Err(terr) => {
654 let mut diag = struct_span_code_err!(
655 tcx.dcx(),
656 cause.span,
657 E0053,
658 "method `{}` has an incompatible return type for trait",
659 trait_m.name
660 );
661 let hir = tcx.hir();
662 infcx.err_ctxt().note_type_err(
663 &mut diag,
664 &cause,
665 hir.get_if_local(impl_m.def_id)
666 .and_then(|node| node.fn_decl())
667 .map(|decl| (decl.output.span(), Cow::from("return type in trait"), false)),
668 Some(param_env.and(infer::ValuePairs::Terms(ExpectedFound {
669 expected: trait_return_ty.into(),
670 found: impl_return_ty.into(),
671 }))),
672 terr,
673 false,
674 None,
675 );
676 return Err(diag.emit());
677 }
678 }
679
680 debug!(?trait_sig, ?impl_sig, "equating function signatures");
681
682 match ocx.eq(&cause, param_env, trait_sig, impl_sig) {
687 Ok(()) => {}
688 Err(terr) => {
689 let emitted = report_trait_method_mismatch(
694 infcx,
695 cause,
696 param_env,
697 terr,
698 (trait_m, trait_sig),
699 (impl_m, impl_sig),
700 impl_trait_ref,
701 );
702 return Err(emitted);
703 }
704 }
705
706 if !unnormalized_trait_sig.output().references_error() && collector.types.is_empty() {
707 tcx.dcx().delayed_bug(
708 "expect >0 RPITITs in call to `collect_return_position_impl_trait_in_trait_tys`",
709 );
710 }
711
712 let collected_types = collector.types;
717 for (_, &(ty, _)) in &collected_types {
718 ocx.register_obligation(traits::Obligation::new(
719 tcx,
720 misc_cause.clone(),
721 param_env,
722 ty::ClauseKind::WellFormed(ty.into()),
723 ));
724 }
725
726 let errors = ocx.select_all_or_error();
729 if !errors.is_empty() {
730 if let Err(guar) = try_report_async_mismatch(tcx, infcx, &errors, trait_m, impl_m, impl_sig)
731 {
732 return Err(guar);
733 }
734
735 let guar = infcx.err_ctxt().report_fulfillment_errors(errors);
736 return Err(guar);
737 }
738
739 ocx.resolve_regions_and_report_errors(impl_m_def_id, param_env, wf_tys)?;
742
743 let mut remapped_types = DefIdMap::default();
744 for (def_id, (ty, args)) in collected_types {
745 match infcx.fully_resolve(ty) {
746 Ok(ty) => {
747 let id_args = GenericArgs::identity_for_item(tcx, def_id);
751 debug!(?id_args, ?args);
752 let map: FxIndexMap<_, _> = std::iter::zip(args, id_args)
753 .skip(tcx.generics_of(trait_m.def_id).count())
754 .filter_map(|(a, b)| Some((a.as_region()?, b.as_region()?)))
755 .collect();
756 debug!(?map);
757
758 let num_trait_args = impl_trait_ref.args.len();
779 let num_impl_args = tcx.generics_of(impl_m.container_id(tcx)).own_params.len();
780 let ty = match ty.try_fold_with(&mut RemapHiddenTyRegions {
781 tcx,
782 map,
783 num_trait_args,
784 num_impl_args,
785 def_id,
786 impl_m_def_id: impl_m.def_id,
787 ty,
788 return_span,
789 }) {
790 Ok(ty) => ty,
791 Err(guar) => Ty::new_error(tcx, guar),
792 };
793 remapped_types.insert(def_id, ty::EarlyBinder::bind(ty));
794 }
795 Err(err) => {
796 tcx.dcx()
801 .span_bug(return_span, format!("could not fully resolve: {ty} => {err:?}"));
802 }
803 }
804 }
805
806 for assoc_item in tcx.associated_types_for_impl_traits_in_associated_fn(trait_m.def_id) {
812 if !remapped_types.contains_key(assoc_item) {
813 remapped_types.insert(
814 *assoc_item,
815 ty::EarlyBinder::bind(Ty::new_error_with_message(
816 tcx,
817 return_span,
818 "missing synthetic item for RPITIT",
819 )),
820 );
821 }
822 }
823
824 Ok(&*tcx.arena.alloc(remapped_types))
825}
826
827struct ImplTraitInTraitCollector<'a, 'tcx, E> {
828 ocx: &'a ObligationCtxt<'a, 'tcx, E>,
829 types: FxIndexMap<DefId, (Ty<'tcx>, ty::GenericArgsRef<'tcx>)>,
830 span: Span,
831 param_env: ty::ParamEnv<'tcx>,
832 body_id: LocalDefId,
833}
834
835impl<'a, 'tcx, E> ImplTraitInTraitCollector<'a, 'tcx, E>
836where
837 E: 'tcx,
838{
839 fn new(
840 ocx: &'a ObligationCtxt<'a, 'tcx, E>,
841 span: Span,
842 param_env: ty::ParamEnv<'tcx>,
843 body_id: LocalDefId,
844 ) -> Self {
845 ImplTraitInTraitCollector { ocx, types: FxIndexMap::default(), span, param_env, body_id }
846 }
847}
848
849impl<'tcx, E> TypeFolder<TyCtxt<'tcx>> for ImplTraitInTraitCollector<'_, 'tcx, E>
850where
851 E: 'tcx,
852{
853 fn cx(&self) -> TyCtxt<'tcx> {
854 self.ocx.infcx.tcx
855 }
856
857 fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
858 if let ty::Alias(ty::Projection, proj) = ty.kind()
859 && self.cx().is_impl_trait_in_trait(proj.def_id)
860 {
861 if let Some((ty, _)) = self.types.get(&proj.def_id) {
862 return *ty;
863 }
864 if proj.args.has_escaping_bound_vars() {
866 bug!("FIXME(RPITIT): error here");
867 }
868 let infer_ty = self.ocx.infcx.next_ty_var(self.span);
870 self.types.insert(proj.def_id, (infer_ty, proj.args));
871 for (pred, pred_span) in self
873 .cx()
874 .explicit_item_bounds(proj.def_id)
875 .iter_instantiated_copied(self.cx(), proj.args)
876 {
877 let pred = pred.fold_with(self);
878 let pred = self.ocx.normalize(
879 &ObligationCause::misc(self.span, self.body_id),
880 self.param_env,
881 pred,
882 );
883
884 self.ocx.register_obligation(traits::Obligation::new(
885 self.cx(),
886 ObligationCause::new(
887 self.span,
888 self.body_id,
889 ObligationCauseCode::WhereClause(proj.def_id, pred_span),
890 ),
891 self.param_env,
892 pred,
893 ));
894 }
895 infer_ty
896 } else {
897 ty.super_fold_with(self)
898 }
899 }
900}
901
902struct RemapHiddenTyRegions<'tcx> {
903 tcx: TyCtxt<'tcx>,
904 map: FxIndexMap<ty::Region<'tcx>, ty::Region<'tcx>>,
907 num_trait_args: usize,
908 num_impl_args: usize,
909 def_id: DefId,
911 impl_m_def_id: DefId,
913 ty: Ty<'tcx>,
915 return_span: Span,
917}
918
919impl<'tcx> ty::FallibleTypeFolder<TyCtxt<'tcx>> for RemapHiddenTyRegions<'tcx> {
920 type Error = ErrorGuaranteed;
921
922 fn cx(&self) -> TyCtxt<'tcx> {
923 self.tcx
924 }
925
926 fn try_fold_region(
927 &mut self,
928 region: ty::Region<'tcx>,
929 ) -> Result<ty::Region<'tcx>, Self::Error> {
930 match region.kind() {
931 ty::ReBound(..) | ty::ReStatic | ty::ReError(_) => return Ok(region),
933 ty::ReLateParam(_) => {}
935 ty::ReEarlyParam(ebr) => {
938 if ebr.index as usize >= self.num_impl_args {
939 } else {
941 return Ok(region);
942 }
943 }
944 ty::ReVar(_) | ty::RePlaceholder(_) | ty::ReErased => unreachable!(
945 "should not have leaked vars or placeholders into hidden type of RPITIT"
946 ),
947 }
948
949 let e = if let Some(id_region) = self.map.get(®ion) {
950 if let ty::ReEarlyParam(e) = id_region.kind() {
951 e
952 } else {
953 bug!(
954 "expected to map region {region} to early-bound identity region, but got {id_region}"
955 );
956 }
957 } else {
958 let guar = match region.opt_param_def_id(self.tcx, self.impl_m_def_id) {
959 Some(def_id) => {
960 let return_span = if let ty::Alias(ty::Opaque, opaque_ty) = self.ty.kind() {
961 self.tcx.def_span(opaque_ty.def_id)
962 } else {
963 self.return_span
964 };
965 self.tcx
966 .dcx()
967 .struct_span_err(
968 return_span,
969 "return type captures more lifetimes than trait definition",
970 )
971 .with_span_label(self.tcx.def_span(def_id), "this lifetime was captured")
972 .with_span_note(
973 self.tcx.def_span(self.def_id),
974 "hidden type must only reference lifetimes captured by this impl trait",
975 )
976 .with_note(format!("hidden type inferred to be `{}`", self.ty))
977 .emit()
978 }
979 None => {
980 self.tcx.dcx().bug("should've been able to remap region");
985 }
986 };
987 return Err(guar);
988 };
989
990 Ok(ty::Region::new_early_param(
991 self.tcx,
992 ty::EarlyParamRegion {
993 name: e.name,
994 index: (e.index as usize - self.num_trait_args + self.num_impl_args) as u32,
995 },
996 ))
997 }
998}
999
1000fn report_trait_method_mismatch<'tcx>(
1001 infcx: &InferCtxt<'tcx>,
1002 mut cause: ObligationCause<'tcx>,
1003 param_env: ty::ParamEnv<'tcx>,
1004 terr: TypeError<'tcx>,
1005 (trait_m, trait_sig): (ty::AssocItem, ty::FnSig<'tcx>),
1006 (impl_m, impl_sig): (ty::AssocItem, ty::FnSig<'tcx>),
1007 impl_trait_ref: ty::TraitRef<'tcx>,
1008) -> ErrorGuaranteed {
1009 let tcx = infcx.tcx;
1010 let (impl_err_span, trait_err_span) =
1011 extract_spans_for_error_reporting(infcx, terr, &cause, impl_m, trait_m);
1012
1013 let mut diag = struct_span_code_err!(
1014 tcx.dcx(),
1015 impl_err_span,
1016 E0053,
1017 "method `{}` has an incompatible type for trait",
1018 trait_m.name
1019 );
1020 match &terr {
1021 TypeError::ArgumentMutability(0) | TypeError::ArgumentSorts(_, 0)
1022 if trait_m.fn_has_self_parameter =>
1023 {
1024 let ty = trait_sig.inputs()[0];
1025 let sugg = match ExplicitSelf::determine(ty, |ty| ty == impl_trait_ref.self_ty()) {
1026 ExplicitSelf::ByValue => "self".to_owned(),
1027 ExplicitSelf::ByReference(_, hir::Mutability::Not) => "&self".to_owned(),
1028 ExplicitSelf::ByReference(_, hir::Mutability::Mut) => "&mut self".to_owned(),
1029 _ => format!("self: {ty}"),
1030 };
1031
1032 let (sig, body) = tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).expect_fn();
1036 let span = tcx
1037 .hir()
1038 .body_param_names(body)
1039 .zip(sig.decl.inputs.iter())
1040 .map(|(param, ty)| param.span.to(ty.span))
1041 .next()
1042 .unwrap_or(impl_err_span);
1043
1044 diag.span_suggestion_verbose(
1045 span,
1046 "change the self-receiver type to match the trait",
1047 sugg,
1048 Applicability::MachineApplicable,
1049 );
1050 }
1051 TypeError::ArgumentMutability(i) | TypeError::ArgumentSorts(_, i) => {
1052 if trait_sig.inputs().len() == *i {
1053 if let ImplItemKind::Fn(sig, _) =
1056 &tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind
1057 && !sig.header.asyncness.is_async()
1058 {
1059 let msg = "change the output type to match the trait";
1060 let ap = Applicability::MachineApplicable;
1061 match sig.decl.output {
1062 hir::FnRetTy::DefaultReturn(sp) => {
1063 let sugg = format!(" -> {}", trait_sig.output());
1064 diag.span_suggestion_verbose(sp, msg, sugg, ap);
1065 }
1066 hir::FnRetTy::Return(hir_ty) => {
1067 let sugg = trait_sig.output();
1068 diag.span_suggestion_verbose(hir_ty.span, msg, sugg, ap);
1069 }
1070 };
1071 };
1072 } else if let Some(trait_ty) = trait_sig.inputs().get(*i) {
1073 diag.span_suggestion_verbose(
1074 impl_err_span,
1075 "change the parameter type to match the trait",
1076 trait_ty,
1077 Applicability::MachineApplicable,
1078 );
1079 }
1080 }
1081 _ => {}
1082 }
1083
1084 cause.span = impl_err_span;
1085 infcx.err_ctxt().note_type_err(
1086 &mut diag,
1087 &cause,
1088 trait_err_span.map(|sp| (sp, Cow::from("type in trait"), false)),
1089 Some(param_env.and(infer::ValuePairs::PolySigs(ExpectedFound {
1090 expected: ty::Binder::dummy(trait_sig),
1091 found: ty::Binder::dummy(impl_sig),
1092 }))),
1093 terr,
1094 false,
1095 None,
1096 );
1097
1098 diag.emit()
1099}
1100
1101fn check_region_bounds_on_impl_item<'tcx>(
1102 tcx: TyCtxt<'tcx>,
1103 impl_m: ty::AssocItem,
1104 trait_m: ty::AssocItem,
1105 delay: bool,
1106) -> Result<(), ErrorGuaranteed> {
1107 let impl_generics = tcx.generics_of(impl_m.def_id);
1108 let impl_params = impl_generics.own_counts().lifetimes;
1109
1110 let trait_generics = tcx.generics_of(trait_m.def_id);
1111 let trait_params = trait_generics.own_counts().lifetimes;
1112
1113 debug!(?trait_generics, ?impl_generics);
1114
1115 if trait_params != impl_params {
1125 let span = tcx
1126 .hir()
1127 .get_generics(impl_m.def_id.expect_local())
1128 .expect("expected impl item to have generics or else we can't compare them")
1129 .span;
1130
1131 let mut generics_span = None;
1132 let mut bounds_span = vec![];
1133 let mut where_span = None;
1134 if let Some(trait_node) = tcx.hir().get_if_local(trait_m.def_id)
1135 && let Some(trait_generics) = trait_node.generics()
1136 {
1137 generics_span = Some(trait_generics.span);
1138 for p in trait_generics.predicates {
1141 if let hir::WherePredicateKind::BoundPredicate(pred) = p.kind {
1142 for b in pred.bounds {
1143 if let hir::GenericBound::Outlives(lt) = b {
1144 bounds_span.push(lt.ident.span);
1145 }
1146 }
1147 }
1148 }
1149 if let Some(impl_node) = tcx.hir().get_if_local(impl_m.def_id)
1150 && let Some(impl_generics) = impl_node.generics()
1151 {
1152 let mut impl_bounds = 0;
1153 for p in impl_generics.predicates {
1154 if let hir::WherePredicateKind::BoundPredicate(pred) = p.kind {
1155 for b in pred.bounds {
1156 if let hir::GenericBound::Outlives(_) = b {
1157 impl_bounds += 1;
1158 }
1159 }
1160 }
1161 }
1162 if impl_bounds == bounds_span.len() {
1163 bounds_span = vec![];
1164 } else if impl_generics.has_where_clause_predicates {
1165 where_span = Some(impl_generics.where_clause_span);
1166 }
1167 }
1168 }
1169 let reported = tcx
1170 .dcx()
1171 .create_err(LifetimesOrBoundsMismatchOnTrait {
1172 span,
1173 item_kind: impl_m.descr(),
1174 ident: impl_m.ident(tcx),
1175 generics_span,
1176 bounds_span,
1177 where_span,
1178 })
1179 .emit_unless(delay);
1180 return Err(reported);
1181 }
1182
1183 Ok(())
1184}
1185
1186#[instrument(level = "debug", skip(infcx))]
1187fn extract_spans_for_error_reporting<'tcx>(
1188 infcx: &infer::InferCtxt<'tcx>,
1189 terr: TypeError<'_>,
1190 cause: &ObligationCause<'tcx>,
1191 impl_m: ty::AssocItem,
1192 trait_m: ty::AssocItem,
1193) -> (Span, Option<Span>) {
1194 let tcx = infcx.tcx;
1195 let mut impl_args = {
1196 let (sig, _) = tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).expect_fn();
1197 sig.decl.inputs.iter().map(|t| t.span).chain(iter::once(sig.decl.output.span()))
1198 };
1199
1200 let trait_args = trait_m.def_id.as_local().map(|def_id| {
1201 let (sig, _) = tcx.hir().expect_trait_item(def_id).expect_fn();
1202 sig.decl.inputs.iter().map(|t| t.span).chain(iter::once(sig.decl.output.span()))
1203 });
1204
1205 match terr {
1206 TypeError::ArgumentMutability(i) | TypeError::ArgumentSorts(ExpectedFound { .. }, i) => {
1207 (impl_args.nth(i).unwrap(), trait_args.and_then(|mut args| args.nth(i)))
1208 }
1209 _ => (cause.span, tcx.hir().span_if_local(trait_m.def_id)),
1210 }
1211}
1212
1213fn compare_self_type<'tcx>(
1214 tcx: TyCtxt<'tcx>,
1215 impl_m: ty::AssocItem,
1216 trait_m: ty::AssocItem,
1217 impl_trait_ref: ty::TraitRef<'tcx>,
1218 delay: bool,
1219) -> Result<(), ErrorGuaranteed> {
1220 let self_string = |method: ty::AssocItem| {
1229 let untransformed_self_ty = match method.container {
1230 ty::AssocItemContainer::Impl => impl_trait_ref.self_ty(),
1231 ty::AssocItemContainer::Trait => tcx.types.self_param,
1232 };
1233 let self_arg_ty = tcx.fn_sig(method.def_id).instantiate_identity().input(0);
1234 let (infcx, param_env) = tcx
1235 .infer_ctxt()
1236 .build_with_typing_env(ty::TypingEnv::non_body_analysis(tcx, method.def_id));
1237 let self_arg_ty = tcx.liberate_late_bound_regions(method.def_id, self_arg_ty);
1238 let can_eq_self = |ty| infcx.can_eq(param_env, untransformed_self_ty, ty);
1239 match ExplicitSelf::determine(self_arg_ty, can_eq_self) {
1240 ExplicitSelf::ByValue => "self".to_owned(),
1241 ExplicitSelf::ByReference(_, hir::Mutability::Not) => "&self".to_owned(),
1242 ExplicitSelf::ByReference(_, hir::Mutability::Mut) => "&mut self".to_owned(),
1243 _ => format!("self: {self_arg_ty}"),
1244 }
1245 };
1246
1247 match (trait_m.fn_has_self_parameter, impl_m.fn_has_self_parameter) {
1248 (false, false) | (true, true) => {}
1249
1250 (false, true) => {
1251 let self_descr = self_string(impl_m);
1252 let impl_m_span = tcx.def_span(impl_m.def_id);
1253 let mut err = struct_span_code_err!(
1254 tcx.dcx(),
1255 impl_m_span,
1256 E0185,
1257 "method `{}` has a `{}` declaration in the impl, but not in the trait",
1258 trait_m.name,
1259 self_descr
1260 );
1261 err.span_label(impl_m_span, format!("`{self_descr}` used in impl"));
1262 if let Some(span) = tcx.hir().span_if_local(trait_m.def_id) {
1263 err.span_label(span, format!("trait method declared without `{self_descr}`"));
1264 } else {
1265 err.note_trait_signature(trait_m.name, trait_m.signature(tcx));
1266 }
1267 return Err(err.emit_unless(delay));
1268 }
1269
1270 (true, false) => {
1271 let self_descr = self_string(trait_m);
1272 let impl_m_span = tcx.def_span(impl_m.def_id);
1273 let mut err = struct_span_code_err!(
1274 tcx.dcx(),
1275 impl_m_span,
1276 E0186,
1277 "method `{}` has a `{}` declaration in the trait, but not in the impl",
1278 trait_m.name,
1279 self_descr
1280 );
1281 err.span_label(impl_m_span, format!("expected `{self_descr}` in impl"));
1282 if let Some(span) = tcx.hir().span_if_local(trait_m.def_id) {
1283 err.span_label(span, format!("`{self_descr}` used in trait"));
1284 } else {
1285 err.note_trait_signature(trait_m.name, trait_m.signature(tcx));
1286 }
1287
1288 return Err(err.emit_unless(delay));
1289 }
1290 }
1291
1292 Ok(())
1293}
1294
1295fn compare_number_of_generics<'tcx>(
1317 tcx: TyCtxt<'tcx>,
1318 impl_: ty::AssocItem,
1319 trait_: ty::AssocItem,
1320 delay: bool,
1321) -> Result<(), ErrorGuaranteed> {
1322 let trait_own_counts = tcx.generics_of(trait_.def_id).own_counts();
1323 let impl_own_counts = tcx.generics_of(impl_.def_id).own_counts();
1324
1325 if (trait_own_counts.types + trait_own_counts.consts)
1329 == (impl_own_counts.types + impl_own_counts.consts)
1330 {
1331 return Ok(());
1332 }
1333
1334 if trait_.is_impl_trait_in_trait() {
1339 tcx.dcx()
1342 .bug("errors comparing numbers of generics of trait/impl functions were not emitted");
1343 }
1344
1345 let matchings = [
1346 ("type", trait_own_counts.types, impl_own_counts.types),
1347 ("const", trait_own_counts.consts, impl_own_counts.consts),
1348 ];
1349
1350 let item_kind = impl_.descr();
1351
1352 let mut err_occurred = None;
1353 for (kind, trait_count, impl_count) in matchings {
1354 if impl_count != trait_count {
1355 let arg_spans = |kind: ty::AssocKind, generics: &hir::Generics<'_>| {
1356 let mut spans = generics
1357 .params
1358 .iter()
1359 .filter(|p| match p.kind {
1360 hir::GenericParamKind::Lifetime {
1361 kind: hir::LifetimeParamKind::Elided(_),
1362 } => {
1363 !matches!(kind, ty::AssocKind::Fn)
1366 }
1367 _ => true,
1368 })
1369 .map(|p| p.span)
1370 .collect::<Vec<Span>>();
1371 if spans.is_empty() {
1372 spans = vec![generics.span]
1373 }
1374 spans
1375 };
1376 let (trait_spans, impl_trait_spans) = if let Some(def_id) = trait_.def_id.as_local() {
1377 let trait_item = tcx.hir().expect_trait_item(def_id);
1378 let arg_spans: Vec<Span> = arg_spans(trait_.kind, trait_item.generics);
1379 let impl_trait_spans: Vec<Span> = trait_item
1380 .generics
1381 .params
1382 .iter()
1383 .filter_map(|p| match p.kind {
1384 GenericParamKind::Type { synthetic: true, .. } => Some(p.span),
1385 _ => None,
1386 })
1387 .collect();
1388 (Some(arg_spans), impl_trait_spans)
1389 } else {
1390 let trait_span = tcx.hir().span_if_local(trait_.def_id);
1391 (trait_span.map(|s| vec![s]), vec![])
1392 };
1393
1394 let impl_item = tcx.hir().expect_impl_item(impl_.def_id.expect_local());
1395 let impl_item_impl_trait_spans: Vec<Span> = impl_item
1396 .generics
1397 .params
1398 .iter()
1399 .filter_map(|p| match p.kind {
1400 GenericParamKind::Type { synthetic: true, .. } => Some(p.span),
1401 _ => None,
1402 })
1403 .collect();
1404 let spans = arg_spans(impl_.kind, impl_item.generics);
1405 let span = spans.first().copied();
1406
1407 let mut err = tcx.dcx().struct_span_err(
1408 spans,
1409 format!(
1410 "{} `{}` has {} {kind} parameter{} but its trait \
1411 declaration has {} {kind} parameter{}",
1412 item_kind,
1413 trait_.name,
1414 impl_count,
1415 pluralize!(impl_count),
1416 trait_count,
1417 pluralize!(trait_count),
1418 kind = kind,
1419 ),
1420 );
1421 err.code(E0049);
1422
1423 let msg =
1424 format!("expected {trait_count} {kind} parameter{}", pluralize!(trait_count),);
1425 if let Some(spans) = trait_spans {
1426 let mut spans = spans.iter();
1427 if let Some(span) = spans.next() {
1428 err.span_label(*span, msg);
1429 }
1430 for span in spans {
1431 err.span_label(*span, "");
1432 }
1433 } else {
1434 err.span_label(tcx.def_span(trait_.def_id), msg);
1435 }
1436
1437 if let Some(span) = span {
1438 err.span_label(
1439 span,
1440 format!("found {} {} parameter{}", impl_count, kind, pluralize!(impl_count),),
1441 );
1442 }
1443
1444 for span in impl_trait_spans.iter().chain(impl_item_impl_trait_spans.iter()) {
1445 err.span_label(*span, "`impl Trait` introduces an implicit type parameter");
1446 }
1447
1448 let reported = err.emit_unless(delay);
1449 err_occurred = Some(reported);
1450 }
1451 }
1452
1453 if let Some(reported) = err_occurred { Err(reported) } else { Ok(()) }
1454}
1455
1456fn compare_number_of_method_arguments<'tcx>(
1457 tcx: TyCtxt<'tcx>,
1458 impl_m: ty::AssocItem,
1459 trait_m: ty::AssocItem,
1460 delay: bool,
1461) -> Result<(), ErrorGuaranteed> {
1462 let impl_m_fty = tcx.fn_sig(impl_m.def_id);
1463 let trait_m_fty = tcx.fn_sig(trait_m.def_id);
1464 let trait_number_args = trait_m_fty.skip_binder().inputs().skip_binder().len();
1465 let impl_number_args = impl_m_fty.skip_binder().inputs().skip_binder().len();
1466
1467 if trait_number_args != impl_number_args {
1468 let trait_span = trait_m
1469 .def_id
1470 .as_local()
1471 .and_then(|def_id| {
1472 let (trait_m_sig, _) = &tcx.hir().expect_trait_item(def_id).expect_fn();
1473 let pos = trait_number_args.saturating_sub(1);
1474 trait_m_sig.decl.inputs.get(pos).map(|arg| {
1475 if pos == 0 {
1476 arg.span
1477 } else {
1478 arg.span.with_lo(trait_m_sig.decl.inputs[0].span.lo())
1479 }
1480 })
1481 })
1482 .or_else(|| tcx.hir().span_if_local(trait_m.def_id));
1483
1484 let (impl_m_sig, _) = &tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).expect_fn();
1485 let pos = impl_number_args.saturating_sub(1);
1486 let impl_span = impl_m_sig
1487 .decl
1488 .inputs
1489 .get(pos)
1490 .map(|arg| {
1491 if pos == 0 {
1492 arg.span
1493 } else {
1494 arg.span.with_lo(impl_m_sig.decl.inputs[0].span.lo())
1495 }
1496 })
1497 .unwrap_or_else(|| tcx.def_span(impl_m.def_id));
1498
1499 let mut err = struct_span_code_err!(
1500 tcx.dcx(),
1501 impl_span,
1502 E0050,
1503 "method `{}` has {} but the declaration in trait `{}` has {}",
1504 trait_m.name,
1505 potentially_plural_count(impl_number_args, "parameter"),
1506 tcx.def_path_str(trait_m.def_id),
1507 trait_number_args
1508 );
1509
1510 if let Some(trait_span) = trait_span {
1511 err.span_label(
1512 trait_span,
1513 format!(
1514 "trait requires {}",
1515 potentially_plural_count(trait_number_args, "parameter")
1516 ),
1517 );
1518 } else {
1519 err.note_trait_signature(trait_m.name, trait_m.signature(tcx));
1520 }
1521
1522 err.span_label(
1523 impl_span,
1524 format!(
1525 "expected {}, found {}",
1526 potentially_plural_count(trait_number_args, "parameter"),
1527 impl_number_args
1528 ),
1529 );
1530
1531 return Err(err.emit_unless(delay));
1532 }
1533
1534 Ok(())
1535}
1536
1537fn compare_synthetic_generics<'tcx>(
1538 tcx: TyCtxt<'tcx>,
1539 impl_m: ty::AssocItem,
1540 trait_m: ty::AssocItem,
1541 delay: bool,
1542) -> Result<(), ErrorGuaranteed> {
1543 let mut error_found = None;
1549 let impl_m_generics = tcx.generics_of(impl_m.def_id);
1550 let trait_m_generics = tcx.generics_of(trait_m.def_id);
1551 let impl_m_type_params =
1552 impl_m_generics.own_params.iter().filter_map(|param| match param.kind {
1553 GenericParamDefKind::Type { synthetic, .. } => Some((param.def_id, synthetic)),
1554 GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => None,
1555 });
1556 let trait_m_type_params =
1557 trait_m_generics.own_params.iter().filter_map(|param| match param.kind {
1558 GenericParamDefKind::Type { synthetic, .. } => Some((param.def_id, synthetic)),
1559 GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => None,
1560 });
1561 for ((impl_def_id, impl_synthetic), (trait_def_id, trait_synthetic)) in
1562 iter::zip(impl_m_type_params, trait_m_type_params)
1563 {
1564 if impl_synthetic != trait_synthetic {
1565 let impl_def_id = impl_def_id.expect_local();
1566 let impl_span = tcx.def_span(impl_def_id);
1567 let trait_span = tcx.def_span(trait_def_id);
1568 let mut err = struct_span_code_err!(
1569 tcx.dcx(),
1570 impl_span,
1571 E0643,
1572 "method `{}` has incompatible signature for trait",
1573 trait_m.name
1574 );
1575 err.span_label(trait_span, "declaration in trait here");
1576 if impl_synthetic {
1577 err.span_label(impl_span, "expected generic parameter, found `impl Trait`");
1580 let _: Option<_> = try {
1581 let new_name = tcx.opt_item_name(trait_def_id)?;
1585 let trait_m = trait_m.def_id.as_local()?;
1586 let trait_m = tcx.hir().expect_trait_item(trait_m);
1587
1588 let impl_m = impl_m.def_id.as_local()?;
1589 let impl_m = tcx.hir().expect_impl_item(impl_m);
1590
1591 let new_generics_span = tcx.def_ident_span(impl_def_id)?.shrink_to_hi();
1594 let generics_span = impl_m.generics.span.substitute_dummy(new_generics_span);
1596 let new_generics =
1598 tcx.sess.source_map().span_to_snippet(trait_m.generics.span).ok()?;
1599
1600 err.multipart_suggestion(
1601 "try changing the `impl Trait` argument to a generic parameter",
1602 vec![
1603 (impl_span, new_name.to_string()),
1605 (generics_span, new_generics),
1609 ],
1610 Applicability::MaybeIncorrect,
1611 );
1612 };
1613 } else {
1614 err.span_label(impl_span, "expected `impl Trait`, found generic parameter");
1617 let _: Option<_> = try {
1618 let impl_m = impl_m.def_id.as_local()?;
1619 let impl_m = tcx.hir().expect_impl_item(impl_m);
1620 let (sig, _) = impl_m.expect_fn();
1621 let input_tys = sig.decl.inputs;
1622
1623 struct Visitor(hir::def_id::LocalDefId);
1624 impl<'v> intravisit::Visitor<'v> for Visitor {
1625 type Result = ControlFlow<Span>;
1626 fn visit_ty(&mut self, ty: &'v hir::Ty<'v, AmbigArg>) -> Self::Result {
1627 if let hir::TyKind::Path(hir::QPath::Resolved(None, path)) = ty.kind
1628 && let Res::Def(DefKind::TyParam, def_id) = path.res
1629 && def_id == self.0.to_def_id()
1630 {
1631 ControlFlow::Break(ty.span)
1632 } else {
1633 intravisit::walk_ty(self, ty)
1634 }
1635 }
1636 }
1637
1638 let span = input_tys
1639 .iter()
1640 .find_map(|ty| Visitor(impl_def_id).visit_ty_unambig(ty).break_value())?;
1641
1642 let bounds = impl_m.generics.bounds_for_param(impl_def_id).next()?.bounds;
1643 let bounds = bounds.first()?.span().to(bounds.last()?.span());
1644 let bounds = tcx.sess.source_map().span_to_snippet(bounds).ok()?;
1645
1646 err.multipart_suggestion(
1647 "try removing the generic parameter and using `impl Trait` instead",
1648 vec![
1649 (impl_m.generics.span, String::new()),
1651 (span, format!("impl {bounds}")),
1653 ],
1654 Applicability::MaybeIncorrect,
1655 );
1656 };
1657 }
1658 error_found = Some(err.emit_unless(delay));
1659 }
1660 }
1661 if let Some(reported) = error_found { Err(reported) } else { Ok(()) }
1662}
1663
1664fn compare_generic_param_kinds<'tcx>(
1690 tcx: TyCtxt<'tcx>,
1691 impl_item: ty::AssocItem,
1692 trait_item: ty::AssocItem,
1693 delay: bool,
1694) -> Result<(), ErrorGuaranteed> {
1695 assert_eq!(impl_item.kind, trait_item.kind);
1696
1697 let ty_const_params_of = |def_id| {
1698 tcx.generics_of(def_id).own_params.iter().filter(|param| {
1699 matches!(
1700 param.kind,
1701 GenericParamDefKind::Const { .. } | GenericParamDefKind::Type { .. }
1702 )
1703 })
1704 };
1705
1706 for (param_impl, param_trait) in
1707 iter::zip(ty_const_params_of(impl_item.def_id), ty_const_params_of(trait_item.def_id))
1708 {
1709 use GenericParamDefKind::*;
1710 if match (¶m_impl.kind, ¶m_trait.kind) {
1711 (Const { .. }, Const { .. })
1712 if tcx.type_of(param_impl.def_id) != tcx.type_of(param_trait.def_id) =>
1713 {
1714 true
1715 }
1716 (Const { .. }, Type { .. }) | (Type { .. }, Const { .. }) => true,
1717 (Const { .. }, Const { .. }) | (Type { .. }, Type { .. }) => false,
1720 (Lifetime { .. }, _) | (_, Lifetime { .. }) => {
1721 bug!("lifetime params are expected to be filtered by `ty_const_params_of`")
1722 }
1723 } {
1724 let param_impl_span = tcx.def_span(param_impl.def_id);
1725 let param_trait_span = tcx.def_span(param_trait.def_id);
1726
1727 let mut err = struct_span_code_err!(
1728 tcx.dcx(),
1729 param_impl_span,
1730 E0053,
1731 "{} `{}` has an incompatible generic parameter for trait `{}`",
1732 impl_item.descr(),
1733 trait_item.name,
1734 &tcx.def_path_str(tcx.parent(trait_item.def_id))
1735 );
1736
1737 let make_param_message = |prefix: &str, param: &ty::GenericParamDef| match param.kind {
1738 Const { .. } => {
1739 format!(
1740 "{} const parameter of type `{}`",
1741 prefix,
1742 tcx.type_of(param.def_id).instantiate_identity()
1743 )
1744 }
1745 Type { .. } => format!("{prefix} type parameter"),
1746 Lifetime { .. } => span_bug!(
1747 tcx.def_span(param.def_id),
1748 "lifetime params are expected to be filtered by `ty_const_params_of`"
1749 ),
1750 };
1751
1752 let trait_header_span = tcx.def_ident_span(tcx.parent(trait_item.def_id)).unwrap();
1753 err.span_label(trait_header_span, "");
1754 err.span_label(param_trait_span, make_param_message("expected", param_trait));
1755
1756 let impl_header_span = tcx.def_span(tcx.parent(impl_item.def_id));
1757 err.span_label(impl_header_span, "");
1758 err.span_label(param_impl_span, make_param_message("found", param_impl));
1759
1760 let reported = err.emit_unless(delay);
1761 return Err(reported);
1762 }
1763 }
1764
1765 Ok(())
1766}
1767
1768fn compare_impl_const<'tcx>(
1769 tcx: TyCtxt<'tcx>,
1770 impl_const_item: ty::AssocItem,
1771 trait_const_item: ty::AssocItem,
1772 impl_trait_ref: ty::TraitRef<'tcx>,
1773) -> Result<(), ErrorGuaranteed> {
1774 compare_number_of_generics(tcx, impl_const_item, trait_const_item, false)?;
1775 compare_generic_param_kinds(tcx, impl_const_item, trait_const_item, false)?;
1776 check_region_bounds_on_impl_item(tcx, impl_const_item, trait_const_item, false)?;
1777 compare_const_predicate_entailment(tcx, impl_const_item, trait_const_item, impl_trait_ref)
1778}
1779
1780#[instrument(level = "debug", skip(tcx))]
1784fn compare_const_predicate_entailment<'tcx>(
1785 tcx: TyCtxt<'tcx>,
1786 impl_ct: ty::AssocItem,
1787 trait_ct: ty::AssocItem,
1788 impl_trait_ref: ty::TraitRef<'tcx>,
1789) -> Result<(), ErrorGuaranteed> {
1790 let impl_ct_def_id = impl_ct.def_id.expect_local();
1791 let impl_ct_span = tcx.def_span(impl_ct_def_id);
1792
1793 let trait_to_impl_args = GenericArgs::identity_for_item(tcx, impl_ct.def_id).rebase_onto(
1799 tcx,
1800 impl_ct.container_id(tcx),
1801 impl_trait_ref.args,
1802 );
1803
1804 let impl_ty = tcx.type_of(impl_ct_def_id).instantiate_identity();
1807
1808 let trait_ty = tcx.type_of(trait_ct.def_id).instantiate(tcx, trait_to_impl_args);
1809 let code = ObligationCauseCode::CompareImplItem {
1810 impl_item_def_id: impl_ct_def_id,
1811 trait_item_def_id: trait_ct.def_id,
1812 kind: impl_ct.kind,
1813 };
1814 let mut cause = ObligationCause::new(impl_ct_span, impl_ct_def_id, code.clone());
1815
1816 let impl_ct_predicates = tcx.predicates_of(impl_ct.def_id);
1817 let trait_ct_predicates = tcx.predicates_of(trait_ct.def_id);
1818
1819 let impl_predicates = tcx.predicates_of(impl_ct_predicates.parent.unwrap());
1822 let mut hybrid_preds = impl_predicates.instantiate_identity(tcx).predicates;
1823 hybrid_preds.extend(
1824 trait_ct_predicates
1825 .instantiate_own(tcx, trait_to_impl_args)
1826 .map(|(predicate, _)| predicate),
1827 );
1828
1829 let param_env = ty::ParamEnv::new(tcx.mk_clauses(&hybrid_preds));
1830 let param_env = traits::normalize_param_env_or_error(
1831 tcx,
1832 param_env,
1833 ObligationCause::misc(impl_ct_span, impl_ct_def_id),
1834 );
1835
1836 let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
1837 let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
1838
1839 let impl_ct_own_bounds = impl_ct_predicates.instantiate_own_identity();
1840 for (predicate, span) in impl_ct_own_bounds {
1841 let cause = ObligationCause::misc(span, impl_ct_def_id);
1842 let predicate = ocx.normalize(&cause, param_env, predicate);
1843
1844 let cause = ObligationCause::new(span, impl_ct_def_id, code.clone());
1845 ocx.register_obligation(traits::Obligation::new(tcx, cause, param_env, predicate));
1846 }
1847
1848 let impl_ty = ocx.normalize(&cause, param_env, impl_ty);
1850 debug!(?impl_ty);
1851
1852 let trait_ty = ocx.normalize(&cause, param_env, trait_ty);
1853 debug!(?trait_ty);
1854
1855 let err = ocx.sup(&cause, param_env, trait_ty, impl_ty);
1856
1857 if let Err(terr) = err {
1858 debug!(?impl_ty, ?trait_ty);
1859
1860 let (ty, _) = tcx.hir().expect_impl_item(impl_ct_def_id).expect_const();
1862 cause.span = ty.span;
1863
1864 let mut diag = struct_span_code_err!(
1865 tcx.dcx(),
1866 cause.span,
1867 E0326,
1868 "implemented const `{}` has an incompatible type for trait",
1869 trait_ct.name
1870 );
1871
1872 let trait_c_span = trait_ct.def_id.as_local().map(|trait_ct_def_id| {
1873 let (ty, _) = tcx.hir().expect_trait_item(trait_ct_def_id).expect_const();
1875 ty.span
1876 });
1877
1878 infcx.err_ctxt().note_type_err(
1879 &mut diag,
1880 &cause,
1881 trait_c_span.map(|span| (span, Cow::from("type in trait"), false)),
1882 Some(param_env.and(infer::ValuePairs::Terms(ExpectedFound {
1883 expected: trait_ty.into(),
1884 found: impl_ty.into(),
1885 }))),
1886 terr,
1887 false,
1888 None,
1889 );
1890 return Err(diag.emit());
1891 };
1892
1893 let errors = ocx.select_all_or_error();
1896 if !errors.is_empty() {
1897 return Err(infcx.err_ctxt().report_fulfillment_errors(errors));
1898 }
1899
1900 ocx.resolve_regions_and_report_errors(impl_ct_def_id, param_env, [])
1901}
1902
1903#[instrument(level = "debug", skip(tcx))]
1904fn compare_impl_ty<'tcx>(
1905 tcx: TyCtxt<'tcx>,
1906 impl_ty: ty::AssocItem,
1907 trait_ty: ty::AssocItem,
1908 impl_trait_ref: ty::TraitRef<'tcx>,
1909) -> Result<(), ErrorGuaranteed> {
1910 compare_number_of_generics(tcx, impl_ty, trait_ty, false)?;
1911 compare_generic_param_kinds(tcx, impl_ty, trait_ty, false)?;
1912 check_region_bounds_on_impl_item(tcx, impl_ty, trait_ty, false)?;
1913 compare_type_predicate_entailment(tcx, impl_ty, trait_ty, impl_trait_ref)?;
1914 check_type_bounds(tcx, trait_ty, impl_ty, impl_trait_ref)
1915}
1916
1917#[instrument(level = "debug", skip(tcx))]
1920fn compare_type_predicate_entailment<'tcx>(
1921 tcx: TyCtxt<'tcx>,
1922 impl_ty: ty::AssocItem,
1923 trait_ty: ty::AssocItem,
1924 impl_trait_ref: ty::TraitRef<'tcx>,
1925) -> Result<(), ErrorGuaranteed> {
1926 let impl_def_id = impl_ty.container_id(tcx);
1927 let trait_to_impl_args = GenericArgs::identity_for_item(tcx, impl_ty.def_id).rebase_onto(
1928 tcx,
1929 impl_def_id,
1930 impl_trait_ref.args,
1931 );
1932
1933 let impl_ty_predicates = tcx.predicates_of(impl_ty.def_id);
1934 let trait_ty_predicates = tcx.predicates_of(trait_ty.def_id);
1935
1936 let impl_ty_own_bounds = impl_ty_predicates.instantiate_own_identity();
1937 if impl_ty_own_bounds.len() == 0 {
1939 return Ok(());
1941 }
1942
1943 let impl_ty_def_id = impl_ty.def_id.expect_local();
1947 debug!(?trait_to_impl_args);
1948
1949 let impl_predicates = tcx.predicates_of(impl_ty_predicates.parent.unwrap());
1952 let mut hybrid_preds = impl_predicates.instantiate_identity(tcx).predicates;
1953 hybrid_preds.extend(
1954 trait_ty_predicates
1955 .instantiate_own(tcx, trait_to_impl_args)
1956 .map(|(predicate, _)| predicate),
1957 );
1958 debug!(?hybrid_preds);
1959
1960 let impl_ty_span = tcx.def_span(impl_ty_def_id);
1961 let normalize_cause = ObligationCause::misc(impl_ty_span, impl_ty_def_id);
1962
1963 let is_conditionally_const = tcx.is_conditionally_const(impl_ty.def_id);
1964 if is_conditionally_const {
1965 hybrid_preds.extend(
1968 tcx.const_conditions(impl_ty_predicates.parent.unwrap())
1969 .instantiate_identity(tcx)
1970 .into_iter()
1971 .chain(
1972 tcx.const_conditions(trait_ty.def_id).instantiate_own(tcx, trait_to_impl_args),
1973 )
1974 .map(|(trait_ref, _)| {
1975 trait_ref.to_host_effect_clause(tcx, ty::BoundConstness::Maybe)
1976 }),
1977 );
1978 }
1979
1980 let param_env = ty::ParamEnv::new(tcx.mk_clauses(&hybrid_preds));
1981 let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause);
1982 debug!(caller_bounds=?param_env.caller_bounds());
1983
1984 let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
1985 let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
1986
1987 for (predicate, span) in impl_ty_own_bounds {
1988 let cause = ObligationCause::misc(span, impl_ty_def_id);
1989 let predicate = ocx.normalize(&cause, param_env, predicate);
1990
1991 let cause = ObligationCause::new(
1992 span,
1993 impl_ty_def_id,
1994 ObligationCauseCode::CompareImplItem {
1995 impl_item_def_id: impl_ty.def_id.expect_local(),
1996 trait_item_def_id: trait_ty.def_id,
1997 kind: impl_ty.kind,
1998 },
1999 );
2000 ocx.register_obligation(traits::Obligation::new(tcx, cause, param_env, predicate));
2001 }
2002
2003 if is_conditionally_const {
2004 let impl_ty_own_const_conditions =
2006 tcx.const_conditions(impl_ty.def_id).instantiate_own_identity();
2007 for (const_condition, span) in impl_ty_own_const_conditions {
2008 let normalize_cause = traits::ObligationCause::misc(span, impl_ty_def_id);
2009 let const_condition = ocx.normalize(&normalize_cause, param_env, const_condition);
2010
2011 let cause = ObligationCause::new(
2012 span,
2013 impl_ty_def_id,
2014 ObligationCauseCode::CompareImplItem {
2015 impl_item_def_id: impl_ty_def_id,
2016 trait_item_def_id: trait_ty.def_id,
2017 kind: impl_ty.kind,
2018 },
2019 );
2020 ocx.register_obligation(traits::Obligation::new(
2021 tcx,
2022 cause,
2023 param_env,
2024 const_condition.to_host_effect_clause(tcx, ty::BoundConstness::Maybe),
2025 ));
2026 }
2027 }
2028
2029 let errors = ocx.select_all_or_error();
2032 if !errors.is_empty() {
2033 let reported = infcx.err_ctxt().report_fulfillment_errors(errors);
2034 return Err(reported);
2035 }
2036
2037 ocx.resolve_regions_and_report_errors(impl_ty_def_id, param_env, [])
2040}
2041
2042#[instrument(level = "debug", skip(tcx))]
2056pub(super) fn check_type_bounds<'tcx>(
2057 tcx: TyCtxt<'tcx>,
2058 trait_ty: ty::AssocItem,
2059 impl_ty: ty::AssocItem,
2060 impl_trait_ref: ty::TraitRef<'tcx>,
2061) -> Result<(), ErrorGuaranteed> {
2062 tcx.ensure_ok().coherent_trait(impl_trait_ref.def_id)?;
2065
2066 let param_env = tcx.param_env(impl_ty.def_id);
2067 debug!(?param_env);
2068
2069 let container_id = impl_ty.container_id(tcx);
2070 let impl_ty_def_id = impl_ty.def_id.expect_local();
2071 let impl_ty_args = GenericArgs::identity_for_item(tcx, impl_ty.def_id);
2072 let rebased_args = impl_ty_args.rebase_onto(tcx, container_id, impl_trait_ref.args);
2073
2074 let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
2075 let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
2076
2077 let impl_ty_span = if impl_ty.is_impl_trait_in_trait() {
2081 tcx.def_span(impl_ty_def_id)
2082 } else {
2083 match tcx.hir_node_by_def_id(impl_ty_def_id) {
2084 hir::Node::TraitItem(hir::TraitItem {
2085 kind: hir::TraitItemKind::Type(_, Some(ty)),
2086 ..
2087 }) => ty.span,
2088 hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Type(ty), .. }) => ty.span,
2089 item => span_bug!(
2090 tcx.def_span(impl_ty_def_id),
2091 "cannot call `check_type_bounds` on item: {item:?}",
2092 ),
2093 }
2094 };
2095 let assumed_wf_types = ocx.assumed_wf_types_and_report_errors(param_env, impl_ty_def_id)?;
2096
2097 let normalize_cause = ObligationCause::new(
2098 impl_ty_span,
2099 impl_ty_def_id,
2100 ObligationCauseCode::CheckAssociatedTypeBounds {
2101 impl_item_def_id: impl_ty.def_id.expect_local(),
2102 trait_item_def_id: trait_ty.def_id,
2103 },
2104 );
2105 let mk_cause = |span: Span| {
2106 let code = ObligationCauseCode::WhereClause(trait_ty.def_id, span);
2107 ObligationCause::new(impl_ty_span, impl_ty_def_id, code)
2108 };
2109
2110 let mut obligations: Vec<_> = tcx
2111 .explicit_item_bounds(trait_ty.def_id)
2112 .iter_instantiated_copied(tcx, rebased_args)
2113 .map(|(concrete_ty_bound, span)| {
2114 debug!(?concrete_ty_bound);
2115 traits::Obligation::new(tcx, mk_cause(span), param_env, concrete_ty_bound)
2116 })
2117 .collect();
2118
2119 if tcx.is_conditionally_const(impl_ty_def_id) {
2121 obligations.extend(
2122 tcx.explicit_implied_const_bounds(trait_ty.def_id)
2123 .iter_instantiated_copied(tcx, rebased_args)
2124 .map(|(c, span)| {
2125 traits::Obligation::new(
2126 tcx,
2127 mk_cause(span),
2128 param_env,
2129 c.to_host_effect_clause(tcx, ty::BoundConstness::Maybe),
2130 )
2131 }),
2132 );
2133 }
2134 debug!(item_bounds=?obligations);
2135
2136 let trait_projection_ty = Ty::new_projection_from_args(tcx, trait_ty.def_id, rebased_args);
2141 let impl_identity_ty = tcx.type_of(impl_ty.def_id).instantiate_identity();
2142 let normalize_param_env = param_env_with_gat_bounds(tcx, impl_ty, impl_trait_ref);
2143 for mut obligation in util::elaborate(tcx, obligations) {
2144 let normalized_predicate = if infcx.next_trait_solver() {
2145 obligation.predicate.fold_with(&mut ReplaceTy {
2146 tcx,
2147 from: trait_projection_ty,
2148 to: impl_identity_ty,
2149 })
2150 } else {
2151 ocx.normalize(&normalize_cause, normalize_param_env, obligation.predicate)
2152 };
2153 debug!(?normalized_predicate);
2154 obligation.predicate = normalized_predicate;
2155
2156 ocx.register_obligation(obligation);
2157 }
2158 let errors = ocx.select_all_or_error();
2161 if !errors.is_empty() {
2162 let reported = infcx.err_ctxt().report_fulfillment_errors(errors);
2163 return Err(reported);
2164 }
2165
2166 ocx.resolve_regions_and_report_errors(impl_ty_def_id, param_env, assumed_wf_types)
2169}
2170
2171struct ReplaceTy<'tcx> {
2172 tcx: TyCtxt<'tcx>,
2173 from: Ty<'tcx>,
2174 to: Ty<'tcx>,
2175}
2176
2177impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReplaceTy<'tcx> {
2178 fn cx(&self) -> TyCtxt<'tcx> {
2179 self.tcx
2180 }
2181
2182 fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
2183 if self.from == ty { self.to } else { ty.super_fold_with(self) }
2184 }
2185}
2186
2187fn param_env_with_gat_bounds<'tcx>(
2235 tcx: TyCtxt<'tcx>,
2236 impl_ty: ty::AssocItem,
2237 impl_trait_ref: ty::TraitRef<'tcx>,
2238) -> ty::ParamEnv<'tcx> {
2239 let param_env = tcx.param_env(impl_ty.def_id);
2240 let container_id = impl_ty.container_id(tcx);
2241 let mut predicates = param_env.caller_bounds().to_vec();
2242
2243 let impl_tys_to_install = match impl_ty.opt_rpitit_info {
2248 None => vec![impl_ty],
2249 Some(
2250 ty::ImplTraitInTraitData::Impl { fn_def_id }
2251 | ty::ImplTraitInTraitData::Trait { fn_def_id, .. },
2252 ) => tcx
2253 .associated_types_for_impl_traits_in_associated_fn(fn_def_id)
2254 .iter()
2255 .map(|def_id| tcx.associated_item(*def_id))
2256 .collect(),
2257 };
2258
2259 for impl_ty in impl_tys_to_install {
2260 let trait_ty = match impl_ty.container {
2261 ty::AssocItemContainer::Trait => impl_ty,
2262 ty::AssocItemContainer::Impl => tcx.associated_item(impl_ty.trait_item_def_id.unwrap()),
2263 };
2264
2265 let mut bound_vars: smallvec::SmallVec<[ty::BoundVariableKind; 8]> =
2266 smallvec::SmallVec::with_capacity(tcx.generics_of(impl_ty.def_id).own_params.len());
2267 let normalize_impl_ty_args = ty::GenericArgs::identity_for_item(tcx, container_id)
2269 .extend_to(tcx, impl_ty.def_id, |param, _| match param.kind {
2270 GenericParamDefKind::Type { .. } => {
2271 let kind = ty::BoundTyKind::Param(param.def_id, param.name);
2272 let bound_var = ty::BoundVariableKind::Ty(kind);
2273 bound_vars.push(bound_var);
2274 Ty::new_bound(
2275 tcx,
2276 ty::INNERMOST,
2277 ty::BoundTy { var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind },
2278 )
2279 .into()
2280 }
2281 GenericParamDefKind::Lifetime => {
2282 let kind = ty::BoundRegionKind::Named(param.def_id, param.name);
2283 let bound_var = ty::BoundVariableKind::Region(kind);
2284 bound_vars.push(bound_var);
2285 ty::Region::new_bound(
2286 tcx,
2287 ty::INNERMOST,
2288 ty::BoundRegion {
2289 var: ty::BoundVar::from_usize(bound_vars.len() - 1),
2290 kind,
2291 },
2292 )
2293 .into()
2294 }
2295 GenericParamDefKind::Const { .. } => {
2296 let bound_var = ty::BoundVariableKind::Const;
2297 bound_vars.push(bound_var);
2298 ty::Const::new_bound(
2299 tcx,
2300 ty::INNERMOST,
2301 ty::BoundVar::from_usize(bound_vars.len() - 1),
2302 )
2303 .into()
2304 }
2305 });
2306 let normalize_impl_ty =
2316 tcx.type_of(impl_ty.def_id).instantiate(tcx, normalize_impl_ty_args);
2317 let rebased_args =
2318 normalize_impl_ty_args.rebase_onto(tcx, container_id, impl_trait_ref.args);
2319 let bound_vars = tcx.mk_bound_variable_kinds(&bound_vars);
2320
2321 match normalize_impl_ty.kind() {
2322 ty::Alias(ty::Projection, proj)
2323 if proj.def_id == trait_ty.def_id && proj.args == rebased_args =>
2324 {
2325 }
2331 _ => predicates.push(
2332 ty::Binder::bind_with_vars(
2333 ty::ProjectionPredicate {
2334 projection_term: ty::AliasTerm::new_from_args(
2335 tcx,
2336 trait_ty.def_id,
2337 rebased_args,
2338 ),
2339 term: normalize_impl_ty.into(),
2340 },
2341 bound_vars,
2342 )
2343 .upcast(tcx),
2344 ),
2345 };
2346 }
2347
2348 ty::ParamEnv::new(tcx.mk_clauses(&predicates))
2349}
2350
2351fn try_report_async_mismatch<'tcx>(
2354 tcx: TyCtxt<'tcx>,
2355 infcx: &InferCtxt<'tcx>,
2356 errors: &[FulfillmentError<'tcx>],
2357 trait_m: ty::AssocItem,
2358 impl_m: ty::AssocItem,
2359 impl_sig: ty::FnSig<'tcx>,
2360) -> Result<(), ErrorGuaranteed> {
2361 if !tcx.asyncness(trait_m.def_id).is_async() {
2362 return Ok(());
2363 }
2364
2365 let ty::Alias(ty::Projection, ty::AliasTy { def_id: async_future_def_id, .. }) =
2366 *tcx.fn_sig(trait_m.def_id).skip_binder().skip_binder().output().kind()
2367 else {
2368 bug!("expected `async fn` to return an RPITIT");
2369 };
2370
2371 for error in errors {
2372 if let ObligationCauseCode::WhereClause(def_id, _) = *error.root_obligation.cause.code()
2373 && def_id == async_future_def_id
2374 && let Some(proj) = error.root_obligation.predicate.as_projection_clause()
2375 && let Some(proj) = proj.no_bound_vars()
2376 && infcx.can_eq(
2377 error.root_obligation.param_env,
2378 proj.term.expect_type(),
2379 impl_sig.output(),
2380 )
2381 {
2382 return Err(tcx.sess.dcx().emit_err(MethodShouldReturnFuture {
2385 span: tcx.def_span(impl_m.def_id),
2386 method_name: tcx.item_ident(impl_m.def_id),
2387 trait_item_span: tcx.hir().span_if_local(trait_m.def_id),
2388 }));
2389 }
2390 }
2391
2392 Ok(())
2393}