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".
67use std::ops::ControlFlow;
89use rustc_errors::FatalError;
10use rustc_hir::def::DefKind;
11use rustc_hir::def_id::DefId;
12use rustc_hir::{selfas hir, LangItem};
13use rustc_middle::query::Providers;
14use rustc_middle::ty::{
15self, EarlyBinder, GenericArgs, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
16TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, Upcast,
17elaborate,
18};
19use rustc_span::{DUMMY_SP, Span};
20use smallvec::SmallVec;
21use tracing::{debug, instrument};
2223use super::elaborate;
24use crate::infer::TyCtxtInferExt;
25pub use crate::traits::DynCompatibilityViolation;
26use crate::traits::query::evaluate_obligation::InferCtxtExt;
27use crate::traits::{
28AssocConstViolation, MethodViolation, Obligation, ObligationCause,
29normalize_param_env_or_error, util,
30};
3132/// Returns the dyn-compatibility violations that affect HIR ty lowering.
33///
34/// Currently that is `Self` in supertraits. This is needed
35/// because `dyn_compatibility_violations` can't be used during
36/// type collection, as type collection is needed for `dyn_compatibility_violations` itself.
37x;#[instrument(level = "debug", skip(tcx), ret)]38pub fn hir_ty_lowering_dyn_compatibility_violations(
39 tcx: TyCtxt<'_>,
40 trait_def_id: DefId,
41) -> Vec<DynCompatibilityViolation> {
42debug_assert!(tcx.generics_of(trait_def_id).has_self);
43 elaborate::supertrait_def_ids(tcx, trait_def_id)
44 .map(|def_id| predicates_reference_self(tcx, def_id, true))
45 .filter(|spans| !spans.is_empty())
46 .map(DynCompatibilityViolation::SupertraitSelf)
47 .collect()
48}
4950fn dyn_compatibility_violations(
51 tcx: TyCtxt<'_>,
52 trait_def_id: DefId,
53) -> &'_ [DynCompatibilityViolation] {
54if 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);
55{
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:55",
"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(55u32),
::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);
56tcx.arena.alloc_from_iter(
57 elaborate::supertrait_def_ids(tcx, trait_def_id)
58 .flat_map(|def_id| dyn_compatibility_violations_for_trait(tcx, def_id)),
59 )
60}
6162fn is_dyn_compatible(tcx: TyCtxt<'_>, trait_def_id: DefId) -> bool {
63tcx.dyn_compatibility_violations(trait_def_id).is_empty()
64}
6566/// We say a method is *vtable safe* if it can be invoked on a trait
67/// object. Note that dyn-compatible traits can have some
68/// non-vtable-safe methods, so long as they require `Self: Sized` or
69/// otherwise ensure that they cannot be used when `Self = Trait`.
70pub fn is_vtable_safe_method(tcx: TyCtxt<'_>, trait_def_id: DefId, method: ty::AssocItem) -> bool {
71if 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);
72{
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:72",
"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(72u32),
::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);
73// Any method that has a `Self: Sized` bound cannot be called.
74if tcx.generics_require_sized_self(method.def_id) {
75return false;
76 }
7778virtual_call_violations_for_method(tcx, trait_def_id, method).is_empty()
79}
8081x;#[instrument(level = "debug", skip(tcx), ret)]82fn dyn_compatibility_violations_for_trait(
83 tcx: TyCtxt<'_>,
84 trait_def_id: DefId,
85) -> Vec<DynCompatibilityViolation> {
86// Check assoc items for violations.
87let mut violations: Vec<_> = tcx
88 .associated_items(trait_def_id)
89 .in_definition_order()
90 .flat_map(|&item| dyn_compatibility_violations_for_assoc_item(tcx, trait_def_id, item))
91 .collect();
9293// Check the trait itself.
94if trait_has_sized_self(tcx, trait_def_id) {
95// We don't want to include the requirement from `Sized` itself to be `Sized` in the list.
96let spans = get_sized_bounds(tcx, trait_def_id);
97 violations.push(DynCompatibilityViolation::SizedSelf(spans));
98 } else if let Some(span) = tcx.trait_def(trait_def_id).force_dyn_incompatible {
99 violations.push(DynCompatibilityViolation::ExplicitlyDynIncompatible([span].into()));
100 }
101102let spans = predicates_reference_self(tcx, trait_def_id, false);
103if !spans.is_empty() {
104 violations.push(DynCompatibilityViolation::SupertraitSelf(spans));
105 }
106let spans = bounds_reference_self(tcx, trait_def_id);
107if !spans.is_empty() {
108 violations.push(DynCompatibilityViolation::SupertraitSelf(spans));
109 }
110let spans = super_predicates_have_non_lifetime_binders(tcx, trait_def_id);
111if !spans.is_empty() {
112 violations.push(DynCompatibilityViolation::SupertraitNonLifetimeBinder(spans));
113 }
114let spans = super_predicates_are_unconditionally_const(tcx, trait_def_id);
115if !spans.is_empty() {
116 violations.push(DynCompatibilityViolation::SupertraitConst(spans));
117 }
118119 violations
120}
121122fn sized_trait_bound_spans<'tcx>(
123 tcx: TyCtxt<'tcx>,
124 bounds: hir::GenericBounds<'tcx>,
125) -> impl 'tcx + Iterator<Item = Span> {
126bounds.iter().filter_map(move |b| match b {
127 hir::GenericBound::Trait(trait_ref)
128if trait_has_sized_self(
129tcx,
130trait_ref.trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise()),
131 ) =>
132 {
133// Fetch spans for supertraits that are `Sized`: `trait T: Super`
134Some(trait_ref.span)
135 }
136_ => None,
137 })
138}
139140fn get_sized_bounds(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span; 1]> {
141tcx.hir_get_if_local(trait_def_id)
142 .and_then(|node| match node {
143 hir::Node::Item(hir::Item {
144 kind: hir::ItemKind::Trait(.., generics, bounds, _),
145 ..
146 }) => Some(
147generics148 .predicates
149 .iter()
150 .filter_map(|pred| {
151match pred.kind {
152 hir::WherePredicateKind::BoundPredicate(pred)
153if pred.bounded_ty.hir_id.owner.to_def_id() == trait_def_id =>
154 {
155// Fetch spans for trait bounds that are Sized:
156 // `trait T where Self: Pred`
157Some(sized_trait_bound_spans(tcx, pred.bounds))
158 }
159_ => None,
160 }
161 })
162 .flatten()
163// Fetch spans for supertraits that are `Sized`: `trait T: Super`.
164.chain(sized_trait_bound_spans(tcx, bounds))
165 .collect::<SmallVec<[Span; 1]>>(),
166 ),
167_ => None,
168 })
169 .unwrap_or_else(SmallVec::new)
170}
171172fn predicates_reference_self(
173 tcx: TyCtxt<'_>,
174 trait_def_id: DefId,
175 supertraits_only: bool,
176) -> SmallVec<[Span; 1]> {
177let trait_ref = ty::Binder::dummy(ty::TraitRef::identity(tcx, trait_def_id));
178let predicates = if supertraits_only {
179tcx.explicit_super_predicates_of(trait_def_id).skip_binder()
180 } else {
181tcx.predicates_of(trait_def_id).predicates
182 };
183predicates184 .iter()
185 .map(|&(predicate, sp)| (predicate.instantiate_supertrait(tcx, trait_ref), sp))
186 .filter_map(|(clause, sp)| {
187// Super predicates cannot allow self projections, since they're
188 // impossible to make into existential bounds without eager resolution
189 // or something.
190 // e.g. `trait A: B<Item = Self::Assoc>`.
191predicate_references_self(tcx, trait_def_id, clause, sp, AllowSelfProjections::No)
192 })
193 .collect()
194}
195196fn bounds_reference_self(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span; 1]> {
197tcx.associated_items(trait_def_id)
198 .in_definition_order()
199// We're only looking at associated type bounds
200.filter(|item| item.is_type())
201// Ignore GATs with `Self: Sized`
202.filter(|item| !tcx.generics_require_sized_self(item.def_id))
203 .flat_map(|item| tcx.explicit_item_bounds(item.def_id).iter_identity_copied())
204 .filter_map(|(clause, sp)| {
205// Item bounds *can* have self projections, since they never get
206 // their self type erased.
207predicate_references_self(tcx, trait_def_id, clause, sp, AllowSelfProjections::Yes)
208 })
209 .collect()
210}
211212fn predicate_references_self<'tcx>(
213 tcx: TyCtxt<'tcx>,
214 trait_def_id: DefId,
215 predicate: ty::Clause<'tcx>,
216 sp: Span,
217 allow_self_projections: AllowSelfProjections,
218) -> Option<Span> {
219match predicate.kind().skip_binder() {
220 ty::ClauseKind::Trait(ref data) => {
221// In the case of a trait predicate, we can skip the "self" type.
222data.trait_ref.args[1..].iter().any(|&arg| contains_illegal_self_type_reference(tcx, trait_def_id, arg, allow_self_projections)).then_some(sp)
223 }
224 ty::ClauseKind::Projection(ref data) => {
225// And similarly for projections. This should be redundant with
226 // the previous check because any projection should have a
227 // matching `Trait` predicate with the same inputs, but we do
228 // the check to be safe.
229 //
230 // It's also won't be redundant if we allow type-generic associated
231 // types for trait objects.
232 //
233 // Note that we *do* allow projection *outputs* to contain
234 // `Self` (i.e., `trait Foo: Bar<Output=Self::Result> { type Result; }`),
235 // we just require the user to specify *both* outputs
236 // in the object type (i.e., `dyn Foo<Output=(), Result=()>`).
237 //
238 // This is ALT2 in issue #56288, see that for discussion of the
239 // possible alternatives.
240data.projection_term.args[1..].iter().any(|&arg| contains_illegal_self_type_reference(tcx, trait_def_id, arg, allow_self_projections)).then_some(sp)
241 }
242 ty::ClauseKind::ConstArgHasType(_ct, ty) => contains_illegal_self_type_reference(tcx, trait_def_id, ty, allow_self_projections).then_some(sp),
243244 ty::ClauseKind::WellFormed(..)
245 | ty::ClauseKind::TypeOutlives(..)
246 | ty::ClauseKind::RegionOutlives(..)
247// FIXME(generic_const_exprs): this can mention `Self`
248| ty::ClauseKind::ConstEvaluatable(..)
249 | ty::ClauseKind::HostEffect(..)
250 | ty::ClauseKind::UnstableFeature(_)
251 => None,
252 }
253}
254255fn super_predicates_have_non_lifetime_binders(
256 tcx: TyCtxt<'_>,
257 trait_def_id: DefId,
258) -> SmallVec<[Span; 1]> {
259tcx.explicit_super_predicates_of(trait_def_id)
260 .iter_identity_copied()
261 .filter_map(|(pred, span)| pred.has_non_region_bound_vars().then_some(span))
262 .collect()
263}
264265/// Checks for `const Trait` supertraits. We're okay with `[const] Trait`,
266/// supertraits since for a non-const instantiation of that trait, the
267/// conditionally-const supertrait is also not required to be const.
268fn super_predicates_are_unconditionally_const(
269 tcx: TyCtxt<'_>,
270 trait_def_id: DefId,
271) -> SmallVec<[Span; 1]> {
272tcx.explicit_super_predicates_of(trait_def_id)
273 .iter_identity_copied()
274 .filter_map(|(pred, span)| {
275if let ty::ClauseKind::HostEffect(_) = pred.kind().skip_binder() {
276Some(span)
277 } else {
278None279 }
280 })
281 .collect()
282}
283284fn trait_has_sized_self(tcx: TyCtxt<'_>, trait_def_id: DefId) -> bool {
285tcx.generics_require_sized_self(trait_def_id)
286}
287288fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
289let Some(sized_def_id) = tcx.lang_items().sized_trait() else {
290return false; /* No Sized trait, can't require it! */
291};
292293// Search for a predicate like `Self: Sized` amongst the trait bounds.
294let predicates = tcx.predicates_of(def_id);
295let predicates = predicates.instantiate_identity(tcx).predicates;
296elaborate(tcx, predicates).any(|pred| match pred.kind().skip_binder() {
297 ty::ClauseKind::Trait(ref trait_pred) => {
298trait_pred.def_id() == sized_def_id && trait_pred.self_ty().is_param(0)
299 }
300 ty::ClauseKind::RegionOutlives(_)
301 | ty::ClauseKind::TypeOutlives(_)
302 | ty::ClauseKind::Projection(_)
303 | ty::ClauseKind::ConstArgHasType(_, _)
304 | ty::ClauseKind::WellFormed(_)
305 | ty::ClauseKind::ConstEvaluatable(_)
306 | ty::ClauseKind::UnstableFeature(_)
307 | ty::ClauseKind::HostEffect(..) => false,
308 })
309}
310311x;#[instrument(level = "debug", skip(tcx), ret)]312pub fn dyn_compatibility_violations_for_assoc_item(
313 tcx: TyCtxt<'_>,
314 trait_def_id: DefId,
315 item: ty::AssocItem,
316) -> Vec<DynCompatibilityViolation> {
317// `final` assoc functions don't prevent a trait from being dyn-compatible
318if tcx.defaultness(item.def_id).is_final() {
319return Vec::new();
320 }
321322// Any item that has a `Self: Sized` requisite is otherwise exempt from the regulations.
323if tcx.generics_require_sized_self(item.def_id) {
324return Vec::new();
325 }
326327let span = || item.ident(tcx).span;
328329match item.kind {
330 ty::AssocKind::Const { name } => {
331// We will permit type associated consts if they are explicitly mentioned in the
332 // trait object type. We can't check this here, as here we only check if it is
333 // guaranteed to not be possible.
334335let mut errors = Vec::new();
336337if tcx.features().min_generic_const_args() {
338if !tcx.generics_of(item.def_id).is_own_empty() {
339 errors.push(AssocConstViolation::Generic);
340 } else if !tcx.is_type_const(item.def_id) {
341 errors.push(AssocConstViolation::NonType);
342 }
343344let ty = ty::Binder::dummy(tcx.type_of(item.def_id).instantiate_identity());
345if contains_illegal_self_type_reference(
346 tcx,
347 trait_def_id,
348 ty,
349 AllowSelfProjections::Yes,
350 ) {
351 errors.push(AssocConstViolation::TypeReferencesSelf);
352 }
353 } else {
354 errors.push(AssocConstViolation::FeatureNotEnabled);
355 }
356357 errors
358 .into_iter()
359 .map(|error| DynCompatibilityViolation::AssocConst(name, error, span()))
360 .collect()
361 }
362 ty::AssocKind::Fn { name, .. } => {
363 virtual_call_violations_for_method(tcx, trait_def_id, item)
364 .into_iter()
365 .map(|v| {
366let node = tcx.hir_get_if_local(item.def_id);
367// Get an accurate span depending on the violation.
368let span = match (&v, node) {
369 (MethodViolation::ReferencesSelfInput(Some(span)), _) => *span,
370 (MethodViolation::UndispatchableReceiver(Some(span)), _) => *span,
371 (MethodViolation::ReferencesImplTraitInTrait(span), _) => *span,
372 (MethodViolation::ReferencesSelfOutput, Some(node)) => {
373 node.fn_decl().map_or(item.ident(tcx).span, |decl| decl.output.span())
374 }
375_ => span(),
376 };
377378 DynCompatibilityViolation::Method(name, v, span)
379 })
380 .collect()
381 }
382 ty::AssocKind::Type { data } => {
383if !tcx.generics_of(item.def_id).is_own_empty()
384 && let ty::AssocTypeData::Normal(name) = data
385 {
386vec![DynCompatibilityViolation::GenericAssocTy(name, span())]
387 } else {
388// We will permit associated types if they are explicitly mentioned in the trait
389 // object type. We can't check this here, as here we only check if it is
390 // guaranteed to not be possible.
391Vec::new()
392 }
393 }
394 }
395}
396397/// Returns `Some(_)` if this method cannot be called on a trait
398/// object; this does not necessarily imply that the enclosing trait
399/// is dyn-incompatible, because the method might have a where clause
400/// `Self: Sized`.
401fn virtual_call_violations_for_method<'tcx>(
402 tcx: TyCtxt<'tcx>,
403 trait_def_id: DefId,
404 method: ty::AssocItem,
405) -> Vec<MethodViolation> {
406let sig = tcx.fn_sig(method.def_id).instantiate_identity();
407408// The method's first parameter must be named `self`
409if !method.is_method() {
410let sugg = if let Some(hir::Node::TraitItem(hir::TraitItem {
411 generics,
412 kind: hir::TraitItemKind::Fn(sig, _),
413 ..
414 })) = tcx.hir_get_if_local(method.def_id).as_ref()
415 {
416let sm = tcx.sess.source_map();
417Some((
418 (
419::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 { ", " }),
420sm.span_through_char(sig.span, '(').shrink_to_hi(),
421 ),
422 (
423::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()),
424generics.tail_span_for_predicate_suggestion(),
425 ),
426 ))
427 } else {
428None429 };
430431// Not having `self` parameter messes up the later checks,
432 // so we need to return instead of pushing
433return ::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)];
434 }
435436let mut errors = Vec::new();
437438for (i, &input_ty) in sig.skip_binder().inputs().iter().enumerate().skip(1) {
439if contains_illegal_self_type_reference(
440 tcx,
441 trait_def_id,
442 sig.rebind(input_ty),
443 AllowSelfProjections::Yes,
444 ) {
445let span = if let Some(hir::Node::TraitItem(hir::TraitItem {
446 kind: hir::TraitItemKind::Fn(sig, _),
447 ..
448 })) = tcx.hir_get_if_local(method.def_id).as_ref()
449 {
450Some(sig.decl.inputs[i].span)
451 } else {
452None
453};
454 errors.push(MethodViolation::ReferencesSelfInput(span));
455 }
456 }
457if contains_illegal_self_type_reference(
458tcx,
459trait_def_id,
460sig.output(),
461 AllowSelfProjections::Yes,
462 ) {
463errors.push(MethodViolation::ReferencesSelfOutput);
464 }
465if let Some(error) = contains_illegal_impl_trait_in_trait(tcx, method.def_id, sig.output()) {
466errors.push(error);
467 }
468if sig.skip_binder().c_variadic {
469errors.push(MethodViolation::CVariadic);
470 }
471472// We can't monomorphize things like `fn foo<A>(...)`.
473let own_counts = tcx.generics_of(method.def_id).own_counts();
474if own_counts.types > 0 || own_counts.consts > 0 {
475errors.push(MethodViolation::Generic);
476 }
477478let receiver_ty = tcx.liberate_late_bound_regions(method.def_id, sig.input(0));
479480// `self: Self` can't be dispatched on.
481 // However, this is considered dyn compatible. We allow it as a special case here.
482 // FIXME(mikeyhew) get rid of this `if` statement once `receiver_is_dispatchable` allows
483 // `Receiver: Unsize<Receiver[Self => dyn Trait]>`.
484if receiver_ty != tcx.types.self_param {
485if !receiver_is_dispatchable(tcx, method, receiver_ty) {
486let span = if let Some(hir::Node::TraitItem(hir::TraitItem {
487 kind: hir::TraitItemKind::Fn(sig, _),
488 ..
489 })) = tcx.hir_get_if_local(method.def_id).as_ref()
490 {
491Some(sig.decl.inputs[0].span)
492 } else {
493None494 };
495errors.push(MethodViolation::UndispatchableReceiver(span));
496 } else {
497// We confirm that the `receiver_is_dispatchable` is accurate later,
498 // see `check_receiver_correct`. It should be kept in sync with this code.
499}
500 }
501502// NOTE: This check happens last, because it results in a lint, and not a
503 // hard error.
504if tcx.predicates_of(method.def_id).predicates.iter().any(|&(pred, _span)| {
505// dyn Trait is okay:
506 //
507 // trait Trait {
508 // fn f(&self) where Self: 'static;
509 // }
510 //
511 // because a trait object can't claim to live longer than the concrete
512 // type. If the lifetime bound holds on dyn Trait then it's guaranteed
513 // to hold as well on the concrete type.
514if pred.as_type_outlives_clause().is_some() {
515return false;
516 }
517518// dyn Trait is okay:
519 //
520 // auto trait AutoTrait {}
521 //
522 // trait Trait {
523 // fn f(&self) where Self: AutoTrait;
524 // }
525 //
526 // because `impl AutoTrait for dyn Trait` is disallowed by coherence.
527 // Traits with a default impl are implemented for a trait object if and
528 // only if the autotrait is one of the trait object's trait bounds, like
529 // in `dyn Trait + AutoTrait`. This guarantees that trait objects only
530 // implement auto traits if the underlying type does as well.
531if let ty::ClauseKind::Trait(ty::TraitPredicate {
532 trait_ref: pred_trait_ref,
533 polarity: ty::PredicatePolarity::Positive,
534 }) = pred.kind().skip_binder()
535 && pred_trait_ref.self_ty() == tcx.types.self_param
536 && tcx.trait_is_auto(pred_trait_ref.def_id)
537 {
538// Consider bounds like `Self: Bound<Self>`. Auto traits are not
539 // allowed to have generic parameters so `auto trait Bound<T> {}`
540 // would already have reported an error at the definition of the
541 // auto trait.
542if pred_trait_ref.args.len() != 1 {
543if !tcx.dcx().has_errors().is_some() {
{
::core::panicking::panic_fmt(format_args!("auto traits cannot have generic parameters"));
}
};assert!(
544 tcx.dcx().has_errors().is_some(),
545"auto traits cannot have generic parameters"
546);
547 }
548return false;
549 }
550551contains_illegal_self_type_reference(tcx, trait_def_id, pred, AllowSelfProjections::Yes)
552 }) {
553errors.push(MethodViolation::WhereClauseReferencesSelf);
554 }
555556errors557}
558559/// Performs a type instantiation to produce the version of `receiver_ty` when `Self = self_ty`.
560/// For example, for `receiver_ty = Rc<Self>` and `self_ty = Foo`, returns `Rc<Foo>`.
561fn receiver_for_self_ty<'tcx>(
562 tcx: TyCtxt<'tcx>,
563 receiver_ty: Ty<'tcx>,
564 self_ty: Ty<'tcx>,
565 method_def_id: DefId,
566) -> Ty<'tcx> {
567{
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:567",
"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(567u32),
::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);
568let args = GenericArgs::for_item(tcx, method_def_id, |param, _| {
569if param.index == 0 { self_ty.into() } else { tcx.mk_param_from_def(param) }
570 });
571572let result = EarlyBinder::bind(receiver_ty).instantiate(tcx, args);
573{
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:573",
"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(573u32),
::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!(
574"receiver_for_self_ty({:?}, {:?}, {:?}) = {:?}",
575 receiver_ty, self_ty, method_def_id, result
576 );
577result578}
579580/// Checks the method's receiver (the `self` argument) can be dispatched on when `Self` is a
581/// trait object. We require that `DispatchableFromDyn` be implemented for the receiver type
582/// in the following way:
583/// - let `Receiver` be the type of the `self` argument, i.e `Self`, `&Self`, `Rc<Self>`,
584/// - require the following bound:
585///
586/// ```ignore (not-rust)
587/// Receiver[Self => T]: DispatchFromDyn<Receiver[Self => dyn Trait]>
588/// ```
589///
590/// where `Foo[X => Y]` means "the same type as `Foo`, but with `X` replaced with `Y`"
591/// (instantiation notation).
592///
593/// Some examples of receiver types and their required obligation:
594/// - `&'a mut self` requires `&'a mut Self: DispatchFromDyn<&'a mut dyn Trait>`,
595/// - `self: Rc<Self>` requires `Rc<Self>: DispatchFromDyn<Rc<dyn Trait>>`,
596/// - `self: Pin<Box<Self>>` requires `Pin<Box<Self>>: DispatchFromDyn<Pin<Box<dyn Trait>>>`.
597///
598/// The only case where the receiver is not dispatchable, but is still a valid receiver
599/// type (just not dyn compatible), is when there is more than one level of pointer indirection.
600/// E.g., `self: &&Self`, `self: &Rc<Self>`, `self: Box<Box<Self>>`. In these cases, there
601/// is no way, or at least no inexpensive way, to coerce the receiver from the version where
602/// `Self = dyn Trait` to the version where `Self = T`, where `T` is the unknown erased type
603/// contained by the trait object, because the object that needs to be coerced is behind
604/// a pointer.
605///
606/// In practice, we cannot use `dyn Trait` explicitly in the obligation because it would result in
607/// a new check that `Trait` is dyn-compatible, creating a cycle.
608/// Instead, we emulate a placeholder by introducing a new type parameter `U` such that
609/// `Self: Unsize<U>` and `U: Trait + MetaSized`, and use `U` in place of `dyn Trait`.
610///
611/// Written as a chalk-style query:
612/// ```ignore (not-rust)
613/// forall (U: Trait + MetaSized) {
614/// if (Self: Unsize<U>) {
615/// Receiver: DispatchFromDyn<Receiver[Self => U]>
616/// }
617/// }
618/// ```
619/// for `self: &'a mut Self`, this means `&'a mut Self: DispatchFromDyn<&'a mut U>`
620/// for `self: Rc<Self>`, this means `Rc<Self>: DispatchFromDyn<Rc<U>>`
621/// for `self: Pin<Box<Self>>`, this means `Pin<Box<Self>>: DispatchFromDyn<Pin<Box<U>>>`
622//
623// FIXME(mikeyhew) when unsized receivers are implemented as part of unsized rvalues, add this
624// fallback query: `Receiver: Unsize<Receiver[Self => U]>` to support receivers like
625// `self: Wrapper<Self>`.
626fn receiver_is_dispatchable<'tcx>(
627 tcx: TyCtxt<'tcx>,
628 method: ty::AssocItem,
629 receiver_ty: Ty<'tcx>,
630) -> bool {
631{
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:631",
"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(631u32),
::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);
632633let (Some(unsize_did), Some(dispatch_from_dyn_did)) =
634 (tcx.lang_items().unsize_trait(), tcx.lang_items().dispatch_from_dyn_trait())
635else {
636{
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:636",
"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(636u32),
::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");
637return false;
638 };
639640// the type `U` in the query
641 // use a bogus type parameter to mimic a forall(U) query using u32::MAX for now.
642let unsized_self_ty: Ty<'tcx> =
643Ty::new_param(tcx, u32::MAX, rustc_span::sym::RustaceansAreAwesome);
644645// `Receiver[Self => U]`
646let unsized_receiver_ty =
647receiver_for_self_ty(tcx, receiver_ty, unsized_self_ty, method.def_id);
648649// create a modified param env, with `Self: Unsize<U>` and `U: Trait` (and all of
650 // its supertraits) added to caller bounds. `U: MetaSized` is already implied here.
651let param_env = {
652// N.B. We generally want to emulate the construction of the `unnormalized_param_env`
653 // in the param-env query here. The fact that we don't just start with the clauses
654 // in the param-env of the method is because those are already normalized, and mixing
655 // normalized and unnormalized copies of predicates in `normalize_param_env_or_error`
656 // will cause ambiguity that the user can't really avoid.
657 //
658 // We leave out certain complexities of the param-env query here. Specifically, we:
659 // 1. Do not add `[const]` bounds since there are no `dyn const Trait`s.
660 // 2. Do not add RPITIT self projection bounds for defaulted methods, since we
661 // are not constructing a param-env for "inside" of the body of the defaulted
662 // method, so we don't really care about projecting to a specific RPIT type,
663 // and because RPITITs are not dyn compatible (yet).
664let mut predicates = tcx.predicates_of(method.def_id).instantiate_identity(tcx).predicates;
665666// Self: Unsize<U>
667let unsize_predicate =
668 ty::TraitRef::new(tcx, unsize_did, [tcx.types.self_param, unsized_self_ty]);
669predicates.push(unsize_predicate.upcast(tcx));
670671// U: Trait<Arg1, ..., ArgN>
672let trait_def_id = method.trait_container(tcx).unwrap();
673let args = GenericArgs::for_item(tcx, trait_def_id, |param, _| {
674if param.index == 0 { unsized_self_ty.into() } else { tcx.mk_param_from_def(param) }
675 });
676let trait_predicate = ty::TraitRef::new_from_args(tcx, trait_def_id, args);
677predicates.push(trait_predicate.upcast(tcx));
678679let meta_sized_predicate = {
680let meta_sized_did = tcx.require_lang_item(LangItem::MetaSized, DUMMY_SP);
681 ty::TraitRef::new(tcx, meta_sized_did, [unsized_self_ty]).upcast(tcx)
682 };
683predicates.push(meta_sized_predicate);
684685normalize_param_env_or_error(
686tcx,
687 ty::ParamEnv::new(tcx.mk_clauses(&predicates)),
688ObligationCause::dummy_with_span(tcx.def_span(method.def_id)),
689 )
690 };
691692// Receiver: DispatchFromDyn<Receiver[Self => U]>
693let obligation = {
694let predicate =
695 ty::TraitRef::new(tcx, dispatch_from_dyn_did, [receiver_ty, unsized_receiver_ty]);
696697Obligation::new(tcx, ObligationCause::dummy(), param_env, predicate)
698 };
699700let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
701// the receiver is dispatchable iff the obligation holds
702infcx.predicate_must_hold_modulo_regions(&obligation)
703}
704705#[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)]
706enum AllowSelfProjections {
707 Yes,
708 No,
709}
710711/// Check if the given value contains illegal `Self` references.
712///
713/// This is somewhat subtle. In general, we want to forbid references to `Self` in the
714/// argument and return types, since the value of `Self` is erased.
715///
716/// However, there is one exception: It is ok to reference `Self` in order to access an
717/// associated type of the current trait, since we retain the value of those associated
718/// types in the trait object type itself.
719///
720/// The same thing holds for associated consts under feature `min_generic_const_args`.
721///
722/// ```rust,ignore (example)
723/// trait SuperTrait {
724/// type X;
725/// }
726///
727/// trait Trait : SuperTrait {
728/// type Y;
729/// fn foo(&self, x: Self) // bad
730/// fn foo(&self) -> Self // bad
731/// fn foo(&self) -> Option<Self> // bad
732/// fn foo(&self) -> Self::Y // OK, desugars to next example
733/// fn foo(&self) -> <Self as Trait>::Y // OK
734/// fn foo(&self) -> Self::X // OK, desugars to next example
735/// fn foo(&self) -> <Self as SuperTrait>::X // OK
736/// }
737/// ```
738///
739/// However, it is not as simple as allowing `Self` in a projected
740/// type, because there are illegal ways to use `Self` as well:
741///
742/// ```rust,ignore (example)
743/// trait Trait : SuperTrait {
744/// ...
745/// fn foo(&self) -> <Self as SomeOtherTrait>::X;
746/// }
747/// ```
748///
749/// Here we will not have the type of `X` recorded in the
750/// object type, and we cannot resolve `Self as SomeOtherTrait`
751/// without knowing what `Self` is.
752fn contains_illegal_self_type_reference<'tcx, T: TypeVisitable<TyCtxt<'tcx>>>(
753 tcx: TyCtxt<'tcx>,
754 trait_def_id: DefId,
755 value: T,
756 allow_self_projections: AllowSelfProjections,
757) -> bool {
758value759 .visit_with(&mut IllegalSelfTypeVisitor {
760tcx,
761trait_def_id,
762 supertraits: None,
763allow_self_projections,
764 })
765 .is_break()
766}
767768struct IllegalSelfTypeVisitor<'tcx> {
769 tcx: TyCtxt<'tcx>,
770 trait_def_id: DefId,
771 supertraits: Option<Vec<ty::TraitRef<'tcx>>>,
772 allow_self_projections: AllowSelfProjections,
773}
774775impl<'tcx> IllegalSelfTypeVisitor<'tcx> {
776fn is_supertrait_of_current_trait(&mut self, trait_ref: ty::TraitRef<'tcx>) -> bool {
777// Compute supertraits of current trait lazily.
778let supertraits = self.supertraits.get_or_insert_with(|| {
779 util::supertraits(
780self.tcx,
781 ty::Binder::dummy(ty::TraitRef::identity(self.tcx, self.trait_def_id)),
782 )
783 .map(|trait_ref| {
784self.tcx.erase_and_anonymize_regions(
785self.tcx.instantiate_bound_regions_with_erased(trait_ref),
786 )
787 })
788 .collect()
789 });
790791// Determine whether the given trait ref is in fact a supertrait of the current trait.
792 // In that case, any derived projections are legal, because the term will be specified
793 // in the trait object type.
794 // Note that we can just use direct equality here because all of these types are part of
795 // the formal parameter listing, and hence there should be no inference variables.
796let trait_ref = trait_ref797 .fold_with(&mut EraseEscapingBoundRegions { tcx: self.tcx, binder: ty::INNERMOST });
798supertraits.contains(&trait_ref)
799 }
800}
801802impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for IllegalSelfTypeVisitor<'tcx> {
803type Result = ControlFlow<()>;
804805fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
806match ty.kind() {
807 ty::Param(_) => {
808if ty == self.tcx.types.self_param {
809 ControlFlow::Break(())
810 } else {
811 ControlFlow::Continue(())
812 }
813 }
814 ty::Alias(ty::Projection, proj) if self.tcx.is_impl_trait_in_trait(proj.def_id) => {
815// We'll deny these later in their own pass
816ControlFlow::Continue(())
817 }
818 ty::Alias(ty::Projection, proj) => {
819match self.allow_self_projections {
820 AllowSelfProjections::Yes => {
821// Only walk contained types if the parent trait is not a supertrait.
822if self.is_supertrait_of_current_trait(proj.trait_ref(self.tcx)) {
823 ControlFlow::Continue(())
824 } else {
825ty.super_visit_with(self)
826 }
827 }
828 AllowSelfProjections::No => ty.super_visit_with(self),
829 }
830 }
831_ => ty.super_visit_with(self),
832 }
833 }
834835fn visit_const(&mut self, ct: ty::Const<'tcx>) -> Self::Result {
836let ct = self.tcx.expand_abstract_consts(ct);
837838match ct.kind() {
839 ty::ConstKind::Unevaluated(proj) if self.tcx.features().min_generic_const_args() => {
840match self.allow_self_projections {
841 AllowSelfProjections::Yes842if let trait_def_id = self.tcx.parent(proj.def)
843 && self.tcx.def_kind(trait_def_id) == DefKind::Trait =>
844 {
845let trait_ref = ty::TraitRef::from_assoc(self.tcx, trait_def_id, proj.args);
846847// Only walk contained consts if the parent trait is not a supertrait.
848if self.is_supertrait_of_current_trait(trait_ref) {
849 ControlFlow::Continue(())
850 } else {
851ct.super_visit_with(self)
852 }
853 }
854_ => ct.super_visit_with(self),
855 }
856 }
857_ => ct.super_visit_with(self),
858 }
859 }
860}
861862struct EraseEscapingBoundRegions<'tcx> {
863 tcx: TyCtxt<'tcx>,
864 binder: ty::DebruijnIndex,
865}
866867impl<'tcx> TypeFolder<TyCtxt<'tcx>> for EraseEscapingBoundRegions<'tcx> {
868fn cx(&self) -> TyCtxt<'tcx> {
869self.tcx
870 }
871872fn fold_binder<T>(&mut self, t: ty::Binder<'tcx, T>) -> ty::Binder<'tcx, T>
873where
874T: TypeFoldable<TyCtxt<'tcx>>,
875 {
876self.binder.shift_in(1);
877let result = t.super_fold_with(self);
878self.binder.shift_out(1);
879result880 }
881882fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
883if let ty::ReBound(ty::BoundVarIndexKind::Bound(debruijn), _) = r.kind()
884 && debruijn < self.binder
885 {
886r887 } else {
888self.tcx.lifetimes.re_erased
889 }
890 }
891}
892893fn contains_illegal_impl_trait_in_trait<'tcx>(
894 tcx: TyCtxt<'tcx>,
895 fn_def_id: DefId,
896 ty: ty::Binder<'tcx, Ty<'tcx>>,
897) -> Option<MethodViolation> {
898let ty = tcx.liberate_late_bound_regions(fn_def_id, ty);
899900if tcx.asyncness(fn_def_id).is_async() {
901// Rendering the error as a separate `async-specific` message is better.
902Some(MethodViolation::AsyncFn)
903 } else {
904ty.visit_with(&mut IllegalRpititVisitor { tcx, allowed: None }).break_value()
905 }
906}
907908struct IllegalRpititVisitor<'tcx> {
909 tcx: TyCtxt<'tcx>,
910 allowed: Option<ty::AliasTy<'tcx>>,
911}
912913impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for IllegalRpititVisitor<'tcx> {
914type Result = ControlFlow<MethodViolation>;
915916fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
917if let ty::Alias(ty::Projection, proj) = *ty.kind()
918 && Some(proj) != self.allowed
919 && self.tcx.is_impl_trait_in_trait(proj.def_id)
920 {
921 ControlFlow::Break(MethodViolation::ReferencesImplTraitInTrait(
922self.tcx.def_span(proj.def_id),
923 ))
924 } else {
925ty.super_visit_with(self)
926 }
927 }
928}
929930pub(crate) fn provide(providers: &mut Providers) {
931*providers = Providers {
932dyn_compatibility_violations,
933is_dyn_compatible,
934generics_require_sized_self,
935 ..*providers936 };
937}