Skip to main content

rustc_hir_analysis/coherence/
orphan.rs

1//! Orphan checker: every impl either implements a trait defined in this
2//! crate or pertains to a type defined in this crate.
3
4use rustc_data_structures::fx::FxIndexSet;
5use rustc_errors::ErrorGuaranteed;
6use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, TyCtxtInferExt};
7use rustc_lint_defs::builtin::UNCOVERED_PARAM_IN_PROJECTION;
8use rustc_middle::ty::{
9    self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode,
10    Unnormalized,
11};
12use rustc_span::def_id::{DefId, LocalDefId};
13use rustc_span::{bug, span_bug};
14use rustc_trait_selection::traits::{
15    self, IsFirstInputType, OrphanCheckErr, OrphanCheckMode, UncoveredTyParams,
16};
17use tracing::{debug, instrument};
18
19use crate::diagnostics;
20
21{}
#[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() ||
            { false } {
        __tracing_attr_span =
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("orphan_check_impl",
                                    "rustc_hir_analysis::coherence::orphan",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("/rustc-dev/3ef0c22cdb86ac42dc6b8f0f1ec36857daa6f2a1/compiler/rustc_hir_analysis/src/coherence/orphan.rs"),
                                    ::tracing_core::__macro_support::Option::Some(21u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::coherence::orphan"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("impl_def_id")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("impl_def_id");
                                                        NAME.as_str()
                                                    }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            { interest = __CALLSITE.interest(); !interest.is_never() }
                        &&
                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                            interest) {
                    let meta = __CALLSITE.metadata();
                    ::tracing::Span::new(meta,
                        &{
                                #[allow(unused_imports)]
                                use ::tracing::field::{debug, display, Value};
                                meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&impl_def_id)
                                                            as &dyn ::tracing::field::Value))])
                            })
                } else {
                    let span =
                        ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                    {};
                    span
                }
            };
        __tracing_attr_guard = __tracing_attr_span.enter();
    }

    #[warn(clippy :: suspicious_else_formatting)]
    {

        #[allow(unknown_lints, unreachable_code, clippy ::
        diverging_sub_expression, clippy :: empty_loop, clippy ::
        let_unit_value, clippy :: let_with_type_underscore, clippy ::
        needless_return, clippy :: unreachable)]
        if false {
            let __tracing_attr_fake_return: Result<(), ErrorGuaranteed> =
                loop {};
            return __tracing_attr_fake_return;
        }
        {
            let trait_ref =
                tcx.impl_trait_ref(impl_def_id).instantiate_identity().skip_norm_wip();
            trait_ref.error_reported()?;
            match orphan_check(tcx, impl_def_id, OrphanCheckMode::Proper) {
                Ok(()) => {}
                Err(err) =>
                    match orphan_check(tcx, impl_def_id,
                            OrphanCheckMode::Compat) {
                        Ok(()) =>
                            match err {
                                OrphanCheckErr::UncoveredTyParams(uncovered_ty_params) => {
                                    let hir_id = tcx.local_def_id_to_hir_id(impl_def_id);
                                    for param_def_id in uncovered_ty_params.uncovered {
                                        let ident = tcx.item_ident(param_def_id);
                                        tcx.emit_node_span_lint(UNCOVERED_PARAM_IN_PROJECTION,
                                            hir_id, ident.span,
                                            diagnostics::UncoveredTyParam {
                                                param: ident,
                                                local_ty: uncovered_ty_params.local_ty,
                                            });
                                    }
                                }
                                OrphanCheckErr::NonLocalInputType(_) => {
                                    ::rustc_span::macros::bug_impl(None,
                                        format_args!("orphanck: shouldn\'t\'ve gotten non-local input tys in compat mode"),
                                        Location::caller())
                                }
                            },
                        Err(err) =>
                            return Err(emit_orphan_check_error(tcx, trait_ref,
                                        impl_def_id, err)),
                    },
            }
            let trait_def_id = trait_ref.def_id;
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("event /rustc-dev/3ef0c22cdb86ac42dc6b8f0f1ec36857daa6f2a1/compiler/rustc_hir_analysis/src/coherence/orphan.rs:92",
                                    "rustc_hir_analysis::coherence::orphan",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("/rustc-dev/3ef0c22cdb86ac42dc6b8f0f1ec36857daa6f2a1/compiler/rustc_hir_analysis/src/coherence/orphan.rs"),
                                    ::tracing_core::__macro_support::Option::Some(92u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::coherence::orphan"),
                                    ::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!("trait_ref={0:?} trait_def_id={1:?} trait_is_auto={2}",
                                                                trait_ref, trait_def_id, tcx.trait_is_auto(trait_def_id)) as
                                                        &dyn ::tracing::field::Value))])
                        });
                } else { ; }
            };
            if tcx.trait_is_auto(trait_def_id) {
                let self_ty = tcx.expand_free_alias_tys(trait_ref.self_ty());
                enum LocalImpl {
                    Allow,
                    Disallow {
                        problematic_kind: &'static str,
                    },
                }
                enum NonlocalImpl {
                    Allow,
                    DisallowBecauseNonlocal,
                    DisallowOther,
                }
                let (local_impl, nonlocal_impl) =
                    match self_ty.kind() {
                        ty::Adt(self_def, _) =>
                            (LocalImpl::Allow,
                                if self_def.did().is_local() {
                                    NonlocalImpl::Allow
                                } else { NonlocalImpl::DisallowBecauseNonlocal }),
                        ty::Foreign(did) =>
                            (LocalImpl::Allow,
                                if did.is_local() {
                                    NonlocalImpl::Allow
                                } else { NonlocalImpl::DisallowBecauseNonlocal }),
                        ty::Dynamic(..) =>
                            (LocalImpl::Disallow { problematic_kind: "trait object" },
                                NonlocalImpl::DisallowOther),
                        ty::Param(..) =>
                            (if self_ty.is_sized(tcx,
                                        ty::TypingEnv::non_body_analysis(tcx, impl_def_id)) {
                                    LocalImpl::Allow
                                } else {
                                    LocalImpl::Disallow { problematic_kind: "generic type" }
                                }, NonlocalImpl::DisallowOther),
                        ty::Alias(_, ty::AliasTy { kind, .. }) => {
                            let problematic_kind =
                                match kind {
                                    ty::Projection { .. } => "associated type",
                                    ty::Free { .. } => "type alias",
                                    ty::Opaque { .. } => "opaque type",
                                    ty::Inherent { .. } => "associated type",
                                };
                            (LocalImpl::Disallow { problematic_kind },
                                NonlocalImpl::DisallowOther)
                        }
                        ty::Bool | ty::Pat(..) | ty::Char | ty::Int(..) |
                            ty::Uint(..) | ty::Float(..) | ty::Str | ty::Array(..) |
                            ty::Slice(..) | ty::RawPtr(..) | ty::Ref(..) | ty::FnPtr(..)
                            | ty::Never | ty::Tuple(..) | ty::UnsafeBinder(_) =>
                            (LocalImpl::Allow, NonlocalImpl::DisallowOther),
                        ty::FnDef(..) | ty::Closure(..) | ty::CoroutineClosure(..) |
                            ty::Coroutine(..) | ty::CoroutineWitness(..) | ty::Bound(..)
                            | ty::Placeholder(..) | ty::Infer(..) => {
                            let sp = tcx.def_span(impl_def_id);
                            ::rustc_span::macros::bug_impl(Some(sp),
                                format_args!("weird self type for autotrait impl"),
                                Location::caller())
                        }
                        ty::Error(..) => (LocalImpl::Allow, NonlocalImpl::Allow),
                    };
                if trait_def_id.is_local() {
                    match local_impl {
                        LocalImpl::Allow => {}
                        LocalImpl::Disallow { problematic_kind } => {
                            return Err(tcx.dcx().emit_err(diagnostics::TraitsWithDefaultImpl {
                                            span: tcx.def_span(impl_def_id),
                                            traits: tcx.def_path_str(trait_def_id),
                                            problematic_kind,
                                            self_ty,
                                        }));
                        }
                    }
                } else {
                    match nonlocal_impl {
                        NonlocalImpl::Allow => {}
                        NonlocalImpl::DisallowBecauseNonlocal => {
                            return Err(tcx.dcx().emit_err(diagnostics::CrossCrateTraitsDefined {
                                            span: tcx.def_span(impl_def_id),
                                            traits: tcx.def_path_str(trait_def_id),
                                        }));
                        }
                        NonlocalImpl::DisallowOther => {
                            return Err(tcx.dcx().emit_err(diagnostics::CrossCrateTraits {
                                            span: tcx.def_span(impl_def_id),
                                            traits: tcx.def_path_str(trait_def_id),
                                            self_ty,
                                        }));
                        }
                    }
                }
            }
            Ok(())
        }
    }
}#[instrument(level = "debug", skip(tcx))]
22pub(crate) fn orphan_check_impl(
23    tcx: TyCtxt<'_>,
24    impl_def_id: LocalDefId,
25) -> Result<(), ErrorGuaranteed> {
26    let trait_ref = tcx.impl_trait_ref(impl_def_id).instantiate_identity().skip_norm_wip();
27    trait_ref.error_reported()?;
28
29    match orphan_check(tcx, impl_def_id, OrphanCheckMode::Proper) {
30        Ok(()) => {}
31        Err(err) => match orphan_check(tcx, impl_def_id, OrphanCheckMode::Compat) {
32            Ok(()) => match err {
33                OrphanCheckErr::UncoveredTyParams(uncovered_ty_params) => {
34                    let hir_id = tcx.local_def_id_to_hir_id(impl_def_id);
35
36                    for param_def_id in uncovered_ty_params.uncovered {
37                        let ident = tcx.item_ident(param_def_id);
38
39                        tcx.emit_node_span_lint(
40                            UNCOVERED_PARAM_IN_PROJECTION,
41                            hir_id,
42                            ident.span,
43                            diagnostics::UncoveredTyParam {
44                                param: ident,
45                                local_ty: uncovered_ty_params.local_ty,
46                            },
47                        );
48                    }
49                }
50                OrphanCheckErr::NonLocalInputType(_) => {
51                    bug!("orphanck: shouldn't've gotten non-local input tys in compat mode")
52                }
53            },
54            Err(err) => return Err(emit_orphan_check_error(tcx, trait_ref, impl_def_id, err)),
55        },
56    }
57
58    let trait_def_id = trait_ref.def_id;
59
60    // In addition to the above rules, we restrict impls of auto traits
61    // so that they can only be implemented on nominal types, such as structs,
62    // enums or foreign types. To see why this restriction exists, consider the
63    // following example (#22978). Imagine that crate A defines an auto trait
64    // `Foo` and a fn that operates on pairs of types:
65    //
66    // ```
67    // // Crate A
68    // auto trait Foo { }
69    // fn two_foos<A:Foo,B:Foo>(..) {
70    //     one_foo::<(A,B)>(..)
71    // }
72    // fn one_foo<T:Foo>(..) { .. }
73    // ```
74    //
75    // This type-checks fine; in particular the fn
76    // `two_foos` is able to conclude that `(A,B):Foo`
77    // because `A:Foo` and `B:Foo`.
78    //
79    // Now imagine that crate B comes along and does the following:
80    //
81    // ```
82    // struct A { }
83    // struct B { }
84    // impl Foo for A { }
85    // impl Foo for B { }
86    // impl !Foo for (A, B) { }
87    // ```
88    //
89    // This final impl is legal according to the orphan
90    // rules, but it invalidates the reasoning from
91    // `two_foos` above.
92    debug!(
93        "trait_ref={:?} trait_def_id={:?} trait_is_auto={}",
94        trait_ref,
95        trait_def_id,
96        tcx.trait_is_auto(trait_def_id)
97    );
98
99    if tcx.trait_is_auto(trait_def_id) {
100        let self_ty = tcx.expand_free_alias_tys(trait_ref.self_ty());
101
102        // If the impl is in the same crate as the auto-trait, almost anything
103        // goes.
104        //
105        //     impl MyAuto for Rc<Something> {}  // okay
106        //     impl<T> !MyAuto for *const T {}   // okay
107        //     impl<T> MyAuto for T {}           // okay
108        //
109        // But there is one important exception: implementing for a trait object
110        // is not allowed.
111        //
112        //     impl MyAuto for dyn Trait {}      // NOT OKAY
113        //     impl<T: ?Sized> MyAuto for T {}   // NOT OKAY
114        //
115        // With this restriction, it's guaranteed that an auto-trait is
116        // implemented for a trait object if and only if the auto-trait is one
117        // of the trait object's trait bounds (or a supertrait of a bound). In
118        // other words `dyn Trait + AutoTrait` always implements AutoTrait,
119        // while `dyn Trait` never implements AutoTrait.
120        //
121        // This is necessary in order for autotrait bounds on methods of trait
122        // objects to be sound.
123        //
124        //     auto trait AutoTrait {}
125        //
126        //     trait DynCompatibleTrait {
127        //         fn f(&self) where Self: AutoTrait;
128        //     }
129        //
130        // We can allow f to be called on `dyn DynCompatibleTrait + AutoTrait`.
131        //
132        // If we didn't deny `impl AutoTrait for dyn Trait`, it would be unsound
133        // for the `DynCompatibleTrait` shown above to be dyn-compatible because someone
134        // could take some type implementing `DynCompatibleTrait` but not `AutoTrait`,
135        // unsize it to `dyn DynCompatibleTrait`, and call `.f()` which has no
136        // concrete implementation (issue #50781).
137        enum LocalImpl {
138            Allow,
139            Disallow { problematic_kind: &'static str },
140        }
141
142        // If the auto-trait is from a dependency, it must only be getting
143        // implemented for a nominal type, and specifically one local to the
144        // current crate.
145        //
146        //     impl<T> Sync for MyStruct<T> {}   // okay
147        //
148        //     impl Sync for Rc<MyStruct> {}     // NOT OKAY
149        enum NonlocalImpl {
150            Allow,
151            DisallowBecauseNonlocal,
152            DisallowOther,
153        }
154
155        // Exhaustive match considering that this logic is essential for
156        // soundness.
157        let (local_impl, nonlocal_impl) = match self_ty.kind() {
158            // struct Struct<T>;
159            // impl AutoTrait for Struct<Foo> {}
160            ty::Adt(self_def, _) => (
161                LocalImpl::Allow,
162                if self_def.did().is_local() {
163                    NonlocalImpl::Allow
164                } else {
165                    NonlocalImpl::DisallowBecauseNonlocal
166                },
167            ),
168
169            // extern { type OpaqueType; }
170            // impl AutoTrait for OpaqueType {}
171            ty::Foreign(did) => (
172                LocalImpl::Allow,
173                if did.is_local() {
174                    NonlocalImpl::Allow
175                } else {
176                    NonlocalImpl::DisallowBecauseNonlocal
177                },
178            ),
179
180            // impl AutoTrait for dyn Trait {}
181            ty::Dynamic(..) => (
182                LocalImpl::Disallow { problematic_kind: "trait object" },
183                NonlocalImpl::DisallowOther,
184            ),
185
186            // impl<T> AutoTrait for T {}
187            // impl<T: ?Sized> AutoTrait for T {}
188            ty::Param(..) => (
189                if self_ty.is_sized(tcx, ty::TypingEnv::non_body_analysis(tcx, impl_def_id)) {
190                    LocalImpl::Allow
191                } else {
192                    LocalImpl::Disallow { problematic_kind: "generic type" }
193                },
194                NonlocalImpl::DisallowOther,
195            ),
196
197            ty::Alias(_, ty::AliasTy { kind, .. }) => {
198                let problematic_kind = match kind {
199                    // trait Id { type This: ?Sized; }
200                    // impl<T: ?Sized> Id for T {
201                    //     type This = T;
202                    // }
203                    // impl<T: ?Sized> AutoTrait for <T as Id>::This {}
204                    ty::Projection { .. } => "associated type",
205                    // type Foo = (impl Sized, bool)
206                    // impl AutoTrait for Foo {}
207                    ty::Free { .. } => "type alias",
208                    // type Opaque = impl Trait;
209                    // impl AutoTrait for Opaque {}
210                    ty::Opaque { .. } => "opaque type",
211                    // ```
212                    // struct S<T>(T);
213                    // impl<T: ?Sized> S<T> {
214                    //     type This = T;
215                    // }
216                    // impl<T: ?Sized> AutoTrait for S<T>::This {}
217                    // ```
218                    // FIXME(inherent_associated_types): The example code above currently leads to a cycle
219                    ty::Inherent { .. } => "associated type",
220                };
221                (LocalImpl::Disallow { problematic_kind }, NonlocalImpl::DisallowOther)
222            }
223
224            ty::Bool
225            | ty::Pat(..)
226            | ty::Char
227            | ty::Int(..)
228            | ty::Uint(..)
229            | ty::Float(..)
230            | ty::Str
231            | ty::Array(..)
232            | ty::Slice(..)
233            | ty::RawPtr(..)
234            | ty::Ref(..)
235            | ty::FnPtr(..)
236            | ty::Never
237            | ty::Tuple(..)
238            | ty::UnsafeBinder(_) => (LocalImpl::Allow, NonlocalImpl::DisallowOther),
239
240            ty::FnDef(..)
241            | ty::Closure(..)
242            | ty::CoroutineClosure(..)
243            | ty::Coroutine(..)
244            | ty::CoroutineWitness(..)
245            | ty::Bound(..)
246            | ty::Placeholder(..)
247            | ty::Infer(..) => {
248                let sp = tcx.def_span(impl_def_id);
249                span_bug!(sp, "weird self type for autotrait impl")
250            }
251
252            ty::Error(..) => (LocalImpl::Allow, NonlocalImpl::Allow),
253        };
254
255        if trait_def_id.is_local() {
256            match local_impl {
257                LocalImpl::Allow => {}
258                LocalImpl::Disallow { problematic_kind } => {
259                    return Err(tcx.dcx().emit_err(diagnostics::TraitsWithDefaultImpl {
260                        span: tcx.def_span(impl_def_id),
261                        traits: tcx.def_path_str(trait_def_id),
262                        problematic_kind,
263                        self_ty,
264                    }));
265                }
266            }
267        } else {
268            match nonlocal_impl {
269                NonlocalImpl::Allow => {}
270                NonlocalImpl::DisallowBecauseNonlocal => {
271                    return Err(tcx.dcx().emit_err(diagnostics::CrossCrateTraitsDefined {
272                        span: tcx.def_span(impl_def_id),
273                        traits: tcx.def_path_str(trait_def_id),
274                    }));
275                }
276                NonlocalImpl::DisallowOther => {
277                    return Err(tcx.dcx().emit_err(diagnostics::CrossCrateTraits {
278                        span: tcx.def_span(impl_def_id),
279                        traits: tcx.def_path_str(trait_def_id),
280                        self_ty,
281                    }));
282                }
283            }
284        }
285    }
286
287    Ok(())
288}
289
290/// Checks the coherence orphan rules.
291///
292/// `impl_def_id` should be the `DefId` of a trait impl.
293///
294/// To pass, either the trait must be local, or else two conditions must be satisfied:
295///
296/// 1. All type parameters in `Self` must be "covered" by some local type constructor.
297/// 2. Some local type must appear in `Self`.
298{}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL &&
            ::tracing::Level::DEBUG <=
                ::tracing::level_filters::LevelFilter::current() || { false }
    {
    __tracing_attr_span =
        {
            use ::tracing::__macro_support::Callsite as _;
            static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                {
                    static META: ::tracing::Metadata<'static> =
                        {
                            ::tracing_core::metadata::Metadata::new("orphan_check",
                                "rustc_hir_analysis::coherence::orphan",
                                ::tracing::Level::DEBUG,
                                ::tracing_core::__macro_support::Option::Some("/rustc-dev/3ef0c22cdb86ac42dc6b8f0f1ec36857daa6f2a1/compiler/rustc_hir_analysis/src/coherence/orphan.rs"),
                                ::tracing_core::__macro_support::Option::Some(298u32),
                                ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::coherence::orphan"),
                                ::tracing_core::field::FieldSet::new(&[{
                                                    const NAME:
                                                        ::tracing::__macro_support::FieldName<{
                                                            ::tracing::__macro_support::FieldName::len("impl_def_id")
                                                        }> =
                                                        ::tracing::__macro_support::FieldName::new("impl_def_id");
                                                    NAME.as_str()
                                                },
                                                {
                                                    const NAME:
                                                        ::tracing::__macro_support::FieldName<{
                                                            ::tracing::__macro_support::FieldName::len("mode")
                                                        }> =
                                                        ::tracing::__macro_support::FieldName::new("mode");
                                                    NAME.as_str()
                                                }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                ::tracing::metadata::Kind::SPAN)
                        };
                    ::tracing::callsite::DefaultCallsite::new(&META)
                };
            let mut interest = ::tracing::subscriber::Interest::never();
            if ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::STATIC_MAX_LEVEL &&
                            ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::LevelFilter::current() &&
                        { interest = __CALLSITE.interest(); !interest.is_never() }
                    &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest) {
                let meta = __CALLSITE.metadata();
                ::tracing::Span::new(meta,
                    &{
                            #[allow(unused_imports)]
                            use ::tracing::field::{debug, display, Value};
                            meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&impl_def_id)
                                                        as &dyn ::tracing::field::Value)),
                                            (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&mode)
                                                        as &dyn ::tracing::field::Value))])
                        })
            } else {
                let span =
                    ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                {};
                span
            }
        };
    __tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
    (move ||
                {

                    #[allow(unknown_lints, unreachable_code, clippy ::
                    diverging_sub_expression, clippy :: empty_loop, clippy ::
                    let_unit_value, clippy :: let_with_type_underscore, clippy
                    :: needless_return, clippy :: unreachable)]
                    if false {
                        let __tracing_attr_fake_return:
                                Result<(),
                                OrphanCheckErr<TyCtxt<'tcx>, FxIndexSet<DefId>>> = loop {};
                        return __tracing_attr_fake_return;
                    }
                    {
                        let trait_ref = tcx.impl_trait_ref(impl_def_id);
                        {
                            use ::tracing::__macro_support::Callsite as _;
                            static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                                {
                                    static META: ::tracing::Metadata<'static> =
                                        {
                                            ::tracing_core::metadata::Metadata::new("event /rustc-dev/3ef0c22cdb86ac42dc6b8f0f1ec36857daa6f2a1/compiler/rustc_hir_analysis/src/coherence/orphan.rs:307",
                                                "rustc_hir_analysis::coherence::orphan",
                                                ::tracing::Level::DEBUG,
                                                ::tracing_core::__macro_support::Option::Some("/rustc-dev/3ef0c22cdb86ac42dc6b8f0f1ec36857daa6f2a1/compiler/rustc_hir_analysis/src/coherence/orphan.rs"),
                                                ::tracing_core::__macro_support::Option::Some(307u32),
                                                ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::coherence::orphan"),
                                                ::tracing_core::field::FieldSet::new(&[{
                                                                    const NAME:
                                                                        ::tracing::__macro_support::FieldName<{
                                                                            ::tracing::__macro_support::FieldName::len("trait_ref")
                                                                        }> =
                                                                        ::tracing::__macro_support::FieldName::new("trait_ref");
                                                                    NAME.as_str()
                                                                }], ::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(&::tracing::field::debug(&trait_ref.skip_binder())
                                                                    as &dyn ::tracing::field::Value))])
                                    });
                            } else { ; }
                        };
                        if let Some(def_id) =
                                trait_ref.skip_binder().def_id.as_local() {
                            {
                                use ::tracing::__macro_support::Callsite as _;
                                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                                    {
                                        static META: ::tracing::Metadata<'static> =
                                            {
                                                ::tracing_core::metadata::Metadata::new("event /rustc-dev/3ef0c22cdb86ac42dc6b8f0f1ec36857daa6f2a1/compiler/rustc_hir_analysis/src/coherence/orphan.rs:311",
                                                    "rustc_hir_analysis::coherence::orphan",
                                                    ::tracing::Level::DEBUG,
                                                    ::tracing_core::__macro_support::Option::Some("/rustc-dev/3ef0c22cdb86ac42dc6b8f0f1ec36857daa6f2a1/compiler/rustc_hir_analysis/src/coherence/orphan.rs"),
                                                    ::tracing_core::__macro_support::Option::Some(311u32),
                                                    ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::coherence::orphan"),
                                                    ::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!("trait {0:?} is local to current crate",
                                                                                def_id) as &dyn ::tracing::field::Value))])
                                        });
                                } else { ; }
                            };
                            return Ok(());
                        }
                        let infcx =
                            tcx.infer_ctxt().with_next_trait_solver(true).enable_next_solver_overflow_fcw(false).build(TypingMode::Coherence);
                        let cause = traits::ObligationCause::dummy();
                        let args =
                            infcx.fresh_args_for_item(cause.span,
                                impl_def_id.to_def_id());
                        let trait_ref =
                            trait_ref.instantiate(tcx, args).skip_norm_wip();
                        let lazily_normalize_ty =
                            |user_ty: Ty<'tcx>|
                                {
                                    let ty::Alias(..) =
                                        user_ty.kind() else { return Ok(user_ty) };
                                    let ocx = traits::ObligationCtxt::new(&infcx);
                                    let ty =
                                        ocx.normalize(&cause, ty::ParamEnv::empty(),
                                            Unnormalized::new_wip(user_ty));
                                    let ty = infcx.deeply_resolve_ignoring_regions(ty);
                                    let errors = ocx.try_evaluate_obligations();
                                    if !errors.no_errors() { return Ok(user_ty); }
                                    Ok::<_, !>(ty)
                                };
                        let result =
                            traits::orphan_check_trait_ref(&infcx, trait_ref,
                                    traits::InCrate::Local { mode },
                                    lazily_normalize_ty).into_ok();
                        result.map_err(|err|
                                match err {
                                    OrphanCheckErr::UncoveredTyParams(UncoveredTyParams {
                                        uncovered, local_ty }) => {
                                        let mut collector =
                                            UncoveredTyParamCollector {
                                                infcx: &infcx,
                                                uncovered_params: Default::default(),
                                            };
                                        uncovered.visit_with(&mut collector);
                                        if true {
                                            if !!collector.uncovered_params.is_empty() {
                                                ::core::panicking::panic("assertion failed: !collector.uncovered_params.is_empty()")
                                            };
                                        };
                                        OrphanCheckErr::UncoveredTyParams(UncoveredTyParams {
                                                uncovered: collector.uncovered_params,
                                                local_ty,
                                            })
                                    }
                                    OrphanCheckErr::NonLocalInputType(tys) => {
                                        let tys =
                                            infcx.probe(|_|
                                                    {
                                                        for (arg, id_arg) in
                                                            std::iter::zip(args,
                                                                ty::GenericArgs::identity_for_item(tcx, impl_def_id)) {
                                                            let _ =
                                                                infcx.at(&cause,
                                                                        ty::ParamEnv::empty()).eq(DefineOpaqueTypes::No, arg,
                                                                    id_arg);
                                                        }
                                                        infcx.deeply_resolve_ignoring_regions(tys)
                                                    });
                                        OrphanCheckErr::NonLocalInputType(tys)
                                    }
                                })
                    }
                })();
{
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/3ef0c22cdb86ac42dc6b8f0f1ec36857daa6f2a1/compiler/rustc_hir_analysis/src/coherence/orphan.rs:298",
                        "rustc_hir_analysis::coherence::orphan",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/3ef0c22cdb86ac42dc6b8f0f1ec36857daa6f2a1/compiler/rustc_hir_analysis/src/coherence/orphan.rs"),
                        ::tracing_core::__macro_support::Option::Some(298u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::coherence::orphan"),
                        ::tracing_core::field::FieldSet::new(&[{
                                            const NAME:
                                                ::tracing::__macro_support::FieldName<{
                                                    ::tracing::__macro_support::FieldName::len("return")
                                                }> =
                                                ::tracing::__macro_support::FieldName::new("return");
                                            NAME.as_str()
                                        }], ::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(&::tracing::field::debug(&x)
                                            as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};
x;#[instrument(level = "debug", skip(tcx), ret)]
299fn orphan_check<'tcx>(
300    tcx: TyCtxt<'tcx>,
301    impl_def_id: LocalDefId,
302    mode: OrphanCheckMode,
303) -> Result<(), OrphanCheckErr<TyCtxt<'tcx>, FxIndexSet<DefId>>> {
304    // We only accept this routine to be invoked on implementations
305    // of a trait, not inherent implementations.
306    let trait_ref = tcx.impl_trait_ref(impl_def_id);
307    debug!(trait_ref = ?trait_ref.skip_binder());
308
309    // If the *trait* is local to the crate, ok.
310    if let Some(def_id) = trait_ref.skip_binder().def_id.as_local() {
311        debug!("trait {def_id:?} is local to current crate");
312        return Ok(());
313    }
314
315    // (1)  Instantiate all generic params with fresh inference vars.
316    let infcx = tcx
317        .infer_ctxt()
318        .with_next_trait_solver(true)
319        .enable_next_solver_overflow_fcw(false)
320        .build(TypingMode::Coherence);
321    let cause = traits::ObligationCause::dummy();
322    let args = infcx.fresh_args_for_item(cause.span, impl_def_id.to_def_id());
323    let trait_ref = trait_ref.instantiate(tcx, args).skip_norm_wip();
324
325    let lazily_normalize_ty = |user_ty: Ty<'tcx>| {
326        let ty::Alias(..) = user_ty.kind() else { return Ok(user_ty) };
327
328        let ocx = traits::ObligationCtxt::new(&infcx);
329        let ty = ocx.normalize(&cause, ty::ParamEnv::empty(), Unnormalized::new_wip(user_ty));
330        let ty = infcx.deeply_resolve_ignoring_regions(ty);
331        let errors = ocx.try_evaluate_obligations();
332        if !errors.no_errors() {
333            return Ok(user_ty);
334        }
335
336        Ok::<_, !>(ty)
337    };
338
339    let result = traits::orphan_check_trait_ref(
340        &infcx,
341        trait_ref,
342        traits::InCrate::Local { mode },
343        lazily_normalize_ty,
344    )
345    .into_ok();
346
347    // (2)  Try to map the remaining inference vars back to generic params.
348    result.map_err(|err| match err {
349        OrphanCheckErr::UncoveredTyParams(UncoveredTyParams { uncovered, local_ty }) => {
350            let mut collector =
351                UncoveredTyParamCollector { infcx: &infcx, uncovered_params: Default::default() };
352            uncovered.visit_with(&mut collector);
353            // FIXME(fmease): This is very likely reachable.
354            debug_assert!(!collector.uncovered_params.is_empty());
355
356            OrphanCheckErr::UncoveredTyParams(UncoveredTyParams {
357                uncovered: collector.uncovered_params,
358                local_ty,
359            })
360        }
361        OrphanCheckErr::NonLocalInputType(tys) => {
362            let tys = infcx.probe(|_| {
363                // Map the unconstrained args back to their params,
364                // ignoring any type unification errors.
365                for (arg, id_arg) in
366                    std::iter::zip(args, ty::GenericArgs::identity_for_item(tcx, impl_def_id))
367                {
368                    let _ = infcx.at(&cause, ty::ParamEnv::empty()).eq(
369                        DefineOpaqueTypes::No,
370                        arg,
371                        id_arg,
372                    );
373                }
374                infcx.deeply_resolve_ignoring_regions(tys)
375            });
376            OrphanCheckErr::NonLocalInputType(tys)
377        }
378    })
379}
380
381fn emit_orphan_check_error<'tcx>(
382    tcx: TyCtxt<'tcx>,
383    trait_ref: ty::TraitRef<'tcx>,
384    impl_def_id: LocalDefId,
385    err: traits::OrphanCheckErr<TyCtxt<'tcx>, FxIndexSet<DefId>>,
386) -> ErrorGuaranteed {
387    match err {
388        traits::OrphanCheckErr::NonLocalInputType(tys) => {
389            let item = tcx.hir_expect_item(impl_def_id);
390            let impl_ = item.expect_impl();
391            let of_trait = impl_.of_trait.unwrap();
392
393            let span = tcx.def_span(impl_def_id);
394            let mut diag = tcx.dcx().create_err(match trait_ref.self_ty().kind() {
395                ty::Adt(..) => diagnostics::OnlyCurrentTraits::Outside { span, note: () },
396                _ if trait_ref.self_ty().is_primitive() => {
397                    diagnostics::OnlyCurrentTraits::Primitive { span, note: () }
398                }
399                _ => diagnostics::OnlyCurrentTraits::Arbitrary { span, note: () },
400            });
401
402            for &(mut ty, is_target_ty) in &tys {
403                let span = if #[allow(non_exhaustive_omitted_patterns)] match is_target_ty {
    IsFirstInputType::Yes => true,
    _ => false,
}matches!(is_target_ty, IsFirstInputType::Yes) {
404                    // Point at `D<A>` in `impl<A, B> for C<B> in D<A>`
405                    impl_.self_ty.span
406                } else {
407                    // Point at `C<B>` in `impl<A, B> for C<B> in D<A>`
408                    of_trait.trait_ref.path.span
409                };
410
411                ty = tcx.erase_and_anonymize_regions(ty);
412
413                let is_foreign =
414                    !trait_ref.def_id.is_local() && #[allow(non_exhaustive_omitted_patterns)] match is_target_ty {
    IsFirstInputType::No => true,
    _ => false,
}matches!(is_target_ty, IsFirstInputType::No);
415
416                match *ty.kind() {
417                    ty::Slice(_) => {
418                        if is_foreign {
419                            diag.subdiagnostic(diagnostics::OnlyCurrentTraitsForeign { span });
420                        } else {
421                            diag.subdiagnostic(diagnostics::OnlyCurrentTraitsName {
422                                span,
423                                name: "slices",
424                            });
425                        }
426                    }
427                    ty::Array(..) => {
428                        if is_foreign {
429                            diag.subdiagnostic(diagnostics::OnlyCurrentTraitsForeign { span });
430                        } else {
431                            diag.subdiagnostic(diagnostics::OnlyCurrentTraitsName {
432                                span,
433                                name: "arrays",
434                            });
435                        }
436                    }
437                    ty::Tuple(..) => {
438                        if is_foreign {
439                            diag.subdiagnostic(diagnostics::OnlyCurrentTraitsForeign { span });
440                        } else {
441                            diag.subdiagnostic(diagnostics::OnlyCurrentTraitsName {
442                                span,
443                                name: "tuples",
444                            });
445                        }
446                    }
447                    ty::Alias(_, ty::AliasTy { kind: ty::Opaque { .. }, .. }) => {
448                        diag.subdiagnostic(diagnostics::OnlyCurrentTraitsOpaque { span });
449                    }
450                    ty::RawPtr(ptr_ty, mutbl) => {
451                        if !trait_ref.self_ty().has_param() {
452                            diag.subdiagnostic(diagnostics::OnlyCurrentTraitsPointerSugg {
453                                wrapper_span: impl_.self_ty.span,
454                                struct_span: item.span.shrink_to_lo(),
455                                mut_key: mutbl.prefix_str(),
456                                ptr_ty,
457                            });
458                        }
459                        diag.subdiagnostic(diagnostics::OnlyCurrentTraitsPointer {
460                            span,
461                            pointer: ty,
462                        });
463                    }
464                    ty::Adt(adt_def, _) => {
465                        if is_foreign {
466                            diag.subdiagnostic(diagnostics::OnlyCurrentTraitsForeign { span });
467                        } else {
468                            diag.subdiagnostic(diagnostics::OnlyCurrentTraitsAdt {
469                                span,
470                                name: tcx.def_path_str(adt_def.did()),
471                            });
472                        }
473                    }
474                    _ => {
475                        if is_foreign {
476                            diag.subdiagnostic(diagnostics::OnlyCurrentTraitsForeign { span });
477                        } else {
478                            diag.subdiagnostic(diagnostics::OnlyCurrentTraitsTy { span, ty });
479                        }
480                    }
481                }
482            }
483
484            diag.emit_err()
485        }
486        traits::OrphanCheckErr::UncoveredTyParams(UncoveredTyParams { uncovered, local_ty }) => {
487            let mut guar = None;
488            for param_def_id in uncovered {
489                guar.get_or_insert(tcx.dcx().emit_err(diagnostics::UncoveredTyParam {
490                    param: tcx.item_ident(param_def_id),
491                    local_ty,
492                }));
493            }
494            guar.unwrap()
495        }
496    }
497}
498
499struct UncoveredTyParamCollector<'cx, 'tcx> {
500    infcx: &'cx InferCtxt<'tcx>,
501    uncovered_params: FxIndexSet<DefId>,
502}
503
504impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for UncoveredTyParamCollector<'_, 'tcx> {
505    fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
506        if !ty.has_type_flags(ty::TypeFlags::HAS_TY_INFER) {
507            return;
508        }
509        let ty::Infer(ty::TyVar(vid)) = *ty.kind() else {
510            return ty.super_visit_with(self);
511        };
512        let origin = self.infcx.type_var_origin(vid);
513        if let Some(def_id) = origin.param_def_id {
514            self.uncovered_params.insert(def_id);
515        }
516    }
517
518    fn visit_const(&mut self, ct: ty::Const<'tcx>) -> Self::Result {
519        if ct.has_type_flags(ty::TypeFlags::HAS_TY_INFER) {
520            ct.super_visit_with(self)
521        }
522    }
523}