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, RegionResolutionError, SubregionOrigin, TyCtxtInferExt};
13use rustc_infer::traits::Obligation;
14use rustc_middle::ty::adjustment::CoerceUnsizedInfo;
15use rustc_middle::ty::print::PrintTraitRefExt as _;
16use rustc_middle::ty::{
17 self, Ty, TyCtxt, TypeVisitableExt, TypingMode, suggest_constraining_type_params,
18};
19use rustc_span::{DUMMY_SP, Span, 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::errors;
29
30pub(super) fn check_trait<'tcx>(
31 tcx: TyCtxt<'tcx>,
32 trait_def_id: DefId,
33 impl_def_id: LocalDefId,
34 impl_header: ty::ImplTraitHeader<'tcx>,
35) -> Result<(), ErrorGuaranteed> {
36 let lang_items = tcx.lang_items();
37 let checker = Checker { tcx, trait_def_id, impl_def_id, impl_header };
38 checker.check(lang_items.drop_trait(), visit_implementation_of_drop)?;
39 checker.check(lang_items.async_drop_trait(), visit_implementation_of_drop)?;
40 checker.check(lang_items.copy_trait(), visit_implementation_of_copy)?;
41 checker.check(lang_items.unpin_trait(), visit_implementation_of_unpin)?;
42 checker.check(lang_items.const_param_ty_trait(), |checker| {
43 visit_implementation_of_const_param_ty(checker)
44 })?;
45 checker.check(lang_items.coerce_unsized_trait(), visit_implementation_of_coerce_unsized)?;
46 checker
47 .check(lang_items.dispatch_from_dyn_trait(), visit_implementation_of_dispatch_from_dyn)?;
48 checker.check(
49 lang_items.coerce_pointee_validated_trait(),
50 visit_implementation_of_coerce_pointee_validity,
51 )?;
52 Ok(())
53}
54
55struct Checker<'tcx> {
56 tcx: TyCtxt<'tcx>,
57 trait_def_id: DefId,
58 impl_def_id: LocalDefId,
59 impl_header: ty::ImplTraitHeader<'tcx>,
60}
61
62impl<'tcx> Checker<'tcx> {
63 fn check(
64 &self,
65 trait_def_id: Option<DefId>,
66 f: impl FnOnce(&Self) -> Result<(), ErrorGuaranteed>,
67 ) -> Result<(), ErrorGuaranteed> {
68 if Some(self.trait_def_id) == trait_def_id { f(self) } else { Ok(()) }
69 }
70}
71
72fn visit_implementation_of_drop(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> {
73 let tcx = checker.tcx;
74 let impl_did = checker.impl_def_id;
75 match checker.impl_header.trait_ref.instantiate_identity().skip_norm_wip().self_ty().kind() {
77 ty::Adt(def, _) if def.did().is_local() => return Ok(()),
78 ty::Error(_) => return Ok(()),
79 _ => {}
80 }
81
82 let impl_ = tcx.hir_expect_item(impl_did).expect_impl();
83
84 Err(tcx.dcx().emit_err(errors::DropImplOnWrongItem {
85 span: impl_.self_ty.span,
86 trait_: tcx.item_name(checker.impl_header.trait_ref.skip_binder().def_id),
87 }))
88}
89
90fn visit_implementation_of_copy(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> {
91 let tcx = checker.tcx;
92 let impl_header = checker.impl_header;
93 let impl_did = checker.impl_def_id;
94 {
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:94",
"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(94u32),
::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);
95
96 let self_type = impl_header.trait_ref.instantiate_identity().skip_norm_wip().self_ty();
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: self_type={0:?} (bound)",
self_type) as &dyn Value))])
});
} else { ; }
};debug!("visit_implementation_of_copy: self_type={:?} (bound)", self_type);
98
99 let param_env = tcx.param_env(impl_did);
100 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());
101
102 {
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:102",
"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(102u32),
::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);
103
104 if let ty::ImplPolarity::Negative = impl_header.polarity {
105 return Ok(());
106 }
107
108 let cause = traits::ObligationCause::misc(DUMMY_SP, impl_did);
109 match type_allowed_to_implement_copy(tcx, param_env, self_type, cause, impl_header.safety) {
110 Ok(()) => Ok(()),
111 Err(CopyImplementationError::InfringingFields(fields)) => {
112 let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
113 Err(infringing_fields_error(
114 tcx,
115 fields.into_iter().map(|(field, ty, reason)| (tcx.def_span(field.did), ty, reason)),
116 LangItem::Copy,
117 impl_did,
118 span,
119 ))
120 }
121 Err(CopyImplementationError::NotAnAdt) => {
122 let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
123 Err(tcx.dcx().emit_err(errors::CopyImplOnNonAdt { span }))
124 }
125 Err(CopyImplementationError::HasDestructor(did)) => {
126 let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
127 let impl_ = tcx.def_span(did);
128 Err(tcx.dcx().emit_err(errors::CopyImplOnTypeWithDtor { span, impl_ }))
129 }
130 Err(CopyImplementationError::HasUnsafeFields) => {
131 let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
132 Err(tcx
133 .dcx()
134 .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)))
135 }
136 }
137}
138
139fn visit_implementation_of_unpin(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> {
140 let tcx = checker.tcx;
141 let impl_header = checker.impl_header;
142 let impl_did = checker.impl_def_id;
143 {
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:143",
"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(143u32),
::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);
144
145 let self_type = impl_header.trait_ref.instantiate_identity().skip_norm_wip().self_ty();
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: self_type={0:?}",
self_type) as &dyn Value))])
});
} else { ; }
};debug!("visit_implementation_of_unpin: self_type={:?}", self_type);
147
148 let span = tcx.def_span(impl_did);
149
150 if tcx.features().pin_ergonomics() {
151 match self_type.kind() {
152 ty::Adt(adt, _) if adt.is_pin_project() => {
159 return Err(tcx.dcx().emit_err(crate::errors::ImplUnpinForPinProjectedType {
160 span,
161 adt_span: tcx.def_span(adt.did()),
162 adt_name: tcx.item_name(adt.did()),
163 }));
164 }
165 ty::Adt(_, _) => {}
166 _ => {
167 return Err(tcx.dcx().span_delayed_bug(span, "impl of `Unpin` for a non-adt type"));
168 }
169 };
170 }
171 Ok(())
172}
173
174fn visit_implementation_of_const_param_ty(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> {
175 let tcx = checker.tcx;
176 let header = checker.impl_header;
177 let impl_did = checker.impl_def_id;
178 let self_type = header.trait_ref.instantiate_identity().skip_norm_wip().self_ty();
179 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());
180
181 let param_env = tcx.param_env(impl_did);
182
183 if let ty::ImplPolarity::Negative | ty::ImplPolarity::Reservation = header.polarity {
184 return Ok(());
185 }
186
187 if tcx.features().const_param_ty_unchecked() {
188 return Ok(());
189 }
190
191 if !tcx.features().adt_const_params() {
192 match *self_type.kind() {
193 ty::Adt(adt, _) if adt.is_struct() => {
194 let struct_vis = tcx.visibility(adt.did());
195 for variant in adt.variants() {
196 for field in &variant.fields {
197 if struct_vis.greater_than(field.vis, tcx) {
198 let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
199 return Err(tcx
200 .dcx()
201 .emit_err(errors::ConstParamTyFieldVisMismatch { span }));
202 }
203 }
204 }
205 }
206
207 _ => {}
208 }
209 }
210
211 let cause = traits::ObligationCause::misc(DUMMY_SP, impl_did);
212 match type_allowed_to_implement_const_param_ty(tcx, param_env, self_type, cause) {
213 Ok(()) => Ok(()),
214 Err(ConstParamTyImplementationError::InfrigingFields(fields)) => {
215 let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
216 Err(infringing_fields_error(
217 tcx,
218 fields.into_iter().map(|(field, ty, reason)| (tcx.def_span(field.did), ty, reason)),
219 LangItem::ConstParamTy,
220 impl_did,
221 span,
222 ))
223 }
224 Err(ConstParamTyImplementationError::NotAnAdtOrBuiltinAllowed) => {
225 let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
226 Err(tcx.dcx().emit_err(errors::ConstParamTyImplOnNonAdt { span }))
227 }
228 Err(ConstParamTyImplementationError::NonExhaustive(attr_span)) => {
229 let defn_span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
230 Err(tcx
231 .dcx()
232 .emit_err(errors::ConstParamTyImplOnNonExhaustive { defn_span, attr_span }))
233 }
234 Err(ConstParamTyImplementationError::InvalidInnerTyOfBuiltinTy(infringing_tys)) => {
235 let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
236 Err(infringing_fields_error(
237 tcx,
238 infringing_tys.into_iter().map(|(ty, reason)| (span, ty, reason)),
239 LangItem::ConstParamTy,
240 impl_did,
241 span,
242 ))
243 }
244 Err(ConstParamTyImplementationError::UnsizedConstParamsFeatureRequired) => {
245 let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
246 Err(tcx.dcx().emit_err(errors::ConstParamTyImplOnUnsized { span }))
247 }
248 }
249}
250
251fn visit_implementation_of_coerce_unsized(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> {
252 let tcx = checker.tcx;
253 let impl_did = checker.impl_def_id;
254 {
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:254",
"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(254u32),
::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);
255
256 tcx.ensure_result().coerce_unsized_info(impl_did)
260}
261
262fn is_from_coerce_pointee_derive(tcx: TyCtxt<'_>, span: Span) -> bool {
263 span.ctxt()
264 .outer_expn_data()
265 .macro_def_id
266 .is_some_and(|def_id| tcx.is_diagnostic_item(sym::CoercePointee, def_id))
267}
268
269fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> {
270 let tcx = checker.tcx;
271 let impl_did = checker.impl_def_id;
272 let trait_ref = checker.impl_header.trait_ref.instantiate_identity().skip_norm_wip();
273 {
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:273",
"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(273u32),
::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);
274
275 let span = tcx.def_span(impl_did);
276 let trait_name = "DispatchFromDyn";
277
278 let source = trait_ref.self_ty();
279 let target = {
280 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));
281
282 trait_ref.args.type_at(1)
283 };
284
285 let mut res = Ok(());
288 tcx.for_each_relevant_impl(
289 tcx.require_lang_item(LangItem::CoerceUnsized, span),
290 source,
291 |impl_def_id| {
292 res = res.and(tcx.ensure_result().coerce_unsized_info(impl_def_id));
293 },
294 );
295 res?;
296
297 {
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:297",
"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(297u32),
::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);
298
299 let param_env = tcx.param_env(impl_did);
300
301 let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
302 let cause = ObligationCause::misc(span, impl_did);
303
304 match (source.kind(), target.kind()) {
313 (&ty::Pat(_, pat_a), &ty::Pat(_, pat_b)) => {
314 if pat_a != pat_b {
315 return Err(tcx.dcx().emit_err(errors::CoerceSamePatKind {
316 span,
317 trait_name,
318 pat_a: pat_a.to_string(),
319 pat_b: pat_b.to_string(),
320 }));
321 }
322 Ok(())
323 }
324
325 (&ty::Ref(r_a, _, mutbl_a), ty::Ref(r_b, _, mutbl_b))
326 if r_a == *r_b && mutbl_a == *mutbl_b =>
327 {
328 Ok(())
329 }
330 (&ty::RawPtr(_, a_mutbl), &ty::RawPtr(_, b_mutbl)) if a_mutbl == b_mutbl => Ok(()),
331 (&ty::Adt(def_a, args_a), &ty::Adt(def_b, args_b))
332 if def_a.is_struct() && def_b.is_struct() =>
333 {
334 if def_a != def_b {
335 let source_path = tcx.def_path_str(def_a.did());
336 let target_path = tcx.def_path_str(def_b.did());
337 return Err(tcx.dcx().emit_err(errors::CoerceSameStruct {
338 span,
339 trait_name,
340 note: true,
341 source_path,
342 target_path,
343 }));
344 }
345
346 if def_a.repr().c() || def_a.repr().packed() {
347 return Err(tcx.dcx().emit_err(errors::DispatchFromDynRepr { span }));
348 }
349
350 let fields = &def_a.non_enum_variant().fields;
351
352 let mut res = Ok(());
353 let coerced_fields = fields
354 .iter_enumerated()
355 .filter_map(|(i, field)| {
356 let unnormalized_ty = tcx.type_of(field.did).instantiate_identity();
358 if tcx
359 .try_normalize_erasing_regions(
360 ty::TypingEnv::non_body_analysis(tcx, def_a.did()),
361 unnormalized_ty,
362 )
363 .unwrap_or(unnormalized_ty.skip_norm_wip())
364 .is_phantom_data()
365 {
366 return None;
367 }
368
369 let ty_a = field.ty(tcx, args_a);
370 let ty_b = field.ty(tcx, args_b);
371
372 if ty_a == ty_b {
374 if let Ok(layout) =
379 tcx.layout_of(infcx.typing_env(param_env).as_query_input(ty_a))
380 && layout.is_1zst()
381 && !ty_a.has_non_region_param()
382 {
383 return None;
385 }
386
387 res = Err(tcx.dcx().emit_err(errors::DispatchFromDynZST {
388 span,
389 name: field.ident(tcx),
390 ty: ty_a,
391 }));
392
393 None
394 } else {
395 Some((i, ty_a, ty_b, tcx.def_span(field.did)))
396 }
397 })
398 .collect::<Vec<_>>();
399 res?;
400
401 if coerced_fields.is_empty() {
402 return Err(tcx.dcx().emit_err(errors::CoerceNoField {
403 span,
404 trait_name,
405 note: true,
406 }));
407 } else if let &[(_, ty_a, ty_b, field_span)] = &coerced_fields[..] {
408 let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
409 ocx.register_obligation(Obligation::new(
410 tcx,
411 cause.clone(),
412 param_env,
413 ty::TraitRef::new(tcx, trait_ref.def_id, [ty_a, ty_b]),
414 ));
415 let errors = ocx.evaluate_obligations_error_on_ambiguity();
416 if !errors.is_empty() {
417 if is_from_coerce_pointee_derive(tcx, span) {
418 return Err(tcx.dcx().emit_err(errors::CoerceFieldValidity {
419 span,
420 trait_name,
421 ty: trait_ref.self_ty(),
422 field_span,
423 field_ty: ty_a,
424 }));
425 } else {
426 return Err(infcx.err_ctxt().report_fulfillment_errors(errors));
427 }
428 }
429
430 ocx.resolve_regions_and_report_errors(impl_did, param_env, [])?;
432
433 Ok(())
434 } else {
435 return Err(tcx.dcx().emit_err(errors::CoerceMulti {
436 span,
437 trait_name,
438 number: coerced_fields.len(),
439 fields: coerced_fields.iter().map(|(_, _, _, s)| *s).collect::<Vec<_>>().into(),
440 }));
441 }
442 }
443 _ => Err(tcx.dcx().emit_err(errors::CoerceUnsizedNonStruct { span, trait_name })),
444 }
445}
446
447pub(crate) fn coerce_unsized_info<'tcx>(
448 tcx: TyCtxt<'tcx>,
449 impl_did: LocalDefId,
450) -> Result<CoerceUnsizedInfo, ErrorGuaranteed> {
451 {
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:451",
"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(451u32),
::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);
452 let span = tcx.def_span(impl_did);
453 let trait_name = "CoerceUnsized";
454
455 let coerce_unsized_trait = tcx.require_lang_item(LangItem::CoerceUnsized, span);
456 let unsize_trait = tcx.require_lang_item(LangItem::Unsize, span);
457
458 let source = tcx.type_of(impl_did).instantiate_identity().skip_norm_wip();
459 let trait_ref = tcx.impl_trait_ref(impl_did).instantiate_identity().skip_norm_wip();
460
461 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);
462 let target = trait_ref.args.type_at(1);
463 {
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:463",
"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(463u32),
::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);
464
465 let param_env = tcx.param_env(impl_did);
466 if !!source.has_escaping_bound_vars() {
::core::panicking::panic("assertion failed: !source.has_escaping_bound_vars()")
};assert!(!source.has_escaping_bound_vars());
467
468 {
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:468",
"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(468u32),
::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);
469
470 let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
471 let cause = ObligationCause::misc(span, impl_did);
472 let check_mutbl = |mt_a: ty::TypeAndMut<'tcx>,
473 mt_b: ty::TypeAndMut<'tcx>,
474 mk_ptr: &dyn Fn(Ty<'tcx>) -> Ty<'tcx>| {
475 if mt_a.mutbl < mt_b.mutbl {
476 infcx
477 .err_ctxt()
478 .report_mismatched_types(
479 &cause,
480 param_env,
481 mk_ptr(mt_b.ty),
482 target,
483 ty::error::TypeError::Mutability,
484 )
485 .emit();
486 }
487 (mt_a.ty, mt_b.ty, unsize_trait, None, span)
488 };
489 let (source, target, trait_def_id, kind, field_span) = match (source.kind(), target.kind()) {
490 (&ty::Pat(ty_a, pat_a), &ty::Pat(ty_b, pat_b)) => {
491 if pat_a != pat_b {
492 return Err(tcx.dcx().emit_err(errors::CoerceSamePatKind {
493 span,
494 trait_name,
495 pat_a: pat_a.to_string(),
496 pat_b: pat_b.to_string(),
497 }));
498 }
499 (ty_a, ty_b, coerce_unsized_trait, None, span)
500 }
501
502 (&ty::Ref(r_a, ty_a, mutbl_a), &ty::Ref(r_b, ty_b, mutbl_b)) => {
503 infcx.sub_regions(
504 SubregionOrigin::RelateObjectBound(span),
505 r_b,
506 r_a,
507 ty::VisibleForLeakCheck::Yes,
508 );
509 let mt_a = ty::TypeAndMut { ty: ty_a, mutbl: mutbl_a };
510 let mt_b = ty::TypeAndMut { ty: ty_b, mutbl: mutbl_b };
511 check_mutbl(mt_a, mt_b, &|ty| Ty::new_imm_ref(tcx, r_b, ty))
512 }
513
514 (&ty::Ref(_, ty_a, mutbl_a), &ty::RawPtr(ty_b, mutbl_b))
515 | (&ty::RawPtr(ty_a, mutbl_a), &ty::RawPtr(ty_b, mutbl_b)) => {
516 let mt_a = ty::TypeAndMut { ty: ty_a, mutbl: mutbl_a };
517 let mt_b = ty::TypeAndMut { ty: ty_b, mutbl: mutbl_b };
518 check_mutbl(mt_a, mt_b, &|ty| Ty::new_imm_ptr(tcx, ty))
519 }
520
521 (&ty::Adt(def_a, args_a), &ty::Adt(def_b, args_b))
522 if def_a.is_struct() && def_b.is_struct() =>
523 {
524 if def_a != def_b {
525 let source_path = tcx.def_path_str(def_a.did());
526 let target_path = tcx.def_path_str(def_b.did());
527 return Err(tcx.dcx().emit_err(errors::CoerceSameStruct {
528 span,
529 trait_name,
530 note: true,
531 source_path,
532 target_path,
533 }));
534 }
535
536 let fields = &def_a.non_enum_variant().fields;
576 let diff_fields = fields
577 .iter_enumerated()
578 .filter_map(|(i, f)| {
579 let (a, b) = (f.ty(tcx, args_a), f.ty(tcx, args_b));
580
581 let unnormalized_ty = tcx.type_of(f.did).instantiate_identity();
583 if tcx
584 .try_normalize_erasing_regions(
585 ty::TypingEnv::non_body_analysis(tcx, def_a.did()),
586 unnormalized_ty,
587 )
588 .unwrap_or(unnormalized_ty.skip_norm_wip())
589 .is_phantom_data()
590 {
591 return None;
592 }
593
594 if a == b {
604 return None;
605 }
606
607 Some((i, a, b, tcx.def_span(f.did)))
610 })
611 .collect::<Vec<_>>();
612
613 if diff_fields.is_empty() {
614 return Err(tcx.dcx().emit_err(errors::CoerceNoField {
615 span,
616 trait_name,
617 note: true,
618 }));
619 } else if diff_fields.len() > 1 {
620 let item = tcx.hir_expect_item(impl_did);
621 let span = if let ItemKind::Impl(hir::Impl { of_trait: Some(of_trait), .. }) =
622 &item.kind
623 {
624 of_trait.trait_ref.path.span
625 } else {
626 tcx.def_span(impl_did)
627 };
628
629 return Err(tcx.dcx().emit_err(errors::CoerceMulti {
630 span,
631 trait_name,
632 number: diff_fields.len(),
633 fields: diff_fields.iter().map(|(_, _, _, s)| *s).collect::<Vec<_>>().into(),
634 }));
635 }
636
637 let (i, a, b, field_span) = diff_fields[0];
638 let kind = ty::adjustment::CustomCoerceUnsized::Struct(i);
639 (a, b, coerce_unsized_trait, Some(kind), field_span)
640 }
641
642 _ => {
643 return Err(tcx.dcx().emit_err(errors::CoerceUnsizedNonStruct { span, trait_name }));
644 }
645 };
646
647 let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
649 let cause = traits::ObligationCause::misc(span, impl_did);
650 let obligation = Obligation::new(
651 tcx,
652 cause,
653 param_env,
654 ty::TraitRef::new(tcx, trait_def_id, [source, target]),
655 );
656 ocx.register_obligation(obligation);
657 let errors = ocx.evaluate_obligations_error_on_ambiguity();
658
659 if !errors.is_empty() {
660 if is_from_coerce_pointee_derive(tcx, span) {
661 return Err(tcx.dcx().emit_err(errors::CoerceFieldValidity {
662 span,
663 trait_name,
664 ty: trait_ref.self_ty(),
665 field_span,
666 field_ty: source,
667 }));
668 } else {
669 return Err(infcx.err_ctxt().report_fulfillment_errors(errors));
670 }
671 }
672
673 ocx.resolve_regions_and_report_errors(impl_did, param_env, [])?;
675
676 Ok(CoerceUnsizedInfo { custom_kind: kind })
677}
678
679fn infringing_fields_error<'tcx>(
680 tcx: TyCtxt<'tcx>,
681 infringing_tys: impl Iterator<Item = (Span, Ty<'tcx>, InfringingFieldsReason<'tcx>)>,
682 lang_item: LangItem,
683 impl_did: LocalDefId,
684 impl_span: Span,
685) -> ErrorGuaranteed {
686 let trait_did = tcx.require_lang_item(lang_item, impl_span);
687
688 let trait_name = tcx.def_path_str(trait_did);
689
690 let mut errors: BTreeMap<_, Vec<_>> = Default::default();
693 let mut bounds = ::alloc::vec::Vec::new()vec![];
694
695 let mut seen_tys = FxHashSet::default();
696
697 let mut label_spans = Vec::new();
698
699 for (span, ty, reason) in infringing_tys {
700 if !seen_tys.insert(ty) {
702 continue;
703 }
704
705 label_spans.push(span);
706
707 match reason {
708 InfringingFieldsReason::Fulfill(fulfillment_errors) => {
709 for error in fulfillment_errors {
710 let error_predicate = error.obligation.predicate;
711 if error_predicate != error.root_obligation.predicate {
717 errors
718 .entry((ty.to_string(), error_predicate.to_string()))
719 .or_default()
720 .push(error.obligation.cause.span);
721 }
722 if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(ty::TraitPredicate {
723 trait_ref,
724 polarity: ty::PredicatePolarity::Positive,
725 ..
726 })) = error_predicate.kind().skip_binder()
727 {
728 let ty = trait_ref.self_ty();
729 if let ty::Param(_) = ty.kind() {
730 bounds.push((
731 ::alloc::__export::must_use({ ::alloc::fmt::format(format_args!("{0}", ty)) })format!("{ty}"),
732 trait_ref.print_trait_sugared().to_string(),
733 Some(trait_ref.def_id),
734 ));
735 }
736 }
737 }
738 }
739 InfringingFieldsReason::Regions(region_errors) => {
740 for error in region_errors {
741 let ty = ty.to_string();
742 match error {
743 RegionResolutionError::ConcreteFailure(origin, a, b) => {
744 let predicate = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}: {1}", b, a))
})format!("{b}: {a}");
745 errors
746 .entry((ty.clone(), predicate.clone()))
747 .or_default()
748 .push(origin.span());
749 if let ty::RegionKind::ReEarlyParam(ebr) = b.kind()
750 && ebr.is_named()
751 {
752 bounds.push((b.to_string(), a.to_string(), None));
753 }
754 }
755 RegionResolutionError::GenericBoundFailure(origin, a, b) => {
756 let predicate = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}: {1}", a, b))
})format!("{a}: {b}");
757 errors
758 .entry((ty.clone(), predicate.clone()))
759 .or_default()
760 .push(origin.span());
761 if let infer::region_constraints::GenericKind::Param(_) = a {
762 bounds.push((a.to_string(), b.to_string(), None));
763 }
764 }
765 _ => continue,
766 }
767 }
768 }
769 }
770 }
771 let mut notes = Vec::new();
772 for ((ty, error_predicate), spans) in errors {
773 let span: MultiSpan = spans.into();
774 notes.push(errors::ImplForTyRequires {
775 span,
776 error_predicate,
777 trait_name: trait_name.clone(),
778 ty,
779 });
780 }
781
782 let mut err = tcx.dcx().create_err(errors::TraitCannotImplForTy {
783 span: impl_span,
784 trait_name,
785 label_spans,
786 notes,
787 });
788
789 suggest_constraining_type_params(
790 tcx,
791 tcx.hir_get_generics(impl_did).expect("impls always have generics"),
792 &mut err,
793 bounds
794 .iter()
795 .map(|(param, constraint, def_id)| (param.as_str(), constraint.as_str(), *def_id)),
796 None,
797 );
798
799 err.emit()
800}
801
802fn visit_implementation_of_coerce_pointee_validity(
803 checker: &Checker<'_>,
804) -> Result<(), ErrorGuaranteed> {
805 let tcx = checker.tcx;
806 let self_ty =
807 tcx.impl_trait_ref(checker.impl_def_id).instantiate_identity().skip_norm_wip().self_ty();
808 let span = tcx.def_span(checker.impl_def_id);
809 if !tcx.is_builtin_derived(checker.impl_def_id.into()) {
810 return Err(tcx.dcx().emit_err(errors::CoercePointeeNoUserValidityAssertion { span }));
811 }
812 let ty::Adt(def, _args) = self_ty.kind() else {
813 return Err(tcx.dcx().emit_err(errors::CoercePointeeNotConcreteType { span }));
814 };
815 let did = def.did();
816 let span = tcx.def_span(did);
818 if !def.is_struct() {
819 return Err(tcx
820 .dcx()
821 .emit_err(errors::CoercePointeeNotStruct { span, kind: def.descr().into() }));
822 }
823 if !def.repr().transparent() {
824 return Err(tcx.dcx().emit_err(errors::CoercePointeeNotTransparent { span }));
825 }
826 if def.all_fields().next().is_none() {
827 return Err(tcx.dcx().emit_err(errors::CoercePointeeNoField { span }));
828 }
829 Ok(())
830}