Skip to main content

rustc_lint/ferrocene/
dynamic_casts.rs

1use std::ops::ControlFlow;
2
3use rustc_abi::{FieldIdx, VariantIdx};
4use rustc_hir::LangItem;
5use rustc_hir::def_id::DefId;
6use rustc_infer::traits::{
7    ImplSourceUserDefinedData, Obligation, ObligationCause, ObligationCauseCode,
8};
9use rustc_middle::middle::codegen_fn_attrs::ferrocene::item_is_validated;
10use rustc_middle::span_bug;
11use rustc_middle::ty::adjustment::CustomCoerceUnsized;
12use rustc_middle::ty::{
13    self, ExistentialPredicate, GenericArgsRef, Instance, PolyTraitRef, ShimKind, Ty, TyCtxt,
14    TypeSuperVisitable as _, TypeVisitable as _, TypingEnv, Unnormalized,
15};
16use rustc_span::Span;
17use rustc_trait_selection::traits::{ObligationCtxt, SelectionContext, supertraits};
18use tracing::{debug, instrument};
19
20use super::UnvalidatedImplCause;
21use crate::ferrocene::{InstantiateResult, LintState, UseKind};
22
23type ImplSource<'tcx> = rustc_infer::traits::ImplSource<'tcx, Span>;
24
25impl<'tcx> LintState<'tcx> {
26    pub(super) fn check_fn_ptr_coercion(
27        &self,
28        source: Ty<'tcx>,
29        dst_trait: PolyTraitRef<'tcx>,
30        try_instantiate: &mut impl FnMut(DefId, GenericArgsRef<'tcx>) -> InstantiateResult<'tcx>,
31        span: Span,
32    ) -> Option<UseKind<'tcx>> {
33        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_lint/src/ferrocene/dynamic_casts.rs:33",
                        "rustc_lint::ferrocene::dynamic_casts",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_lint/src/ferrocene/dynamic_casts.rs"),
                        ::tracing_core::__macro_support::Option::Some(33u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_lint::ferrocene::dynamic_casts"),
                        ::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};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("check cast of {0:?} to function pointer",
                                                    source) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("check cast of {source:?} to function pointer");
34        let tcx = self.tcx;
35
36        match self.instance_of_ty(source, Some(dst_trait), try_instantiate, span) {
37            Some(instance) => {
38                if #[allow(non_exhaustive_omitted_patterns)] match instance.def {
    ty::InstanceKind::Virtual(..) => true,
    _ => false,
}matches!(instance.def, ty::InstanceKind::Virtual(..)) {
39                    // This is a `<dyn Trait>::method as fn()` cast.
40                    // That shim is synthesized and therefore covered under the compiler
41                    // qualification. It can't be called unless someone gets a `dyn Trait`, in which
42                    // case we'll lint the unsizing cast.
43                    None
44                } else if item_is_validated(tcx, instance.def_id()).validated() {
45                    None
46                } else {
47                    Some(UseKind::FnPtrCast(instance))
48                }
49            }
50            // Uncaught fn pointer casts are ok because the post-mono pass will check them later.
51            // FIXME: this is messy, split this out into `check_dyn_trait_coercion`
52            None if Some(dst_trait.def_id()) == tcx.lang_items().fn_ptr_trait() => None,
53            // FIXME: feature(unboxed_closures)
54            None if source.is_adt() => None,
55            // Don't remove this panic. If you do so before adding `check_dyn_trait_coercion` to
56            // the post-mono pass, it will fail to catch real uses of unvalidated items in
57            // non-degenerate programs.
58            None => ::rustc_middle::util::bug::span_bug_fmt(span,
    format_args!("unimplemented: pre-mono cast from {0} to dyn {1}() that fails to instantiate",
        source, dst_trait))span_bug!(
59                span,
60                "unimplemented: pre-mono cast from {source} to dyn {dst_trait}() that fails to instantiate"
61            ),
62        }
63    }
64
65    /// Given a `source` expression that has an unsizing cast to `dest`, determine
66    /// whether the cast is valid. If not, return a [`TraitObjectCast`](UseKind::TraitObjectCast) showing why not.
67    ///
68    /// This works in four main parts:
69    /// 1. "Peel" as many types as possible. For example, if we are casting `Vec<Box<String>>` to
70    ///    `Vec<Box<dyn Display + Clone + Sync>`, peel that to `String` and
71    ///    `dyn Display + Clone + Sync`. We call these `coerce_src` and `coerce_dst`.
72    /// 2. Determine all traits in `dest`'s type that have at least one method. For example,
73    ///    `dyn Display + Clone + Sync` contains the traits `Display` and `Clone`.
74    /// 3. For each trait, find `coerce_src`'s implementation of it. For example,
75    ///    `impl Display for String`.
76    /// 4. For each method in the impl, check whether it's validated. For example, we would check
77    ///    `<String as Diplay>::fmt`, see that it's unvalidated, and return its `DefId` in the
78    ///    `UseKind`.
79    x;#[instrument(skip(self, try_instantiate, span), ret)]
80    pub(super) fn check_dyn_trait_coercion(
81        &self,
82        dest_ty: Ty<'tcx>,
83        source_ty: Ty<'tcx>,
84        typing_env: TypingEnv<'tcx>,
85        try_instantiate: &mut impl FnMut(DefId, GenericArgsRef<'tcx>) -> InstantiateResult<'tcx>,
86        span: Span,
87    ) -> Option<UseKind<'tcx>> {
88        let tcx = self.tcx;
89
90        let (coerce_src, coerce_dst) =
91            self.peel_unsized_tys(source_ty, dest_ty, typing_env, span)?;
92        debug!(
93            "saw unsized coercion from {source_ty:?} -> {dest_ty:?} (peeled: {coerce_src:?} -> {coerce_dst:?})",
94        );
95
96        if matches!(coerce_src.kind(), ty::Dynamic(..) | ty::FnPtr(..)) {
97            // upcasting from a `dyn Trait` to a `dyn SuperTrait`.
98            // We already checked this when we originally cast to `dyn Trait`.
99            return None;
100        }
101
102        let bound_traits = self.dyn_trait_refs(coerce_src, coerce_dst);
103        // NOTE: this only checks functions directly on the `trait_ref`.
104        // Supertraits are already handled in `dyn_trait_refs` as a separate trait.
105        for trait_ref in bound_traits {
106            // First, check if we are casting to a `dyn Fn*` trait.
107            // If so, this is disallowed no matter what, for the same reason as casting
108            // to a function pointer.
109            if tcx.fn_trait_kind_from_def_id(trait_ref.def_id()).is_some() {
110                if let Some(use_) =
111                    self.check_fn_ptr_coercion(coerce_src, trait_ref, try_instantiate, span)
112                {
113                    return Some(use_);
114                } else {
115                    continue;
116                }
117            }
118
119            if tcx
120                .associated_item_def_ids(trait_ref.def_id())
121                .iter()
122                .find(|&id| tcx.def_kind(*id).is_fn_like())
123                .is_none()
124            {
125                // not possible to call any functions on this trait object, casting is always ok.
126                continue;
127            };
128            let impl_ = self.find_trait_impl(trait_ref, typing_env, span);
129
130            match impl_ {
131                ImplSource::UserDefined(ImplSourceUserDefinedData {
132                    impl_def_id,
133                    args: _,
134                    nested: _,
135                }) => {
136                    // This function in the impl needs to be marked with `prevalidated`.
137                    if let Some(impl_fn) = self.find_unvalidated_impl_fn(impl_def_id) {
138                        return Some(UseKind::TraitObjectCast(
139                            UnvalidatedImplCause::AssocFn(impl_fn),
140                            coerce_src,
141                        ));
142                    }
143                }
144                // builtin impls are always ok
145                ImplSource::Builtin(..) => continue,
146                ImplSource::Param(_obligations) => {
147                    // This is something like the following:
148                    // ```
149                    // fn foo<T: Display + 'static>(x: T) -> Box<dyn Display> {
150                    //     Box::new(x)
151                    // }
152                    // ```
153                    // We can't resolve `x.fmt` until post-mono, so we can't point to the reason
154                    // the cast is disallowed.
155
156                    // NOTE: this can give an empty list of obligations in weird cases like
157                    // `core::mem::DiscriminantKind`, which is automatically implemented for any Sized type.
158                    return Some(UseKind::TraitObjectCast(
159                        UnvalidatedImplCause::UnresolvedGenericImpl(trait_ref),
160                        coerce_src,
161                    ));
162                }
163            }
164        }
165        None
166    }
167
168    /// Given a call to a function-like type, return the instantiated function definition,
169    /// or `None` if we can't find it until it's been monomorphized.
170    ///
171    /// Panics if given a type that isn't callable.
172    pub(super) fn instance_of_ty(
173        &self,
174        ty: Ty<'tcx>,
175        fn_trait_ref: Option<PolyTraitRef<'tcx>>,
176        try_instantiate: &mut impl FnMut(DefId, GenericArgsRef<'tcx>) -> InstantiateResult<'tcx>,
177        span: Span,
178    ) -> Option<Instance<'tcx>> {
179        let tcx = self.tcx;
180
181        match ty.kind() {
182            ty::FnDef(maybe_trait_fn, generic_args) => {
183                // Indeterminate results are handled later by a post-mono pass that checks the
184                // instantiation is validated. For now just ignore errors.
185                try_instantiate(*maybe_trait_fn, generic_args.no_bound_vars().unwrap()).instance()
186            }
187            ty::Closure(def_id, args) => {
188                Some(Instance::resolve_closure(tcx, *def_id, args, ty::ClosureKind::FnOnce))
189            }
190            ty::CoroutineClosure(def_id, args) => {
191                let coroutine_closure_def_id = *def_id;
192                // See comment in `rustc_ty_utils::instance::resolve_associated_item`.
193                let instance = if ty::ClosureKind::FnOnce == args.as_coroutine_closure().kind() {
194                    Instance::new_raw(coroutine_closure_def_id, args)
195                } else {
196                    let trait_id = fn_trait_ref.unwrap().def_id();
197                    let target_kind = tcx.fn_trait_kind_from_def_id(trait_id).unwrap();
198                    Instance {
199                        def: ty::InstanceKind::Shim(ShimKind::ConstructCoroutineInClosure {
200                            coroutine_closure_def_id,
201                            receiver_by_ref: target_kind != ty::ClosureKind::FnOnce,
202                        }),
203                        args,
204                    }
205                };
206                Some(instance)
207            }
208            // FIXME: `feature(unboxed_closures)`.
209            // Right now we just ignore `fn_trait_ref`, but it's passed in here so that we can call
210            // `find_trait_impl(fn_trait_ref.with_self_ty(ty)`.
211            ty::Adt(..) => None,
212            // Reference to a function or function pointer.
213            ty::Ref(_, ty, _) => self.instance_of_ty(*ty, fn_trait_ref, try_instantiate, span),
214            // We assume that all functions pointers are valid. Proof:
215            // 1. If the function was validated, no problem.
216            // 2. If the function was unvalidated, and is a literal or assigned to a local
217            //    variable, then either:
218            //    - We can resolve it to a concrete instance, in which case we would have caught it in `ZstLiteral` above.
219            //    - We can't resolve it yet, but it stays a unique function type, so we will
220            //    catch the call later in the post-mono pass.
221            //    - We can't resolve it yet and it's cast to a function pointer so we don't
222            //    have enough info to catch it post-mono when it's called. In this case we
223            //    catch it in `ReifyFnPtr` above.
224            // 3. If the function was passed as an argument, then either:
225            //   - We were called by an unvalidated function. No problem.
226            //   - We were called by a validated function. This lint will run on that
227            //   function too, and we will catch it there at the time it is checked /
228            //   monomorphized.
229            // 4. If this is a closure then either:
230            //   - It was defined in this function, in which case we treat it as also
231            //   validated.
232            //   - It was passed as an argument, which is ok by 3).
233            //   - It is a global const/static, so we catch it in `NamedConst`/`StaticRef` above.
234            ty::FnPtr(..) => None,
235            other => ::rustc_middle::util::bug::span_bug_fmt(span,
    format_args!("unsupported call kind {0:?}", other))span_bug!(span, "unsupported call kind {other:?}"),
236        }
237    }
238
239    /// Given an `Unsize` coersion from `src_ty` to `dst_ty`, return the innermost "difference"
240    /// between the two. Returns `None` if this isn't a cast to a trait object.
241    ///
242    /// This is quite similar to `struct_lockstep_tails_for_codegen`, except it considers all ZSTs,
243    /// not just those at the tail.
244    ///
245    /// c.f. [Zulip](https://rust-lang.zulipchat.com/#narrow/channel/182449-t-compiler.2Fhelp/topic/Get.20a.20type's.20impl.20for.20a.20trait/with/570837962)
246    ///
247    /// See [`CoerceUnsized`](https://doc.rust-lang.org/std/ops/trait.CoerceUnsized.html) for a full
248    /// list of types we need to handle here.
249    ///
250    /// This is adapted from `rustc_monomorphize::collector::find_tails_for_unsizing`.
251    fn peel_unsized_tys(
252        &self,
253        src_ty: Ty<'tcx>,
254        dst_ty: Ty<'tcx>,
255        typing_env: TypingEnv<'tcx>,
256        span: Span,
257    ) -> Option<(Ty<'tcx>, Ty<'tcx>)> {
258        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_lint/src/ferrocene/dynamic_casts.rs:258",
                        "rustc_lint::ferrocene::dynamic_casts",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_lint/src/ferrocene/dynamic_casts.rs"),
                        ::tracing_core::__macro_support::Option::Some(258u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_lint::ferrocene::dynamic_casts"),
                        ::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};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("unsize_ptr: {0:?} => {1:?}",
                                                    src_ty, dst_ty) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("unsize_ptr: {:?} => {:?}", src_ty, dst_ty);
259
260        let tcx = self.tcx;
261        let (mut src_inner, mut dst_inner) = (src_ty, dst_ty);
262
263        let get_adt_field = |adt_def: ty::AdtDef<'_>, args, idx: FieldIdx| {
264            let variant = adt_def.variant(VariantIdx::ZERO);
265            let field_ty = variant.fields[idx].ty(tcx, args).skip_norm_wip();
266            tcx.normalize_erasing_regions(typing_env, Unnormalized::new(field_ty))
267        };
268
269        loop {
270            {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_lint/src/ferrocene/dynamic_casts.rs:270",
                        "rustc_lint::ferrocene::dynamic_casts",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_lint/src/ferrocene/dynamic_casts.rs"),
                        ::tracing_core::__macro_support::Option::Some(270u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_lint::ferrocene::dynamic_casts"),
                        ::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};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("peel_tys step: src={0:?}, dst={1:?}",
                                                    src_inner, dst_inner) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("peel_tys step: src={src_inner:?}, dst={dst_inner:?}");
271            match (src_inner.kind(), dst_inner.kind()) {
272                /* End conditions. */
273                (_, ty::Dynamic(..)) => return Some((src_inner, dst_inner)),
274                // There's only ever one unsizing coercion at once.
275                // Even if this is a `[dyn Trait; N]`, we would have checked it earlier.
276                // Return now so we don't crash trying to prove that the array implements `Trait`.
277                (ty::Array(..), ty::Slice(..)) => return None,
278
279                /* We've finished handling CoerceUnsized; now handle Unsize.
280                 * From here onward, the only thing we'll ever hit in the loop is `Dynamic` or
281                 * `Array` (handled above). */
282                (ty::Ref(_, a, _), ty::Ref(_, b, _)) | (ty::RawPtr(a, _), ty::RawPtr(b, _)) => {
283                    (src_inner, dst_inner) =
284                        tcx.struct_lockstep_tails_for_codegen(*a, *b, typing_env);
285                }
286
287                /* Handle CoerceUnsized.
288                 * This is the only part of the loop that recurses more than once. */
289                (ty::Pat(a, _), ty::Pat(b, _)) => {
290                    (src_inner, dst_inner) = (*a, *b);
291                }
292
293                (ty::Adt(src_def, src_args), ty::Adt(dst_def, dst_args)) => {
294                    {
    match (&src_def.did(), &dst_def.did()) {
        (left_val, right_val) => {
            if !(*left_val == *right_val) {
                let kind = ::core::panicking::AssertKind::Eq;
                ::core::panicking::assert_failed(kind, &*left_val,
                    &*right_val, ::core::option::Option::None);
            }
        }
    }
};assert_eq!(src_def.did(), dst_def.did());
295
296                    if let Some(boxed) = src_inner.boxed_ty() {
297                        src_inner = boxed;
298                        dst_inner = dst_inner.boxed_ty().unwrap();
299                        continue;
300                    }
301
302                    let field = match self.custom_coerce_unsize_info(src_inner, dst_inner, span) {
303                        Some(CustomCoerceUnsized::Struct(idx)) => idx,
304                        None => {
305                            // Iterate this struct looking for a `!Sized` field.
306                            let mut unsized_field = None;
307                            for (idx, def) in
308                                dst_def.variant(VariantIdx::ZERO).fields.iter_enumerated()
309                            {
310                                if !def.ty(tcx, dst_args).skip_norm_wip().is_sized(tcx, typing_env)
311                                {
312                                    unsized_field = Some(idx);
313                                    break;
314                                }
315                            }
316                            unsized_field.unwrap_or_else(|| {
317                                ::rustc_middle::util::bug::span_bug_fmt(span,
    format_args!("Adt with no CoerceUnsized impl and no !Sized field? {0:?}",
        dst_inner));span_bug!(span, "Adt with no CoerceUnsized impl and no !Sized field? {dst_inner:?}");
318                            })
319                        }
320                    };
321                    src_inner = get_adt_field(*src_def, src_args, field);
322                    dst_inner = get_adt_field(*dst_def, dst_args, field);
323                }
324                _ => ::rustc_middle::util::bug::span_bug_fmt(span,
    format_args!("mismatched types trying to coerce from {0:?} to {1:?}",
        src_ty, dst_ty))span_bug!(
325                    span,
326                    "mismatched types trying to coerce from {src_ty:?} to {dst_ty:?}"
327                ),
328            }
329        }
330    }
331
332    // copied from rustc_monomorphize
333    fn custom_coerce_unsize_info(
334        &self,
335        source_ty: Ty<'tcx>,
336        target_ty: Ty<'tcx>,
337        span: Span,
338    ) -> Option<CustomCoerceUnsized> {
339        let tcx = self.tcx;
340        let trait_ref = ty::TraitRef::new(
341            tcx,
342            tcx.require_lang_item(LangItem::CoerceUnsized, span),
343            [source_ty, target_ty],
344        );
345
346        match tcx.codegen_select_candidate(
347            ty::TypingEnv::fully_monomorphized().as_query_input(trait_ref),
348        ) {
349            Ok(rustc_infer::traits::ImplSource::UserDefined(ImplSourceUserDefinedData {
350                impl_def_id,
351                ..
352            })) => Some(tcx.coerce_unsized_info(*impl_def_id).unwrap().custom_kind.unwrap()),
353            _ => None,
354        }
355    }
356
357    /// Given an `impl`, find the first associated function that isn't validated.
358    ///
359    /// FIXME: list all unvalidated functions, not just the first.
360    fn find_unvalidated_impl_fn(&self, impl_block: DefId) -> Option<DefId> {
361        let tcx = self.tcx;
362
363        let trait_to_impl_map = tcx.impl_item_implementor_ids(impl_block);
364        for trait_item in tcx.associated_item_def_ids(tcx.impl_trait_id(impl_block)) {
365            {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_lint/src/ferrocene/dynamic_casts.rs:365",
                        "rustc_lint::ferrocene::dynamic_casts",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_lint/src/ferrocene/dynamic_casts.rs"),
                        ::tracing_core::__macro_support::Option::Some(365u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_lint::ferrocene::dynamic_casts"),
                        ::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};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("considering {0:?}",
                                                    trait_item) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("considering {trait_item:?}");
366            if !tcx.def_kind(*trait_item).is_fn_like() {
367                {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_lint/src/ferrocene/dynamic_casts.rs:367",
                        "rustc_lint::ferrocene::dynamic_casts",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_lint/src/ferrocene/dynamic_casts.rs"),
                        ::tracing_core::__macro_support::Option::Some(367u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_lint::ferrocene::dynamic_casts"),
                        ::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};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("ignoring non-fn {0:?}",
                                                    trait_item) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("ignoring non-fn {trait_item:?}");
368                continue;
369            }
370
371            // Need this map so we consider default trait fns even if they're not mentioned in the
372            // impl block.
373            let impl_fn = *trait_to_impl_map.get(trait_item).unwrap_or(trait_item);
374
375            if item_is_validated(tcx, impl_fn).validated() {
376                continue;
377            }
378
379            {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_lint/src/ferrocene/dynamic_casts.rs:379",
                        "rustc_lint::ferrocene::dynamic_casts",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_lint/src/ferrocene/dynamic_casts.rs"),
                        ::tracing_core::__macro_support::Option::Some(379u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_lint::ferrocene::dynamic_casts"),
                        ::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};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("found unvalidated method {0:?}",
                                                    impl_fn) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("found unvalidated method {impl_fn:?}");
380            // This function in the impl needs to be marked with `prevalidated`.
381            return Some(impl_fn);
382        }
383        return None;
384    }
385
386    fn find_trait_impl(
387        &self,
388        trait_ref: PolyTraitRef<'tcx>,
389        typing_env: TypingEnv<'tcx>,
390        span: Span,
391    ) -> ImplSource<'tcx> {
392        match self.try_find_trait_impl(trait_ref, typing_env, span) {
393            Some(found) => found,
394            None => ::rustc_middle::util::bug::span_bug_fmt(span,
    format_args!("failed to resolve impl: {0:?}", trait_ref))span_bug!(span, "failed to resolve impl: {trait_ref:?}"),
395        }
396    }
397
398    /// Given a `Trait<Ty>` reference, find `impl Trait for Ty`.
399    ///
400    /// This calls into the [trait solver] to select a suitable impl block.
401    ///
402    /// c.f. [`hax::exporter::traits::resolution::shallow_resolve_trait_ref`](https://github.com/AeneasVerif/hax/blob/3c2b6f01af4a4362dd855b811aa910ad173d546f/frontend/exporter/src/traits/resolution.rs#L666)
403    ///
404    /// Ideally, this would never return None, but sometimes our code is buggy ... failures here
405    /// only degrade the diagnostic, they don't cause soundness issues.
406    ///
407    /// [trait solver]: https://rustc-dev-guide.rust-lang.org/traits/resolution.html
408    fn try_find_trait_impl(
409        &self,
410        trait_ref: PolyTraitRef<'tcx>,
411        typing_env: TypingEnv<'tcx>,
412        span: Span,
413    ) -> Option<ImplSource<'tcx>> {
414        use rustc_infer::infer::TyCtxtInferExt;
415
416        let tcx = self.tcx;
417        let (infcx, param_env) =
418            tcx.infer_ctxt().ignoring_regions().build_with_typing_env(typing_env);
419        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_lint/src/ferrocene/dynamic_casts.rs:419",
                        "rustc_lint::ferrocene::dynamic_casts",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_lint/src/ferrocene/dynamic_casts.rs"),
                        ::tracing_core::__macro_support::Option::Some(419u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_lint::ferrocene::dynamic_casts"),
                        ::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};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("resolving impl for {0:?}",
                                                    trait_ref) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("resolving impl for {trait_ref:?}");
420
421        // Find the impl block.
422        let mut selcx = SelectionContext::new(&infcx);
423        let cause = ObligationCause::new(span, self.item, ObligationCauseCode::ExprAssignable);
424        // Normalize the trait ref.
425        let trait_ref = tcx.normalize_erasing_regions(typing_env, Unnormalized::new(trait_ref));
426        // method selection doesn't care about regions.
427        let trait_ref = tcx.instantiate_bound_regions_with_erased(trait_ref);
428        let obligation = Obligation::new(tcx, cause, param_env, trait_ref);
429        let selection = match selcx.select(&obligation) {
430            Ok(selection) => selection?,
431            Err(e) => {
432                {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_lint/src/ferrocene/dynamic_casts.rs:432",
                        "rustc_lint::ferrocene::dynamic_casts",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_lint/src/ferrocene/dynamic_casts.rs"),
                        ::tracing_core::__macro_support::Option::Some(432u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_lint::ferrocene::dynamic_casts"),
                        ::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};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("type checking failed for trait upcast? {0:?}",
                                                    e) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("type checking failed for trait upcast? {e:?}");
433                return None;
434            }
435        };
436        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_lint/src/ferrocene/dynamic_casts.rs:436",
                        "rustc_lint::ferrocene::dynamic_casts",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_lint/src/ferrocene/dynamic_casts.rs"),
                        ::tracing_core::__macro_support::Option::Some(436u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_lint::ferrocene::dynamic_casts"),
                        ::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};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("selected {0:?}",
                                                    selection) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("selected {selection:?}");
437
438        // Sanity check: make sure all `where` clauses on our `impl` are upheld.
439        let ocx = ObligationCtxt::new(&infcx);
440        let impl_source = selection.map(|o| {
441            {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_lint/src/ferrocene/dynamic_casts.rs:441",
                        "rustc_lint::ferrocene::dynamic_casts",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_lint/src/ferrocene/dynamic_casts.rs"),
                        ::tracing_core::__macro_support::Option::Some(441u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_lint::ferrocene::dynamic_casts"),
                        ::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};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("registering obligation {0:?}",
                                                    o) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("registering obligation {o:?}");
442            let span = o.cause.span;
443            ocx.register_obligation(o);
444            span
445        });
446        let errors = ocx.evaluate_obligations_error_on_ambiguity();
447        if !errors.is_empty() {
448            {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_lint/src/ferrocene/dynamic_casts.rs:448",
                        "rustc_lint::ferrocene::dynamic_casts",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_lint/src/ferrocene/dynamic_casts.rs"),
                        ::tracing_core::__macro_support::Option::Some(448u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_lint::ferrocene::dynamic_casts"),
                        ::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};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("impl obligations not met for trait upcast: {0:?}",
                                                    errors) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("impl obligations not met for trait upcast: {errors:?}");
449            return None;
450        }
451
452        let normalized_impl =
453            tcx.erase_and_anonymize_regions(infcx.resolve_vars_if_possible(impl_source));
454        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_lint/src/ferrocene/dynamic_casts.rs:454",
                        "rustc_lint::ferrocene::dynamic_casts",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_lint/src/ferrocene/dynamic_casts.rs"),
                        ::tracing_core::__macro_support::Option::Some(454u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_lint::ferrocene::dynamic_casts"),
                        ::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};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("found impl {0:?}",
                                                    normalized_impl) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("found impl {normalized_impl:?}");
455        Some(normalized_impl)
456    }
457
458    /// Given a Rust type, find (at any level of nesting) `dyn Trait` objects contained within it that
459    /// have at least one method.
460    /// For example, `dyn Send + Sync + Display + Clone` would return `[Display, Clone]`.
461    fn dyn_trait_refs(
462        &self,
463        source_ty: Ty<'tcx>,
464        dst_ty: Ty<'tcx>,
465    ) -> Vec<ty::Binder<'tcx, ty::TraitRef<'tcx>>> {
466        struct FindDynTraitVisitor<'tcx>(TyCtxt<'tcx>, Ty<'tcx>);
467
468        impl<'tcx> ty::TypeVisitor<TyCtxt<'tcx>> for FindDynTraitVisitor<'tcx> {
469            type Result = ControlFlow<Vec<ty::Binder<'tcx, ty::TraitRef<'tcx>>>>;
470
471            fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
472                match t.kind() {
473                    ty::Dynamic(bound_predicates, _lifetime) => {
474                        let mut traits = ::alloc::vec::Vec::new()vec![];
475                        for predicate in *bound_predicates {
476                            {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_lint/src/ferrocene/dynamic_casts.rs:476",
                        "rustc_lint::ferrocene::dynamic_casts",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_lint/src/ferrocene/dynamic_casts.rs"),
                        ::tracing_core::__macro_support::Option::Some(476u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_lint::ferrocene::dynamic_casts"),
                        ::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};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("considering {0:?}",
                                                    predicate) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("considering {predicate:?}");
477                            let trait_ = predicate
478                                .map_bound(|p| match p {
479                                    // auto traits do not allow calling methods
480                                    ExistentialPredicate::AutoTrait(_) => None,
481                                    // We don't care about associated type bounds.
482                                    // They restrict which impl is selected, but that's all they do.
483                                    // We already require the implementation of the trait to be validated
484                                    // (that's the `Trait` predicate below), so which impl gets picked
485                                    // doesn't matter as long we know which one it is.
486                                    ExistentialPredicate::Projection(_) => None,
487                                    ExistentialPredicate::Trait(t) => Some(t),
488                                })
489                                .transpose();
490                            if let Some(t) = trait_ {
491                                let t = t.with_self_ty(self.0, self.1);
492                                traits.push(t);
493                                traits.extend(supertraits(self.0, t));
494                            }
495                        }
496                        // FIXME: is it possible to have multiple Dynamic types in a single top-level
497                        // type? how? maybe with an enum?
498                        ControlFlow::Break(traits)
499                    }
500                    _ => t.super_visit_with(self),
501                }
502            }
503        }
504
505        let cf = dst_ty.visit_with(&mut FindDynTraitVisitor(self.tcx, source_ty));
506        cf.break_value().unwrap_or_default()
507    }
508}