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_id::DefId;
11use rustc_hir::{selfas hir, LangItem};
12use rustc_middle::query::Providers;
13use rustc_middle::ty::{
14self, EarlyBinder, GenericArgs, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
15TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, Upcast,
16elaborate,
17};
18use rustc_span::{DUMMY_SP, Span};
19use smallvec::SmallVec;
20use tracing::{debug, instrument};
2122use super::elaborate;
23use crate::infer::TyCtxtInferExt;
24pub use crate::traits::DynCompatibilityViolation;
25use crate::traits::query::evaluate_obligation::InferCtxtExt;
26use crate::traits::{
27MethodViolationCode, Obligation, ObligationCause, normalize_param_env_or_error, util,
28};
2930/// Returns the dyn-compatibility violations that affect HIR ty lowering.
31///
32/// Currently that is `Self` in supertraits. This is needed
33/// because `dyn_compatibility_violations` can't be used during
34/// type collection, as type collection is needed for `dyn_compatibility_violations` itself.
35x;#[instrument(level = "debug", skip(tcx), ret)]36pub fn hir_ty_lowering_dyn_compatibility_violations(
37 tcx: TyCtxt<'_>,
38 trait_def_id: DefId,
39) -> Vec<DynCompatibilityViolation> {
40debug_assert!(tcx.generics_of(trait_def_id).has_self);
41 elaborate::supertrait_def_ids(tcx, trait_def_id)
42 .map(|def_id| predicates_reference_self(tcx, def_id, true))
43 .filter(|spans| !spans.is_empty())
44 .map(DynCompatibilityViolation::SupertraitSelf)
45 .collect()
46}
4748fn dyn_compatibility_violations(
49 tcx: TyCtxt<'_>,
50 trait_def_id: DefId,
51) -> &'_ [DynCompatibilityViolation] {
52if 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);
53{
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:53",
"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(53u32),
::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);
54tcx.arena.alloc_from_iter(
55 elaborate::supertrait_def_ids(tcx, trait_def_id)
56 .flat_map(|def_id| dyn_compatibility_violations_for_trait(tcx, def_id)),
57 )
58}
5960fn is_dyn_compatible(tcx: TyCtxt<'_>, trait_def_id: DefId) -> bool {
61tcx.dyn_compatibility_violations(trait_def_id).is_empty()
62}
6364/// We say a method is *vtable safe* if it can be invoked on a trait
65/// object. Note that dyn-compatible traits can have some
66/// non-vtable-safe methods, so long as they require `Self: Sized` or
67/// otherwise ensure that they cannot be used when `Self = Trait`.
68pub fn is_vtable_safe_method(tcx: TyCtxt<'_>, trait_def_id: DefId, method: ty::AssocItem) -> bool {
69if 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);
70{
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:70",
"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(70u32),
::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);
71// Any method that has a `Self: Sized` bound cannot be called.
72if tcx.generics_require_sized_self(method.def_id) {
73return false;
74 }
7576virtual_call_violations_for_method(tcx, trait_def_id, method).is_empty()
77}
7879x;#[instrument(level = "debug", skip(tcx), ret)]80fn dyn_compatibility_violations_for_trait(
81 tcx: TyCtxt<'_>,
82 trait_def_id: DefId,
83) -> Vec<DynCompatibilityViolation> {
84// Check assoc items for violations.
85let mut violations: Vec<_> = tcx
86 .associated_items(trait_def_id)
87 .in_definition_order()
88 .flat_map(|&item| dyn_compatibility_violations_for_assoc_item(tcx, trait_def_id, item))
89 .collect();
9091// Check the trait itself.
92if trait_has_sized_self(tcx, trait_def_id) {
93// We don't want to include the requirement from `Sized` itself to be `Sized` in the list.
94let spans = get_sized_bounds(tcx, trait_def_id);
95 violations.push(DynCompatibilityViolation::SizedSelf(spans));
96 }
97let spans = predicates_reference_self(tcx, trait_def_id, false);
98if !spans.is_empty() {
99 violations.push(DynCompatibilityViolation::SupertraitSelf(spans));
100 }
101let spans = bounds_reference_self(tcx, trait_def_id);
102if !spans.is_empty() {
103 violations.push(DynCompatibilityViolation::SupertraitSelf(spans));
104 }
105let spans = super_predicates_have_non_lifetime_binders(tcx, trait_def_id);
106if !spans.is_empty() {
107 violations.push(DynCompatibilityViolation::SupertraitNonLifetimeBinder(spans));
108 }
109let spans = super_predicates_are_unconditionally_const(tcx, trait_def_id);
110if !spans.is_empty() {
111 violations.push(DynCompatibilityViolation::SupertraitConst(spans));
112 }
113114 violations
115}
116117fn sized_trait_bound_spans<'tcx>(
118 tcx: TyCtxt<'tcx>,
119 bounds: hir::GenericBounds<'tcx>,
120) -> impl 'tcx + Iterator<Item = Span> {
121bounds.iter().filter_map(move |b| match b {
122 hir::GenericBound::Trait(trait_ref)
123if trait_has_sized_self(
124tcx,
125trait_ref.trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise()),
126 ) =>
127 {
128// Fetch spans for supertraits that are `Sized`: `trait T: Super`
129Some(trait_ref.span)
130 }
131_ => None,
132 })
133}
134135fn get_sized_bounds(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span; 1]> {
136tcx.hir_get_if_local(trait_def_id)
137 .and_then(|node| match node {
138 hir::Node::Item(hir::Item {
139 kind: hir::ItemKind::Trait(.., generics, bounds, _),
140 ..
141 }) => Some(
142generics143 .predicates
144 .iter()
145 .filter_map(|pred| {
146match pred.kind {
147 hir::WherePredicateKind::BoundPredicate(pred)
148if pred.bounded_ty.hir_id.owner.to_def_id() == trait_def_id =>
149 {
150// Fetch spans for trait bounds that are Sized:
151 // `trait T where Self: Pred`
152Some(sized_trait_bound_spans(tcx, pred.bounds))
153 }
154_ => None,
155 }
156 })
157 .flatten()
158// Fetch spans for supertraits that are `Sized`: `trait T: Super`.
159.chain(sized_trait_bound_spans(tcx, bounds))
160 .collect::<SmallVec<[Span; 1]>>(),
161 ),
162_ => None,
163 })
164 .unwrap_or_else(SmallVec::new)
165}
166167fn predicates_reference_self(
168 tcx: TyCtxt<'_>,
169 trait_def_id: DefId,
170 supertraits_only: bool,
171) -> SmallVec<[Span; 1]> {
172let trait_ref = ty::Binder::dummy(ty::TraitRef::identity(tcx, trait_def_id));
173let predicates = if supertraits_only {
174tcx.explicit_super_predicates_of(trait_def_id).skip_binder()
175 } else {
176tcx.predicates_of(trait_def_id).predicates
177 };
178predicates179 .iter()
180 .map(|&(predicate, sp)| (predicate.instantiate_supertrait(tcx, trait_ref), sp))
181 .filter_map(|(clause, sp)| {
182// Super predicates cannot allow self projections, since they're
183 // impossible to make into existential bounds without eager resolution
184 // or something.
185 // e.g. `trait A: B<Item = Self::Assoc>`.
186predicate_references_self(tcx, trait_def_id, clause, sp, AllowSelfProjections::No)
187 })
188 .collect()
189}
190191fn bounds_reference_self(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span; 1]> {
192tcx.associated_items(trait_def_id)
193 .in_definition_order()
194// We're only looking at associated type bounds
195.filter(|item| item.is_type())
196// Ignore GATs with `Self: Sized`
197.filter(|item| !tcx.generics_require_sized_self(item.def_id))
198 .flat_map(|item| tcx.explicit_item_bounds(item.def_id).iter_identity_copied())
199 .filter_map(|(clause, sp)| {
200// Item bounds *can* have self projections, since they never get
201 // their self type erased.
202predicate_references_self(tcx, trait_def_id, clause, sp, AllowSelfProjections::Yes)
203 })
204 .collect()
205}
206207fn predicate_references_self<'tcx>(
208 tcx: TyCtxt<'tcx>,
209 trait_def_id: DefId,
210 predicate: ty::Clause<'tcx>,
211 sp: Span,
212 allow_self_projections: AllowSelfProjections,
213) -> Option<Span> {
214match predicate.kind().skip_binder() {
215 ty::ClauseKind::Trait(ref data) => {
216// In the case of a trait predicate, we can skip the "self" type.
217data.trait_ref.args[1..].iter().any(|&arg| contains_illegal_self_type_reference(tcx, trait_def_id, arg, allow_self_projections)).then_some(sp)
218 }
219 ty::ClauseKind::Projection(ref data) => {
220// And similarly for projections. This should be redundant with
221 // the previous check because any projection should have a
222 // matching `Trait` predicate with the same inputs, but we do
223 // the check to be safe.
224 //
225 // It's also won't be redundant if we allow type-generic associated
226 // types for trait objects.
227 //
228 // Note that we *do* allow projection *outputs* to contain
229 // `self` (i.e., `trait Foo: Bar<Output=Self::Result> { type Result; }`),
230 // we just require the user to specify *both* outputs
231 // in the object type (i.e., `dyn Foo<Output=(), Result=()>`).
232 //
233 // This is ALT2 in issue #56288, see that for discussion of the
234 // possible alternatives.
235data.projection_term.args[1..].iter().any(|&arg| contains_illegal_self_type_reference(tcx, trait_def_id, arg, allow_self_projections)).then_some(sp)
236 }
237 ty::ClauseKind::ConstArgHasType(_ct, ty) => contains_illegal_self_type_reference(tcx, trait_def_id, ty, allow_self_projections).then_some(sp),
238239 ty::ClauseKind::WellFormed(..)
240 | ty::ClauseKind::TypeOutlives(..)
241 | ty::ClauseKind::RegionOutlives(..)
242// FIXME(generic_const_exprs): this can mention `Self`
243| ty::ClauseKind::ConstEvaluatable(..)
244 | ty::ClauseKind::HostEffect(..)
245 | ty::ClauseKind::UnstableFeature(_)
246 => None,
247 }
248}
249250fn super_predicates_have_non_lifetime_binders(
251 tcx: TyCtxt<'_>,
252 trait_def_id: DefId,
253) -> SmallVec<[Span; 1]> {
254tcx.explicit_super_predicates_of(trait_def_id)
255 .iter_identity_copied()
256 .filter_map(|(pred, span)| pred.has_non_region_bound_vars().then_some(span))
257 .collect()
258}
259260/// Checks for `const Trait` supertraits. We're okay with `[const] Trait`,
261/// supertraits since for a non-const instantiation of that trait, the
262/// conditionally-const supertrait is also not required to be const.
263fn super_predicates_are_unconditionally_const(
264 tcx: TyCtxt<'_>,
265 trait_def_id: DefId,
266) -> SmallVec<[Span; 1]> {
267tcx.explicit_super_predicates_of(trait_def_id)
268 .iter_identity_copied()
269 .filter_map(|(pred, span)| {
270if let ty::ClauseKind::HostEffect(_) = pred.kind().skip_binder() {
271Some(span)
272 } else {
273None274 }
275 })
276 .collect()
277}
278279fn trait_has_sized_self(tcx: TyCtxt<'_>, trait_def_id: DefId) -> bool {
280tcx.generics_require_sized_self(trait_def_id)
281}
282283fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
284let Some(sized_def_id) = tcx.lang_items().sized_trait() else {
285return false; /* No Sized trait, can't require it! */
286};
287288// Search for a predicate like `Self : Sized` amongst the trait bounds.
289let predicates = tcx.predicates_of(def_id);
290let predicates = predicates.instantiate_identity(tcx).predicates;
291elaborate(tcx, predicates).any(|pred| match pred.kind().skip_binder() {
292 ty::ClauseKind::Trait(ref trait_pred) => {
293trait_pred.def_id() == sized_def_id && trait_pred.self_ty().is_param(0)
294 }
295 ty::ClauseKind::RegionOutlives(_)
296 | ty::ClauseKind::TypeOutlives(_)
297 | ty::ClauseKind::Projection(_)
298 | ty::ClauseKind::ConstArgHasType(_, _)
299 | ty::ClauseKind::WellFormed(_)
300 | ty::ClauseKind::ConstEvaluatable(_)
301 | ty::ClauseKind::UnstableFeature(_)
302 | ty::ClauseKind::HostEffect(..) => false,
303 })
304}
305306/// Returns `Some(_)` if this item makes the containing trait dyn-incompatible.
307x;#[instrument(level = "debug", skip(tcx), ret)]308pub fn dyn_compatibility_violations_for_assoc_item(
309 tcx: TyCtxt<'_>,
310 trait_def_id: DefId,
311 item: ty::AssocItem,
312) -> Vec<DynCompatibilityViolation> {
313// Any item that has a `Self : Sized` requisite is otherwise
314 // exempt from the regulations.
315if tcx.generics_require_sized_self(item.def_id) {
316return Vec::new();
317 }
318319match item.kind {
320// Associated consts are never dyn-compatible, as they can't have `where` bounds yet at all,
321 // and associated const bounds in trait objects aren't a thing yet either.
322ty::AssocKind::Const { name } => {
323vec![DynCompatibilityViolation::AssocConst(name, item.ident(tcx).span)]
324 }
325 ty::AssocKind::Fn { name, .. } => {
326 virtual_call_violations_for_method(tcx, trait_def_id, item)
327 .into_iter()
328 .map(|v| {
329let node = tcx.hir_get_if_local(item.def_id);
330// Get an accurate span depending on the violation.
331let span = match (&v, node) {
332 (MethodViolationCode::ReferencesSelfInput(Some(span)), _) => *span,
333 (MethodViolationCode::UndispatchableReceiver(Some(span)), _) => *span,
334 (MethodViolationCode::ReferencesImplTraitInTrait(span), _) => *span,
335 (MethodViolationCode::ReferencesSelfOutput, Some(node)) => {
336 node.fn_decl().map_or(item.ident(tcx).span, |decl| decl.output.span())
337 }
338_ => item.ident(tcx).span,
339 };
340341 DynCompatibilityViolation::Method(name, v, span)
342 })
343 .collect()
344 }
345// Associated types can only be dyn-compatible if they have `Self: Sized` bounds.
346ty::AssocKind::Type { .. } => {
347if !tcx.generics_of(item.def_id).is_own_empty() && !item.is_impl_trait_in_trait() {
348vec![DynCompatibilityViolation::GAT(item.name(), item.ident(tcx).span)]
349 } else {
350// We will permit associated types if they are explicitly mentioned in the trait object.
351 // We can't check this here, as here we only check if it is guaranteed to not be possible.
352Vec::new()
353 }
354 }
355 }
356}
357358/// Returns `Some(_)` if this method cannot be called on a trait
359/// object; this does not necessarily imply that the enclosing trait
360/// is dyn-incompatible, because the method might have a where clause
361/// `Self: Sized`.
362fn virtual_call_violations_for_method<'tcx>(
363 tcx: TyCtxt<'tcx>,
364 trait_def_id: DefId,
365 method: ty::AssocItem,
366) -> Vec<MethodViolationCode> {
367let sig = tcx.fn_sig(method.def_id).instantiate_identity();
368369// The method's first parameter must be named `self`
370if !method.is_method() {
371let sugg = if let Some(hir::Node::TraitItem(hir::TraitItem {
372 generics,
373 kind: hir::TraitItemKind::Fn(sig, _),
374 ..
375 })) = tcx.hir_get_if_local(method.def_id).as_ref()
376 {
377let sm = tcx.sess.source_map();
378Some((
379 (
380::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 { ", " }),
381sm.span_through_char(sig.span, '(').shrink_to_hi(),
382 ),
383 (
384::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()),
385generics.tail_span_for_predicate_suggestion(),
386 ),
387 ))
388 } else {
389None390 };
391392// Not having `self` parameter messes up the later checks,
393 // so we need to return instead of pushing
394return <[_]>::into_vec(::alloc::boxed::box_new([MethodViolationCode::StaticMethod(sugg)]))vec![MethodViolationCode::StaticMethod(sugg)];
395 }
396397let mut errors = Vec::new();
398399for (i, &input_ty) in sig.skip_binder().inputs().iter().enumerate().skip(1) {
400if contains_illegal_self_type_reference(
401 tcx,
402 trait_def_id,
403 sig.rebind(input_ty),
404 AllowSelfProjections::Yes,
405 ) {
406let span = if let Some(hir::Node::TraitItem(hir::TraitItem {
407 kind: hir::TraitItemKind::Fn(sig, _),
408 ..
409 })) = tcx.hir_get_if_local(method.def_id).as_ref()
410 {
411Some(sig.decl.inputs[i].span)
412 } else {
413None
414};
415 errors.push(MethodViolationCode::ReferencesSelfInput(span));
416 }
417 }
418if contains_illegal_self_type_reference(
419tcx,
420trait_def_id,
421sig.output(),
422 AllowSelfProjections::Yes,
423 ) {
424errors.push(MethodViolationCode::ReferencesSelfOutput);
425 }
426if let Some(code) = contains_illegal_impl_trait_in_trait(tcx, method.def_id, sig.output()) {
427errors.push(code);
428 }
429if sig.skip_binder().c_variadic {
430errors.push(MethodViolationCode::CVariadic);
431 }
432433// We can't monomorphize things like `fn foo<A>(...)`.
434let own_counts = tcx.generics_of(method.def_id).own_counts();
435if own_counts.types > 0 || own_counts.consts > 0 {
436errors.push(MethodViolationCode::Generic);
437 }
438439let receiver_ty = tcx.liberate_late_bound_regions(method.def_id, sig.input(0));
440441// `self: Self` can't be dispatched on.
442 // However, this is considered dyn compatible. We allow it as a special case here.
443 // FIXME(mikeyhew) get rid of this `if` statement once `receiver_is_dispatchable` allows
444 // `Receiver: Unsize<Receiver[Self => dyn Trait]>`.
445if receiver_ty != tcx.types.self_param {
446if !receiver_is_dispatchable(tcx, method, receiver_ty) {
447let span = if let Some(hir::Node::TraitItem(hir::TraitItem {
448 kind: hir::TraitItemKind::Fn(sig, _),
449 ..
450 })) = tcx.hir_get_if_local(method.def_id).as_ref()
451 {
452Some(sig.decl.inputs[0].span)
453 } else {
454None455 };
456errors.push(MethodViolationCode::UndispatchableReceiver(span));
457 } else {
458// We confirm that the `receiver_is_dispatchable` is accurate later,
459 // see `check_receiver_correct`. It should be kept in sync with this code.
460}
461 }
462463// NOTE: This check happens last, because it results in a lint, and not a
464 // hard error.
465if tcx.predicates_of(method.def_id).predicates.iter().any(|&(pred, _span)| {
466// dyn Trait is okay:
467 //
468 // trait Trait {
469 // fn f(&self) where Self: 'static;
470 // }
471 //
472 // because a trait object can't claim to live longer than the concrete
473 // type. If the lifetime bound holds on dyn Trait then it's guaranteed
474 // to hold as well on the concrete type.
475if pred.as_type_outlives_clause().is_some() {
476return false;
477 }
478479// dyn Trait is okay:
480 //
481 // auto trait AutoTrait {}
482 //
483 // trait Trait {
484 // fn f(&self) where Self: AutoTrait;
485 // }
486 //
487 // because `impl AutoTrait for dyn Trait` is disallowed by coherence.
488 // Traits with a default impl are implemented for a trait object if and
489 // only if the autotrait is one of the trait object's trait bounds, like
490 // in `dyn Trait + AutoTrait`. This guarantees that trait objects only
491 // implement auto traits if the underlying type does as well.
492if let ty::ClauseKind::Trait(ty::TraitPredicate {
493 trait_ref: pred_trait_ref,
494 polarity: ty::PredicatePolarity::Positive,
495 }) = pred.kind().skip_binder()
496 && pred_trait_ref.self_ty() == tcx.types.self_param
497 && tcx.trait_is_auto(pred_trait_ref.def_id)
498 {
499// Consider bounds like `Self: Bound<Self>`. Auto traits are not
500 // allowed to have generic parameters so `auto trait Bound<T> {}`
501 // would already have reported an error at the definition of the
502 // auto trait.
503if pred_trait_ref.args.len() != 1 {
504if !tcx.dcx().has_errors().is_some() {
{
::core::panicking::panic_fmt(format_args!("auto traits cannot have generic parameters"));
}
};assert!(
505 tcx.dcx().has_errors().is_some(),
506"auto traits cannot have generic parameters"
507);
508 }
509return false;
510 }
511512contains_illegal_self_type_reference(tcx, trait_def_id, pred, AllowSelfProjections::Yes)
513 }) {
514errors.push(MethodViolationCode::WhereClauseReferencesSelf);
515 }
516517errors518}
519520/// Performs a type instantiation to produce the version of `receiver_ty` when `Self = self_ty`.
521/// For example, for `receiver_ty = Rc<Self>` and `self_ty = Foo`, returns `Rc<Foo>`.
522fn receiver_for_self_ty<'tcx>(
523 tcx: TyCtxt<'tcx>,
524 receiver_ty: Ty<'tcx>,
525 self_ty: Ty<'tcx>,
526 method_def_id: DefId,
527) -> Ty<'tcx> {
528{
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:528",
"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(528u32),
::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);
529let args = GenericArgs::for_item(tcx, method_def_id, |param, _| {
530if param.index == 0 { self_ty.into() } else { tcx.mk_param_from_def(param) }
531 });
532533let result = EarlyBinder::bind(receiver_ty).instantiate(tcx, args);
534{
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:534",
"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(534u32),
::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!(
535"receiver_for_self_ty({:?}, {:?}, {:?}) = {:?}",
536 receiver_ty, self_ty, method_def_id, result
537 );
538result539}
540541/// Checks the method's receiver (the `self` argument) can be dispatched on when `Self` is a
542/// trait object. We require that `DispatchableFromDyn` be implemented for the receiver type
543/// in the following way:
544/// - let `Receiver` be the type of the `self` argument, i.e `Self`, `&Self`, `Rc<Self>`,
545/// - require the following bound:
546///
547/// ```ignore (not-rust)
548/// Receiver[Self => T]: DispatchFromDyn<Receiver[Self => dyn Trait]>
549/// ```
550///
551/// where `Foo[X => Y]` means "the same type as `Foo`, but with `X` replaced with `Y`"
552/// (instantiation notation).
553///
554/// Some examples of receiver types and their required obligation:
555/// - `&'a mut self` requires `&'a mut Self: DispatchFromDyn<&'a mut dyn Trait>`,
556/// - `self: Rc<Self>` requires `Rc<Self>: DispatchFromDyn<Rc<dyn Trait>>`,
557/// - `self: Pin<Box<Self>>` requires `Pin<Box<Self>>: DispatchFromDyn<Pin<Box<dyn Trait>>>`.
558///
559/// The only case where the receiver is not dispatchable, but is still a valid receiver
560/// type (just not dyn compatible), is when there is more than one level of pointer indirection.
561/// E.g., `self: &&Self`, `self: &Rc<Self>`, `self: Box<Box<Self>>`. In these cases, there
562/// is no way, or at least no inexpensive way, to coerce the receiver from the version where
563/// `Self = dyn Trait` to the version where `Self = T`, where `T` is the unknown erased type
564/// contained by the trait object, because the object that needs to be coerced is behind
565/// a pointer.
566///
567/// In practice, we cannot use `dyn Trait` explicitly in the obligation because it would result in
568/// a new check that `Trait` is dyn-compatible, creating a cycle.
569/// Instead, we emulate a placeholder by introducing a new type parameter `U` such that
570/// `Self: Unsize<U>` and `U: Trait + MetaSized`, and use `U` in place of `dyn Trait`.
571///
572/// Written as a chalk-style query:
573/// ```ignore (not-rust)
574/// forall (U: Trait + MetaSized) {
575/// if (Self: Unsize<U>) {
576/// Receiver: DispatchFromDyn<Receiver[Self => U]>
577/// }
578/// }
579/// ```
580/// for `self: &'a mut Self`, this means `&'a mut Self: DispatchFromDyn<&'a mut U>`
581/// for `self: Rc<Self>`, this means `Rc<Self>: DispatchFromDyn<Rc<U>>`
582/// for `self: Pin<Box<Self>>`, this means `Pin<Box<Self>>: DispatchFromDyn<Pin<Box<U>>>`
583//
584// FIXME(mikeyhew) when unsized receivers are implemented as part of unsized rvalues, add this
585// fallback query: `Receiver: Unsize<Receiver[Self => U]>` to support receivers like
586// `self: Wrapper<Self>`.
587fn receiver_is_dispatchable<'tcx>(
588 tcx: TyCtxt<'tcx>,
589 method: ty::AssocItem,
590 receiver_ty: Ty<'tcx>,
591) -> bool {
592{
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:592",
"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(592u32),
::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);
593594let (Some(unsize_did), Some(dispatch_from_dyn_did)) =
595 (tcx.lang_items().unsize_trait(), tcx.lang_items().dispatch_from_dyn_trait())
596else {
597{
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:597",
"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(597u32),
::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");
598return false;
599 };
600601// the type `U` in the query
602 // use a bogus type parameter to mimic a forall(U) query using u32::MAX for now.
603let unsized_self_ty: Ty<'tcx> =
604Ty::new_param(tcx, u32::MAX, rustc_span::sym::RustaceansAreAwesome);
605606// `Receiver[Self => U]`
607let unsized_receiver_ty =
608receiver_for_self_ty(tcx, receiver_ty, unsized_self_ty, method.def_id);
609610// create a modified param env, with `Self: Unsize<U>` and `U: Trait` (and all of
611 // its supertraits) added to caller bounds. `U: MetaSized` is already implied here.
612let param_env = {
613// N.B. We generally want to emulate the construction of the `unnormalized_param_env`
614 // in the param-env query here. The fact that we don't just start with the clauses
615 // in the param-env of the method is because those are already normalized, and mixing
616 // normalized and unnormalized copies of predicates in `normalize_param_env_or_error`
617 // will cause ambiguity that the user can't really avoid.
618 //
619 // We leave out certain complexities of the param-env query here. Specifically, we:
620 // 1. Do not add `[const]` bounds since there are no `dyn const Trait`s.
621 // 2. Do not add RPITIT self projection bounds for defaulted methods, since we
622 // are not constructing a param-env for "inside" of the body of the defaulted
623 // method, so we don't really care about projecting to a specific RPIT type,
624 // and because RPITITs are not dyn compatible (yet).
625let mut predicates = tcx.predicates_of(method.def_id).instantiate_identity(tcx).predicates;
626627// Self: Unsize<U>
628let unsize_predicate =
629 ty::TraitRef::new(tcx, unsize_did, [tcx.types.self_param, unsized_self_ty]);
630predicates.push(unsize_predicate.upcast(tcx));
631632// U: Trait<Arg1, ..., ArgN>
633let trait_def_id = method.trait_container(tcx).unwrap();
634let args = GenericArgs::for_item(tcx, trait_def_id, |param, _| {
635if param.index == 0 { unsized_self_ty.into() } else { tcx.mk_param_from_def(param) }
636 });
637let trait_predicate = ty::TraitRef::new_from_args(tcx, trait_def_id, args);
638predicates.push(trait_predicate.upcast(tcx));
639640let meta_sized_predicate = {
641let meta_sized_did = tcx.require_lang_item(LangItem::MetaSized, DUMMY_SP);
642 ty::TraitRef::new(tcx, meta_sized_did, [unsized_self_ty]).upcast(tcx)
643 };
644predicates.push(meta_sized_predicate);
645646normalize_param_env_or_error(
647tcx,
648 ty::ParamEnv::new(tcx.mk_clauses(&predicates)),
649ObligationCause::dummy_with_span(tcx.def_span(method.def_id)),
650 )
651 };
652653// Receiver: DispatchFromDyn<Receiver[Self => U]>
654let obligation = {
655let predicate =
656 ty::TraitRef::new(tcx, dispatch_from_dyn_did, [receiver_ty, unsized_receiver_ty]);
657658Obligation::new(tcx, ObligationCause::dummy(), param_env, predicate)
659 };
660661let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
662// the receiver is dispatchable iff the obligation holds
663infcx.predicate_must_hold_modulo_regions(&obligation)
664}
665666#[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)]
667enum AllowSelfProjections {
668 Yes,
669 No,
670}
671672/// This is somewhat subtle. In general, we want to forbid
673/// references to `Self` in the argument and return types,
674/// since the value of `Self` is erased. However, there is one
675/// exception: it is ok to reference `Self` in order to access
676/// an associated type of the current trait, since we retain
677/// the value of those associated types in the object type
678/// itself.
679///
680/// ```rust,ignore (example)
681/// trait SuperTrait {
682/// type X;
683/// }
684///
685/// trait Trait : SuperTrait {
686/// type Y;
687/// fn foo(&self, x: Self) // bad
688/// fn foo(&self) -> Self // bad
689/// fn foo(&self) -> Option<Self> // bad
690/// fn foo(&self) -> Self::Y // OK, desugars to next example
691/// fn foo(&self) -> <Self as Trait>::Y // OK
692/// fn foo(&self) -> Self::X // OK, desugars to next example
693/// fn foo(&self) -> <Self as SuperTrait>::X // OK
694/// }
695/// ```
696///
697/// However, it is not as simple as allowing `Self` in a projected
698/// type, because there are illegal ways to use `Self` as well:
699///
700/// ```rust,ignore (example)
701/// trait Trait : SuperTrait {
702/// ...
703/// fn foo(&self) -> <Self as SomeOtherTrait>::X;
704/// }
705/// ```
706///
707/// Here we will not have the type of `X` recorded in the
708/// object type, and we cannot resolve `Self as SomeOtherTrait`
709/// without knowing what `Self` is.
710fn contains_illegal_self_type_reference<'tcx, T: TypeVisitable<TyCtxt<'tcx>>>(
711 tcx: TyCtxt<'tcx>,
712 trait_def_id: DefId,
713 value: T,
714 allow_self_projections: AllowSelfProjections,
715) -> bool {
716value717 .visit_with(&mut IllegalSelfTypeVisitor {
718tcx,
719trait_def_id,
720 supertraits: None,
721allow_self_projections,
722 })
723 .is_break()
724}
725726struct IllegalSelfTypeVisitor<'tcx> {
727 tcx: TyCtxt<'tcx>,
728 trait_def_id: DefId,
729 supertraits: Option<Vec<ty::TraitRef<'tcx>>>,
730 allow_self_projections: AllowSelfProjections,
731}
732733impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for IllegalSelfTypeVisitor<'tcx> {
734type Result = ControlFlow<()>;
735736fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
737match t.kind() {
738 ty::Param(_) => {
739if t == self.tcx.types.self_param {
740 ControlFlow::Break(())
741 } else {
742 ControlFlow::Continue(())
743 }
744 }
745 ty::Alias(ty::Projection, data) if self.tcx.is_impl_trait_in_trait(data.def_id) => {
746// We'll deny these later in their own pass
747ControlFlow::Continue(())
748 }
749 ty::Alias(ty::Projection, data) => {
750match self.allow_self_projections {
751 AllowSelfProjections::Yes => {
752// This is a projected type `<Foo as SomeTrait>::X`.
753754 // Compute supertraits of current trait lazily.
755if self.supertraits.is_none() {
756self.supertraits = Some(
757 util::supertraits(
758self.tcx,
759 ty::Binder::dummy(ty::TraitRef::identity(
760self.tcx,
761self.trait_def_id,
762 )),
763 )
764 .map(|trait_ref| {
765self.tcx.erase_and_anonymize_regions(
766self.tcx.instantiate_bound_regions_with_erased(trait_ref),
767 )
768 })
769 .collect(),
770 );
771 }
772773// Determine whether the trait reference `Foo as
774 // SomeTrait` is in fact a supertrait of the
775 // current trait. In that case, this type is
776 // legal, because the type `X` will be specified
777 // in the object type. Note that we can just use
778 // direct equality here because all of these types
779 // are part of the formal parameter listing, and
780 // hence there should be no inference variables.
781let is_supertrait_of_current_trait =
782self.supertraits.as_ref().unwrap().contains(
783&data.trait_ref(self.tcx).fold_with(
784&mut EraseEscapingBoundRegions {
785 tcx: self.tcx,
786 binder: ty::INNERMOST,
787 },
788 ),
789 );
790791// only walk contained types if it's not a super trait
792if is_supertrait_of_current_trait {
793 ControlFlow::Continue(())
794 } else {
795t.super_visit_with(self) // POSSIBLY reporting an error
796}
797 }
798 AllowSelfProjections::No => t.super_visit_with(self),
799 }
800 }
801_ => t.super_visit_with(self),
802 }
803 }
804805fn visit_const(&mut self, ct: ty::Const<'tcx>) -> Self::Result {
806// Constants can only influence dyn-compatibility if they are generic and reference `Self`.
807 // This is only possible for unevaluated constants, so we walk these here.
808self.tcx.expand_abstract_consts(ct).super_visit_with(self)
809 }
810}
811812struct EraseEscapingBoundRegions<'tcx> {
813 tcx: TyCtxt<'tcx>,
814 binder: ty::DebruijnIndex,
815}
816817impl<'tcx> TypeFolder<TyCtxt<'tcx>> for EraseEscapingBoundRegions<'tcx> {
818fn cx(&self) -> TyCtxt<'tcx> {
819self.tcx
820 }
821822fn fold_binder<T>(&mut self, t: ty::Binder<'tcx, T>) -> ty::Binder<'tcx, T>
823where
824T: TypeFoldable<TyCtxt<'tcx>>,
825 {
826self.binder.shift_in(1);
827let result = t.super_fold_with(self);
828self.binder.shift_out(1);
829result830 }
831832fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
833if let ty::ReBound(ty::BoundVarIndexKind::Bound(debruijn), _) = r.kind()
834 && debruijn < self.binder
835 {
836r837 } else {
838self.tcx.lifetimes.re_erased
839 }
840 }
841}
842843fn contains_illegal_impl_trait_in_trait<'tcx>(
844 tcx: TyCtxt<'tcx>,
845 fn_def_id: DefId,
846 ty: ty::Binder<'tcx, Ty<'tcx>>,
847) -> Option<MethodViolationCode> {
848let ty = tcx.liberate_late_bound_regions(fn_def_id, ty);
849850if tcx.asyncness(fn_def_id).is_async() {
851// Rendering the error as a separate `async-specific` message is better.
852Some(MethodViolationCode::AsyncFn)
853 } else {
854ty.visit_with(&mut IllegalRpititVisitor { tcx, allowed: None }).break_value()
855 }
856}
857858struct IllegalRpititVisitor<'tcx> {
859 tcx: TyCtxt<'tcx>,
860 allowed: Option<ty::AliasTy<'tcx>>,
861}
862863impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for IllegalRpititVisitor<'tcx> {
864type Result = ControlFlow<MethodViolationCode>;
865866fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
867if let ty::Alias(ty::Projection, proj) = *ty.kind()
868 && Some(proj) != self.allowed
869 && self.tcx.is_impl_trait_in_trait(proj.def_id)
870 {
871 ControlFlow::Break(MethodViolationCode::ReferencesImplTraitInTrait(
872self.tcx.def_span(proj.def_id),
873 ))
874 } else {
875ty.super_visit_with(self)
876 }
877 }
878}
879880pub(crate) fn provide(providers: &mut Providers) {
881*providers = Providers {
882dyn_compatibility_violations,
883is_dyn_compatible,
884generics_require_sized_self,
885 ..*providers886 };
887}