1use 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
31x;#[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
65pub 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 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 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 if trait_has_sized_self(tcx, trait_def_id) {
94 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 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 Some(sized_trait_bound_spans(tcx, pred.bounds))
157 }
158 _ => None,
159 }
160 })
161 .flatten()
162 .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 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 .filter(|item| item.is_type())
200 .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 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 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 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 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
292fn 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; };
320
321 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 if tcx.defaultness(item.def_id).is_final() {
352 return Vec::new();
353 }
354
355 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 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 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 Vec::new()
427 }
428 }
429 }
430}
431
432fn 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 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 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 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 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 }
535 }
536
537 if tcx.predicates_of(method.def_id).predicates.iter().any(|&(pred, _span)| {
540 if pred.as_type_outlives_clause().is_some() {
550 return false;
551 }
552
553 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 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
594fn 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
615fn 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 let unsized_self_ty: Ty<'tcx> =
685 Ty::new_param(tcx, u32::MAX, rustc_span::sym::RustaceansAreAwesome);
686
687 let unsized_receiver_ty =
689 receiver_for_self_ty(tcx, receiver_ty, unsized_self_ty, method.def_id);
690
691 let param_env = {
694 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 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 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 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 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
759fn 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 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 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 ControlFlow::Continue(())
867 }
868 ty::Alias(proj @ ty::AliasTy { kind: ty::Projection { .. }, .. }) => {
869 match self.allow_self_projections {
870 AllowSelfProjections::Yes => {
871 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 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 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}