Skip to main content

rustc_hir_analysis/coherence/
builtin.rs

1//! Check properties that are required by built-in traits and set
2//! up data structures required by type-checking/codegen.
3
4use std::collections::BTreeMap;
5
6use rustc_data_structures::fx::FxHashSet;
7use rustc_errors::{ErrorGuaranteed, MultiSpan};
8use rustc_hir as hir;
9use rustc_hir::ItemKind;
10use rustc_hir::attrs::lang_items::LangItem;
11use rustc_hir::def_id::{DefId, LocalDefId};
12use rustc_infer::infer::{self, InferCtxt, RegionResolutionError, SubregionOrigin, TyCtxtInferExt};
13use rustc_infer::traits::{Obligation, TraitErrors};
14use rustc_middle::ty::adjustment::CoerceUnsizedInfo;
15use rustc_middle::ty::print::PrintTraitRefExt as _;
16use rustc_middle::ty::{
17    self, Ty, TyCtxt, TypeVisitableExt, TypingMode, Unnormalized, suggest_constraining_type_params,
18};
19use rustc_span::{DUMMY_SP, Ident, Span, Symbol, sym};
20use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
21use rustc_trait_selection::traits::misc::{
22    ConstParamTyImplementationError, CopyImplementationError, InfringingFieldsReason,
23    type_allowed_to_implement_const_param_ty, type_allowed_to_implement_copy,
24};
25use rustc_trait_selection::traits::{self, ObligationCause, ObligationCtxt};
26use tracing::debug;
27
28use crate::diagnostics;
29
30mod coerce_shared;
31
32pub(super) fn check_trait<'tcx>(
33    tcx: TyCtxt<'tcx>,
34    trait_def_id: DefId,
35    impl_def_id: LocalDefId,
36    impl_header: ty::ImplTraitHeader<'tcx>,
37) -> Result<(), ErrorGuaranteed> {
38    let checker = Checker { tcx, impl_def_id, impl_header };
39    match tcx.as_lang_item(trait_def_id) {
40        Some(LangItem::Drop) => visit_implementation_of_drop(&checker),
41        Some(LangItem::AsyncDrop) => visit_implementation_of_drop(&checker),
42        Some(LangItem::Copy) => visit_implementation_of_copy(&checker),
43        Some(LangItem::Unpin) => visit_implementation_of_unpin(&checker),
44        Some(LangItem::ConstParamTy) => visit_implementation_of_const_param_ty(&checker),
45        Some(LangItem::CoerceUnsized) => visit_implementation_of_coerce_unsized(&checker),
46        Some(LangItem::Reborrow) => visit_implementation_of_reborrow(&checker),
47        Some(LangItem::CoerceShared) => visit_implementation_of_coerce_shared(&checker),
48        Some(LangItem::DispatchFromDyn) => visit_implementation_of_dispatch_from_dyn(&checker),
49        Some(LangItem::CoercePointeeValidated) => {
50            visit_implementation_of_coerce_pointee_validity(&checker)
51        }
52        _ => Ok(()),
53    }
54}
55
56struct Checker<'tcx> {
57    tcx: TyCtxt<'tcx>,
58    impl_def_id: LocalDefId,
59    impl_header: ty::ImplTraitHeader<'tcx>,
60}
61
62fn visit_implementation_of_drop(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> {
63    let tcx = checker.tcx;
64    let impl_did = checker.impl_def_id;
65    // Destructors only work on local ADT types.
66    match checker.impl_header.trait_ref.instantiate_identity().skip_norm_wip().self_ty().kind() {
67        ty::Adt(def, _) if def.did().is_local() => return Ok(()),
68        ty::Error(_) => return Ok(()),
69        _ => {}
70    }
71
72    let impl_ = tcx.hir_expect_item(impl_did).expect_impl();
73
74    Err(tcx.dcx().emit_err(diagnostics::DropImplOnWrongItem {
75        span: impl_.self_ty.span,
76        trait_: tcx.item_name(checker.impl_header.trait_ref.skip_binder().def_id),
77    }))
78}
79
80fn visit_implementation_of_copy(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> {
81    let tcx = checker.tcx;
82    let impl_header = checker.impl_header;
83    let impl_did = checker.impl_def_id;
84    {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_hir_analysis/src/coherence/builtin.rs:84",
                        "rustc_hir_analysis::coherence::builtin",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_hir_analysis/src/coherence/builtin.rs"),
                        ::tracing_core::__macro_support::Option::Some(84u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::coherence::builtin"),
                        ::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!("visit_implementation_of_copy: impl_did={0:?}",
                                                    impl_did) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("visit_implementation_of_copy: impl_did={:?}", impl_did);
85
86    let self_type = impl_header.trait_ref.instantiate_identity().skip_norm_wip().self_ty();
87    {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_hir_analysis/src/coherence/builtin.rs:87",
                        "rustc_hir_analysis::coherence::builtin",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_hir_analysis/src/coherence/builtin.rs"),
                        ::tracing_core::__macro_support::Option::Some(87u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::coherence::builtin"),
                        ::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!("visit_implementation_of_copy: self_type={0:?} (bound)",
                                                    self_type) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("visit_implementation_of_copy: self_type={:?} (bound)", self_type);
88
89    let param_env = tcx.param_env(impl_did);
90    if !!self_type.has_escaping_bound_vars() {
    ::core::panicking::panic("assertion failed: !self_type.has_escaping_bound_vars()")
};assert!(!self_type.has_escaping_bound_vars());
91
92    {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_hir_analysis/src/coherence/builtin.rs:92",
                        "rustc_hir_analysis::coherence::builtin",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_hir_analysis/src/coherence/builtin.rs"),
                        ::tracing_core::__macro_support::Option::Some(92u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::coherence::builtin"),
                        ::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!("visit_implementation_of_copy: self_type={0:?} (free)",
                                                    self_type) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("visit_implementation_of_copy: self_type={:?} (free)", self_type);
93
94    if let ty::ImplPolarity::Negative = impl_header.polarity {
95        return Ok(());
96    }
97
98    let cause = traits::ObligationCause::misc(DUMMY_SP, impl_did);
99    match type_allowed_to_implement_copy(tcx, param_env, self_type, cause, impl_header.safety) {
100        Ok(()) => Ok(()),
101        Err(CopyImplementationError::InfringingFields(fields)) => {
102            let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
103            Err(infringing_fields_error(
104                tcx,
105                fields.into_iter().map(|(field, ty, reason)| (tcx.def_span(field.did), ty, reason)),
106                LangItem::Copy,
107                impl_did,
108                span,
109            ))
110        }
111        Err(CopyImplementationError::NotAnAdt) => {
112            let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
113            Err(tcx.dcx().emit_err(diagnostics::CopyImplOnNonAdt { span }))
114        }
115        Err(CopyImplementationError::HasDestructor(did)) => {
116            let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
117            let impl_ = tcx.def_span(did);
118            Err(tcx.dcx().emit_err(diagnostics::CopyImplOnTypeWithDtor { span, impl_ }))
119        }
120        Err(CopyImplementationError::HasUnsafeFields) => {
121            let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
122            Err(tcx
123                .dcx()
124                .span_delayed_bug(span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("cannot implement `Copy` for `{0}`",
                self_type))
    })format!("cannot implement `Copy` for `{}`", self_type)))
125        }
126    }
127}
128
129fn visit_implementation_of_unpin(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> {
130    let tcx = checker.tcx;
131    let impl_header = checker.impl_header;
132    let impl_did = checker.impl_def_id;
133    {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_hir_analysis/src/coherence/builtin.rs:133",
                        "rustc_hir_analysis::coherence::builtin",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_hir_analysis/src/coherence/builtin.rs"),
                        ::tracing_core::__macro_support::Option::Some(133u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::coherence::builtin"),
                        ::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!("visit_implementation_of_unpin: impl_did={0:?}",
                                                    impl_did) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("visit_implementation_of_unpin: impl_did={:?}", impl_did);
134
135    let self_type = impl_header.trait_ref.instantiate_identity().skip_norm_wip().self_ty();
136    {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_hir_analysis/src/coherence/builtin.rs:136",
                        "rustc_hir_analysis::coherence::builtin",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_hir_analysis/src/coherence/builtin.rs"),
                        ::tracing_core::__macro_support::Option::Some(136u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::coherence::builtin"),
                        ::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!("visit_implementation_of_unpin: self_type={0:?}",
                                                    self_type) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("visit_implementation_of_unpin: self_type={:?}", self_type);
137
138    let span = tcx.def_span(impl_did);
139
140    if tcx.features().pin_ergonomics() {
141        match self_type.kind() {
142            // Soundness concerns: a type `T` annotated with `#[pin_v2]` is allowed to project
143            // `Pin<&mut T>` to its field `Pin<&mut U>` safely (even if `U: !Unpin`).
144            // If `T` is allowed to impl `Unpin` manually (note that `Unpin` is a safe trait,
145            // which cannot carry safety properties), then `&mut U` could be obtained from
146            // `&mut T` that dereferenced by `Pin<&mut T>`, which breaks the safety contract of
147            // `Pin<&mut U>` for `U: !Unpin`.
148            ty::Adt(adt, _) if adt.is_pin_project() => {
149                return Err(tcx.dcx().emit_err(crate::diagnostics::ImplUnpinForPinProjectedType {
150                    span,
151                    adt_span: tcx.def_span(adt.did()),
152                    adt_name: tcx.item_name(adt.did()),
153                }));
154            }
155            ty::Adt(_, _) => {}
156            // `extern type`s have no fields, so they can't be structurally pinned.
157            ty::Foreign(_) => {}
158            _ => {
159                return Err(tcx.dcx().span_delayed_bug(span, "impl of `Unpin` for a non-adt type"));
160            }
161        };
162    }
163    Ok(())
164}
165
166fn visit_implementation_of_const_param_ty(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> {
167    let tcx = checker.tcx;
168    let header = checker.impl_header;
169    let impl_did = checker.impl_def_id;
170    let self_type = header.trait_ref.instantiate_identity().skip_norm_wip().self_ty();
171    if !!self_type.has_escaping_bound_vars() {
    ::core::panicking::panic("assertion failed: !self_type.has_escaping_bound_vars()")
};assert!(!self_type.has_escaping_bound_vars());
172
173    let param_env = tcx.param_env(impl_did);
174
175    if let ty::ImplPolarity::Negative = header.polarity {
176        return Ok(());
177    }
178
179    if tcx.features().const_param_ty_unchecked() {
180        return Ok(());
181    }
182
183    if !tcx.features().adt_const_params() {
184        match *self_type.kind() {
185            ty::Adt(adt, _) if adt.is_struct() => {
186                let struct_vis = tcx.visibility(adt.did());
187                for variant in adt.variants() {
188                    for field in &variant.fields {
189                        if struct_vis.greater_than(field.vis, tcx) {
190                            let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
191                            return Err(tcx
192                                .dcx()
193                                .emit_err(diagnostics::ConstParamTyFieldVisMismatch { span }));
194                        }
195                    }
196                }
197            }
198
199            _ => {}
200        }
201    }
202
203    let cause = traits::ObligationCause::misc(DUMMY_SP, impl_did);
204    match type_allowed_to_implement_const_param_ty(tcx, param_env, self_type, cause) {
205        Ok(()) => Ok(()),
206        Err(ConstParamTyImplementationError::InfrigingFields(fields)) => {
207            let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
208            Err(infringing_fields_error(
209                tcx,
210                fields.into_iter().map(|(field, ty, reason)| (tcx.def_span(field.did), ty, reason)),
211                LangItem::ConstParamTy,
212                impl_did,
213                span,
214            ))
215        }
216        Err(ConstParamTyImplementationError::NotAnAdtOrBuiltinAllowed) => {
217            let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
218            Err(tcx.dcx().emit_err(diagnostics::ConstParamTyImplOnNonAdt { span }))
219        }
220        Err(ConstParamTyImplementationError::NonExhaustive(attr_span)) => {
221            let defn_span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
222            Err(tcx
223                .dcx()
224                .emit_err(diagnostics::ConstParamTyImplOnNonExhaustive { defn_span, attr_span }))
225        }
226        Err(ConstParamTyImplementationError::InvalidInnerTyOfBuiltinTy(infringing_tys)) => {
227            let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
228            Err(infringing_fields_error(
229                tcx,
230                infringing_tys.into_iter().map(|(ty, reason)| (span, ty, reason)),
231                LangItem::ConstParamTy,
232                impl_did,
233                span,
234            ))
235        }
236        Err(ConstParamTyImplementationError::UnsizedConstParamsFeatureRequired) => {
237            let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
238            Err(tcx.dcx().emit_err(diagnostics::ConstParamTyImplOnUnsized { span }))
239        }
240    }
241}
242
243fn visit_implementation_of_coerce_unsized(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> {
244    let tcx = checker.tcx;
245    let impl_did = checker.impl_def_id;
246    {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_hir_analysis/src/coherence/builtin.rs:246",
                        "rustc_hir_analysis::coherence::builtin",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_hir_analysis/src/coherence/builtin.rs"),
                        ::tracing_core::__macro_support::Option::Some(246u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::coherence::builtin"),
                        ::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!("visit_implementation_of_coerce_unsized: impl_did={0:?}",
                                                    impl_did) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("visit_implementation_of_coerce_unsized: impl_did={:?}", impl_did);
247
248    // Just compute this for the side-effects, in particular reporting
249    // errors; other parts of the code may demand it for the info of
250    // course.
251    tcx.ensure_result().coerce_unsized_info(impl_did)
252}
253
254fn visit_implementation_of_reborrow(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> {
255    let tcx = checker.tcx;
256    let impl_did = checker.impl_def_id;
257    {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_hir_analysis/src/coherence/builtin.rs:257",
                        "rustc_hir_analysis::coherence::builtin",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_hir_analysis/src/coherence/builtin.rs"),
                        ::tracing_core::__macro_support::Option::Some(257u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::coherence::builtin"),
                        ::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!("visit_implementation_of_reborrow: impl_did={0:?}",
                                                    impl_did) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("visit_implementation_of_reborrow: impl_did={:?}", impl_did);
258
259    // Just compute this for the side-effects, in particular reporting
260    // errors; other parts of the code may demand it for the info of
261    // course.
262    reborrow_info(tcx, impl_did)
263}
264
265fn visit_implementation_of_coerce_shared(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> {
266    let tcx = checker.tcx;
267    let impl_did = checker.impl_def_id;
268    {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_hir_analysis/src/coherence/builtin.rs:268",
                        "rustc_hir_analysis::coherence::builtin",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_hir_analysis/src/coherence/builtin.rs"),
                        ::tracing_core::__macro_support::Option::Some(268u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::coherence::builtin"),
                        ::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!("visit_implementation_of_coerce_shared: impl_did={0:?}",
                                                    impl_did) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("visit_implementation_of_coerce_shared: impl_did={:?}", impl_did);
269
270    // Just compute this for the side-effects, in particular reporting
271    // errors; other parts of the code may demand it for the info of
272    // course.
273    coerce_shared::coerce_shared_info(tcx, impl_did)
274}
275
276fn is_from_coerce_pointee_derive(tcx: TyCtxt<'_>, span: Span) -> bool {
277    span.ctxt()
278        .outer_expn_data()
279        .macro_def_id
280        .is_some_and(|def_id| tcx.is_diagnostic_item(sym::CoercePointee, def_id))
281}
282
283fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> {
284    let tcx = checker.tcx;
285    let impl_did = checker.impl_def_id;
286    let trait_ref = checker.impl_header.trait_ref.instantiate_identity().skip_norm_wip();
287    {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_hir_analysis/src/coherence/builtin.rs:287",
                        "rustc_hir_analysis::coherence::builtin",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_hir_analysis/src/coherence/builtin.rs"),
                        ::tracing_core::__macro_support::Option::Some(287u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::coherence::builtin"),
                        ::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!("visit_implementation_of_dispatch_from_dyn: impl_did={0:?}",
                                                    impl_did) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("visit_implementation_of_dispatch_from_dyn: impl_did={:?}", impl_did);
288
289    let span = tcx.def_span(impl_did);
290    let trait_name = "DispatchFromDyn";
291
292    let source = trait_ref.self_ty();
293    let target = {
294        if !tcx.is_lang_item(trait_ref.def_id, LangItem::DispatchFromDyn) {
    ::core::panicking::panic("assertion failed: tcx.is_lang_item(trait_ref.def_id, LangItem::DispatchFromDyn)")
};assert!(tcx.is_lang_item(trait_ref.def_id, LangItem::DispatchFromDyn));
295
296        trait_ref.args.type_at(1)
297    };
298
299    // Check `CoercePointee` impl is WF -- if not, then there's no reason to report
300    // redundant errors for `DispatchFromDyn`. This is best effort, though.
301    let mut res = Ok(());
302    tcx.for_each_relevant_impl(
303        tcx.require_lang_item(LangItem::CoerceUnsized, span),
304        source,
305        |impl_def_id| {
306            res = res.and(tcx.ensure_result().coerce_unsized_info(impl_def_id));
307        },
308    );
309    res?;
310
311    {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_hir_analysis/src/coherence/builtin.rs:311",
                        "rustc_hir_analysis::coherence::builtin",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_hir_analysis/src/coherence/builtin.rs"),
                        ::tracing_core::__macro_support::Option::Some(311u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::coherence::builtin"),
                        ::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!("visit_implementation_of_dispatch_from_dyn: {0:?} -> {1:?}",
                                                    source, target) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("visit_implementation_of_dispatch_from_dyn: {:?} -> {:?}", source, target);
312
313    let param_env = tcx.param_env(impl_did);
314
315    let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
316    let cause = ObligationCause::misc(span, impl_did);
317
318    // Later parts of the compiler rely on all DispatchFromDyn types to be ABI-compatible with raw
319    // pointers. This is enforced here: we only allow impls for references, raw pointers, and things
320    // that are effectively repr(transparent) newtypes around types that already hav a
321    // DispatchedFromDyn impl. We cannot literally use repr(transparent) on those types since some
322    // of them support an allocator, but we ensure that for the cases where the type implements this
323    // trait, they *do* satisfy the repr(transparent) rules, and then we assume that everything else
324    // in the compiler (in particular, all the call ABI logic) will treat them as repr(transparent)
325    // even if they do not carry that attribute.
326    match (source.kind(), target.kind()) {
327        (&ty::Pat(_, pat_a), &ty::Pat(_, pat_b)) => {
328            if pat_a != pat_b {
329                return Err(tcx.dcx().emit_err(diagnostics::CoerceSamePatKind {
330                    span,
331                    trait_name,
332                    pat_a: pat_a.to_string(),
333                    pat_b: pat_b.to_string(),
334                }));
335            }
336            Ok(())
337        }
338
339        (&ty::Ref(r_a, _, mutbl_a), ty::Ref(r_b, _, mutbl_b))
340            if r_a == *r_b && mutbl_a == *mutbl_b =>
341        {
342            Ok(())
343        }
344        (&ty::RawPtr(_, a_mutbl), &ty::RawPtr(_, b_mutbl)) if a_mutbl == b_mutbl => Ok(()),
345        (&ty::Adt(def_a, args_a), &ty::Adt(def_b, args_b))
346            if def_a.is_struct() && def_b.is_struct() =>
347        {
348            if def_a != def_b {
349                let source_path = tcx.def_path_str(def_a.did());
350                let target_path = tcx.def_path_str(def_b.did());
351                return Err(tcx.dcx().emit_err(diagnostics::CoerceSameStruct {
352                    span,
353                    trait_name,
354                    note: true,
355                    source_path,
356                    target_path,
357                }));
358            }
359
360            if def_a.repr().c() || def_a.repr().packed() {
361                return Err(tcx.dcx().emit_err(diagnostics::DispatchFromDynRepr { span }));
362            }
363
364            let fields = &def_a.non_enum_variant().fields;
365
366            let mut res = Ok(());
367            let coerced_fields = fields
368                .iter_enumerated()
369                .filter_map(|(i, field)| {
370                    // Ignore PhantomData fields
371                    let unnormalized_ty = tcx.type_of(field.did).instantiate_identity();
372                    if tcx
373                        .try_normalize_erasing_regions(
374                            ty::TypingEnv::non_body_analysis(tcx, def_a.did()),
375                            unnormalized_ty,
376                        )
377                        .unwrap_or(unnormalized_ty.skip_norm_wip())
378                        .is_phantom_data()
379                    {
380                        return None;
381                    }
382
383                    let ty_a = field.ty(tcx, args_a).skip_norm_wip();
384                    let ty_b = field.ty(tcx, args_b).skip_norm_wip();
385
386                    // FIXME: We could do normalization here, but is it really worth it?
387                    if ty_a == ty_b {
388                        // Allow 1-ZSTs that don't mention type params.
389                        //
390                        // Allowing type params here would allow us to possibly transmute
391                        // between ZSTs, which may be used to create library unsoundness.
392                        if let Ok(layout) =
393                            tcx.layout_of(infcx.typing_env(param_env).as_query_input(ty_a))
394                            && layout.is_1zst()
395                            && !ty_a.has_non_region_param()
396                        {
397                            // ignore 1-ZST fields
398                            return None;
399                        }
400
401                        res = Err(tcx.dcx().emit_err(diagnostics::DispatchFromDynZST {
402                            span,
403                            name: field.ident(tcx),
404                            ty: ty_a,
405                        }));
406
407                        None
408                    } else {
409                        Some((i, ty_a, ty_b, tcx.def_span(field.did)))
410                    }
411                })
412                .collect::<Vec<_>>();
413            res?;
414
415            if coerced_fields.is_empty() {
416                return Err(tcx.dcx().emit_err(diagnostics::CoerceNoField {
417                    span,
418                    trait_name,
419                    note: true,
420                }));
421            } else if let &[(_, ty_a, ty_b, field_span)] = &coerced_fields[..] {
422                let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
423                ocx.register_obligation(Obligation::new(
424                    tcx,
425                    cause.clone(),
426                    param_env,
427                    ty::TraitRef::new(tcx, trait_ref.def_id, [ty_a, ty_b]),
428                ));
429                let errors = ocx.evaluate_obligations_error_on_ambiguity();
430                if let TraitErrors::HasErrors(errors) = errors {
431                    if is_from_coerce_pointee_derive(tcx, span) {
432                        return Err(tcx.dcx().emit_err(diagnostics::CoerceFieldValidity {
433                            span,
434                            trait_name,
435                            ty: trait_ref.self_ty(),
436                            field_span,
437                            field_ty: ty_a,
438                        }));
439                    } else {
440                        return Err(infcx.err_ctxt().report_fulfillment_errors(errors));
441                    }
442                }
443
444                // Finally, resolve all regions.
445                ocx.resolve_regions_and_report_errors(impl_did, param_env, [])?;
446
447                Ok(())
448            } else {
449                return Err(tcx.dcx().emit_err(diagnostics::CoerceMulti {
450                    span,
451                    trait_name,
452                    number: coerced_fields.len(),
453                    fields: coerced_fields.iter().map(|(_, _, _, s)| *s).collect::<Vec<_>>().into(),
454                }));
455            }
456        }
457        _ => Err(tcx.dcx().emit_err(diagnostics::CoerceUnsizedNonStruct { span, trait_name })),
458    }
459}
460
461pub(crate) fn reborrow_info<'tcx>(
462    tcx: TyCtxt<'tcx>,
463    impl_did: LocalDefId,
464) -> Result<(), ErrorGuaranteed> {
465    {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_hir_analysis/src/coherence/builtin.rs:465",
                        "rustc_hir_analysis::coherence::builtin",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_hir_analysis/src/coherence/builtin.rs"),
                        ::tracing_core::__macro_support::Option::Some(465u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::coherence::builtin"),
                        ::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!("compute_reborrow_info(impl_did={0:?})",
                                                    impl_did) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("compute_reborrow_info(impl_did={:?})", impl_did);
466    let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
467    let span = tcx.def_span(impl_did);
468    let trait_name = "Reborrow";
469
470    let reborrow_trait = tcx.require_lang_item(LangItem::Reborrow, span);
471
472    let source = tcx.type_of(impl_did).instantiate_identity().skip_norm_wip();
473    let trait_ref = tcx.impl_trait_ref(impl_did).instantiate_identity().skip_norm_wip();
474
475    if trait_impl_lifetime_params_count(tcx, impl_did) != 1 {
476        return Err(tcx
477            .dcx()
478            .emit_err(diagnostics::CoerceSharedNotSingleLifetimeParam { span, trait_name }));
479    }
480
481    {
    match (&trait_ref.def_id, &reborrow_trait) {
        (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!(trait_ref.def_id, reborrow_trait);
482    let param_env = tcx.param_env(impl_did);
483    if !!source.has_escaping_bound_vars() {
    ::core::panicking::panic("assertion failed: !source.has_escaping_bound_vars()")
};assert!(!source.has_escaping_bound_vars());
484
485    let (def, args) = match source.kind() {
486        &ty::Adt(def, args) if def.is_struct() => (def, args),
487        _ => {
488            // Note: reusing error here as it takes trait_name as argument.
489            return Err(tcx
490                .dcx()
491                .emit_err(diagnostics::CoerceUnsizedNonStruct { span, trait_name }));
492        }
493    };
494
495    let lifetimes_count = generic_lifetime_params_count(args);
496    let data_fields = collect_reborrow_data_fields(tcx, def, args);
497
498    if lifetimes_count != 1 {
499        let item = tcx.hir_expect_item(impl_did);
500        let _span = if let ItemKind::Impl(hir::Impl { of_trait: Some(of_trait), .. }) = &item.kind {
501            of_trait.trait_ref.path.span
502        } else {
503            tcx.def_span(impl_did)
504        };
505
506        return Err(tcx.dcx().emit_err(diagnostics::CoerceSharedMulti { span, trait_name }));
507    }
508
509    if data_fields.is_empty() {
510        return Ok(());
511    }
512
513    let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
514    // We've found some data fields. They must all be either be Copy or Reborrow.
515    for mut field in data_fields {
516        field.ty = ocx
517            .deeply_normalize(
518                &traits::ObligationCause::misc(field.span, impl_did),
519                param_env,
520                Unnormalized::new_wip(field.ty),
521            )
522            .map_err(|errors| infcx.err_ctxt().report_fulfillment_errors(errors))?;
523        if field_type_is_reborrow(
524            tcx,
525            &infcx,
526            reborrow_trait,
527            impl_did,
528            param_env,
529            field.ty,
530            field.span,
531        ) {
532            // Field implements Reborrow, check remaining fields.
533            continue;
534        }
535
536        // Field does not implement Reborrow: it must be Copy.
537        assert_field_type_is_copy(tcx, &infcx, impl_did, param_env, field.ty, field.span)?;
538    }
539
540    Ok(())
541}
542
543fn trait_impl_lifetime_params_count(tcx: TyCtxt<'_>, did: LocalDefId) -> usize {
544    tcx.generics_of(did)
545        .own_params
546        .iter()
547        .filter(|p| #[allow(non_exhaustive_omitted_patterns)] match p.kind {
    ty::GenericParamDefKind::Lifetime => true,
    _ => false,
}matches!(p.kind, ty::GenericParamDefKind::Lifetime))
548        .count()
549}
550
551fn generic_lifetime_params_count(args: &[ty::GenericArg<'_>]) -> usize {
552    args.iter().filter(|arg| arg.as_region().is_some()).count()
553}
554
555#[derive(#[automatically_derived]
#[doc(hidden)]
unsafe impl<'tcx> ::core::clone::TrivialClone for ReborrowDataField<'tcx> { }
#[automatically_derived]
impl<'tcx> ::core::clone::Clone for ReborrowDataField<'tcx> {
    #[inline]
    fn clone(&self) -> ReborrowDataField<'tcx> {
        let _: ::core::clone::AssertParamIsClone<Ident>;
        let _: ::core::clone::AssertParamIsClone<Symbol>;
        let _: ::core::clone::AssertParamIsClone<Ty<'tcx>>;
        let _: ::core::clone::AssertParamIsClone<Span>;
        *self
    }
}Clone, #[automatically_derived]
impl<'tcx> ::core::marker::Copy for ReborrowDataField<'tcx> { }Copy)]
556struct ReborrowDataField<'tcx> {
557    ident: Ident,
558    name: Symbol,
559    ty: Ty<'tcx>,
560    span: Span,
561}
562
563fn collect_reborrow_data_fields<'tcx>(
564    tcx: TyCtxt<'tcx>,
565    def: ty::AdtDef<'tcx>,
566    args: ty::GenericArgsRef<'tcx>,
567) -> Vec<ReborrowDataField<'tcx>> {
568    def.non_enum_variant()
569        .fields
570        .iter()
571        .filter_map(|field| {
572            let ty = field.ty(tcx, args).skip_norm_wip();
573            (!ty.is_phantom_data()).then_some(ReborrowDataField {
574                ident: field.ident(tcx),
575                name: field.name,
576                ty,
577                span: tcx.def_span(field.did),
578            })
579        })
580        .collect()
581}
582
583fn field_type_is_reborrow<'tcx>(
584    tcx: TyCtxt<'tcx>,
585    infcx: &InferCtxt<'tcx>,
586    reborrow_trait: DefId,
587    impl_did: LocalDefId,
588    param_env: ty::ParamEnv<'tcx>,
589    ty: Ty<'tcx>,
590    span: Span,
591) -> bool {
592    if ty.ref_mutability() == Some(ty::Mutability::Mut) {
593        // Mutable references are Reborrow but not really.
594        return true;
595    }
596
597    let ocx = ObligationCtxt::new(infcx);
598    let cause = traits::ObligationCause::misc(span, impl_did);
599    ocx.register_obligation(Obligation::new(
600        tcx,
601        cause,
602        param_env,
603        ty::TraitRef::new(tcx, reborrow_trait, [ty]),
604    ));
605    ocx.evaluate_obligations_error_on_ambiguity().no_errors()
606}
607
608fn field_type_is_copy<'tcx>(
609    tcx: TyCtxt<'tcx>,
610    infcx: &InferCtxt<'tcx>,
611    impl_did: LocalDefId,
612    param_env: ty::ParamEnv<'tcx>,
613    ty: Ty<'tcx>,
614    span: Span,
615) -> bool {
616    let copy_trait = tcx.require_lang_item(LangItem::Copy, span);
617    let ocx = ObligationCtxt::new(infcx);
618    let cause = traits::ObligationCause::misc(span, impl_did);
619    ocx.register_obligation(Obligation::new(
620        tcx,
621        cause,
622        param_env,
623        ty::TraitRef::new(tcx, copy_trait, [ty]),
624    ));
625    ocx.evaluate_obligations_error_on_ambiguity().no_errors()
626}
627
628fn assert_field_type_is_copy<'tcx>(
629    tcx: TyCtxt<'tcx>,
630    infcx: &InferCtxt<'tcx>,
631    impl_did: LocalDefId,
632    param_env: ty::ParamEnv<'tcx>,
633    ty: Ty<'tcx>,
634    span: Span,
635) -> Result<(), ErrorGuaranteed> {
636    let copy_trait = tcx.require_lang_item(LangItem::Copy, span);
637    let ocx = ObligationCtxt::new_with_diagnostics(infcx);
638    let cause = traits::ObligationCause::misc(span, impl_did);
639    let obligation =
640        Obligation::new(tcx, cause, param_env, ty::TraitRef::new(tcx, copy_trait, [ty]));
641    ocx.register_obligation(obligation);
642    let errors = ocx.evaluate_obligations_error_on_ambiguity();
643
644    if let TraitErrors::HasErrors(errors) = errors {
645        Err(infcx.err_ctxt().report_fulfillment_errors(errors))
646    } else {
647        Ok(())
648    }
649}
650
651pub(crate) fn coerce_unsized_info<'tcx>(
652    tcx: TyCtxt<'tcx>,
653    impl_did: LocalDefId,
654) -> Result<CoerceUnsizedInfo, ErrorGuaranteed> {
655    {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_hir_analysis/src/coherence/builtin.rs:655",
                        "rustc_hir_analysis::coherence::builtin",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_hir_analysis/src/coherence/builtin.rs"),
                        ::tracing_core::__macro_support::Option::Some(655u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::coherence::builtin"),
                        ::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!("compute_coerce_unsized_info(impl_did={0:?})",
                                                    impl_did) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("compute_coerce_unsized_info(impl_did={:?})", impl_did);
656    let span = tcx.def_span(impl_did);
657    let trait_name = "CoerceUnsized";
658
659    let coerce_unsized_trait = tcx.require_lang_item(LangItem::CoerceUnsized, span);
660    let unsize_trait = tcx.require_lang_item(LangItem::Unsize, span);
661
662    let source = tcx.type_of(impl_did).instantiate_identity().skip_norm_wip();
663    let trait_ref = tcx.impl_trait_ref(impl_did).instantiate_identity().skip_norm_wip();
664
665    {
    match (&trait_ref.def_id, &coerce_unsized_trait) {
        (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!(trait_ref.def_id, coerce_unsized_trait);
666    let target = trait_ref.args.type_at(1);
667    {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_hir_analysis/src/coherence/builtin.rs:667",
                        "rustc_hir_analysis::coherence::builtin",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_hir_analysis/src/coherence/builtin.rs"),
                        ::tracing_core::__macro_support::Option::Some(667u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::coherence::builtin"),
                        ::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!("visit_implementation_of_coerce_unsized: {0:?} -> {1:?} (bound)",
                                                    source, target) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("visit_implementation_of_coerce_unsized: {:?} -> {:?} (bound)", source, target);
668
669    let param_env = tcx.param_env(impl_did);
670    if !!source.has_escaping_bound_vars() {
    ::core::panicking::panic("assertion failed: !source.has_escaping_bound_vars()")
};assert!(!source.has_escaping_bound_vars());
671
672    {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_hir_analysis/src/coherence/builtin.rs:672",
                        "rustc_hir_analysis::coherence::builtin",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_hir_analysis/src/coherence/builtin.rs"),
                        ::tracing_core::__macro_support::Option::Some(672u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::coherence::builtin"),
                        ::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!("visit_implementation_of_coerce_unsized: {0:?} -> {1:?} (free)",
                                                    source, target) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("visit_implementation_of_coerce_unsized: {:?} -> {:?} (free)", source, target);
673
674    let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
675    let cause = ObligationCause::misc(span, impl_did);
676    let check_mutbl = |mt_a: ty::TypeAndMut<'tcx>,
677                       mt_b: ty::TypeAndMut<'tcx>,
678                       mk_ptr: &dyn Fn(Ty<'tcx>) -> Ty<'tcx>| {
679        if mt_a.mutbl < mt_b.mutbl {
680            infcx
681                .err_ctxt()
682                .report_mismatched_types(
683                    &cause,
684                    param_env,
685                    mk_ptr(mt_b.ty),
686                    target,
687                    ty::error::TypeError::Mutability,
688                )
689                .emit();
690        }
691        (mt_a.ty, mt_b.ty, unsize_trait, None, span)
692    };
693    let (source, target, trait_def_id, kind, field_span) = match (source.kind(), target.kind()) {
694        (&ty::Pat(ty_a, pat_a), &ty::Pat(ty_b, pat_b)) => {
695            if pat_a != pat_b {
696                return Err(tcx.dcx().emit_err(diagnostics::CoerceSamePatKind {
697                    span,
698                    trait_name,
699                    pat_a: pat_a.to_string(),
700                    pat_b: pat_b.to_string(),
701                }));
702            }
703            (ty_a, ty_b, coerce_unsized_trait, None, span)
704        }
705
706        (&ty::Ref(r_a, ty_a, mutbl_a), &ty::Ref(r_b, ty_b, mutbl_b)) => {
707            infcx.sub_regions(
708                SubregionOrigin::RelateObjectBound(span),
709                r_b,
710                r_a,
711                ty::VisibleForLeakCheck::Yes,
712            );
713            let mt_a = ty::TypeAndMut { ty: ty_a, mutbl: mutbl_a };
714            let mt_b = ty::TypeAndMut { ty: ty_b, mutbl: mutbl_b };
715            check_mutbl(mt_a, mt_b, &|ty| Ty::new_imm_ref(tcx, r_b, ty))
716        }
717
718        (&ty::Ref(_, ty_a, mutbl_a), &ty::RawPtr(ty_b, mutbl_b))
719        | (&ty::RawPtr(ty_a, mutbl_a), &ty::RawPtr(ty_b, mutbl_b)) => {
720            let mt_a = ty::TypeAndMut { ty: ty_a, mutbl: mutbl_a };
721            let mt_b = ty::TypeAndMut { ty: ty_b, mutbl: mutbl_b };
722            check_mutbl(mt_a, mt_b, &|ty| Ty::new_imm_ptr(tcx, ty))
723        }
724
725        (&ty::Adt(def_a, args_a), &ty::Adt(def_b, args_b))
726            if def_a.is_struct() && def_b.is_struct() =>
727        {
728            if def_a != def_b {
729                let source_path = tcx.def_path_str(def_a.did());
730                let target_path = tcx.def_path_str(def_b.did());
731                return Err(tcx.dcx().emit_err(diagnostics::CoerceSameStruct {
732                    span,
733                    trait_name,
734                    note: true,
735                    source_path,
736                    target_path,
737                }));
738            }
739
740            // Here we are considering a case of converting
741            // `S<P0...Pn>` to `S<Q0...Qn>`. As an example, let's imagine a struct `Foo<T, U>`,
742            // which acts like a pointer to `U`, but carries along some extra data of type `T`:
743            //
744            //     struct Foo<T, U> {
745            //         extra: T,
746            //         ptr: *mut U,
747            //     }
748            //
749            // We might have an impl that allows (e.g.) `Foo<T, [i32; 3]>` to be unsized
750            // to `Foo<T, [i32]>`. That impl would look like:
751            //
752            //   impl<T, U: Unsize<V>, V> CoerceUnsized<Foo<T, V>> for Foo<T, U> {}
753            //
754            // Here `U = [i32; 3]` and `V = [i32]`. At runtime,
755            // when this coercion occurs, we would be changing the
756            // field `ptr` from a thin pointer of type `*mut [i32;
757            // 3]` to a wide pointer of type `*mut [i32]` (with
758            // extra data `3`). **The purpose of this check is to
759            // make sure that we know how to do this conversion.**
760            //
761            // To check if this impl is legal, we would walk down
762            // the fields of `Foo` and consider their types with
763            // both generic parameters. We are looking to find that
764            // exactly one (non-phantom) field has changed its
765            // type, which we will expect to be the pointer that
766            // is becoming fat (we could probably generalize this
767            // to multiple thin pointers of the same type becoming
768            // fat, but we don't). In this case:
769            //
770            // - `extra` has type `T` before and type `T` after
771            // - `ptr` has type `*mut U` before and type `*mut V` after
772            //
773            // Since just one field changed, we would then check
774            // that `*mut U: CoerceUnsized<*mut V>` is implemented
775            // (in other words, that we know how to do this
776            // conversion). This will work out because `U:
777            // Unsize<V>`, and we have a builtin rule that `*mut
778            // U` can be coerced to `*mut V` if `U: Unsize<V>`.
779            let fields = &def_a.non_enum_variant().fields;
780            let diff_fields = fields
781                .iter_enumerated()
782                .filter_map(|(i, f)| {
783                    let (a, b) =
784                        (f.ty(tcx, args_a).skip_norm_wip(), f.ty(tcx, args_b).skip_norm_wip());
785
786                    // Ignore PhantomData fields
787                    let unnormalized_ty = tcx.type_of(f.did).instantiate_identity();
788                    if tcx
789                        .try_normalize_erasing_regions(
790                            ty::TypingEnv::non_body_analysis(tcx, def_a.did()),
791                            unnormalized_ty,
792                        )
793                        .unwrap_or(unnormalized_ty.skip_norm_wip())
794                        .is_phantom_data()
795                    {
796                        return None;
797                    }
798
799                    // Ignore fields that aren't changed; it may
800                    // be that we could get away with subtyping or
801                    // something more accepting, but we use
802                    // equality because we want to be able to
803                    // perform this check without computing
804                    // variance or constraining opaque types' hidden types.
805                    // (This is because we may have to evaluate constraint
806                    // expressions in the course of execution.)
807                    // See e.g., #41936.
808                    if a == b {
809                        return None;
810                    }
811
812                    // Collect up all fields that were significantly changed
813                    // i.e., those that contain T in coerce_unsized T -> U
814                    Some((i, a, b, tcx.def_span(f.did)))
815                })
816                .collect::<Vec<_>>();
817
818            if diff_fields.is_empty() {
819                return Err(tcx.dcx().emit_err(diagnostics::CoerceNoField {
820                    span,
821                    trait_name,
822                    note: true,
823                }));
824            } else if diff_fields.len() > 1 {
825                let item = tcx.hir_expect_item(impl_did);
826                let span = if let ItemKind::Impl(hir::Impl { of_trait: Some(of_trait), .. }) =
827                    &item.kind
828                {
829                    of_trait.trait_ref.path.span
830                } else {
831                    tcx.def_span(impl_did)
832                };
833
834                return Err(tcx.dcx().emit_err(diagnostics::CoerceMulti {
835                    span,
836                    trait_name,
837                    number: diff_fields.len(),
838                    fields: diff_fields.iter().map(|(_, _, _, s)| *s).collect::<Vec<_>>().into(),
839                }));
840            }
841
842            let (i, a, b, field_span) = diff_fields[0];
843            let kind = ty::adjustment::CustomCoerceUnsized::Struct(i);
844            (a, b, coerce_unsized_trait, Some(kind), field_span)
845        }
846
847        _ => {
848            return Err(tcx
849                .dcx()
850                .emit_err(diagnostics::CoerceUnsizedNonStruct { span, trait_name }));
851        }
852    };
853
854    // Register an obligation for `A: Trait<B>`.
855    let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
856    let cause = traits::ObligationCause::misc(span, impl_did);
857    let obligation = Obligation::new(
858        tcx,
859        cause,
860        param_env,
861        ty::TraitRef::new(tcx, trait_def_id, [source, target]),
862    );
863    ocx.register_obligation(obligation);
864    let errors = ocx.evaluate_obligations_error_on_ambiguity();
865
866    if let TraitErrors::HasErrors(errors) = errors {
867        if is_from_coerce_pointee_derive(tcx, span) {
868            return Err(tcx.dcx().emit_err(diagnostics::CoerceFieldValidity {
869                span,
870                trait_name,
871                ty: trait_ref.self_ty(),
872                field_span,
873                field_ty: source,
874            }));
875        } else {
876            return Err(infcx.err_ctxt().report_fulfillment_errors(errors));
877        }
878    }
879
880    // Finally, resolve all regions.
881    ocx.resolve_regions_and_report_errors(impl_did, param_env, [])?;
882
883    Ok(CoerceUnsizedInfo { custom_kind: kind })
884}
885
886fn infringing_fields_error<'tcx>(
887    tcx: TyCtxt<'tcx>,
888    infringing_tys: impl Iterator<Item = (Span, Ty<'tcx>, InfringingFieldsReason<'tcx>)>,
889    lang_item: LangItem,
890    impl_did: LocalDefId,
891    impl_span: Span,
892) -> ErrorGuaranteed {
893    let trait_did = tcx.require_lang_item(lang_item, impl_span);
894
895    let trait_name = tcx.def_path_str(trait_did);
896
897    // We'll try to suggest constraining type parameters to fulfill the requirements of
898    // their `Copy` implementation.
899    let mut errors: BTreeMap<_, Vec<_>> = Default::default();
900    let mut bounds = ::alloc::vec::Vec::new()vec![];
901
902    let mut seen_tys = FxHashSet::default();
903
904    let mut label_spans = Vec::new();
905
906    for (span, ty, reason) in infringing_tys {
907        // Only report an error once per type.
908        if !seen_tys.insert(ty) {
909            continue;
910        }
911
912        label_spans.push(span);
913
914        match reason {
915            InfringingFieldsReason::Fulfill(fulfillment_errors) => {
916                for error in fulfillment_errors {
917                    let error_predicate = error.obligation.predicate;
918                    // Only note if it's not the root obligation, otherwise it's trivial and
919                    // should be self-explanatory (i.e. a field literally doesn't implement Copy).
920
921                    // FIXME: This error could be more descriptive, especially if the error_predicate
922                    // contains a foreign type or if it's a deeply nested type...
923                    if error_predicate != error.root_obligation.predicate {
924                        errors
925                            .entry((ty.to_string(), error_predicate.to_string()))
926                            .or_default()
927                            .push(error.obligation.cause.span);
928                    }
929                    if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(ty::TraitClause {
930                        trait_ref,
931                        polarity: ty::ClausePolarity::Positive,
932                        ..
933                    })) = error_predicate.kind().skip_binder()
934                    {
935                        let ty = trait_ref.self_ty();
936                        if let ty::Param(_) = ty.kind() {
937                            bounds.push((
938                                ::alloc::__export::must_use({ ::alloc::fmt::format(format_args!("{0}", ty)) })format!("{ty}"),
939                                trait_ref.print_trait_sugared().to_string(),
940                                Some(trait_ref.def_id),
941                            ));
942                        }
943                    }
944                }
945            }
946            InfringingFieldsReason::Regions(region_errors) => {
947                for error in region_errors {
948                    let ty = ty.to_string();
949                    match error {
950                        RegionResolutionError::ConcreteFailure(origin, a, b) => {
951                            let predicate = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}: {1}", b, a))
    })format!("{b}: {a}");
952                            errors
953                                .entry((ty.clone(), predicate.clone()))
954                                .or_default()
955                                .push(origin.span());
956                            if let ty::RegionKind::ReEarlyParam(ebr) = b.kind()
957                                && ebr.is_named()
958                            {
959                                bounds.push((b.to_string(), a.to_string(), None));
960                            }
961                        }
962                        RegionResolutionError::GenericBoundFailure(origin, a, b) => {
963                            let predicate = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}: {1}", a, b))
    })format!("{a}: {b}");
964                            errors
965                                .entry((ty.clone(), predicate.clone()))
966                                .or_default()
967                                .push(origin.span());
968                            if let infer::region_constraints::GenericKind::Param(_) = a {
969                                bounds.push((a.to_string(), b.to_string(), None));
970                            }
971                        }
972                        _ => continue,
973                    }
974                }
975            }
976        }
977    }
978    let mut notes = Vec::new();
979    for ((ty, error_predicate), spans) in errors {
980        let span: MultiSpan = spans.into();
981        notes.push(diagnostics::ImplForTyRequires {
982            span,
983            error_predicate,
984            trait_name: trait_name.clone(),
985            ty,
986        });
987    }
988
989    let mut err = tcx.dcx().create_err(diagnostics::TraitCannotImplForTy {
990        span: impl_span,
991        trait_name,
992        label_spans,
993        notes,
994    });
995
996    suggest_constraining_type_params(
997        tcx,
998        tcx.hir_get_generics(impl_did).expect("impls always have generics"),
999        &mut err,
1000        bounds
1001            .iter()
1002            .map(|(param, constraint, def_id)| (param.as_str(), constraint.as_str(), *def_id)),
1003        None,
1004    );
1005
1006    err.emit()
1007}
1008
1009fn visit_implementation_of_coerce_pointee_validity(
1010    checker: &Checker<'_>,
1011) -> Result<(), ErrorGuaranteed> {
1012    let tcx = checker.tcx;
1013    let self_ty =
1014        tcx.impl_trait_ref(checker.impl_def_id).instantiate_identity().skip_norm_wip().self_ty();
1015    let span = tcx.def_span(checker.impl_def_id);
1016    if !tcx.is_builtin_derived(checker.impl_def_id.into()) {
1017        return Err(tcx.dcx().emit_err(diagnostics::CoercePointeeNoUserValidityAssertion { span }));
1018    }
1019    let ty::Adt(def, _args) = self_ty.kind() else {
1020        return Err(tcx.dcx().emit_err(diagnostics::CoercePointeeNotConcreteType { span }));
1021    };
1022    let did = def.did();
1023    // Now get a more precise span of the `struct`.
1024    let span = tcx.def_span(did);
1025    if !def.is_struct() {
1026        return Err(tcx
1027            .dcx()
1028            .emit_err(diagnostics::CoercePointeeNotStruct { span, kind: def.descr().into() }));
1029    }
1030    if !def.repr().transparent() {
1031        return Err(tcx.dcx().emit_err(diagnostics::CoercePointeeNotTransparent { span }));
1032    }
1033    if def.all_fields().next().is_none() {
1034        return Err(tcx.dcx().emit_err(diagnostics::CoercePointeeNoField { span }));
1035    }
1036    Ok(())
1037}