Skip to main content

rustc_trait_selection/traits/
dyn_compatibility.rs

1//! "Dyn-compatibility"[^1] refers to the ability for a trait to be converted
2//! to a trait object. In general, traits may only be converted to a trait
3//! object if certain criteria are met.
4//!
5//! [^1]: Formerly known as "object safety".
6
7use 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, Unnormalized,
16    Upcast, 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    AssocConstViolation, MethodViolation, Obligation, ObligationCause,
28    normalize_param_env_or_error, util,
29};
30
31/// Returns the dyn-compatibility violations that affect HIR ty lowering.
32///
33/// Currently that is `Self` in supertraits. This is needed
34/// because `dyn_compatibility_violations` can't be used during
35/// type collection, as type collection is needed for `dyn_compatibility_violations` itself.
36x;#[instrument(level = "debug", skip(tcx), ret)]
37pub fn hir_ty_lowering_dyn_compatibility_violations(
38    tcx: TyCtxt<'_>,
39    trait_def_id: DefId,
40) -> Vec<DynCompatibilityViolation> {
41    debug_assert!(tcx.generics_of(trait_def_id).has_self);
42    elaborate::supertrait_def_ids(tcx, trait_def_id)
43        .map(|def_id| predicates_reference_self(tcx, def_id, true))
44        .filter(|spans| !spans.is_empty())
45        .map(DynCompatibilityViolation::SupertraitSelf)
46        .collect()
47}
48
49fn dyn_compatibility_violations(
50    tcx: TyCtxt<'_>,
51    trait_def_id: DefId,
52) -> &'_ [DynCompatibilityViolation] {
53    if true {
    if !tcx.generics_of(trait_def_id).has_self {
        ::core::panicking::panic("assertion failed: tcx.generics_of(trait_def_id).has_self")
    };
};debug_assert!(tcx.generics_of(trait_def_id).has_self);
54    {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs:54",
                        "rustc_trait_selection::traits::dyn_compatibility",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs"),
                        ::tracing_core::__macro_support::Option::Some(54u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::dyn_compatibility"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("dyn_compatibility_violations: {0:?}",
                                                    trait_def_id) as &dyn Value))])
            });
    } else { ; }
};debug!("dyn_compatibility_violations: {:?}", trait_def_id);
55    tcx.arena.alloc_from_iter(
56        elaborate::supertrait_def_ids(tcx, trait_def_id)
57            .flat_map(|def_id| dyn_compatibility_violations_for_trait(tcx, def_id)),
58    )
59}
60
61fn is_dyn_compatible(tcx: TyCtxt<'_>, trait_def_id: DefId) -> bool {
62    tcx.dyn_compatibility_violations(trait_def_id).is_empty()
63}
64
65/// We say a method is *vtable safe* if it can be invoked on a trait
66/// object. Note that dyn-compatible traits can have some
67/// non-vtable-safe methods, so long as they require `Self: Sized` or
68/// otherwise ensure that they cannot be used when `Self = Trait`.
69pub fn is_vtable_safe_method(tcx: TyCtxt<'_>, trait_def_id: DefId, method: ty::AssocItem) -> bool {
70    if true {
    if !tcx.generics_of(trait_def_id).has_self {
        ::core::panicking::panic("assertion failed: tcx.generics_of(trait_def_id).has_self")
    };
};debug_assert!(tcx.generics_of(trait_def_id).has_self);
71    {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs:71",
                        "rustc_trait_selection::traits::dyn_compatibility",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs"),
                        ::tracing_core::__macro_support::Option::Some(71u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::dyn_compatibility"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("is_vtable_safe_method({0:?}, {1:?})",
                                                    trait_def_id, method) as &dyn Value))])
            });
    } else { ; }
};debug!("is_vtable_safe_method({:?}, {:?})", trait_def_id, method);
72    // Any method that has a `Self: Sized` bound cannot be called.
73    if tcx.generics_require_sized_self(method.def_id) {
74        return false;
75    }
76
77    virtual_call_violations_for_method(tcx, trait_def_id, method).is_empty()
78}
79
80x;#[instrument(level = "debug", skip(tcx), ret)]
81fn dyn_compatibility_violations_for_trait(
82    tcx: TyCtxt<'_>,
83    trait_def_id: DefId,
84) -> Vec<DynCompatibilityViolation> {
85    // Check assoc items for violations.
86    let mut violations: Vec<_> = tcx
87        .associated_items(trait_def_id)
88        .in_definition_order()
89        .flat_map(|&item| dyn_compatibility_violations_for_assoc_item(tcx, trait_def_id, item))
90        .collect();
91
92    // Check the trait itself.
93    if trait_has_sized_self(tcx, trait_def_id) {
94        // We don't want to include the requirement from `Sized` itself to be `Sized` in the list.
95        let spans = get_sized_bounds(tcx, trait_def_id);
96        violations.push(DynCompatibilityViolation::SizedSelf(spans));
97    } else if let Some(span) = tcx.trait_def(trait_def_id).force_dyn_incompatible {
98        violations.push(DynCompatibilityViolation::ExplicitlyDynIncompatible([span].into()));
99    }
100
101    let spans = predicates_reference_self(tcx, trait_def_id, false);
102    if !spans.is_empty() {
103        violations.push(DynCompatibilityViolation::SupertraitSelf(spans));
104    }
105    let spans = bounds_reference_self(tcx, trait_def_id);
106    if !spans.is_empty() {
107        violations.push(DynCompatibilityViolation::SupertraitSelf(spans));
108    }
109    let spans = super_predicates_have_non_lifetime_binders(tcx, trait_def_id);
110    if !spans.is_empty() {
111        violations.push(DynCompatibilityViolation::SupertraitNonLifetimeBinder(spans));
112    }
113    let spans = super_predicates_are_unconditionally_const(tcx, trait_def_id);
114    if !spans.is_empty() {
115        violations.push(DynCompatibilityViolation::SupertraitConst(spans));
116    }
117
118    violations
119}
120
121fn sized_trait_bound_spans<'tcx>(
122    tcx: TyCtxt<'tcx>,
123    bounds: hir::GenericBounds<'tcx>,
124) -> impl 'tcx + Iterator<Item = Span> {
125    bounds.iter().filter_map(move |b| match b {
126        hir::GenericBound::Trait(trait_ref)
127            if trait_has_sized_self(
128                tcx,
129                trait_ref.trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise()),
130            ) =>
131        {
132            // Fetch spans for supertraits that are `Sized`: `trait T: Super`
133            Some(trait_ref.span)
134        }
135        _ => None,
136    })
137}
138
139fn get_sized_bounds(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span; 1]> {
140    tcx.hir_get_if_local(trait_def_id)
141        .and_then(|node| match node {
142            hir::Node::Item(hir::Item {
143                kind: hir::ItemKind::Trait { generics, bounds, .. },
144                ..
145            }) => Some(
146                generics
147                    .predicates
148                    .iter()
149                    .filter_map(|pred| {
150                        match pred.kind {
151                            hir::WherePredicateKind::BoundPredicate(pred)
152                                if pred.bounded_ty.hir_id.owner.to_def_id() == trait_def_id =>
153                            {
154                                // Fetch spans for trait bounds that are Sized:
155                                // `trait T where Self: Pred`
156                                Some(sized_trait_bound_spans(tcx, pred.bounds))
157                            }
158                            _ => None,
159                        }
160                    })
161                    .flatten()
162                    // Fetch spans for supertraits that are `Sized`: `trait T: Super`.
163                    .chain(sized_trait_bound_spans(tcx, bounds))
164                    .collect::<SmallVec<[Span; 1]>>(),
165            ),
166            _ => None,
167        })
168        .unwrap_or_else(SmallVec::new)
169}
170
171fn predicates_reference_self(
172    tcx: TyCtxt<'_>,
173    trait_def_id: DefId,
174    supertraits_only: bool,
175) -> SmallVec<[Span; 1]> {
176    let trait_ref = ty::Binder::dummy(ty::TraitRef::identity(tcx, trait_def_id));
177    let predicates = if supertraits_only {
178        tcx.explicit_super_predicates_of(trait_def_id).skip_binder()
179    } else {
180        tcx.predicates_of(trait_def_id).predicates
181    };
182    predicates
183        .iter()
184        .map(|&(predicate, sp)| (predicate.instantiate_supertrait(tcx, trait_ref), sp))
185        .filter_map(|(clause, sp)| {
186            // Super predicates cannot allow self projections, since they're
187            // impossible to make into existential bounds without eager resolution
188            // or something.
189            // e.g. `trait A: B<Item = Self::Assoc>`.
190            predicate_references_self(tcx, trait_def_id, clause, sp, AllowSelfProjections::No)
191        })
192        .collect()
193}
194
195fn bounds_reference_self(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span; 1]> {
196    tcx.associated_items(trait_def_id)
197        .in_definition_order()
198        // We're only looking at associated type bounds
199        .filter(|item| item.is_type())
200        // Ignore GATs with `Self: Sized`
201        .filter(|item| !tcx.generics_require_sized_self(item.def_id))
202        .flat_map(|item| {
203            tcx.explicit_item_bounds(item.def_id)
204                .iter_identity_copied()
205                .map(Unnormalized::skip_norm_wip)
206        })
207        .filter_map(|(clause, sp)| {
208            // Item bounds *can* have self projections, since they never get
209            // their self type erased.
210            predicate_references_self(tcx, trait_def_id, clause, sp, AllowSelfProjections::Yes)
211        })
212        .collect()
213}
214
215fn predicate_references_self<'tcx>(
216    tcx: TyCtxt<'tcx>,
217    trait_def_id: DefId,
218    predicate: ty::Clause<'tcx>,
219    sp: Span,
220    allow_self_projections: AllowSelfProjections,
221) -> Option<Span> {
222    match predicate.kind().skip_binder() {
223        ty::ClauseKind::Trait(ref data) => {
224            // In the case of a trait predicate, we can skip the "self" type.
225            data.trait_ref.args[1..]
226                .iter()
227                .any(|&arg| {
228                    contains_illegal_self_type_reference(
229                        tcx,
230                        trait_def_id,
231                        arg,
232                        allow_self_projections,
233                    )
234                })
235                .then_some(sp)
236        }
237        ty::ClauseKind::Projection(ref data) => {
238            // And similarly for projections. This should be redundant with
239            // the previous check because any projection should have a
240            // matching `Trait` predicate with the same inputs, but we do
241            // the check to be safe.
242            //
243            // It's also won't be redundant if we allow type-generic associated
244            // types for trait objects.
245            //
246            // Note that we *do* allow projection *outputs* to contain
247            // `Self` (i.e., `trait Foo: Bar<Output=Self::Result> { type Result; }`),
248            // we just require the user to specify *both* outputs
249            // in the object type (i.e., `dyn Foo<Output=(), Result=()>`).
250            //
251            // This is ALT2 in issue #56288, see that for discussion of the
252            // possible alternatives.
253            data.projection_term.args[1..]
254                .iter()
255                .any(|&arg| {
256                    contains_illegal_self_type_reference(
257                        tcx,
258                        trait_def_id,
259                        arg,
260                        allow_self_projections,
261                    )
262                })
263                .then_some(sp)
264        }
265        ty::ClauseKind::ConstArgHasType(_ct, ty) => {
266            contains_illegal_self_type_reference(tcx, trait_def_id, ty, allow_self_projections)
267                .then_some(sp)
268        }
269
270        ty::ClauseKind::WellFormed(..)
271        | ty::ClauseKind::TypeOutlives(..)
272        | ty::ClauseKind::RegionOutlives(..)
273        | ty::ClauseKind::HostEffect(..)
274        | ty::ClauseKind::UnstableFeature(_) => None,
275
276        // FIXME(generic_const_exprs): this can mention `Self`
277        ty::ClauseKind::ConstEvaluatable(..) => None,
278    }
279}
280
281fn super_predicates_have_non_lifetime_binders(
282    tcx: TyCtxt<'_>,
283    trait_def_id: DefId,
284) -> SmallVec<[Span; 1]> {
285    tcx.explicit_super_predicates_of(trait_def_id)
286        .iter_identity_copied()
287        .map(Unnormalized::skip_norm_wip)
288        .filter_map(|(pred, span)| pred.has_non_region_bound_vars().then_some(span))
289        .collect()
290}
291
292/// Checks for `const Trait` supertraits. We're okay with `[const] Trait`,
293/// supertraits since for a non-const instantiation of that trait, the
294/// conditionally-const supertrait is also not required to be const.
295fn super_predicates_are_unconditionally_const(
296    tcx: TyCtxt<'_>,
297    trait_def_id: DefId,
298) -> SmallVec<[Span; 1]> {
299    tcx.explicit_super_predicates_of(trait_def_id)
300        .iter_identity_copied()
301        .map(Unnormalized::skip_norm_wip)
302        .filter_map(|(pred, span)| {
303            if let ty::ClauseKind::HostEffect(_) = pred.kind().skip_binder() {
304                Some(span)
305            } else {
306                None
307            }
308        })
309        .collect()
310}
311
312fn trait_has_sized_self(tcx: TyCtxt<'_>, trait_def_id: DefId) -> bool {
313    tcx.generics_require_sized_self(trait_def_id)
314}
315
316fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
317    let Some(sized_def_id) = tcx.lang_items().sized_trait() else {
318        return false; /* No Sized trait, can't require it! */
319    };
320
321    // Search for a predicate like `Self: Sized` amongst the trait bounds.
322    let predicates: Vec<_> = tcx
323        .predicates_of(def_id)
324        .instantiate_identity(tcx)
325        .predicates
326        .into_iter()
327        .map(Unnormalized::skip_norm_wip)
328        .collect();
329    elaborate(tcx, predicates).any(|pred| match pred.kind().skip_binder() {
330        ty::ClauseKind::Trait(ref trait_pred) => {
331            trait_pred.def_id() == sized_def_id && trait_pred.self_ty().is_param(0)
332        }
333        ty::ClauseKind::RegionOutlives(_)
334        | ty::ClauseKind::TypeOutlives(_)
335        | ty::ClauseKind::Projection(_)
336        | ty::ClauseKind::ConstArgHasType(_, _)
337        | ty::ClauseKind::WellFormed(_)
338        | ty::ClauseKind::ConstEvaluatable(_)
339        | ty::ClauseKind::UnstableFeature(_)
340        | ty::ClauseKind::HostEffect(..) => false,
341    })
342}
343
344x;#[instrument(level = "debug", skip(tcx), ret)]
345pub fn dyn_compatibility_violations_for_assoc_item(
346    tcx: TyCtxt<'_>,
347    trait_def_id: DefId,
348    item: ty::AssocItem,
349) -> Vec<DynCompatibilityViolation> {
350    // `final` assoc functions don't prevent a trait from being dyn-compatible
351    if tcx.defaultness(item.def_id).is_final() {
352        return Vec::new();
353    }
354
355    // Any item that has a `Self: Sized` requisite is otherwise exempt from the regulations.
356    if tcx.generics_require_sized_self(item.def_id) {
357        return Vec::new();
358    }
359
360    let span = || item.ident(tcx).span;
361
362    match item.kind {
363        ty::AssocKind::Const { name, is_type_const } => {
364            // We will permit type associated consts if they are explicitly mentioned in the
365            // trait object type. We can't check this here, as here we only check if it is
366            // guaranteed to not be possible.
367
368            let mut errors = Vec::new();
369
370            if tcx.features().min_generic_const_args() {
371                if !tcx.generics_of(item.def_id).is_own_empty() {
372                    errors.push(AssocConstViolation::Generic);
373                } else if !is_type_const {
374                    errors.push(AssocConstViolation::NonType);
375                }
376
377                let ty = ty::Binder::dummy(
378                    tcx.type_of(item.def_id).instantiate_identity().skip_norm_wip(),
379                );
380                if contains_illegal_self_type_reference(
381                    tcx,
382                    trait_def_id,
383                    ty,
384                    AllowSelfProjections::Yes,
385                ) {
386                    errors.push(AssocConstViolation::TypeReferencesSelf);
387                }
388            } else {
389                errors.push(AssocConstViolation::FeatureNotEnabled);
390            }
391
392            errors
393                .into_iter()
394                .map(|error| DynCompatibilityViolation::AssocConst(name, error, span()))
395                .collect()
396        }
397        ty::AssocKind::Fn { name, .. } => {
398            virtual_call_violations_for_method(tcx, trait_def_id, item)
399                .into_iter()
400                .map(|v| {
401                    let node = tcx.hir_get_if_local(item.def_id);
402                    // Get an accurate span depending on the violation.
403                    let span = match (&v, node) {
404                        (MethodViolation::ReferencesSelfInput(Some(span)), _) => *span,
405                        (MethodViolation::UndispatchableReceiver(Some(span)), _) => *span,
406                        (MethodViolation::ReferencesImplTraitInTrait(span), _) => *span,
407                        (MethodViolation::ReferencesSelfOutput, Some(node)) => {
408                            node.fn_decl().map_or(item.ident(tcx).span, |decl| decl.output.span())
409                        }
410                        _ => span(),
411                    };
412
413                    DynCompatibilityViolation::Method(name, v, span)
414                })
415                .collect()
416        }
417        ty::AssocKind::Type { data } => {
418            if !tcx.generics_of(item.def_id).is_own_empty()
419                && let ty::AssocTypeData::Normal(name) = data
420            {
421                vec![DynCompatibilityViolation::GenericAssocTy(name, span())]
422            } else {
423                // We will permit associated types if they are explicitly mentioned in the trait
424                // object type. We can't check this here, as here we only check if it is
425                // guaranteed to not be possible.
426                Vec::new()
427            }
428        }
429    }
430}
431
432/// Returns `Some(_)` if this method cannot be called on a trait
433/// object; this does not necessarily imply that the enclosing trait
434/// is dyn-incompatible, because the method might have a where clause
435/// `Self: Sized`.
436fn virtual_call_violations_for_method<'tcx>(
437    tcx: TyCtxt<'tcx>,
438    trait_def_id: DefId,
439    method: ty::AssocItem,
440) -> Vec<MethodViolation> {
441    let sig = tcx.fn_sig(method.def_id).instantiate_identity().skip_norm_wip();
442
443    // The method's first parameter must be named `self`
444    if !method.is_method() {
445        let sugg = if let Some(hir::Node::TraitItem(hir::TraitItem {
446            generics,
447            kind: hir::TraitItemKind::Fn(sig, _),
448            ..
449        })) = tcx.hir_get_if_local(method.def_id).as_ref()
450        {
451            let sm = tcx.sess.source_map();
452            Some((
453                (
454                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("&self{0}",
                if sig.decl.inputs.is_empty() { "" } else { ", " }))
    })format!("&self{}", if sig.decl.inputs.is_empty() { "" } else { ", " }),
455                    sm.span_through_char(sig.span, '(').shrink_to_hi(),
456                ),
457                (
458                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} Self: Sized",
                generics.add_where_or_trailing_comma()))
    })format!("{} Self: Sized", generics.add_where_or_trailing_comma()),
459                    generics.tail_span_for_predicate_suggestion(),
460                ),
461            ))
462        } else {
463            None
464        };
465
466        // Not having `self` parameter messes up the later checks,
467        // so we need to return instead of pushing
468        return ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [MethodViolation::StaticMethod(sugg)]))vec![MethodViolation::StaticMethod(sugg)];
469    }
470
471    let mut errors = Vec::new();
472
473    for (i, &input_ty) in sig.skip_binder().inputs().iter().enumerate().skip(1) {
474        if contains_illegal_self_type_reference(
475            tcx,
476            trait_def_id,
477            sig.rebind(input_ty),
478            AllowSelfProjections::Yes,
479        ) {
480            let span = if let Some(hir::Node::TraitItem(hir::TraitItem {
481                kind: hir::TraitItemKind::Fn(sig, _),
482                ..
483            })) = tcx.hir_get_if_local(method.def_id).as_ref()
484            {
485                Some(sig.decl.inputs[i].span)
486            } else {
487                None
488            };
489            errors.push(MethodViolation::ReferencesSelfInput(span));
490        }
491    }
492    if contains_illegal_self_type_reference(
493        tcx,
494        trait_def_id,
495        sig.output(),
496        AllowSelfProjections::Yes,
497    ) {
498        errors.push(MethodViolation::ReferencesSelfOutput);
499    }
500    if let Some(error) = contains_illegal_impl_trait_in_trait(tcx, method.def_id, sig.output()) {
501        errors.push(error);
502    }
503    if sig.skip_binder().c_variadic() {
504        errors.push(MethodViolation::CVariadic);
505    }
506
507    // We can't monomorphize things like `fn foo<A>(...)`.
508    let own_counts = tcx.generics_of(method.def_id).own_counts();
509    if own_counts.types > 0 || own_counts.consts > 0 {
510        errors.push(MethodViolation::Generic);
511    }
512
513    let receiver_ty = tcx.liberate_late_bound_regions(method.def_id, sig.input(0));
514
515    // `self: Self` can't be dispatched on.
516    // However, this is considered dyn compatible. We allow it as a special case here.
517    // FIXME(mikeyhew) get rid of this `if` statement once `receiver_is_dispatchable` allows
518    // `Receiver: Unsize<Receiver[Self => dyn Trait]>`.
519    if receiver_ty != tcx.types.self_param {
520        if !receiver_is_dispatchable(tcx, method, receiver_ty) {
521            let span = if let Some(hir::Node::TraitItem(hir::TraitItem {
522                kind: hir::TraitItemKind::Fn(sig, _),
523                ..
524            })) = tcx.hir_get_if_local(method.def_id).as_ref()
525            {
526                Some(sig.decl.inputs[0].span)
527            } else {
528                None
529            };
530            errors.push(MethodViolation::UndispatchableReceiver(span));
531        } else {
532            // We confirm that the `receiver_is_dispatchable` is accurate later,
533            // see `check_receiver_correct`. It should be kept in sync with this code.
534        }
535    }
536
537    // NOTE: This check happens last, because it results in a lint, and not a
538    // hard error.
539    if tcx.predicates_of(method.def_id).predicates.iter().any(|&(pred, _span)| {
540        // dyn Trait is okay:
541        //
542        //     trait Trait {
543        //         fn f(&self) where Self: 'static;
544        //     }
545        //
546        // because a trait object can't claim to live longer than the concrete
547        // type. If the lifetime bound holds on dyn Trait then it's guaranteed
548        // to hold as well on the concrete type.
549        if pred.as_type_outlives_clause().is_some() {
550            return false;
551        }
552
553        // dyn Trait is okay:
554        //
555        //     auto trait AutoTrait {}
556        //
557        //     trait Trait {
558        //         fn f(&self) where Self: AutoTrait;
559        //     }
560        //
561        // because `impl AutoTrait for dyn Trait` is disallowed by coherence.
562        // Traits with a default impl are implemented for a trait object if and
563        // only if the autotrait is one of the trait object's trait bounds, like
564        // in `dyn Trait + AutoTrait`. This guarantees that trait objects only
565        // implement auto traits if the underlying type does as well.
566        if let ty::ClauseKind::Trait(ty::TraitPredicate {
567            trait_ref: pred_trait_ref,
568            polarity: ty::PredicatePolarity::Positive,
569        }) = pred.kind().skip_binder()
570            && pred_trait_ref.self_ty() == tcx.types.self_param
571            && tcx.trait_is_auto(pred_trait_ref.def_id)
572        {
573            // Consider bounds like `Self: Bound<Self>`. Auto traits are not
574            // allowed to have generic parameters so `auto trait Bound<T> {}`
575            // would already have reported an error at the definition of the
576            // auto trait.
577            if pred_trait_ref.args.len() != 1 {
578                if !tcx.dcx().has_errors().is_some() {
    {
        ::core::panicking::panic_fmt(format_args!("auto traits cannot have generic parameters"));
    }
};assert!(
579                    tcx.dcx().has_errors().is_some(),
580                    "auto traits cannot have generic parameters"
581                );
582            }
583            return false;
584        }
585
586        contains_illegal_self_type_reference(tcx, trait_def_id, pred, AllowSelfProjections::Yes)
587    }) {
588        errors.push(MethodViolation::WhereClauseReferencesSelf);
589    }
590
591    errors
592}
593
594/// Performs a type instantiation to produce the version of `receiver_ty` when `Self = self_ty`.
595/// For example, for `receiver_ty = Rc<Self>` and `self_ty = Foo`, returns `Rc<Foo>`.
596fn receiver_for_self_ty<'tcx>(
597    tcx: TyCtxt<'tcx>,
598    receiver_ty: Ty<'tcx>,
599    self_ty: Ty<'tcx>,
600    method_def_id: DefId,
601) -> Ty<'tcx> {
602    {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs:602",
                        "rustc_trait_selection::traits::dyn_compatibility",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs"),
                        ::tracing_core::__macro_support::Option::Some(602u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::dyn_compatibility"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("receiver_for_self_ty({0:?}, {1:?}, {2:?})",
                                                    receiver_ty, self_ty, method_def_id) as &dyn Value))])
            });
    } else { ; }
};debug!("receiver_for_self_ty({:?}, {:?}, {:?})", receiver_ty, self_ty, method_def_id);
603    let args = GenericArgs::for_item(tcx, method_def_id, |param, _| {
604        if param.index == 0 { self_ty.into() } else { tcx.mk_param_from_def(param) }
605    });
606
607    let result = EarlyBinder::bind(receiver_ty).instantiate(tcx, args).skip_norm_wip();
608    {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs:608",
                        "rustc_trait_selection::traits::dyn_compatibility",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs"),
                        ::tracing_core::__macro_support::Option::Some(608u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::dyn_compatibility"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("receiver_for_self_ty({0:?}, {1:?}, {2:?}) = {3:?}",
                                                    receiver_ty, self_ty, method_def_id, result) as
                                            &dyn Value))])
            });
    } else { ; }
};debug!(
609        "receiver_for_self_ty({:?}, {:?}, {:?}) = {:?}",
610        receiver_ty, self_ty, method_def_id, result
611    );
612    result
613}
614
615/// Checks the method's receiver (the `self` argument) can be dispatched on when `Self` is a
616/// trait object. We require that `DispatchableFromDyn` be implemented for the receiver type
617/// in the following way:
618/// - let `Receiver` be the type of the `self` argument, i.e `Self`, `&Self`, `Rc<Self>`,
619/// - require the following bound:
620///
621///   ```ignore (not-rust)
622///   Receiver[Self => T]: DispatchFromDyn<Receiver[Self => dyn Trait]>
623///   ```
624///
625///   where `Foo[X => Y]` means "the same type as `Foo`, but with `X` replaced with `Y`"
626///   (instantiation notation).
627///
628/// Some examples of receiver types and their required obligation:
629/// - `&'a mut self` requires `&'a mut Self: DispatchFromDyn<&'a mut dyn Trait>`,
630/// - `self: Rc<Self>` requires `Rc<Self>: DispatchFromDyn<Rc<dyn Trait>>`,
631/// - `self: Pin<Box<Self>>` requires `Pin<Box<Self>>: DispatchFromDyn<Pin<Box<dyn Trait>>>`.
632///
633/// The only case where the receiver is not dispatchable, but is still a valid receiver
634/// type (just not dyn compatible), is when there is more than one level of pointer indirection.
635/// E.g., `self: &&Self`, `self: &Rc<Self>`, `self: Box<Box<Self>>`. In these cases, there
636/// is no way, or at least no inexpensive way, to coerce the receiver from the version where
637/// `Self = dyn Trait` to the version where `Self = T`, where `T` is the unknown erased type
638/// contained by the trait object, because the object that needs to be coerced is behind
639/// a pointer.
640///
641/// If lowering already produced an error in the receiver type, we conservatively treat it as
642/// undispatchable instead of asking the solver.
643///
644/// In practice, we cannot use `dyn Trait` explicitly in the obligation because it would result in
645/// a new check that `Trait` is dyn-compatible, creating a cycle.
646/// Instead, we emulate a placeholder by introducing a new type parameter `U` such that
647/// `Self: Unsize<U>` and `U: Trait + MetaSized`, and use `U` in place of `dyn Trait`.
648///
649/// Written as a chalk-style query:
650/// ```ignore (not-rust)
651/// forall (U: Trait + MetaSized) {
652///     if (Self: Unsize<U>) {
653///         Receiver: DispatchFromDyn<Receiver[Self => U]>
654///     }
655/// }
656/// ```
657/// for `self: &'a mut Self`, this means `&'a mut Self: DispatchFromDyn<&'a mut U>`
658/// for `self: Rc<Self>`, this means `Rc<Self>: DispatchFromDyn<Rc<U>>`
659/// for `self: Pin<Box<Self>>`, this means `Pin<Box<Self>>: DispatchFromDyn<Pin<Box<U>>>`
660//
661// FIXME(mikeyhew) when unsized receivers are implemented as part of unsized rvalues, add this
662// fallback query: `Receiver: Unsize<Receiver[Self => U]>` to support receivers like
663// `self: Wrapper<Self>`.
664fn receiver_is_dispatchable<'tcx>(
665    tcx: TyCtxt<'tcx>,
666    method: ty::AssocItem,
667    receiver_ty: Ty<'tcx>,
668) -> bool {
669    {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs:669",
                        "rustc_trait_selection::traits::dyn_compatibility",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs"),
                        ::tracing_core::__macro_support::Option::Some(669u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::dyn_compatibility"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("receiver_is_dispatchable: method = {0:?}, receiver_ty = {1:?}",
                                                    method, receiver_ty) as &dyn Value))])
            });
    } else { ; }
};debug!("receiver_is_dispatchable: method = {:?}, receiver_ty = {:?}", method, receiver_ty);
670
671    if receiver_ty.references_error() {
672        return false;
673    }
674
675    let (Some(unsize_did), Some(dispatch_from_dyn_did)) =
676        (tcx.lang_items().unsize_trait(), tcx.lang_items().dispatch_from_dyn_trait())
677    else {
678        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs:678",
                        "rustc_trait_selection::traits::dyn_compatibility",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs"),
                        ::tracing_core::__macro_support::Option::Some(678u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::dyn_compatibility"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("receiver_is_dispatchable: Missing `Unsize` or `DispatchFromDyn` traits")
                                            as &dyn Value))])
            });
    } else { ; }
};debug!("receiver_is_dispatchable: Missing `Unsize` or `DispatchFromDyn` traits");
679        return false;
680    };
681
682    // the type `U` in the query
683    // use a bogus type parameter to mimic a forall(U) query using u32::MAX for now.
684    let unsized_self_ty: Ty<'tcx> =
685        Ty::new_param(tcx, u32::MAX, rustc_span::sym::RustaceansAreAwesome);
686
687    // `Receiver[Self => U]`
688    let unsized_receiver_ty =
689        receiver_for_self_ty(tcx, receiver_ty, unsized_self_ty, method.def_id);
690
691    // create a modified param env, with `Self: Unsize<U>` and `U: Trait` (and all of
692    // its supertraits) added to caller bounds. `U: MetaSized` is already implied here.
693    let param_env = {
694        // N.B. We generally want to emulate the construction of the `unnormalized_param_env`
695        // in the param-env query here. The fact that we don't just start with the clauses
696        // in the param-env of the method is because those are already normalized, and mixing
697        // normalized and unnormalized copies of predicates in `normalize_param_env_or_error`
698        // will cause ambiguity that the user can't really avoid.
699        //
700        // We leave out certain complexities of the param-env query here. Specifically, we:
701        // 1. Do not add `[const]` bounds since there are no `dyn const Trait`s.
702        // 2. Do not add RPITIT self projection bounds for defaulted methods, since we
703        //    are not constructing a param-env for "inside" of the body of the defaulted
704        //    method, so we don't really care about projecting to a specific RPIT type,
705        //    and because RPITITs are not dyn compatible (yet).
706        let mut predicates: Vec<_> = tcx
707            .predicates_of(method.def_id)
708            .instantiate_identity(tcx)
709            .predicates
710            .into_iter()
711            .map(Unnormalized::skip_norm_wip)
712            .collect();
713
714        // Self: Unsize<U>
715        let unsize_predicate =
716            ty::TraitRef::new(tcx, unsize_did, [tcx.types.self_param, unsized_self_ty]);
717        predicates.push(unsize_predicate.upcast(tcx));
718
719        // U: Trait<Arg1, ..., ArgN>
720        let trait_def_id = method.trait_container(tcx).unwrap();
721        let args = GenericArgs::for_item(tcx, trait_def_id, |param, _| {
722            if param.index == 0 { unsized_self_ty.into() } else { tcx.mk_param_from_def(param) }
723        });
724        let trait_predicate = ty::TraitRef::new_from_args(tcx, trait_def_id, args);
725        predicates.push(trait_predicate.upcast(tcx));
726
727        let meta_sized_predicate = {
728            let meta_sized_did = tcx.require_lang_item(LangItem::MetaSized, DUMMY_SP);
729            ty::TraitRef::new(tcx, meta_sized_did, [unsized_self_ty]).upcast(tcx)
730        };
731        predicates.push(meta_sized_predicate);
732
733        normalize_param_env_or_error(
734            tcx,
735            ty::ParamEnv::new(tcx.mk_clauses(&predicates)),
736            ObligationCause::dummy_with_span(tcx.def_span(method.def_id)),
737        )
738    };
739
740    // Receiver: DispatchFromDyn<Receiver[Self => U]>
741    let obligation = {
742        let predicate =
743            ty::TraitRef::new(tcx, dispatch_from_dyn_did, [receiver_ty, unsized_receiver_ty]);
744
745        Obligation::new(tcx, ObligationCause::dummy(), param_env, predicate)
746    };
747
748    let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
749    // the receiver is dispatchable iff the obligation holds
750    infcx.predicate_must_hold_modulo_regions(&obligation)
751}
752
753#[derive(#[automatically_derived]
impl ::core::marker::Copy for AllowSelfProjections { }Copy, #[automatically_derived]
impl ::core::clone::Clone for AllowSelfProjections {
    #[inline]
    fn clone(&self) -> AllowSelfProjections { *self }
}Clone)]
754enum AllowSelfProjections {
755    Yes,
756    No,
757}
758
759/// Check if the given value contains illegal `Self` references.
760///
761/// This is somewhat subtle. In general, we want to forbid references to `Self` in the
762/// argument and return types, since the value of `Self` is erased.
763///
764/// However, there is one exception: It is ok to reference `Self` in order to access an
765/// associated type of the current trait, since we retain the value of those associated
766/// types in the trait object type itself.
767///
768/// The same thing holds for associated consts under feature `min_generic_const_args`.
769///
770/// ```rust,ignore (example)
771/// trait SuperTrait {
772///     type X;
773/// }
774///
775/// trait Trait : SuperTrait {
776///     type Y;
777///     fn foo(&self, x: Self) // bad
778///     fn foo(&self) -> Self // bad
779///     fn foo(&self) -> Option<Self> // bad
780///     fn foo(&self) -> Self::Y // OK, desugars to next example
781///     fn foo(&self) -> <Self as Trait>::Y // OK
782///     fn foo(&self) -> Self::X // OK, desugars to next example
783///     fn foo(&self) -> <Self as SuperTrait>::X // OK
784/// }
785/// ```
786///
787/// However, it is not as simple as allowing `Self` in a projected
788/// type, because there are illegal ways to use `Self` as well:
789///
790/// ```rust,ignore (example)
791/// trait Trait : SuperTrait {
792///     ...
793///     fn foo(&self) -> <Self as SomeOtherTrait>::X;
794/// }
795/// ```
796///
797/// Here we will not have the type of `X` recorded in the
798/// object type, and we cannot resolve `Self as SomeOtherTrait`
799/// without knowing what `Self` is.
800fn contains_illegal_self_type_reference<'tcx, T: TypeVisitable<TyCtxt<'tcx>>>(
801    tcx: TyCtxt<'tcx>,
802    trait_def_id: DefId,
803    value: T,
804    allow_self_projections: AllowSelfProjections,
805) -> bool {
806    value
807        .visit_with(&mut IllegalSelfTypeVisitor {
808            tcx,
809            trait_def_id,
810            supertraits: None,
811            allow_self_projections,
812        })
813        .is_break()
814}
815
816struct IllegalSelfTypeVisitor<'tcx> {
817    tcx: TyCtxt<'tcx>,
818    trait_def_id: DefId,
819    supertraits: Option<Vec<ty::TraitRef<'tcx>>>,
820    allow_self_projections: AllowSelfProjections,
821}
822
823impl<'tcx> IllegalSelfTypeVisitor<'tcx> {
824    fn is_supertrait_of_current_trait(&mut self, trait_ref: ty::TraitRef<'tcx>) -> bool {
825        // Compute supertraits of current trait lazily.
826        let supertraits = self.supertraits.get_or_insert_with(|| {
827            util::supertraits(
828                self.tcx,
829                ty::Binder::dummy(ty::TraitRef::identity(self.tcx, self.trait_def_id)),
830            )
831            .map(|trait_ref| {
832                self.tcx.erase_and_anonymize_regions(
833                    self.tcx.instantiate_bound_regions_with_erased(trait_ref),
834                )
835            })
836            .collect()
837        });
838
839        // Determine whether the given trait ref is in fact a supertrait of the current trait.
840        // In that case, any derived projections are legal, because the term will be specified
841        // in the trait object type.
842        // Note that we can just use direct equality here because all of these types are part of
843        // the formal parameter listing, and hence there should be no inference variables.
844        let trait_ref = trait_ref
845            .fold_with(&mut EraseEscapingBoundRegions { tcx: self.tcx, binder: ty::INNERMOST });
846        supertraits.contains(&trait_ref)
847    }
848}
849
850impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for IllegalSelfTypeVisitor<'tcx> {
851    type Result = ControlFlow<()>;
852
853    fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
854        match ty.kind() {
855            ty::Param(_) => {
856                if ty == self.tcx.types.self_param {
857                    ControlFlow::Break(())
858                } else {
859                    ControlFlow::Continue(())
860                }
861            }
862            ty::Alias(ty::AliasTy { kind: ty::Projection { def_id }, .. })
863                if self.tcx.is_impl_trait_in_trait(*def_id) =>
864            {
865                // We'll deny these later in their own pass
866                ControlFlow::Continue(())
867            }
868            ty::Alias(proj @ ty::AliasTy { kind: ty::Projection { .. }, .. }) => {
869                match self.allow_self_projections {
870                    AllowSelfProjections::Yes => {
871                        // Only walk contained types if the parent trait is not a supertrait.
872                        if self.is_supertrait_of_current_trait(proj.trait_ref(self.tcx)) {
873                            ControlFlow::Continue(())
874                        } else {
875                            ty.super_visit_with(self)
876                        }
877                    }
878                    AllowSelfProjections::No => ty.super_visit_with(self),
879                }
880            }
881            _ => ty.super_visit_with(self),
882        }
883    }
884
885    fn visit_const(&mut self, ct: ty::Const<'tcx>) -> Self::Result {
886        let ct = self.tcx.expand_abstract_consts(ct);
887
888        match ct.kind() {
889            ty::ConstKind::Unevaluated(
890                proj @ ty::UnevaluatedConst {
891                    kind: ty::UnevaluatedConstKind::Projection { .. },
892                    ..
893                },
894            ) if self.tcx.features().min_generic_const_args() => {
895                match self.allow_self_projections {
896                    AllowSelfProjections::Yes => {
897                        let trait_def_id = self.tcx.parent(proj.kind.def_id());
898                        let trait_ref = ty::TraitRef::from_assoc(self.tcx, trait_def_id, proj.args);
899
900                        // Only walk contained consts if the parent trait is not a supertrait.
901                        if self.is_supertrait_of_current_trait(trait_ref) {
902                            ControlFlow::Continue(())
903                        } else {
904                            ct.super_visit_with(self)
905                        }
906                    }
907                    AllowSelfProjections::No => ct.super_visit_with(self),
908                }
909            }
910            _ => ct.super_visit_with(self),
911        }
912    }
913}
914
915struct EraseEscapingBoundRegions<'tcx> {
916    tcx: TyCtxt<'tcx>,
917    binder: ty::DebruijnIndex,
918}
919
920impl<'tcx> TypeFolder<TyCtxt<'tcx>> for EraseEscapingBoundRegions<'tcx> {
921    fn cx(&self) -> TyCtxt<'tcx> {
922        self.tcx
923    }
924
925    fn fold_binder<T>(&mut self, t: ty::Binder<'tcx, T>) -> ty::Binder<'tcx, T>
926    where
927        T: TypeFoldable<TyCtxt<'tcx>>,
928    {
929        self.binder.shift_in(1);
930        let result = t.super_fold_with(self);
931        self.binder.shift_out(1);
932        result
933    }
934
935    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
936        if let ty::ReBound(ty::BoundVarIndexKind::Bound(debruijn), _) = r.kind()
937            && debruijn < self.binder
938        {
939            r
940        } else {
941            self.tcx.lifetimes.re_erased
942        }
943    }
944}
945
946fn contains_illegal_impl_trait_in_trait<'tcx>(
947    tcx: TyCtxt<'tcx>,
948    fn_def_id: DefId,
949    ty: ty::Binder<'tcx, Ty<'tcx>>,
950) -> Option<MethodViolation> {
951    let ty = tcx.liberate_late_bound_regions(fn_def_id, ty);
952
953    if tcx.asyncness(fn_def_id).is_async() {
954        // Rendering the error as a separate `async-specific` message is better.
955        Some(MethodViolation::AsyncFn)
956    } else {
957        ty.visit_with(&mut IllegalRpititVisitor { tcx, allowed: None }).break_value()
958    }
959}
960
961struct IllegalRpititVisitor<'tcx> {
962    tcx: TyCtxt<'tcx>,
963    allowed: Option<ty::AliasTy<'tcx>>,
964}
965
966impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for IllegalRpititVisitor<'tcx> {
967    type Result = ControlFlow<MethodViolation>;
968
969    fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
970        if let ty::Alias(proj @ ty::AliasTy { kind: ty::Projection { def_id }, .. }) = *ty.kind()
971            && Some(proj) != self.allowed
972            && self.tcx.is_impl_trait_in_trait(def_id)
973        {
974            ControlFlow::Break(MethodViolation::ReferencesImplTraitInTrait(
975                self.tcx.def_span(def_id),
976            ))
977        } else {
978            ty.super_visit_with(self)
979        }
980    }
981}
982
983pub(crate) fn provide(providers: &mut Providers) {
984    *providers = Providers {
985        dyn_compatibility_violations,
986        is_dyn_compatible,
987        generics_require_sized_self,
988        ..*providers
989    };
990}