rustc_trait_selection/traits/
dyn_compatibility.rs1use std::ops::ControlFlow;
8
9use rustc_errors::FatalError;
10use rustc_hir::def_id::DefId;
11use rustc_hir::{self as hir, LangItem};
12use rustc_middle::query::Providers;
13use rustc_middle::ty::{
14 self, EarlyBinder, GenericArgs, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
15 TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, Upcast,
16 elaborate,
17};
18use rustc_span::{DUMMY_SP, Span};
19use smallvec::SmallVec;
20use tracing::{debug, instrument};
21
22use super::elaborate;
23use crate::infer::TyCtxtInferExt;
24pub use crate::traits::DynCompatibilityViolation;
25use crate::traits::query::evaluate_obligation::InferCtxtExt;
26use crate::traits::{
27 MethodViolationCode, Obligation, ObligationCause, normalize_param_env_or_error, util,
28};
29
30#[instrument(level = "debug", skip(tcx), ret)]
36pub fn hir_ty_lowering_dyn_compatibility_violations(
37 tcx: TyCtxt<'_>,
38 trait_def_id: DefId,
39) -> Vec<DynCompatibilityViolation> {
40 debug_assert!(tcx.generics_of(trait_def_id).has_self);
41 elaborate::supertrait_def_ids(tcx, trait_def_id)
42 .map(|def_id| predicates_reference_self(tcx, def_id, true))
43 .filter(|spans| !spans.is_empty())
44 .map(DynCompatibilityViolation::SupertraitSelf)
45 .collect()
46}
47
48fn dyn_compatibility_violations(
49 tcx: TyCtxt<'_>,
50 trait_def_id: DefId,
51) -> &'_ [DynCompatibilityViolation] {
52 debug_assert!(tcx.generics_of(trait_def_id).has_self);
53 debug!("dyn_compatibility_violations: {:?}", trait_def_id);
54 tcx.arena.alloc_from_iter(
55 elaborate::supertrait_def_ids(tcx, trait_def_id)
56 .flat_map(|def_id| dyn_compatibility_violations_for_trait(tcx, def_id)),
57 )
58}
59
60fn is_dyn_compatible(tcx: TyCtxt<'_>, trait_def_id: DefId) -> bool {
61 tcx.dyn_compatibility_violations(trait_def_id).is_empty()
62}
63
64pub fn is_vtable_safe_method(tcx: TyCtxt<'_>, trait_def_id: DefId, method: ty::AssocItem) -> bool {
69 debug_assert!(tcx.generics_of(trait_def_id).has_self);
70 debug!("is_vtable_safe_method({:?}, {:?})", trait_def_id, method);
71 if tcx.generics_require_sized_self(method.def_id) {
73 return false;
74 }
75
76 virtual_call_violations_for_method(tcx, trait_def_id, method).is_empty()
77}
78
79#[instrument(level = "debug", skip(tcx), ret)]
80fn dyn_compatibility_violations_for_trait(
81 tcx: TyCtxt<'_>,
82 trait_def_id: DefId,
83) -> Vec<DynCompatibilityViolation> {
84 let mut violations: Vec<_> = tcx
86 .associated_items(trait_def_id)
87 .in_definition_order()
88 .flat_map(|&item| dyn_compatibility_violations_for_assoc_item(tcx, trait_def_id, item))
89 .collect();
90
91 if trait_has_sized_self(tcx, trait_def_id) {
93 let spans = get_sized_bounds(tcx, trait_def_id);
95 violations.push(DynCompatibilityViolation::SizedSelf(spans));
96 }
97 let spans = predicates_reference_self(tcx, trait_def_id, false);
98 if !spans.is_empty() {
99 violations.push(DynCompatibilityViolation::SupertraitSelf(spans));
100 }
101 let spans = bounds_reference_self(tcx, trait_def_id);
102 if !spans.is_empty() {
103 violations.push(DynCompatibilityViolation::SupertraitSelf(spans));
104 }
105 let spans = super_predicates_have_non_lifetime_binders(tcx, trait_def_id);
106 if !spans.is_empty() {
107 violations.push(DynCompatibilityViolation::SupertraitNonLifetimeBinder(spans));
108 }
109 let spans = super_predicates_are_unconditionally_const(tcx, trait_def_id);
110 if !spans.is_empty() {
111 violations.push(DynCompatibilityViolation::SupertraitConst(spans));
112 }
113
114 violations
115}
116
117fn sized_trait_bound_spans<'tcx>(
118 tcx: TyCtxt<'tcx>,
119 bounds: hir::GenericBounds<'tcx>,
120) -> impl 'tcx + Iterator<Item = Span> {
121 bounds.iter().filter_map(move |b| match b {
122 hir::GenericBound::Trait(trait_ref)
123 if trait_has_sized_self(
124 tcx,
125 trait_ref.trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise()),
126 ) =>
127 {
128 Some(trait_ref.span)
130 }
131 _ => None,
132 })
133}
134
135fn get_sized_bounds(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span; 1]> {
136 tcx.hir_get_if_local(trait_def_id)
137 .and_then(|node| match node {
138 hir::Node::Item(hir::Item {
139 kind: hir::ItemKind::Trait(.., generics, bounds, _),
140 ..
141 }) => Some(
142 generics
143 .predicates
144 .iter()
145 .filter_map(|pred| {
146 match pred.kind {
147 hir::WherePredicateKind::BoundPredicate(pred)
148 if pred.bounded_ty.hir_id.owner.to_def_id() == trait_def_id =>
149 {
150 Some(sized_trait_bound_spans(tcx, pred.bounds))
153 }
154 _ => None,
155 }
156 })
157 .flatten()
158 .chain(sized_trait_bound_spans(tcx, bounds))
160 .collect::<SmallVec<[Span; 1]>>(),
161 ),
162 _ => None,
163 })
164 .unwrap_or_else(SmallVec::new)
165}
166
167fn predicates_reference_self(
168 tcx: TyCtxt<'_>,
169 trait_def_id: DefId,
170 supertraits_only: bool,
171) -> SmallVec<[Span; 1]> {
172 let trait_ref = ty::Binder::dummy(ty::TraitRef::identity(tcx, trait_def_id));
173 let predicates = if supertraits_only {
174 tcx.explicit_super_predicates_of(trait_def_id).skip_binder()
175 } else {
176 tcx.predicates_of(trait_def_id).predicates
177 };
178 predicates
179 .iter()
180 .map(|&(predicate, sp)| (predicate.instantiate_supertrait(tcx, trait_ref), sp))
181 .filter_map(|(clause, sp)| {
182 predicate_references_self(tcx, trait_def_id, clause, sp, AllowSelfProjections::No)
187 })
188 .collect()
189}
190
191fn bounds_reference_self(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span; 1]> {
192 tcx.associated_items(trait_def_id)
193 .in_definition_order()
194 .filter(|item| item.is_type())
196 .filter(|item| !tcx.generics_require_sized_self(item.def_id))
198 .flat_map(|item| tcx.explicit_item_bounds(item.def_id).iter_identity_copied())
199 .filter_map(|(clause, sp)| {
200 predicate_references_self(tcx, trait_def_id, clause, sp, AllowSelfProjections::Yes)
203 })
204 .collect()
205}
206
207fn predicate_references_self<'tcx>(
208 tcx: TyCtxt<'tcx>,
209 trait_def_id: DefId,
210 predicate: ty::Clause<'tcx>,
211 sp: Span,
212 allow_self_projections: AllowSelfProjections,
213) -> Option<Span> {
214 match predicate.kind().skip_binder() {
215 ty::ClauseKind::Trait(ref data) => {
216 data.trait_ref.args[1..].iter().any(|&arg| contains_illegal_self_type_reference(tcx, trait_def_id, arg, allow_self_projections)).then_some(sp)
218 }
219 ty::ClauseKind::Projection(ref data) => {
220 data.projection_term.args[1..].iter().any(|&arg| contains_illegal_self_type_reference(tcx, trait_def_id, arg, allow_self_projections)).then_some(sp)
236 }
237 ty::ClauseKind::ConstArgHasType(_ct, ty) => contains_illegal_self_type_reference(tcx, trait_def_id, ty, allow_self_projections).then_some(sp),
238
239 ty::ClauseKind::WellFormed(..)
240 | ty::ClauseKind::TypeOutlives(..)
241 | ty::ClauseKind::RegionOutlives(..)
242 | ty::ClauseKind::ConstEvaluatable(..)
244 | ty::ClauseKind::HostEffect(..)
245 | ty::ClauseKind::UnstableFeature(_)
246 => None,
247 }
248}
249
250fn super_predicates_have_non_lifetime_binders(
251 tcx: TyCtxt<'_>,
252 trait_def_id: DefId,
253) -> SmallVec<[Span; 1]> {
254 tcx.explicit_super_predicates_of(trait_def_id)
255 .iter_identity_copied()
256 .filter_map(|(pred, span)| pred.has_non_region_bound_vars().then_some(span))
257 .collect()
258}
259
260fn super_predicates_are_unconditionally_const(
264 tcx: TyCtxt<'_>,
265 trait_def_id: DefId,
266) -> SmallVec<[Span; 1]> {
267 tcx.explicit_super_predicates_of(trait_def_id)
268 .iter_identity_copied()
269 .filter_map(|(pred, span)| {
270 if let ty::ClauseKind::HostEffect(_) = pred.kind().skip_binder() {
271 Some(span)
272 } else {
273 None
274 }
275 })
276 .collect()
277}
278
279fn trait_has_sized_self(tcx: TyCtxt<'_>, trait_def_id: DefId) -> bool {
280 tcx.generics_require_sized_self(trait_def_id)
281}
282
283fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
284 let Some(sized_def_id) = tcx.lang_items().sized_trait() else {
285 return false; };
287
288 let predicates = tcx.predicates_of(def_id);
290 let predicates = predicates.instantiate_identity(tcx).predicates;
291 elaborate(tcx, predicates).any(|pred| match pred.kind().skip_binder() {
292 ty::ClauseKind::Trait(ref trait_pred) => {
293 trait_pred.def_id() == sized_def_id && trait_pred.self_ty().is_param(0)
294 }
295 ty::ClauseKind::RegionOutlives(_)
296 | ty::ClauseKind::TypeOutlives(_)
297 | ty::ClauseKind::Projection(_)
298 | ty::ClauseKind::ConstArgHasType(_, _)
299 | ty::ClauseKind::WellFormed(_)
300 | ty::ClauseKind::ConstEvaluatable(_)
301 | ty::ClauseKind::UnstableFeature(_)
302 | ty::ClauseKind::HostEffect(..) => false,
303 })
304}
305
306#[instrument(level = "debug", skip(tcx), ret)]
308pub fn dyn_compatibility_violations_for_assoc_item(
309 tcx: TyCtxt<'_>,
310 trait_def_id: DefId,
311 item: ty::AssocItem,
312) -> Vec<DynCompatibilityViolation> {
313 if tcx.generics_require_sized_self(item.def_id) {
316 return Vec::new();
317 }
318
319 match item.kind {
320 ty::AssocKind::Const { name } => {
323 vec![DynCompatibilityViolation::AssocConst(name, item.ident(tcx).span)]
324 }
325 ty::AssocKind::Fn { name, .. } => {
326 virtual_call_violations_for_method(tcx, trait_def_id, item)
327 .into_iter()
328 .map(|v| {
329 let node = tcx.hir_get_if_local(item.def_id);
330 let span = match (&v, node) {
332 (MethodViolationCode::ReferencesSelfInput(Some(span)), _) => *span,
333 (MethodViolationCode::UndispatchableReceiver(Some(span)), _) => *span,
334 (MethodViolationCode::ReferencesImplTraitInTrait(span), _) => *span,
335 (MethodViolationCode::ReferencesSelfOutput, Some(node)) => {
336 node.fn_decl().map_or(item.ident(tcx).span, |decl| decl.output.span())
337 }
338 _ => item.ident(tcx).span,
339 };
340
341 DynCompatibilityViolation::Method(name, v, span)
342 })
343 .collect()
344 }
345 ty::AssocKind::Type { .. } => {
347 if !tcx.generics_of(item.def_id).is_own_empty() && !item.is_impl_trait_in_trait() {
348 vec![DynCompatibilityViolation::GAT(item.name(), item.ident(tcx).span)]
349 } else {
350 Vec::new()
353 }
354 }
355 }
356}
357
358fn virtual_call_violations_for_method<'tcx>(
363 tcx: TyCtxt<'tcx>,
364 trait_def_id: DefId,
365 method: ty::AssocItem,
366) -> Vec<MethodViolationCode> {
367 let sig = tcx.fn_sig(method.def_id).instantiate_identity();
368
369 if !method.is_method() {
371 let sugg = if let Some(hir::Node::TraitItem(hir::TraitItem {
372 generics,
373 kind: hir::TraitItemKind::Fn(sig, _),
374 ..
375 })) = tcx.hir_get_if_local(method.def_id).as_ref()
376 {
377 let sm = tcx.sess.source_map();
378 Some((
379 (
380 format!("&self{}", if sig.decl.inputs.is_empty() { "" } else { ", " }),
381 sm.span_through_char(sig.span, '(').shrink_to_hi(),
382 ),
383 (
384 format!("{} Self: Sized", generics.add_where_or_trailing_comma()),
385 generics.tail_span_for_predicate_suggestion(),
386 ),
387 ))
388 } else {
389 None
390 };
391
392 return vec![MethodViolationCode::StaticMethod(sugg)];
395 }
396
397 let mut errors = Vec::new();
398
399 for (i, &input_ty) in sig.skip_binder().inputs().iter().enumerate().skip(1) {
400 if contains_illegal_self_type_reference(
401 tcx,
402 trait_def_id,
403 sig.rebind(input_ty),
404 AllowSelfProjections::Yes,
405 ) {
406 let span = if let Some(hir::Node::TraitItem(hir::TraitItem {
407 kind: hir::TraitItemKind::Fn(sig, _),
408 ..
409 })) = tcx.hir_get_if_local(method.def_id).as_ref()
410 {
411 Some(sig.decl.inputs[i].span)
412 } else {
413 None
414 };
415 errors.push(MethodViolationCode::ReferencesSelfInput(span));
416 }
417 }
418 if contains_illegal_self_type_reference(
419 tcx,
420 trait_def_id,
421 sig.output(),
422 AllowSelfProjections::Yes,
423 ) {
424 errors.push(MethodViolationCode::ReferencesSelfOutput);
425 }
426 if let Some(code) = contains_illegal_impl_trait_in_trait(tcx, method.def_id, sig.output()) {
427 errors.push(code);
428 }
429
430 let own_counts = tcx.generics_of(method.def_id).own_counts();
432 if own_counts.types > 0 || own_counts.consts > 0 {
433 errors.push(MethodViolationCode::Generic);
434 }
435
436 let receiver_ty = tcx.liberate_late_bound_regions(method.def_id, sig.input(0));
437
438 if receiver_ty != tcx.types.self_param {
443 if !receiver_is_dispatchable(tcx, method, receiver_ty) {
444 let span = if let Some(hir::Node::TraitItem(hir::TraitItem {
445 kind: hir::TraitItemKind::Fn(sig, _),
446 ..
447 })) = tcx.hir_get_if_local(method.def_id).as_ref()
448 {
449 Some(sig.decl.inputs[0].span)
450 } else {
451 None
452 };
453 errors.push(MethodViolationCode::UndispatchableReceiver(span));
454 } else {
455 }
458 }
459
460 if tcx.predicates_of(method.def_id).predicates.iter().any(|&(pred, _span)| {
463 if pred.as_type_outlives_clause().is_some() {
473 return false;
474 }
475
476 if let ty::ClauseKind::Trait(ty::TraitPredicate {
490 trait_ref: pred_trait_ref,
491 polarity: ty::PredicatePolarity::Positive,
492 }) = pred.kind().skip_binder()
493 && pred_trait_ref.self_ty() == tcx.types.self_param
494 && tcx.trait_is_auto(pred_trait_ref.def_id)
495 {
496 if pred_trait_ref.args.len() != 1 {
501 assert!(
502 tcx.dcx().has_errors().is_some(),
503 "auto traits cannot have generic parameters"
504 );
505 }
506 return false;
507 }
508
509 contains_illegal_self_type_reference(tcx, trait_def_id, pred, AllowSelfProjections::Yes)
510 }) {
511 errors.push(MethodViolationCode::WhereClauseReferencesSelf);
512 }
513
514 errors
515}
516
517fn receiver_for_self_ty<'tcx>(
520 tcx: TyCtxt<'tcx>,
521 receiver_ty: Ty<'tcx>,
522 self_ty: Ty<'tcx>,
523 method_def_id: DefId,
524) -> Ty<'tcx> {
525 debug!("receiver_for_self_ty({:?}, {:?}, {:?})", receiver_ty, self_ty, method_def_id);
526 let args = GenericArgs::for_item(tcx, method_def_id, |param, _| {
527 if param.index == 0 { self_ty.into() } else { tcx.mk_param_from_def(param) }
528 });
529
530 let result = EarlyBinder::bind(receiver_ty).instantiate(tcx, args);
531 debug!(
532 "receiver_for_self_ty({:?}, {:?}, {:?}) = {:?}",
533 receiver_ty, self_ty, method_def_id, result
534 );
535 result
536}
537
538fn receiver_is_dispatchable<'tcx>(
585 tcx: TyCtxt<'tcx>,
586 method: ty::AssocItem,
587 receiver_ty: Ty<'tcx>,
588) -> bool {
589 debug!("receiver_is_dispatchable: method = {:?}, receiver_ty = {:?}", method, receiver_ty);
590
591 let (Some(unsize_did), Some(dispatch_from_dyn_did)) =
592 (tcx.lang_items().unsize_trait(), tcx.lang_items().dispatch_from_dyn_trait())
593 else {
594 debug!("receiver_is_dispatchable: Missing `Unsize` or `DispatchFromDyn` traits");
595 return false;
596 };
597
598 let unsized_self_ty: Ty<'tcx> =
601 Ty::new_param(tcx, u32::MAX, rustc_span::sym::RustaceansAreAwesome);
602
603 let unsized_receiver_ty =
605 receiver_for_self_ty(tcx, receiver_ty, unsized_self_ty, method.def_id);
606
607 let param_env = {
610 let mut predicates = tcx.predicates_of(method.def_id).instantiate_identity(tcx).predicates;
623
624 let unsize_predicate =
626 ty::TraitRef::new(tcx, unsize_did, [tcx.types.self_param, unsized_self_ty]);
627 predicates.push(unsize_predicate.upcast(tcx));
628
629 let trait_def_id = method.trait_container(tcx).unwrap();
631 let args = GenericArgs::for_item(tcx, trait_def_id, |param, _| {
632 if param.index == 0 { unsized_self_ty.into() } else { tcx.mk_param_from_def(param) }
633 });
634 let trait_predicate = ty::TraitRef::new_from_args(tcx, trait_def_id, args);
635 predicates.push(trait_predicate.upcast(tcx));
636
637 let meta_sized_predicate = {
638 let meta_sized_did = tcx.require_lang_item(LangItem::MetaSized, DUMMY_SP);
639 ty::TraitRef::new(tcx, meta_sized_did, [unsized_self_ty]).upcast(tcx)
640 };
641 predicates.push(meta_sized_predicate);
642
643 normalize_param_env_or_error(
644 tcx,
645 ty::ParamEnv::new(tcx.mk_clauses(&predicates)),
646 ObligationCause::dummy_with_span(tcx.def_span(method.def_id)),
647 )
648 };
649
650 let obligation = {
652 let predicate =
653 ty::TraitRef::new(tcx, dispatch_from_dyn_did, [receiver_ty, unsized_receiver_ty]);
654
655 Obligation::new(tcx, ObligationCause::dummy(), param_env, predicate)
656 };
657
658 let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
659 infcx.predicate_must_hold_modulo_regions(&obligation)
661}
662
663#[derive(Copy, Clone)]
664enum AllowSelfProjections {
665 Yes,
666 No,
667}
668
669fn contains_illegal_self_type_reference<'tcx, T: TypeVisitable<TyCtxt<'tcx>>>(
708 tcx: TyCtxt<'tcx>,
709 trait_def_id: DefId,
710 value: T,
711 allow_self_projections: AllowSelfProjections,
712) -> bool {
713 value
714 .visit_with(&mut IllegalSelfTypeVisitor {
715 tcx,
716 trait_def_id,
717 supertraits: None,
718 allow_self_projections,
719 })
720 .is_break()
721}
722
723struct IllegalSelfTypeVisitor<'tcx> {
724 tcx: TyCtxt<'tcx>,
725 trait_def_id: DefId,
726 supertraits: Option<Vec<ty::TraitRef<'tcx>>>,
727 allow_self_projections: AllowSelfProjections,
728}
729
730impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for IllegalSelfTypeVisitor<'tcx> {
731 type Result = ControlFlow<()>;
732
733 fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
734 match t.kind() {
735 ty::Param(_) => {
736 if t == self.tcx.types.self_param {
737 ControlFlow::Break(())
738 } else {
739 ControlFlow::Continue(())
740 }
741 }
742 ty::Alias(ty::Projection, data) if self.tcx.is_impl_trait_in_trait(data.def_id) => {
743 ControlFlow::Continue(())
745 }
746 ty::Alias(ty::Projection, data) => {
747 match self.allow_self_projections {
748 AllowSelfProjections::Yes => {
749 if self.supertraits.is_none() {
753 self.supertraits = Some(
754 util::supertraits(
755 self.tcx,
756 ty::Binder::dummy(ty::TraitRef::identity(
757 self.tcx,
758 self.trait_def_id,
759 )),
760 )
761 .map(|trait_ref| {
762 self.tcx.erase_and_anonymize_regions(
763 self.tcx.instantiate_bound_regions_with_erased(trait_ref),
764 )
765 })
766 .collect(),
767 );
768 }
769
770 let is_supertrait_of_current_trait =
779 self.supertraits.as_ref().unwrap().contains(
780 &data.trait_ref(self.tcx).fold_with(
781 &mut EraseEscapingBoundRegions {
782 tcx: self.tcx,
783 binder: ty::INNERMOST,
784 },
785 ),
786 );
787
788 if is_supertrait_of_current_trait {
790 ControlFlow::Continue(())
791 } else {
792 t.super_visit_with(self) }
794 }
795 AllowSelfProjections::No => t.super_visit_with(self),
796 }
797 }
798 _ => t.super_visit_with(self),
799 }
800 }
801
802 fn visit_const(&mut self, ct: ty::Const<'tcx>) -> Self::Result {
803 self.tcx.expand_abstract_consts(ct).super_visit_with(self)
806 }
807}
808
809struct EraseEscapingBoundRegions<'tcx> {
810 tcx: TyCtxt<'tcx>,
811 binder: ty::DebruijnIndex,
812}
813
814impl<'tcx> TypeFolder<TyCtxt<'tcx>> for EraseEscapingBoundRegions<'tcx> {
815 fn cx(&self) -> TyCtxt<'tcx> {
816 self.tcx
817 }
818
819 fn fold_binder<T>(&mut self, t: ty::Binder<'tcx, T>) -> ty::Binder<'tcx, T>
820 where
821 T: TypeFoldable<TyCtxt<'tcx>>,
822 {
823 self.binder.shift_in(1);
824 let result = t.super_fold_with(self);
825 self.binder.shift_out(1);
826 result
827 }
828
829 fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
830 if let ty::ReBound(debruijn, _) = r.kind()
831 && debruijn < self.binder
832 {
833 r
834 } else {
835 self.tcx.lifetimes.re_erased
836 }
837 }
838}
839
840fn contains_illegal_impl_trait_in_trait<'tcx>(
841 tcx: TyCtxt<'tcx>,
842 fn_def_id: DefId,
843 ty: ty::Binder<'tcx, Ty<'tcx>>,
844) -> Option<MethodViolationCode> {
845 let ty = tcx.liberate_late_bound_regions(fn_def_id, ty);
846
847 if tcx.asyncness(fn_def_id).is_async() {
848 Some(MethodViolationCode::AsyncFn)
850 } else {
851 ty.visit_with(&mut IllegalRpititVisitor { tcx, allowed: None }).break_value()
852 }
853}
854
855struct IllegalRpititVisitor<'tcx> {
856 tcx: TyCtxt<'tcx>,
857 allowed: Option<ty::AliasTy<'tcx>>,
858}
859
860impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for IllegalRpititVisitor<'tcx> {
861 type Result = ControlFlow<MethodViolationCode>;
862
863 fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
864 if let ty::Alias(ty::Projection, proj) = *ty.kind()
865 && Some(proj) != self.allowed
866 && self.tcx.is_impl_trait_in_trait(proj.def_id)
867 {
868 ControlFlow::Break(MethodViolationCode::ReferencesImplTraitInTrait(
869 self.tcx.def_span(proj.def_id),
870 ))
871 } else {
872 ty.super_visit_with(self)
873 }
874 }
875}
876
877pub(crate) fn provide(providers: &mut Providers) {
878 *providers = Providers {
879 dyn_compatibility_violations,
880 is_dyn_compatible,
881 generics_require_sized_self,
882 ..*providers
883 };
884}