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
34pub(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#[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(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 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 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.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#[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 = 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 match ocx.eq(&cause, param_env, trait_sig, impl_sig) {
683 Ok(()) => {}
684 Err(terr) => {
685 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 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 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 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 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 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 tcx.dcx()
797 .span_bug(return_span, format!("could not fully resolve: {ty} => {err:?}"));
798 }
799 }
800 }
801
802 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 if proj.args.has_escaping_bound_vars() {
862 bug!("FIXME(RPITIT): error here");
863 }
864 let infer_ty = self.ocx.infcx.next_ty_var(self.span);
866 self.types.insert(proj.def_id, (infer_ty, proj.args));
867 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: FxIndexMap<ty::Region<'tcx>, ty::Region<'tcx>>,
903 num_trait_args: usize,
904 num_impl_args: usize,
905 def_id: DefId,
907 impl_m_def_id: DefId,
909 ty: Ty<'tcx>,
911 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 ty::ReBound(..) | ty::ReStatic | ty::ReError(_) => return Ok(region),
929 ty::ReLateParam(_) => {}
931 ty::ReEarlyParam(ebr) => {
934 if ebr.index as usize >= self.num_impl_args {
935 } 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(®ion) {
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 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
996fn 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 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 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 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 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 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 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
1559fn 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 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 if trait_.is_impl_trait_in_trait() {
1603 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 !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 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 err.span_label(impl_span, "expected generic parameter, found `impl Trait`");
1844 let _: Option<_> = try {
1845 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 let new_generics_span = tcx.def_ident_span(impl_def_id)?.shrink_to_hi();
1858 let generics_span = impl_m.generics.span.substitute_dummy(new_generics_span);
1860 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 (impl_span, new_name.to_string()),
1869 (generics_span, new_generics),
1873 ],
1874 Applicability::MaybeIncorrect,
1875 );
1876 };
1877 } else {
1878 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 (impl_m.generics.span, String::new()),
1915 (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
1928fn 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 (¶m_impl.kind, ¶m_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 (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#[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 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 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 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 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 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 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 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#[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 impl_ty_own_bounds.len() == 0 {
2203 return Ok(());
2205 }
2206
2207 let impl_ty_def_id = impl_ty.def_id.expect_local();
2211 debug!(?trait_to_impl_args);
2212
2213 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 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 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 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 ocx.resolve_regions_and_report_errors(impl_ty_def_id, param_env, [])
2304}
2305
2306#[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 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 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 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 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 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 ocx.resolve_regions_and_report_errors(impl_ty_def_id, param_env, assumed_wf_types)
2429}
2430
2431fn 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 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 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 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 }
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
2598fn 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 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}