1use 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::def_id::{DefId, LocalDefId};
11use rustc_hir::lang_items::LangItem;
12use rustc_infer::infer::{self, InferCtxt, RegionResolutionError, SubregionOrigin, TyCtxtInferExt};
13use rustc_infer::traits::{Obligation, PredicateObligations};
14use rustc_middle::ty::adjustment::CoerceUnsizedInfo;
15use rustc_middle::ty::print::PrintTraitRefExt as _;
16use rustc_middle::ty::relate::solver_relating::RelateExt;
17use rustc_middle::ty::{
18 self, Ty, TyCtxt, TypeVisitableExt, TypingMode, Unnormalized, suggest_constraining_type_params,
19};
20use rustc_span::{DUMMY_SP, Span, sym};
21use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
22use rustc_trait_selection::traits::misc::{
23 ConstParamTyImplementationError, CopyImplementationError, InfringingFieldsReason,
24 type_allowed_to_implement_const_param_ty, type_allowed_to_implement_copy,
25};
26use rustc_trait_selection::traits::{self, FulfillmentError, ObligationCause, ObligationCtxt};
27use tracing::debug;
28
29use crate::diagnostics;
30
31pub(super) fn check_trait<'tcx>(
32 tcx: TyCtxt<'tcx>,
33 trait_def_id: DefId,
34 impl_def_id: LocalDefId,
35 impl_header: ty::ImplTraitHeader<'tcx>,
36) -> Result<(), ErrorGuaranteed> {
37 let lang_items = tcx.lang_items();
38 let checker = Checker { tcx, trait_def_id, impl_def_id, impl_header };
39 checker.check(lang_items.drop_trait(), visit_implementation_of_drop)?;
40 checker.check(lang_items.async_drop_trait(), visit_implementation_of_drop)?;
41 checker.check(lang_items.copy_trait(), visit_implementation_of_copy)?;
42 checker.check(lang_items.unpin_trait(), visit_implementation_of_unpin)?;
43 checker.check(lang_items.const_param_ty_trait(), |checker| {
44 visit_implementation_of_const_param_ty(checker)
45 })?;
46 checker.check(lang_items.coerce_unsized_trait(), visit_implementation_of_coerce_unsized)?;
47 checker.check(lang_items.reborrow(), visit_implementation_of_reborrow)?;
48 checker.check(lang_items.coerce_shared(), visit_implementation_of_coerce_shared)?;
49 checker
50 .check(lang_items.dispatch_from_dyn_trait(), visit_implementation_of_dispatch_from_dyn)?;
51 checker.check(
52 lang_items.coerce_pointee_validated_trait(),
53 visit_implementation_of_coerce_pointee_validity,
54 )?;
55 Ok(())
56}
57
58struct Checker<'tcx> {
59 tcx: TyCtxt<'tcx>,
60 trait_def_id: DefId,
61 impl_def_id: LocalDefId,
62 impl_header: ty::ImplTraitHeader<'tcx>,
63}
64
65impl<'tcx> Checker<'tcx> {
66 fn check(
67 &self,
68 trait_def_id: Option<DefId>,
69 f: impl FnOnce(&Self) -> Result<(), ErrorGuaranteed>,
70 ) -> Result<(), ErrorGuaranteed> {
71 if Some(self.trait_def_id) == trait_def_id { f(self) } else { Ok(()) }
72 }
73}
74
75fn visit_implementation_of_drop(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> {
76 let tcx = checker.tcx;
77 let impl_did = checker.impl_def_id;
78 match checker.impl_header.trait_ref.instantiate_identity().skip_norm_wip().self_ty().kind() {
80 ty::Adt(def, _) if def.did().is_local() => return Ok(()),
81 ty::Error(_) => return Ok(()),
82 _ => {}
83 }
84
85 let impl_ = tcx.hir_expect_item(impl_did).expect_impl();
86
87 Err(tcx.dcx().emit_err(diagnostics::DropImplOnWrongItem {
88 span: impl_.self_ty.span,
89 trait_: tcx.item_name(checker.impl_header.trait_ref.skip_binder().def_id),
90 }))
91}
92
93fn visit_implementation_of_copy(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> {
94 let tcx = checker.tcx;
95 let impl_header = checker.impl_header;
96 let impl_did = checker.impl_def_id;
97 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_analysis/src/coherence/builtin.rs:97",
"rustc_hir_analysis::coherence::builtin",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_analysis/src/coherence/builtin.rs"),
::tracing_core::__macro_support::Option::Some(97u32),
::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};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("visit_implementation_of_copy: impl_did={0:?}",
impl_did) as &dyn Value))])
});
} else { ; }
};debug!("visit_implementation_of_copy: impl_did={:?}", impl_did);
98
99 let self_type = impl_header.trait_ref.instantiate_identity().skip_norm_wip().self_ty();
100 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_analysis/src/coherence/builtin.rs:100",
"rustc_hir_analysis::coherence::builtin",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_analysis/src/coherence/builtin.rs"),
::tracing_core::__macro_support::Option::Some(100u32),
::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};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("visit_implementation_of_copy: self_type={0:?} (bound)",
self_type) as &dyn Value))])
});
} else { ; }
};debug!("visit_implementation_of_copy: self_type={:?} (bound)", self_type);
101
102 let param_env = tcx.param_env(impl_did);
103 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());
104
105 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_analysis/src/coherence/builtin.rs:105",
"rustc_hir_analysis::coherence::builtin",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_analysis/src/coherence/builtin.rs"),
::tracing_core::__macro_support::Option::Some(105u32),
::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};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("visit_implementation_of_copy: self_type={0:?} (free)",
self_type) as &dyn Value))])
});
} else { ; }
};debug!("visit_implementation_of_copy: self_type={:?} (free)", self_type);
106
107 if let ty::ImplPolarity::Negative = impl_header.polarity {
108 return Ok(());
109 }
110
111 let cause = traits::ObligationCause::misc(DUMMY_SP, impl_did);
112 match type_allowed_to_implement_copy(tcx, param_env, self_type, cause, impl_header.safety) {
113 Ok(()) => Ok(()),
114 Err(CopyImplementationError::InfringingFields(fields)) => {
115 let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
116 Err(infringing_fields_error(
117 tcx,
118 fields.into_iter().map(|(field, ty, reason)| (tcx.def_span(field.did), ty, reason)),
119 LangItem::Copy,
120 impl_did,
121 span,
122 ))
123 }
124 Err(CopyImplementationError::NotAnAdt) => {
125 let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
126 Err(tcx.dcx().emit_err(diagnostics::CopyImplOnNonAdt { span }))
127 }
128 Err(CopyImplementationError::HasDestructor(did)) => {
129 let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
130 let impl_ = tcx.def_span(did);
131 Err(tcx.dcx().emit_err(diagnostics::CopyImplOnTypeWithDtor { span, impl_ }))
132 }
133 Err(CopyImplementationError::HasUnsafeFields) => {
134 let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
135 Err(tcx
136 .dcx()
137 .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)))
138 }
139 }
140}
141
142fn visit_implementation_of_unpin(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> {
143 let tcx = checker.tcx;
144 let impl_header = checker.impl_header;
145 let impl_did = checker.impl_def_id;
146 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_analysis/src/coherence/builtin.rs:146",
"rustc_hir_analysis::coherence::builtin",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_analysis/src/coherence/builtin.rs"),
::tracing_core::__macro_support::Option::Some(146u32),
::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};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("visit_implementation_of_unpin: impl_did={0:?}",
impl_did) as &dyn Value))])
});
} else { ; }
};debug!("visit_implementation_of_unpin: impl_did={:?}", impl_did);
147
148 let self_type = impl_header.trait_ref.instantiate_identity().skip_norm_wip().self_ty();
149 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_analysis/src/coherence/builtin.rs:149",
"rustc_hir_analysis::coherence::builtin",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_analysis/src/coherence/builtin.rs"),
::tracing_core::__macro_support::Option::Some(149u32),
::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};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("visit_implementation_of_unpin: self_type={0:?}",
self_type) as &dyn Value))])
});
} else { ; }
};debug!("visit_implementation_of_unpin: self_type={:?}", self_type);
150
151 let span = tcx.def_span(impl_did);
152
153 if tcx.features().pin_ergonomics() {
154 match self_type.kind() {
155 ty::Adt(adt, _) if adt.is_pin_project() => {
162 return Err(tcx.dcx().emit_err(crate::diagnostics::ImplUnpinForPinProjectedType {
163 span,
164 adt_span: tcx.def_span(adt.did()),
165 adt_name: tcx.item_name(adt.did()),
166 }));
167 }
168 ty::Adt(_, _) => {}
169 _ => {
170 return Err(tcx.dcx().span_delayed_bug(span, "impl of `Unpin` for a non-adt type"));
171 }
172 };
173 }
174 Ok(())
175}
176
177fn visit_implementation_of_const_param_ty(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> {
178 let tcx = checker.tcx;
179 let header = checker.impl_header;
180 let impl_did = checker.impl_def_id;
181 let self_type = header.trait_ref.instantiate_identity().skip_norm_wip().self_ty();
182 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());
183
184 let param_env = tcx.param_env(impl_did);
185
186 if let ty::ImplPolarity::Negative | ty::ImplPolarity::Reservation = header.polarity {
187 return Ok(());
188 }
189
190 if tcx.features().const_param_ty_unchecked() {
191 return Ok(());
192 }
193
194 if !tcx.features().adt_const_params() {
195 match *self_type.kind() {
196 ty::Adt(adt, _) if adt.is_struct() => {
197 let struct_vis = tcx.visibility(adt.did());
198 for variant in adt.variants() {
199 for field in &variant.fields {
200 if struct_vis.greater_than(field.vis, tcx) {
201 let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
202 return Err(tcx
203 .dcx()
204 .emit_err(diagnostics::ConstParamTyFieldVisMismatch { span }));
205 }
206 }
207 }
208 }
209
210 _ => {}
211 }
212 }
213
214 let cause = traits::ObligationCause::misc(DUMMY_SP, impl_did);
215 match type_allowed_to_implement_const_param_ty(tcx, param_env, self_type, cause) {
216 Ok(()) => Ok(()),
217 Err(ConstParamTyImplementationError::InfrigingFields(fields)) => {
218 let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
219 Err(infringing_fields_error(
220 tcx,
221 fields.into_iter().map(|(field, ty, reason)| (tcx.def_span(field.did), ty, reason)),
222 LangItem::ConstParamTy,
223 impl_did,
224 span,
225 ))
226 }
227 Err(ConstParamTyImplementationError::NotAnAdtOrBuiltinAllowed) => {
228 let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
229 Err(tcx.dcx().emit_err(diagnostics::ConstParamTyImplOnNonAdt { span }))
230 }
231 Err(ConstParamTyImplementationError::NonExhaustive(attr_span)) => {
232 let defn_span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
233 Err(tcx
234 .dcx()
235 .emit_err(diagnostics::ConstParamTyImplOnNonExhaustive { defn_span, attr_span }))
236 }
237 Err(ConstParamTyImplementationError::InvalidInnerTyOfBuiltinTy(infringing_tys)) => {
238 let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
239 Err(infringing_fields_error(
240 tcx,
241 infringing_tys.into_iter().map(|(ty, reason)| (span, ty, reason)),
242 LangItem::ConstParamTy,
243 impl_did,
244 span,
245 ))
246 }
247 Err(ConstParamTyImplementationError::UnsizedConstParamsFeatureRequired) => {
248 let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
249 Err(tcx.dcx().emit_err(diagnostics::ConstParamTyImplOnUnsized { span }))
250 }
251 }
252}
253
254fn visit_implementation_of_coerce_unsized(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 compiler/rustc_hir_analysis/src/coherence/builtin.rs:257",
"rustc_hir_analysis::coherence::builtin",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("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};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("visit_implementation_of_coerce_unsized: impl_did={0:?}",
impl_did) as &dyn Value))])
});
} else { ; }
};debug!("visit_implementation_of_coerce_unsized: impl_did={:?}", impl_did);
258
259 tcx.ensure_result().coerce_unsized_info(impl_did)
263}
264
265fn visit_implementation_of_reborrow(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 compiler/rustc_hir_analysis/src/coherence/builtin.rs:268",
"rustc_hir_analysis::coherence::builtin",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("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};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("visit_implementation_of_reborrow: impl_did={0:?}",
impl_did) as &dyn Value))])
});
} else { ; }
};debug!("visit_implementation_of_reborrow: impl_did={:?}", impl_did);
269
270 reborrow_info(tcx, impl_did)
274}
275
276fn visit_implementation_of_coerce_shared(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> {
277 let tcx = checker.tcx;
278 let impl_did = checker.impl_def_id;
279 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_analysis/src/coherence/builtin.rs:279",
"rustc_hir_analysis::coherence::builtin",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_analysis/src/coherence/builtin.rs"),
::tracing_core::__macro_support::Option::Some(279u32),
::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};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("visit_implementation_of_coerce_shared: impl_did={0:?}",
impl_did) as &dyn Value))])
});
} else { ; }
};debug!("visit_implementation_of_coerce_shared: impl_did={:?}", impl_did);
280
281 coerce_shared_info(tcx, impl_did)
285}
286
287fn is_from_coerce_pointee_derive(tcx: TyCtxt<'_>, span: Span) -> bool {
288 span.ctxt()
289 .outer_expn_data()
290 .macro_def_id
291 .is_some_and(|def_id| tcx.is_diagnostic_item(sym::CoercePointee, def_id))
292}
293
294fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> {
295 let tcx = checker.tcx;
296 let impl_did = checker.impl_def_id;
297 let trait_ref = checker.impl_header.trait_ref.instantiate_identity().skip_norm_wip();
298 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_analysis/src/coherence/builtin.rs:298",
"rustc_hir_analysis::coherence::builtin",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_analysis/src/coherence/builtin.rs"),
::tracing_core::__macro_support::Option::Some(298u32),
::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};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("visit_implementation_of_dispatch_from_dyn: impl_did={0:?}",
impl_did) as &dyn Value))])
});
} else { ; }
};debug!("visit_implementation_of_dispatch_from_dyn: impl_did={:?}", impl_did);
299
300 let span = tcx.def_span(impl_did);
301 let trait_name = "DispatchFromDyn";
302
303 let source = trait_ref.self_ty();
304 let target = {
305 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));
306
307 trait_ref.args.type_at(1)
308 };
309
310 let mut res = Ok(());
313 tcx.for_each_relevant_impl(
314 tcx.require_lang_item(LangItem::CoerceUnsized, span),
315 source,
316 |impl_def_id| {
317 res = res.and(tcx.ensure_result().coerce_unsized_info(impl_def_id));
318 },
319 );
320 res?;
321
322 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_analysis/src/coherence/builtin.rs:322",
"rustc_hir_analysis::coherence::builtin",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_analysis/src/coherence/builtin.rs"),
::tracing_core::__macro_support::Option::Some(322u32),
::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};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("visit_implementation_of_dispatch_from_dyn: {0:?} -> {1:?}",
source, target) as &dyn Value))])
});
} else { ; }
};debug!("visit_implementation_of_dispatch_from_dyn: {:?} -> {:?}", source, target);
323
324 let param_env = tcx.param_env(impl_did);
325
326 let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
327 let cause = ObligationCause::misc(span, impl_did);
328
329 match (source.kind(), target.kind()) {
338 (&ty::Pat(_, pat_a), &ty::Pat(_, pat_b)) => {
339 if pat_a != pat_b {
340 return Err(tcx.dcx().emit_err(diagnostics::CoerceSamePatKind {
341 span,
342 trait_name,
343 pat_a: pat_a.to_string(),
344 pat_b: pat_b.to_string(),
345 }));
346 }
347 Ok(())
348 }
349
350 (&ty::Ref(r_a, _, mutbl_a), ty::Ref(r_b, _, mutbl_b))
351 if r_a == *r_b && mutbl_a == *mutbl_b =>
352 {
353 Ok(())
354 }
355 (&ty::RawPtr(_, a_mutbl), &ty::RawPtr(_, b_mutbl)) if a_mutbl == b_mutbl => Ok(()),
356 (&ty::Adt(def_a, args_a), &ty::Adt(def_b, args_b))
357 if def_a.is_struct() && def_b.is_struct() =>
358 {
359 if def_a != def_b {
360 let source_path = tcx.def_path_str(def_a.did());
361 let target_path = tcx.def_path_str(def_b.did());
362 return Err(tcx.dcx().emit_err(diagnostics::CoerceSameStruct {
363 span,
364 trait_name,
365 note: true,
366 source_path,
367 target_path,
368 }));
369 }
370
371 if def_a.repr().c() || def_a.repr().packed() {
372 return Err(tcx.dcx().emit_err(diagnostics::DispatchFromDynRepr { span }));
373 }
374
375 let fields = &def_a.non_enum_variant().fields;
376
377 let mut res = Ok(());
378 let coerced_fields = fields
379 .iter_enumerated()
380 .filter_map(|(i, field)| {
381 let unnormalized_ty = tcx.type_of(field.did).instantiate_identity();
383 if tcx
384 .try_normalize_erasing_regions(
385 ty::TypingEnv::non_body_analysis(tcx, def_a.did()),
386 unnormalized_ty,
387 )
388 .unwrap_or(unnormalized_ty.skip_norm_wip())
389 .is_phantom_data()
390 {
391 return None;
392 }
393
394 let ty_a = field.ty(tcx, args_a).skip_norm_wip();
395 let ty_b = field.ty(tcx, args_b).skip_norm_wip();
396
397 if ty_a == ty_b {
399 if let Ok(layout) =
404 tcx.layout_of(infcx.typing_env(param_env).as_query_input(ty_a))
405 && layout.is_1zst()
406 && !ty_a.has_non_region_param()
407 {
408 return None;
410 }
411
412 res = Err(tcx.dcx().emit_err(diagnostics::DispatchFromDynZST {
413 span,
414 name: field.ident(tcx),
415 ty: ty_a,
416 }));
417
418 None
419 } else {
420 Some((i, ty_a, ty_b, tcx.def_span(field.did)))
421 }
422 })
423 .collect::<Vec<_>>();
424 res?;
425
426 if coerced_fields.is_empty() {
427 return Err(tcx.dcx().emit_err(diagnostics::CoerceNoField {
428 span,
429 trait_name,
430 note: true,
431 }));
432 } else if let &[(_, ty_a, ty_b, field_span)] = &coerced_fields[..] {
433 let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
434 ocx.register_obligation(Obligation::new(
435 tcx,
436 cause.clone(),
437 param_env,
438 ty::TraitRef::new(tcx, trait_ref.def_id, [ty_a, ty_b]),
439 ));
440 let errors = ocx.evaluate_obligations_error_on_ambiguity();
441 if !errors.is_empty() {
442 if is_from_coerce_pointee_derive(tcx, span) {
443 return Err(tcx.dcx().emit_err(diagnostics::CoerceFieldValidity {
444 span,
445 trait_name,
446 ty: trait_ref.self_ty(),
447 field_span,
448 field_ty: ty_a,
449 }));
450 } else {
451 return Err(infcx.err_ctxt().report_fulfillment_errors(errors));
452 }
453 }
454
455 ocx.resolve_regions_and_report_errors(impl_did, param_env, [])?;
457
458 Ok(())
459 } else {
460 return Err(tcx.dcx().emit_err(diagnostics::CoerceMulti {
461 span,
462 trait_name,
463 number: coerced_fields.len(),
464 fields: coerced_fields.iter().map(|(_, _, _, s)| *s).collect::<Vec<_>>().into(),
465 }));
466 }
467 }
468 _ => Err(tcx.dcx().emit_err(diagnostics::CoerceUnsizedNonStruct { span, trait_name })),
469 }
470}
471
472fn structurally_normalize_ty<'tcx>(
473 tcx: TyCtxt<'tcx>,
474 infcx: &InferCtxt<'tcx>,
475 impl_did: LocalDefId,
476 span: Span,
477 ty: Unnormalized<'tcx, Ty<'tcx>>,
478) -> Option<(Ty<'tcx>, PredicateObligations<'tcx>)> {
479 let ocx = ObligationCtxt::new(infcx);
480 let Ok(normalized_ty) = ocx.structurally_normalize_ty(
481 &traits::ObligationCause::misc(span, impl_did),
482 tcx.param_env(impl_did),
483 ty,
484 ) else {
485 return None;
488 };
489 let errors = ocx.try_evaluate_obligations();
490 if !errors.is_empty() {
491 if infcx.next_trait_solver() {
492 ::core::panicking::panic("internal error: entered unreachable code");unreachable!();
493 }
494 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_analysis/src/coherence/builtin.rs:496",
"rustc_hir_analysis::coherence::builtin",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_analysis/src/coherence/builtin.rs"),
::tracing_core::__macro_support::Option::Some(496u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::coherence::builtin"),
::tracing_core::field::FieldSet::new(&["message", "errors"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("encountered errors while fulfilling")
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&errors) as
&dyn Value))])
});
} else { ; }
};debug!(?errors, "encountered errors while fulfilling");
497 return None;
498 }
499
500 Some((normalized_ty, ocx.into_pending_obligations()))
501}
502
503pub(crate) fn reborrow_info<'tcx>(
504 tcx: TyCtxt<'tcx>,
505 impl_did: LocalDefId,
506) -> Result<(), ErrorGuaranteed> {
507 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_analysis/src/coherence/builtin.rs:507",
"rustc_hir_analysis::coherence::builtin",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_analysis/src/coherence/builtin.rs"),
::tracing_core::__macro_support::Option::Some(507u32),
::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};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("compute_reborrow_info(impl_did={0:?})",
impl_did) as &dyn Value))])
});
} else { ; }
};debug!("compute_reborrow_info(impl_did={:?})", impl_did);
508 let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
509 let span = tcx.def_span(impl_did);
510 let trait_name = "Reborrow";
511
512 let reborrow_trait = tcx.require_lang_item(LangItem::Reborrow, span);
513
514 let source = tcx.type_of(impl_did).instantiate_identity().skip_norm_wip();
515 let trait_ref = tcx.impl_trait_ref(impl_did).instantiate_identity().skip_norm_wip();
516
517 if trait_impl_lifetime_params_count(tcx, impl_did) != 1 {
518 return Err(tcx
519 .dcx()
520 .emit_err(diagnostics::CoerceSharedNotSingleLifetimeParam { span, trait_name }));
521 }
522
523 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);
524 let param_env = tcx.param_env(impl_did);
525 if !!source.has_escaping_bound_vars() {
::core::panicking::panic("assertion failed: !source.has_escaping_bound_vars()")
};assert!(!source.has_escaping_bound_vars());
526
527 let (def, args) = match source.kind() {
528 &ty::Adt(def, args) if def.is_struct() => (def, args),
529 _ => {
530 return Err(tcx
532 .dcx()
533 .emit_err(diagnostics::CoerceUnsizedNonStruct { span, trait_name }));
534 }
535 };
536
537 let lifetimes_count = generic_lifetime_params_count(args);
538 let data_fields = collect_struct_data_fields(tcx, def, args);
539
540 if lifetimes_count != 1 {
541 let item = tcx.hir_expect_item(impl_did);
542 let _span = if let ItemKind::Impl(hir::Impl { of_trait: Some(of_trait), .. }) = &item.kind {
543 of_trait.trait_ref.path.span
544 } else {
545 tcx.def_span(impl_did)
546 };
547
548 return Err(tcx.dcx().emit_err(diagnostics::CoerceSharedMulti { span, trait_name }));
549 }
550
551 if data_fields.is_empty() {
552 return Ok(());
553 }
554
555 for (field, span) in data_fields {
557 if assert_field_type_is_reborrow(
558 tcx,
559 &infcx,
560 reborrow_trait,
561 impl_did,
562 param_env,
563 field,
564 span,
565 )
566 .is_ok()
567 {
568 continue;
570 }
571
572 assert_field_type_is_copy(tcx, &infcx, impl_did, param_env, field, span)?;
574 }
575
576 Ok(())
577}
578
579fn assert_field_type_is_reborrow<'tcx>(
580 tcx: TyCtxt<'tcx>,
581 infcx: &InferCtxt<'tcx>,
582 reborrow_trait: DefId,
583 impl_did: LocalDefId,
584 param_env: ty::ParamEnv<'tcx>,
585 ty: Ty<'tcx>,
586 span: Span,
587) -> Result<(), Vec<FulfillmentError<'tcx>>> {
588 if ty.ref_mutability() == Some(ty::Mutability::Mut) {
589 return Ok(());
591 }
592 let ocx = ObligationCtxt::new_with_diagnostics(infcx);
593 let cause = traits::ObligationCause::misc(span, impl_did);
594 let obligation =
595 Obligation::new(tcx, cause, param_env, ty::TraitRef::new(tcx, reborrow_trait, [ty]));
596 ocx.register_obligation(obligation);
597 let errors = ocx.evaluate_obligations_error_on_ambiguity();
598
599 if !errors.is_empty() { Err(errors) } else { Ok(()) }
600}
601
602pub(crate) fn coerce_shared_info<'tcx>(
603 tcx: TyCtxt<'tcx>,
604 impl_did: LocalDefId,
605) -> Result<(), ErrorGuaranteed> {
606 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_analysis/src/coherence/builtin.rs:606",
"rustc_hir_analysis::coherence::builtin",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_analysis/src/coherence/builtin.rs"),
::tracing_core::__macro_support::Option::Some(606u32),
::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};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("compute_coerce_shared_info(impl_did={0:?})",
impl_did) as &dyn Value))])
});
} else { ; }
};debug!("compute_coerce_shared_info(impl_did={:?})", impl_did);
607 let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
608 let span = tcx.def_span(impl_did);
609 let trait_name = "CoerceShared";
610
611 let coerce_shared_trait = tcx.require_lang_item(LangItem::CoerceShared, span);
612
613 let source = tcx.type_of(impl_did).instantiate_identity().skip_norm_wip();
614 let trait_ref = tcx.impl_trait_ref(impl_did).instantiate_identity().skip_norm_wip();
615
616 if trait_impl_lifetime_params_count(tcx, impl_did) != 1 {
617 return Err(tcx
618 .dcx()
619 .emit_err(diagnostics::CoerceSharedNotSingleLifetimeParam { span, trait_name }));
620 }
621
622 match (&trait_ref.def_id, &coerce_shared_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_shared_trait);
623 let Some((target, _obligations)) = structurally_normalize_ty(
624 tcx,
625 &infcx,
626 impl_did,
627 span,
628 Unnormalized::new_wip(trait_ref.args.type_at(1)),
629 ) else {
630 {
::core::panicking::panic_fmt(format_args!("not yet implemented: {0}",
format_args!("something went wrong with structurally_normalize_ty")));
};todo!("something went wrong with structurally_normalize_ty");
631 };
632
633 let param_env = tcx.param_env(impl_did);
634 if !!source.has_escaping_bound_vars() {
::core::panicking::panic("assertion failed: !source.has_escaping_bound_vars()")
};assert!(!source.has_escaping_bound_vars());
635
636 let data = match (source.kind(), target.kind()) {
637 (&ty::Adt(def_a, args_a), &ty::Adt(def_b, args_b))
638 if def_a.is_struct() && def_b.is_struct() =>
639 {
640 let a_lifetimes_count = generic_lifetime_params_count(args_a);
646 let a_data_fields = collect_struct_data_fields(tcx, def_a, args_a);
647 let b_lifetimes_count = generic_lifetime_params_count(args_b);
648 let b_data_fields = collect_struct_data_fields(tcx, def_b, args_b);
649
650 if a_lifetimes_count != 1
651 || b_lifetimes_count != 1
652 || a_data_fields.len() > 1
653 || b_data_fields.len() > 1
654 || a_data_fields.len() != b_data_fields.len()
655 {
656 let item = tcx.hir_expect_item(impl_did);
657 let span = if let ItemKind::Impl(hir::Impl { of_trait: Some(of_trait), .. }) =
658 &item.kind
659 {
660 of_trait.trait_ref.path.span
661 } else {
662 tcx.def_span(impl_did)
663 };
664
665 return Err(tcx
666 .dcx()
667 .emit_err(diagnostics::CoerceSharedMulti { span, trait_name }));
668 }
669
670 if a_data_fields.len() == 1 {
671 let (a, span_a) = a_data_fields[0];
674 let (b, span_b) = b_data_fields[0];
675
676 Some((a, b, coerce_shared_trait, span_a, span_b))
677 } else {
678 None
681 }
682 }
683
684 _ => {
685 return Err(tcx
687 .dcx()
688 .emit_err(diagnostics::CoerceUnsizedNonStruct { span, trait_name }));
689 }
690 };
691
692 if let Some((source, target, trait_def_id, source_field_span, _target_field_span)) = data {
694 if source.ref_mutability() == Some(ty::Mutability::Mut)
700 && target.ref_mutability() == Some(ty::Mutability::Not)
701 && infcx
702 .eq_structurally_relating_aliases(
703 param_env,
704 source.peel_refs(),
705 target.peel_refs(),
706 source_field_span,
707 )
708 .is_ok()
709 {
710 return Ok(());
712 }
713 if infcx
714 .eq_structurally_relating_aliases(param_env, source, target, source_field_span)
715 .is_err()
716 {
717 let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
721 let cause = traits::ObligationCause::misc(span, impl_did);
722 let obligation = Obligation::new(
723 tcx,
724 cause,
725 param_env,
726 ty::TraitRef::new(tcx, trait_def_id, [source, target]),
727 );
728 ocx.register_obligation(obligation);
729 let errors = ocx.evaluate_obligations_error_on_ambiguity();
730
731 if !errors.is_empty() {
732 return Err(infcx.err_ctxt().report_fulfillment_errors(errors));
733 }
734 ocx.resolve_regions_and_report_errors(impl_did, param_env, [])?;
736 } else {
737 assert_field_type_is_copy(tcx, &infcx, impl_did, param_env, source, source_field_span)?;
739 }
740 }
741
742 Ok(())
743}
744
745fn trait_impl_lifetime_params_count(tcx: TyCtxt<'_>, did: LocalDefId) -> usize {
746 tcx.generics_of(did)
747 .own_params
748 .iter()
749 .filter(|p| #[allow(non_exhaustive_omitted_patterns)] match p.kind {
ty::GenericParamDefKind::Lifetime => true,
_ => false,
}matches!(p.kind, ty::GenericParamDefKind::Lifetime))
750 .count()
751}
752
753fn generic_lifetime_params_count(args: &[ty::GenericArg<'_>]) -> usize {
754 args.iter().filter(|arg| arg.as_region().is_some()).count()
755}
756
757fn collect_struct_data_fields<'tcx>(
759 tcx: TyCtxt<'tcx>,
760 def: ty::AdtDef<'tcx>,
761 args: ty::GenericArgsRef<'tcx>,
762) -> Vec<(Ty<'tcx>, Span)> {
763 def.non_enum_variant()
764 .fields
765 .iter()
766 .filter_map(|f| {
767 let ty = f.ty(tcx, args).skip_norm_wip();
769 if ty.is_phantom_data() {
770 return None;
771 }
772 Some((ty, tcx.def_span(f.did)))
773 })
774 .collect()
775}
776
777fn assert_field_type_is_copy<'tcx>(
778 tcx: TyCtxt<'tcx>,
779 infcx: &InferCtxt<'tcx>,
780 impl_did: LocalDefId,
781 param_env: ty::ParamEnv<'tcx>,
782 ty: Ty<'tcx>,
783 span: Span,
784) -> Result<(), ErrorGuaranteed> {
785 let copy_trait = tcx.require_lang_item(LangItem::Copy, span);
786 let ocx = ObligationCtxt::new_with_diagnostics(infcx);
787 let cause = traits::ObligationCause::misc(span, impl_did);
788 let obligation =
789 Obligation::new(tcx, cause, param_env, ty::TraitRef::new(tcx, copy_trait, [ty]));
790 ocx.register_obligation(obligation);
791 let errors = ocx.evaluate_obligations_error_on_ambiguity();
792
793 if !errors.is_empty() {
794 Err(infcx.err_ctxt().report_fulfillment_errors(errors))
795 } else {
796 Ok(())
797 }
798}
799
800pub(crate) fn coerce_unsized_info<'tcx>(
801 tcx: TyCtxt<'tcx>,
802 impl_did: LocalDefId,
803) -> Result<CoerceUnsizedInfo, ErrorGuaranteed> {
804 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_analysis/src/coherence/builtin.rs:804",
"rustc_hir_analysis::coherence::builtin",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_analysis/src/coherence/builtin.rs"),
::tracing_core::__macro_support::Option::Some(804u32),
::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};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("compute_coerce_unsized_info(impl_did={0:?})",
impl_did) as &dyn Value))])
});
} else { ; }
};debug!("compute_coerce_unsized_info(impl_did={:?})", impl_did);
805 let span = tcx.def_span(impl_did);
806 let trait_name = "CoerceUnsized";
807
808 let coerce_unsized_trait = tcx.require_lang_item(LangItem::CoerceUnsized, span);
809 let unsize_trait = tcx.require_lang_item(LangItem::Unsize, span);
810
811 let source = tcx.type_of(impl_did).instantiate_identity().skip_norm_wip();
812 let trait_ref = tcx.impl_trait_ref(impl_did).instantiate_identity().skip_norm_wip();
813
814 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);
815 let target = trait_ref.args.type_at(1);
816 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_analysis/src/coherence/builtin.rs:816",
"rustc_hir_analysis::coherence::builtin",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_analysis/src/coherence/builtin.rs"),
::tracing_core::__macro_support::Option::Some(816u32),
::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};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("visit_implementation_of_coerce_unsized: {0:?} -> {1:?} (bound)",
source, target) as &dyn Value))])
});
} else { ; }
};debug!("visit_implementation_of_coerce_unsized: {:?} -> {:?} (bound)", source, target);
817
818 let param_env = tcx.param_env(impl_did);
819 if !!source.has_escaping_bound_vars() {
::core::panicking::panic("assertion failed: !source.has_escaping_bound_vars()")
};assert!(!source.has_escaping_bound_vars());
820
821 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_analysis/src/coherence/builtin.rs:821",
"rustc_hir_analysis::coherence::builtin",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_analysis/src/coherence/builtin.rs"),
::tracing_core::__macro_support::Option::Some(821u32),
::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};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("visit_implementation_of_coerce_unsized: {0:?} -> {1:?} (free)",
source, target) as &dyn Value))])
});
} else { ; }
};debug!("visit_implementation_of_coerce_unsized: {:?} -> {:?} (free)", source, target);
822
823 let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
824 let cause = ObligationCause::misc(span, impl_did);
825 let check_mutbl = |mt_a: ty::TypeAndMut<'tcx>,
826 mt_b: ty::TypeAndMut<'tcx>,
827 mk_ptr: &dyn Fn(Ty<'tcx>) -> Ty<'tcx>| {
828 if mt_a.mutbl < mt_b.mutbl {
829 infcx
830 .err_ctxt()
831 .report_mismatched_types(
832 &cause,
833 param_env,
834 mk_ptr(mt_b.ty),
835 target,
836 ty::error::TypeError::Mutability,
837 )
838 .emit();
839 }
840 (mt_a.ty, mt_b.ty, unsize_trait, None, span)
841 };
842 let (source, target, trait_def_id, kind, field_span) = match (source.kind(), target.kind()) {
843 (&ty::Pat(ty_a, pat_a), &ty::Pat(ty_b, pat_b)) => {
844 if pat_a != pat_b {
845 return Err(tcx.dcx().emit_err(diagnostics::CoerceSamePatKind {
846 span,
847 trait_name,
848 pat_a: pat_a.to_string(),
849 pat_b: pat_b.to_string(),
850 }));
851 }
852 (ty_a, ty_b, coerce_unsized_trait, None, span)
853 }
854
855 (&ty::Ref(r_a, ty_a, mutbl_a), &ty::Ref(r_b, ty_b, mutbl_b)) => {
856 infcx.sub_regions(
857 SubregionOrigin::RelateObjectBound(span),
858 r_b,
859 r_a,
860 ty::VisibleForLeakCheck::Yes,
861 );
862 let mt_a = ty::TypeAndMut { ty: ty_a, mutbl: mutbl_a };
863 let mt_b = ty::TypeAndMut { ty: ty_b, mutbl: mutbl_b };
864 check_mutbl(mt_a, mt_b, &|ty| Ty::new_imm_ref(tcx, r_b, ty))
865 }
866
867 (&ty::Ref(_, ty_a, mutbl_a), &ty::RawPtr(ty_b, mutbl_b))
868 | (&ty::RawPtr(ty_a, mutbl_a), &ty::RawPtr(ty_b, mutbl_b)) => {
869 let mt_a = ty::TypeAndMut { ty: ty_a, mutbl: mutbl_a };
870 let mt_b = ty::TypeAndMut { ty: ty_b, mutbl: mutbl_b };
871 check_mutbl(mt_a, mt_b, &|ty| Ty::new_imm_ptr(tcx, ty))
872 }
873
874 (&ty::Adt(def_a, args_a), &ty::Adt(def_b, args_b))
875 if def_a.is_struct() && def_b.is_struct() =>
876 {
877 if def_a != def_b {
878 let source_path = tcx.def_path_str(def_a.did());
879 let target_path = tcx.def_path_str(def_b.did());
880 return Err(tcx.dcx().emit_err(diagnostics::CoerceSameStruct {
881 span,
882 trait_name,
883 note: true,
884 source_path,
885 target_path,
886 }));
887 }
888
889 let fields = &def_a.non_enum_variant().fields;
929 let diff_fields = fields
930 .iter_enumerated()
931 .filter_map(|(i, f)| {
932 let (a, b) =
933 (f.ty(tcx, args_a).skip_norm_wip(), f.ty(tcx, args_b).skip_norm_wip());
934
935 let unnormalized_ty = tcx.type_of(f.did).instantiate_identity();
937 if tcx
938 .try_normalize_erasing_regions(
939 ty::TypingEnv::non_body_analysis(tcx, def_a.did()),
940 unnormalized_ty,
941 )
942 .unwrap_or(unnormalized_ty.skip_norm_wip())
943 .is_phantom_data()
944 {
945 return None;
946 }
947
948 if a == b {
958 return None;
959 }
960
961 Some((i, a, b, tcx.def_span(f.did)))
964 })
965 .collect::<Vec<_>>();
966
967 if diff_fields.is_empty() {
968 return Err(tcx.dcx().emit_err(diagnostics::CoerceNoField {
969 span,
970 trait_name,
971 note: true,
972 }));
973 } else if diff_fields.len() > 1 {
974 let item = tcx.hir_expect_item(impl_did);
975 let span = if let ItemKind::Impl(hir::Impl { of_trait: Some(of_trait), .. }) =
976 &item.kind
977 {
978 of_trait.trait_ref.path.span
979 } else {
980 tcx.def_span(impl_did)
981 };
982
983 return Err(tcx.dcx().emit_err(diagnostics::CoerceMulti {
984 span,
985 trait_name,
986 number: diff_fields.len(),
987 fields: diff_fields.iter().map(|(_, _, _, s)| *s).collect::<Vec<_>>().into(),
988 }));
989 }
990
991 let (i, a, b, field_span) = diff_fields[0];
992 let kind = ty::adjustment::CustomCoerceUnsized::Struct(i);
993 (a, b, coerce_unsized_trait, Some(kind), field_span)
994 }
995
996 _ => {
997 return Err(tcx
998 .dcx()
999 .emit_err(diagnostics::CoerceUnsizedNonStruct { span, trait_name }));
1000 }
1001 };
1002
1003 let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
1005 let cause = traits::ObligationCause::misc(span, impl_did);
1006 let obligation = Obligation::new(
1007 tcx,
1008 cause,
1009 param_env,
1010 ty::TraitRef::new(tcx, trait_def_id, [source, target]),
1011 );
1012 ocx.register_obligation(obligation);
1013 let errors = ocx.evaluate_obligations_error_on_ambiguity();
1014
1015 if !errors.is_empty() {
1016 if is_from_coerce_pointee_derive(tcx, span) {
1017 return Err(tcx.dcx().emit_err(diagnostics::CoerceFieldValidity {
1018 span,
1019 trait_name,
1020 ty: trait_ref.self_ty(),
1021 field_span,
1022 field_ty: source,
1023 }));
1024 } else {
1025 return Err(infcx.err_ctxt().report_fulfillment_errors(errors));
1026 }
1027 }
1028
1029 ocx.resolve_regions_and_report_errors(impl_did, param_env, [])?;
1031
1032 Ok(CoerceUnsizedInfo { custom_kind: kind })
1033}
1034
1035fn infringing_fields_error<'tcx>(
1036 tcx: TyCtxt<'tcx>,
1037 infringing_tys: impl Iterator<Item = (Span, Ty<'tcx>, InfringingFieldsReason<'tcx>)>,
1038 lang_item: LangItem,
1039 impl_did: LocalDefId,
1040 impl_span: Span,
1041) -> ErrorGuaranteed {
1042 let trait_did = tcx.require_lang_item(lang_item, impl_span);
1043
1044 let trait_name = tcx.def_path_str(trait_did);
1045
1046 let mut errors: BTreeMap<_, Vec<_>> = Default::default();
1049 let mut bounds = ::alloc::vec::Vec::new()vec![];
1050
1051 let mut seen_tys = FxHashSet::default();
1052
1053 let mut label_spans = Vec::new();
1054
1055 for (span, ty, reason) in infringing_tys {
1056 if !seen_tys.insert(ty) {
1058 continue;
1059 }
1060
1061 label_spans.push(span);
1062
1063 match reason {
1064 InfringingFieldsReason::Fulfill(fulfillment_errors) => {
1065 for error in fulfillment_errors {
1066 let error_predicate = error.obligation.predicate;
1067 if error_predicate != error.root_obligation.predicate {
1073 errors
1074 .entry((ty.to_string(), error_predicate.to_string()))
1075 .or_default()
1076 .push(error.obligation.cause.span);
1077 }
1078 if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(ty::TraitPredicate {
1079 trait_ref,
1080 polarity: ty::PredicatePolarity::Positive,
1081 ..
1082 })) = error_predicate.kind().skip_binder()
1083 {
1084 let ty = trait_ref.self_ty();
1085 if let ty::Param(_) = ty.kind() {
1086 bounds.push((
1087 ::alloc::__export::must_use({ ::alloc::fmt::format(format_args!("{0}", ty)) })format!("{ty}"),
1088 trait_ref.print_trait_sugared().to_string(),
1089 Some(trait_ref.def_id),
1090 ));
1091 }
1092 }
1093 }
1094 }
1095 InfringingFieldsReason::Regions(region_errors) => {
1096 for error in region_errors {
1097 let ty = ty.to_string();
1098 match error {
1099 RegionResolutionError::ConcreteFailure(origin, a, b) => {
1100 let predicate = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}: {1}", b, a))
})format!("{b}: {a}");
1101 errors
1102 .entry((ty.clone(), predicate.clone()))
1103 .or_default()
1104 .push(origin.span());
1105 if let ty::RegionKind::ReEarlyParam(ebr) = b.kind()
1106 && ebr.is_named()
1107 {
1108 bounds.push((b.to_string(), a.to_string(), None));
1109 }
1110 }
1111 RegionResolutionError::GenericBoundFailure(origin, a, b) => {
1112 let predicate = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}: {1}", a, b))
})format!("{a}: {b}");
1113 errors
1114 .entry((ty.clone(), predicate.clone()))
1115 .or_default()
1116 .push(origin.span());
1117 if let infer::region_constraints::GenericKind::Param(_) = a {
1118 bounds.push((a.to_string(), b.to_string(), None));
1119 }
1120 }
1121 _ => continue,
1122 }
1123 }
1124 }
1125 }
1126 }
1127 let mut notes = Vec::new();
1128 for ((ty, error_predicate), spans) in errors {
1129 let span: MultiSpan = spans.into();
1130 notes.push(diagnostics::ImplForTyRequires {
1131 span,
1132 error_predicate,
1133 trait_name: trait_name.clone(),
1134 ty,
1135 });
1136 }
1137
1138 let mut err = tcx.dcx().create_err(diagnostics::TraitCannotImplForTy {
1139 span: impl_span,
1140 trait_name,
1141 label_spans,
1142 notes,
1143 });
1144
1145 suggest_constraining_type_params(
1146 tcx,
1147 tcx.hir_get_generics(impl_did).expect("impls always have generics"),
1148 &mut err,
1149 bounds
1150 .iter()
1151 .map(|(param, constraint, def_id)| (param.as_str(), constraint.as_str(), *def_id)),
1152 None,
1153 );
1154
1155 err.emit()
1156}
1157
1158fn visit_implementation_of_coerce_pointee_validity(
1159 checker: &Checker<'_>,
1160) -> Result<(), ErrorGuaranteed> {
1161 let tcx = checker.tcx;
1162 let self_ty =
1163 tcx.impl_trait_ref(checker.impl_def_id).instantiate_identity().skip_norm_wip().self_ty();
1164 let span = tcx.def_span(checker.impl_def_id);
1165 if !tcx.is_builtin_derived(checker.impl_def_id.into()) {
1166 return Err(tcx.dcx().emit_err(diagnostics::CoercePointeeNoUserValidityAssertion { span }));
1167 }
1168 let ty::Adt(def, _args) = self_ty.kind() else {
1169 return Err(tcx.dcx().emit_err(diagnostics::CoercePointeeNotConcreteType { span }));
1170 };
1171 let did = def.did();
1172 let span = tcx.def_span(did);
1174 if !def.is_struct() {
1175 return Err(tcx
1176 .dcx()
1177 .emit_err(diagnostics::CoercePointeeNotStruct { span, kind: def.descr().into() }));
1178 }
1179 if !def.repr().transparent() {
1180 return Err(tcx.dcx().emit_err(diagnostics::CoercePointeeNotTransparent { span }));
1181 }
1182 if def.all_fields().next().is_none() {
1183 return Err(tcx.dcx().emit_err(diagnostics::CoercePointeeNoField { span }));
1184 }
1185 Ok(())
1186}