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