1use std::ops::ControlFlow;
8
9use rustc_errors::FatalError;
10use rustc_hir::def::DefKind;
11use rustc_hir::def_id::DefId;
12use rustc_hir::{self as hir, LangItem};
13use rustc_middle::query::Providers;
14use rustc_middle::ty::{
15 self, EarlyBinder, GenericArgs, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
16 TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, Unnormalized,
17 Upcast, elaborate,
18};
19use rustc_span::{DUMMY_SP, Span};
20use smallvec::SmallVec;
21use tracing::{debug, instrument};
22
23use super::elaborate;
24use crate::infer::TyCtxtInferExt;
25pub use crate::traits::DynCompatibilityViolation;
26use crate::traits::query::evaluate_obligation::InferCtxtExt;
27use crate::traits::{
28 AssocConstViolation, MethodViolation, Obligation, ObligationCause,
29 normalize_param_env_or_error, util,
30};
31
32x;#[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> {
42 debug_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}
49
50fn dyn_compatibility_violations(
51 tcx: TyCtxt<'_>,
52 trait_def_id: DefId,
53) -> &'_ [DynCompatibilityViolation] {
54 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);
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);
56 tcx.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}
61
62fn is_dyn_compatible(tcx: TyCtxt<'_>, trait_def_id: DefId) -> bool {
63 tcx.dyn_compatibility_violations(trait_def_id).is_empty()
64}
65
66pub fn is_vtable_safe_method(tcx: TyCtxt<'_>, trait_def_id: DefId, method: ty::AssocItem) -> bool {
71 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);
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 if tcx.generics_require_sized_self(method.def_id) {
75 return false;
76 }
77
78 virtual_call_violations_for_method(tcx, trait_def_id, method).is_empty()
79}
80
81x;#[instrument(level = "debug", skip(tcx), ret)]
82fn dyn_compatibility_violations_for_trait(
83 tcx: TyCtxt<'_>,
84 trait_def_id: DefId,
85) -> Vec<DynCompatibilityViolation> {
86 let 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();
92
93 if trait_has_sized_self(tcx, trait_def_id) {
95 let 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 }
101
102 let spans = predicates_reference_self(tcx, trait_def_id, false);
103 if !spans.is_empty() {
104 violations.push(DynCompatibilityViolation::SupertraitSelf(spans));
105 }
106 let spans = bounds_reference_self(tcx, trait_def_id);
107 if !spans.is_empty() {
108 violations.push(DynCompatibilityViolation::SupertraitSelf(spans));
109 }
110 let spans = super_predicates_have_non_lifetime_binders(tcx, trait_def_id);
111 if !spans.is_empty() {
112 violations.push(DynCompatibilityViolation::SupertraitNonLifetimeBinder(spans));
113 }
114 let spans = super_predicates_are_unconditionally_const(tcx, trait_def_id);
115 if !spans.is_empty() {
116 violations.push(DynCompatibilityViolation::SupertraitConst(spans));
117 }
118
119 violations
120}
121
122fn sized_trait_bound_spans<'tcx>(
123 tcx: TyCtxt<'tcx>,
124 bounds: hir::GenericBounds<'tcx>,
125) -> impl 'tcx + Iterator<Item = Span> {
126 bounds.iter().filter_map(move |b| match b {
127 hir::GenericBound::Trait(trait_ref)
128 if trait_has_sized_self(
129 tcx,
130 trait_ref.trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise()),
131 ) =>
132 {
133 Some(trait_ref.span)
135 }
136 _ => None,
137 })
138}
139
140fn get_sized_bounds(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span; 1]> {
141 tcx.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(
147 generics
148 .predicates
149 .iter()
150 .filter_map(|pred| {
151 match pred.kind {
152 hir::WherePredicateKind::BoundPredicate(pred)
153 if pred.bounded_ty.hir_id.owner.to_def_id() == trait_def_id =>
154 {
155 Some(sized_trait_bound_spans(tcx, pred.bounds))
158 }
159 _ => None,
160 }
161 })
162 .flatten()
163 .chain(sized_trait_bound_spans(tcx, bounds))
165 .collect::<SmallVec<[Span; 1]>>(),
166 ),
167 _ => None,
168 })
169 .unwrap_or_else(SmallVec::new)
170}
171
172fn predicates_reference_self(
173 tcx: TyCtxt<'_>,
174 trait_def_id: DefId,
175 supertraits_only: bool,
176) -> SmallVec<[Span; 1]> {
177 let trait_ref = ty::Binder::dummy(ty::TraitRef::identity(tcx, trait_def_id));
178 let predicates = if supertraits_only {
179 tcx.explicit_super_predicates_of(trait_def_id).skip_binder()
180 } else {
181 tcx.predicates_of(trait_def_id).predicates
182 };
183 predicates
184 .iter()
185 .map(|&(predicate, sp)| (predicate.instantiate_supertrait(tcx, trait_ref), sp))
186 .filter_map(|(clause, sp)| {
187 predicate_references_self(tcx, trait_def_id, clause, sp, AllowSelfProjections::No)
192 })
193 .collect()
194}
195
196fn bounds_reference_self(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span; 1]> {
197 tcx.associated_items(trait_def_id)
198 .in_definition_order()
199 .filter(|item| item.is_type())
201 .filter(|item| !tcx.generics_require_sized_self(item.def_id))
203 .flat_map(|item| {
204 tcx.explicit_item_bounds(item.def_id)
205 .iter_identity_copied()
206 .map(Unnormalized::skip_norm_wip)
207 })
208 .filter_map(|(clause, sp)| {
209 predicate_references_self(tcx, trait_def_id, clause, sp, AllowSelfProjections::Yes)
212 })
213 .collect()
214}
215
216fn predicate_references_self<'tcx>(
217 tcx: TyCtxt<'tcx>,
218 trait_def_id: DefId,
219 predicate: ty::Clause<'tcx>,
220 sp: Span,
221 allow_self_projections: AllowSelfProjections,
222) -> Option<Span> {
223 match predicate.kind().skip_binder() {
224 ty::ClauseKind::Trait(ref data) => {
225 data.trait_ref.args[1..].iter().any(|&arg| contains_illegal_self_type_reference(tcx, trait_def_id, arg, allow_self_projections)).then_some(sp)
227 }
228 ty::ClauseKind::Projection(ref data) => {
229 data.projection_term.args[1..].iter().any(|&arg| contains_illegal_self_type_reference(tcx, trait_def_id, arg, allow_self_projections)).then_some(sp)
245 }
246 ty::ClauseKind::ConstArgHasType(_ct, ty) => contains_illegal_self_type_reference(tcx, trait_def_id, ty, allow_self_projections).then_some(sp),
247
248 ty::ClauseKind::WellFormed(..)
249 | ty::ClauseKind::TypeOutlives(..)
250 | ty::ClauseKind::RegionOutlives(..)
251 | ty::ClauseKind::ConstEvaluatable(..)
253 | ty::ClauseKind::HostEffect(..)
254 | ty::ClauseKind::UnstableFeature(_)
255 => None,
256 }
257}
258
259fn super_predicates_have_non_lifetime_binders(
260 tcx: TyCtxt<'_>,
261 trait_def_id: DefId,
262) -> SmallVec<[Span; 1]> {
263 tcx.explicit_super_predicates_of(trait_def_id)
264 .iter_identity_copied()
265 .map(Unnormalized::skip_norm_wip)
266 .filter_map(|(pred, span)| pred.has_non_region_bound_vars().then_some(span))
267 .collect()
268}
269
270fn super_predicates_are_unconditionally_const(
274 tcx: TyCtxt<'_>,
275 trait_def_id: DefId,
276) -> SmallVec<[Span; 1]> {
277 tcx.explicit_super_predicates_of(trait_def_id)
278 .iter_identity_copied()
279 .map(Unnormalized::skip_norm_wip)
280 .filter_map(|(pred, span)| {
281 if let ty::ClauseKind::HostEffect(_) = pred.kind().skip_binder() {
282 Some(span)
283 } else {
284 None
285 }
286 })
287 .collect()
288}
289
290fn trait_has_sized_self(tcx: TyCtxt<'_>, trait_def_id: DefId) -> bool {
291 tcx.generics_require_sized_self(trait_def_id)
292}
293
294fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
295 let Some(sized_def_id) = tcx.lang_items().sized_trait() else {
296 return false; };
298
299 let predicates: Vec<_> = tcx
301 .predicates_of(def_id)
302 .instantiate_identity(tcx)
303 .predicates
304 .into_iter()
305 .map(Unnormalized::skip_norm_wip)
306 .collect();
307 elaborate(tcx, predicates).any(|pred| match pred.kind().skip_binder() {
308 ty::ClauseKind::Trait(ref trait_pred) => {
309 trait_pred.def_id() == sized_def_id && trait_pred.self_ty().is_param(0)
310 }
311 ty::ClauseKind::RegionOutlives(_)
312 | ty::ClauseKind::TypeOutlives(_)
313 | ty::ClauseKind::Projection(_)
314 | ty::ClauseKind::ConstArgHasType(_, _)
315 | ty::ClauseKind::WellFormed(_)
316 | ty::ClauseKind::ConstEvaluatable(_)
317 | ty::ClauseKind::UnstableFeature(_)
318 | ty::ClauseKind::HostEffect(..) => false,
319 })
320}
321
322x;#[instrument(level = "debug", skip(tcx), ret)]
323pub fn dyn_compatibility_violations_for_assoc_item(
324 tcx: TyCtxt<'_>,
325 trait_def_id: DefId,
326 item: ty::AssocItem,
327) -> Vec<DynCompatibilityViolation> {
328 if tcx.defaultness(item.def_id).is_final() {
330 return Vec::new();
331 }
332
333 if tcx.generics_require_sized_self(item.def_id) {
335 return Vec::new();
336 }
337
338 let span = || item.ident(tcx).span;
339
340 match item.kind {
341 ty::AssocKind::Const { name, is_type_const } => {
342 let mut errors = Vec::new();
347
348 if tcx.features().min_generic_const_args() {
349 if !tcx.generics_of(item.def_id).is_own_empty() {
350 errors.push(AssocConstViolation::Generic);
351 } else if !is_type_const {
352 errors.push(AssocConstViolation::NonType);
353 }
354
355 let ty = ty::Binder::dummy(
356 tcx.type_of(item.def_id).instantiate_identity().skip_norm_wip(),
357 );
358 if contains_illegal_self_type_reference(
359 tcx,
360 trait_def_id,
361 ty,
362 AllowSelfProjections::Yes,
363 ) {
364 errors.push(AssocConstViolation::TypeReferencesSelf);
365 }
366 } else {
367 errors.push(AssocConstViolation::FeatureNotEnabled);
368 }
369
370 errors
371 .into_iter()
372 .map(|error| DynCompatibilityViolation::AssocConst(name, error, span()))
373 .collect()
374 }
375 ty::AssocKind::Fn { name, .. } => {
376 virtual_call_violations_for_method(tcx, trait_def_id, item)
377 .into_iter()
378 .map(|v| {
379 let node = tcx.hir_get_if_local(item.def_id);
380 let span = match (&v, node) {
382 (MethodViolation::ReferencesSelfInput(Some(span)), _) => *span,
383 (MethodViolation::UndispatchableReceiver(Some(span)), _) => *span,
384 (MethodViolation::ReferencesImplTraitInTrait(span), _) => *span,
385 (MethodViolation::ReferencesSelfOutput, Some(node)) => {
386 node.fn_decl().map_or(item.ident(tcx).span, |decl| decl.output.span())
387 }
388 _ => span(),
389 };
390
391 DynCompatibilityViolation::Method(name, v, span)
392 })
393 .collect()
394 }
395 ty::AssocKind::Type { data } => {
396 if !tcx.generics_of(item.def_id).is_own_empty()
397 && let ty::AssocTypeData::Normal(name) = data
398 {
399 vec![DynCompatibilityViolation::GenericAssocTy(name, span())]
400 } else {
401 Vec::new()
405 }
406 }
407 }
408}
409
410fn virtual_call_violations_for_method<'tcx>(
415 tcx: TyCtxt<'tcx>,
416 trait_def_id: DefId,
417 method: ty::AssocItem,
418) -> Vec<MethodViolation> {
419 let sig = tcx.fn_sig(method.def_id).instantiate_identity().skip_norm_wip();
420
421 if !method.is_method() {
423 let sugg = if let Some(hir::Node::TraitItem(hir::TraitItem {
424 generics,
425 kind: hir::TraitItemKind::Fn(sig, _),
426 ..
427 })) = tcx.hir_get_if_local(method.def_id).as_ref()
428 {
429 let sm = tcx.sess.source_map();
430 Some((
431 (
432 ::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 { ", " }),
433 sm.span_through_char(sig.span, '(').shrink_to_hi(),
434 ),
435 (
436 ::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()),
437 generics.tail_span_for_predicate_suggestion(),
438 ),
439 ))
440 } else {
441 None
442 };
443
444 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)];
447 }
448
449 let mut errors = Vec::new();
450
451 for (i, &input_ty) in sig.skip_binder().inputs().iter().enumerate().skip(1) {
452 if contains_illegal_self_type_reference(
453 tcx,
454 trait_def_id,
455 sig.rebind(input_ty),
456 AllowSelfProjections::Yes,
457 ) {
458 let span = if let Some(hir::Node::TraitItem(hir::TraitItem {
459 kind: hir::TraitItemKind::Fn(sig, _),
460 ..
461 })) = tcx.hir_get_if_local(method.def_id).as_ref()
462 {
463 Some(sig.decl.inputs[i].span)
464 } else {
465 None
466 };
467 errors.push(MethodViolation::ReferencesSelfInput(span));
468 }
469 }
470 if contains_illegal_self_type_reference(
471 tcx,
472 trait_def_id,
473 sig.output(),
474 AllowSelfProjections::Yes,
475 ) {
476 errors.push(MethodViolation::ReferencesSelfOutput);
477 }
478 if let Some(error) = contains_illegal_impl_trait_in_trait(tcx, method.def_id, sig.output()) {
479 errors.push(error);
480 }
481 if sig.skip_binder().c_variadic() {
482 errors.push(MethodViolation::CVariadic);
483 }
484
485 let own_counts = tcx.generics_of(method.def_id).own_counts();
487 if own_counts.types > 0 || own_counts.consts > 0 {
488 errors.push(MethodViolation::Generic);
489 }
490
491 let receiver_ty = tcx.liberate_late_bound_regions(method.def_id, sig.input(0));
492
493 if receiver_ty != tcx.types.self_param {
498 if !receiver_is_dispatchable(tcx, method, receiver_ty) {
499 let span = if let Some(hir::Node::TraitItem(hir::TraitItem {
500 kind: hir::TraitItemKind::Fn(sig, _),
501 ..
502 })) = tcx.hir_get_if_local(method.def_id).as_ref()
503 {
504 Some(sig.decl.inputs[0].span)
505 } else {
506 None
507 };
508 errors.push(MethodViolation::UndispatchableReceiver(span));
509 } else {
510 }
513 }
514
515 if tcx.predicates_of(method.def_id).predicates.iter().any(|&(pred, _span)| {
518 if pred.as_type_outlives_clause().is_some() {
528 return false;
529 }
530
531 if let ty::ClauseKind::Trait(ty::TraitPredicate {
545 trait_ref: pred_trait_ref,
546 polarity: ty::PredicatePolarity::Positive,
547 }) = pred.kind().skip_binder()
548 && pred_trait_ref.self_ty() == tcx.types.self_param
549 && tcx.trait_is_auto(pred_trait_ref.def_id)
550 {
551 if pred_trait_ref.args.len() != 1 {
556 if !tcx.dcx().has_errors().is_some() {
{
::core::panicking::panic_fmt(format_args!("auto traits cannot have generic parameters"));
}
};assert!(
557 tcx.dcx().has_errors().is_some(),
558 "auto traits cannot have generic parameters"
559 );
560 }
561 return false;
562 }
563
564 contains_illegal_self_type_reference(tcx, trait_def_id, pred, AllowSelfProjections::Yes)
565 }) {
566 errors.push(MethodViolation::WhereClauseReferencesSelf);
567 }
568
569 errors
570}
571
572fn receiver_for_self_ty<'tcx>(
575 tcx: TyCtxt<'tcx>,
576 receiver_ty: Ty<'tcx>,
577 self_ty: Ty<'tcx>,
578 method_def_id: DefId,
579) -> Ty<'tcx> {
580 {
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:580",
"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(580u32),
::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);
581 let args = GenericArgs::for_item(tcx, method_def_id, |param, _| {
582 if param.index == 0 { self_ty.into() } else { tcx.mk_param_from_def(param) }
583 });
584
585 let result = EarlyBinder::bind(receiver_ty).instantiate(tcx, args).skip_norm_wip();
586 {
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:586",
"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(586u32),
::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!(
587 "receiver_for_self_ty({:?}, {:?}, {:?}) = {:?}",
588 receiver_ty, self_ty, method_def_id, result
589 );
590 result
591}
592
593fn receiver_is_dispatchable<'tcx>(
643 tcx: TyCtxt<'tcx>,
644 method: ty::AssocItem,
645 receiver_ty: Ty<'tcx>,
646) -> bool {
647 {
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:647",
"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(647u32),
::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);
648
649 if receiver_ty.references_error() {
650 return false;
651 }
652
653 let (Some(unsize_did), Some(dispatch_from_dyn_did)) =
654 (tcx.lang_items().unsize_trait(), tcx.lang_items().dispatch_from_dyn_trait())
655 else {
656 {
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:656",
"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(656u32),
::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");
657 return false;
658 };
659
660 let unsized_self_ty: Ty<'tcx> =
663 Ty::new_param(tcx, u32::MAX, rustc_span::sym::RustaceansAreAwesome);
664
665 let unsized_receiver_ty =
667 receiver_for_self_ty(tcx, receiver_ty, unsized_self_ty, method.def_id);
668
669 let param_env = {
672 let mut predicates: Vec<_> = tcx
685 .predicates_of(method.def_id)
686 .instantiate_identity(tcx)
687 .predicates
688 .into_iter()
689 .map(Unnormalized::skip_norm_wip)
690 .collect();
691
692 let unsize_predicate =
694 ty::TraitRef::new(tcx, unsize_did, [tcx.types.self_param, unsized_self_ty]);
695 predicates.push(unsize_predicate.upcast(tcx));
696
697 let trait_def_id = method.trait_container(tcx).unwrap();
699 let args = GenericArgs::for_item(tcx, trait_def_id, |param, _| {
700 if param.index == 0 { unsized_self_ty.into() } else { tcx.mk_param_from_def(param) }
701 });
702 let trait_predicate = ty::TraitRef::new_from_args(tcx, trait_def_id, args);
703 predicates.push(trait_predicate.upcast(tcx));
704
705 let meta_sized_predicate = {
706 let meta_sized_did = tcx.require_lang_item(LangItem::MetaSized, DUMMY_SP);
707 ty::TraitRef::new(tcx, meta_sized_did, [unsized_self_ty]).upcast(tcx)
708 };
709 predicates.push(meta_sized_predicate);
710
711 normalize_param_env_or_error(
712 tcx,
713 ty::ParamEnv::new(tcx.mk_clauses(&predicates)),
714 ObligationCause::dummy_with_span(tcx.def_span(method.def_id)),
715 )
716 };
717
718 let obligation = {
720 let predicate =
721 ty::TraitRef::new(tcx, dispatch_from_dyn_did, [receiver_ty, unsized_receiver_ty]);
722
723 Obligation::new(tcx, ObligationCause::dummy(), param_env, predicate)
724 };
725
726 let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
727 infcx.predicate_must_hold_modulo_regions(&obligation)
729}
730
731#[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)]
732enum AllowSelfProjections {
733 Yes,
734 No,
735}
736
737fn contains_illegal_self_type_reference<'tcx, T: TypeVisitable<TyCtxt<'tcx>>>(
779 tcx: TyCtxt<'tcx>,
780 trait_def_id: DefId,
781 value: T,
782 allow_self_projections: AllowSelfProjections,
783) -> bool {
784 value
785 .visit_with(&mut IllegalSelfTypeVisitor {
786 tcx,
787 trait_def_id,
788 supertraits: None,
789 allow_self_projections,
790 })
791 .is_break()
792}
793
794struct IllegalSelfTypeVisitor<'tcx> {
795 tcx: TyCtxt<'tcx>,
796 trait_def_id: DefId,
797 supertraits: Option<Vec<ty::TraitRef<'tcx>>>,
798 allow_self_projections: AllowSelfProjections,
799}
800
801impl<'tcx> IllegalSelfTypeVisitor<'tcx> {
802 fn is_supertrait_of_current_trait(&mut self, trait_ref: ty::TraitRef<'tcx>) -> bool {
803 let supertraits = self.supertraits.get_or_insert_with(|| {
805 util::supertraits(
806 self.tcx,
807 ty::Binder::dummy(ty::TraitRef::identity(self.tcx, self.trait_def_id)),
808 )
809 .map(|trait_ref| {
810 self.tcx.erase_and_anonymize_regions(
811 self.tcx.instantiate_bound_regions_with_erased(trait_ref),
812 )
813 })
814 .collect()
815 });
816
817 let trait_ref = trait_ref
823 .fold_with(&mut EraseEscapingBoundRegions { tcx: self.tcx, binder: ty::INNERMOST });
824 supertraits.contains(&trait_ref)
825 }
826}
827
828impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for IllegalSelfTypeVisitor<'tcx> {
829 type Result = ControlFlow<()>;
830
831 fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
832 match ty.kind() {
833 ty::Param(_) => {
834 if ty == self.tcx.types.self_param {
835 ControlFlow::Break(())
836 } else {
837 ControlFlow::Continue(())
838 }
839 }
840 ty::Alias(ty::AliasTy { kind: ty::Projection { def_id }, .. })
841 if self.tcx.is_impl_trait_in_trait(*def_id) =>
842 {
843 ControlFlow::Continue(())
845 }
846 ty::Alias(proj @ ty::AliasTy { kind: ty::Projection { .. }, .. }) => {
847 match self.allow_self_projections {
848 AllowSelfProjections::Yes => {
849 if self.is_supertrait_of_current_trait(proj.trait_ref(self.tcx)) {
851 ControlFlow::Continue(())
852 } else {
853 ty.super_visit_with(self)
854 }
855 }
856 AllowSelfProjections::No => ty.super_visit_with(self),
857 }
858 }
859 _ => ty.super_visit_with(self),
860 }
861 }
862
863 fn visit_const(&mut self, ct: ty::Const<'tcx>) -> Self::Result {
864 let ct = self.tcx.expand_abstract_consts(ct);
865
866 match ct.kind() {
867 ty::ConstKind::Unevaluated(proj) if self.tcx.features().min_generic_const_args() => {
868 match self.allow_self_projections {
869 AllowSelfProjections::Yes
870 if let trait_def_id = self.tcx.parent(proj.def)
871 && self.tcx.def_kind(trait_def_id) == DefKind::Trait =>
872 {
873 let trait_ref = ty::TraitRef::from_assoc(self.tcx, trait_def_id, proj.args);
874
875 if self.is_supertrait_of_current_trait(trait_ref) {
877 ControlFlow::Continue(())
878 } else {
879 ct.super_visit_with(self)
880 }
881 }
882 _ => ct.super_visit_with(self),
883 }
884 }
885 _ => ct.super_visit_with(self),
886 }
887 }
888}
889
890struct EraseEscapingBoundRegions<'tcx> {
891 tcx: TyCtxt<'tcx>,
892 binder: ty::DebruijnIndex,
893}
894
895impl<'tcx> TypeFolder<TyCtxt<'tcx>> for EraseEscapingBoundRegions<'tcx> {
896 fn cx(&self) -> TyCtxt<'tcx> {
897 self.tcx
898 }
899
900 fn fold_binder<T>(&mut self, t: ty::Binder<'tcx, T>) -> ty::Binder<'tcx, T>
901 where
902 T: TypeFoldable<TyCtxt<'tcx>>,
903 {
904 self.binder.shift_in(1);
905 let result = t.super_fold_with(self);
906 self.binder.shift_out(1);
907 result
908 }
909
910 fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
911 if let ty::ReBound(ty::BoundVarIndexKind::Bound(debruijn), _) = r.kind()
912 && debruijn < self.binder
913 {
914 r
915 } else {
916 self.tcx.lifetimes.re_erased
917 }
918 }
919}
920
921fn contains_illegal_impl_trait_in_trait<'tcx>(
922 tcx: TyCtxt<'tcx>,
923 fn_def_id: DefId,
924 ty: ty::Binder<'tcx, Ty<'tcx>>,
925) -> Option<MethodViolation> {
926 let ty = tcx.liberate_late_bound_regions(fn_def_id, ty);
927
928 if tcx.asyncness(fn_def_id).is_async() {
929 Some(MethodViolation::AsyncFn)
931 } else {
932 ty.visit_with(&mut IllegalRpititVisitor { tcx, allowed: None }).break_value()
933 }
934}
935
936struct IllegalRpititVisitor<'tcx> {
937 tcx: TyCtxt<'tcx>,
938 allowed: Option<ty::AliasTy<'tcx>>,
939}
940
941impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for IllegalRpititVisitor<'tcx> {
942 type Result = ControlFlow<MethodViolation>;
943
944 fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
945 if let ty::Alias(proj @ ty::AliasTy { kind: ty::Projection { def_id }, .. }) = *ty.kind()
946 && Some(proj) != self.allowed
947 && self.tcx.is_impl_trait_in_trait(def_id)
948 {
949 ControlFlow::Break(MethodViolation::ReferencesImplTraitInTrait(
950 self.tcx.def_span(def_id),
951 ))
952 } else {
953 ty.super_visit_with(self)
954 }
955 }
956}
957
958pub(crate) fn provide(providers: &mut Providers) {
959 *providers = Providers {
960 dyn_compatibility_violations,
961 is_dyn_compatible,
962 generics_require_sized_self,
963 ..*providers
964 };
965}