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;
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 checker = Checker { tcx, impl_def_id, impl_header };
38 match tcx.as_lang_item(trait_def_id) {
39 Some(LangItem::Drop) => visit_implementation_of_drop(&checker),
40 Some(LangItem::AsyncDrop) => visit_implementation_of_drop(&checker),
41 Some(LangItem::Copy) => visit_implementation_of_copy(&checker),
42 Some(LangItem::Unpin) => visit_implementation_of_unpin(&checker),
43 Some(LangItem::ConstParamTy) => visit_implementation_of_const_param_ty(&checker),
44 Some(LangItem::CoerceUnsized) => visit_implementation_of_coerce_unsized(&checker),
45 Some(LangItem::Reborrow) => visit_implementation_of_reborrow(&checker),
46 Some(LangItem::CoerceShared) => visit_implementation_of_coerce_shared(&checker),
47 Some(LangItem::DispatchFromDyn) => visit_implementation_of_dispatch_from_dyn(&checker),
48 Some(LangItem::CoercePointeeValidated) => {
49 visit_implementation_of_coerce_pointee_validity(&checker)
50 }
51 _ => Ok(()),
52 }
53}
54
55struct Checker<'tcx> {
56 tcx: TyCtxt<'tcx>,
57 impl_def_id: LocalDefId,
58 impl_header: ty::ImplTraitHeader<'tcx>,
59}
60
61fn visit_implementation_of_drop(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> {
62 let tcx = checker.tcx;
63 let impl_did = checker.impl_def_id;
64 match checker.impl_header.trait_ref.instantiate_identity().skip_norm_wip().self_ty().kind() {
66 ty::Adt(def, _) if def.did().is_local() => return Ok(()),
67 ty::Error(_) => return Ok(()),
68 _ => {}
69 }
70
71 let impl_ = tcx.hir_expect_item(impl_did).expect_impl();
72
73 Err(tcx.dcx().emit_err(diagnostics::DropImplOnWrongItem {
74 span: impl_.self_ty.span,
75 trait_: tcx.item_name(checker.impl_header.trait_ref.skip_binder().def_id),
76 }))
77}
78
79fn visit_implementation_of_copy(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> {
80 let tcx = checker.tcx;
81 let impl_header = checker.impl_header;
82 let impl_did = checker.impl_def_id;
83 {
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:83",
"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(83u32),
::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);
84
85 let self_type = impl_header.trait_ref.instantiate_identity().skip_norm_wip().self_ty();
86 {
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:86",
"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(86u32),
::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);
87
88 let param_env = tcx.param_env(impl_did);
89 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());
90
91 {
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:91",
"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(91u32),
::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);
92
93 if let ty::ImplPolarity::Negative = impl_header.polarity {
94 return Ok(());
95 }
96
97 let cause = traits::ObligationCause::misc(DUMMY_SP, impl_did);
98 match type_allowed_to_implement_copy(tcx, param_env, self_type, cause, impl_header.safety) {
99 Ok(()) => Ok(()),
100 Err(CopyImplementationError::InfringingFields(fields)) => {
101 let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
102 Err(infringing_fields_error(
103 tcx,
104 fields.into_iter().map(|(field, ty, reason)| (tcx.def_span(field.did), ty, reason)),
105 LangItem::Copy,
106 impl_did,
107 span,
108 ))
109 }
110 Err(CopyImplementationError::NotAnAdt) => {
111 let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
112 Err(tcx.dcx().emit_err(diagnostics::CopyImplOnNonAdt { span }))
113 }
114 Err(CopyImplementationError::HasDestructor(did)) => {
115 let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
116 let impl_ = tcx.def_span(did);
117 Err(tcx.dcx().emit_err(diagnostics::CopyImplOnTypeWithDtor { span, impl_ }))
118 }
119 Err(CopyImplementationError::HasUnsafeFields) => {
120 let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
121 Err(tcx
122 .dcx()
123 .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)))
124 }
125 }
126}
127
128fn visit_implementation_of_unpin(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> {
129 let tcx = checker.tcx;
130 let impl_header = checker.impl_header;
131 let impl_did = checker.impl_def_id;
132 {
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:132",
"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(132u32),
::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);
133
134 let self_type = impl_header.trait_ref.instantiate_identity().skip_norm_wip().self_ty();
135 {
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:135",
"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(135u32),
::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);
136
137 let span = tcx.def_span(impl_did);
138
139 if tcx.features().pin_ergonomics() {
140 match self_type.kind() {
141 ty::Adt(adt, _) if adt.is_pin_project() => {
148 return Err(tcx.dcx().emit_err(crate::diagnostics::ImplUnpinForPinProjectedType {
149 span,
150 adt_span: tcx.def_span(adt.did()),
151 adt_name: tcx.item_name(adt.did()),
152 }));
153 }
154 ty::Adt(_, _) => {}
155 _ => {
156 return Err(tcx.dcx().span_delayed_bug(span, "impl of `Unpin` for a non-adt type"));
157 }
158 };
159 }
160 Ok(())
161}
162
163fn visit_implementation_of_const_param_ty(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> {
164 let tcx = checker.tcx;
165 let header = checker.impl_header;
166 let impl_did = checker.impl_def_id;
167 let self_type = header.trait_ref.instantiate_identity().skip_norm_wip().self_ty();
168 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());
169
170 let param_env = tcx.param_env(impl_did);
171
172 if let ty::ImplPolarity::Negative | ty::ImplPolarity::Reservation = header.polarity {
173 return Ok(());
174 }
175
176 if tcx.features().const_param_ty_unchecked() {
177 return Ok(());
178 }
179
180 if !tcx.features().adt_const_params() {
181 match *self_type.kind() {
182 ty::Adt(adt, _) if adt.is_struct() => {
183 let struct_vis = tcx.visibility(adt.did());
184 for variant in adt.variants() {
185 for field in &variant.fields {
186 if struct_vis.greater_than(field.vis, tcx) {
187 let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
188 return Err(tcx
189 .dcx()
190 .emit_err(diagnostics::ConstParamTyFieldVisMismatch { span }));
191 }
192 }
193 }
194 }
195
196 _ => {}
197 }
198 }
199
200 let cause = traits::ObligationCause::misc(DUMMY_SP, impl_did);
201 match type_allowed_to_implement_const_param_ty(tcx, param_env, self_type, cause) {
202 Ok(()) => Ok(()),
203 Err(ConstParamTyImplementationError::InfrigingFields(fields)) => {
204 let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
205 Err(infringing_fields_error(
206 tcx,
207 fields.into_iter().map(|(field, ty, reason)| (tcx.def_span(field.did), ty, reason)),
208 LangItem::ConstParamTy,
209 impl_did,
210 span,
211 ))
212 }
213 Err(ConstParamTyImplementationError::NotAnAdtOrBuiltinAllowed) => {
214 let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
215 Err(tcx.dcx().emit_err(diagnostics::ConstParamTyImplOnNonAdt { span }))
216 }
217 Err(ConstParamTyImplementationError::NonExhaustive(attr_span)) => {
218 let defn_span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
219 Err(tcx
220 .dcx()
221 .emit_err(diagnostics::ConstParamTyImplOnNonExhaustive { defn_span, attr_span }))
222 }
223 Err(ConstParamTyImplementationError::InvalidInnerTyOfBuiltinTy(infringing_tys)) => {
224 let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
225 Err(infringing_fields_error(
226 tcx,
227 infringing_tys.into_iter().map(|(ty, reason)| (span, ty, reason)),
228 LangItem::ConstParamTy,
229 impl_did,
230 span,
231 ))
232 }
233 Err(ConstParamTyImplementationError::UnsizedConstParamsFeatureRequired) => {
234 let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
235 Err(tcx.dcx().emit_err(diagnostics::ConstParamTyImplOnUnsized { span }))
236 }
237 }
238}
239
240fn visit_implementation_of_coerce_unsized(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> {
241 let tcx = checker.tcx;
242 let impl_did = checker.impl_def_id;
243 {
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:243",
"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(243u32),
::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);
244
245 tcx.ensure_result().coerce_unsized_info(impl_did)
249}
250
251fn visit_implementation_of_reborrow(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_reborrow: impl_did={0:?}",
impl_did) as &dyn Value))])
});
} else { ; }
};debug!("visit_implementation_of_reborrow: impl_did={:?}", impl_did);
255
256 reborrow_info(tcx, impl_did)
260}
261
262fn visit_implementation_of_coerce_shared(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> {
263 let tcx = checker.tcx;
264 let impl_did = checker.impl_def_id;
265 {
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:265",
"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(265u32),
::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);
266
267 coerce_shared_info(tcx, impl_did)
271}
272
273fn is_from_coerce_pointee_derive(tcx: TyCtxt<'_>, span: Span) -> bool {
274 span.ctxt()
275 .outer_expn_data()
276 .macro_def_id
277 .is_some_and(|def_id| tcx.is_diagnostic_item(sym::CoercePointee, def_id))
278}
279
280fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> {
281 let tcx = checker.tcx;
282 let impl_did = checker.impl_def_id;
283 let trait_ref = checker.impl_header.trait_ref.instantiate_identity().skip_norm_wip();
284 {
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:284",
"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(284u32),
::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);
285
286 let span = tcx.def_span(impl_did);
287 let trait_name = "DispatchFromDyn";
288
289 let source = trait_ref.self_ty();
290 let target = {
291 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));
292
293 trait_ref.args.type_at(1)
294 };
295
296 let mut res = Ok(());
299 tcx.for_each_relevant_impl(
300 tcx.require_lang_item(LangItem::CoerceUnsized, span),
301 source,
302 |impl_def_id| {
303 res = res.and(tcx.ensure_result().coerce_unsized_info(impl_def_id));
304 },
305 );
306 res?;
307
308 {
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:308",
"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(308u32),
::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);
309
310 let param_env = tcx.param_env(impl_did);
311
312 let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
313 let cause = ObligationCause::misc(span, impl_did);
314
315 match (source.kind(), target.kind()) {
324 (&ty::Pat(_, pat_a), &ty::Pat(_, pat_b)) => {
325 if pat_a != pat_b {
326 return Err(tcx.dcx().emit_err(diagnostics::CoerceSamePatKind {
327 span,
328 trait_name,
329 pat_a: pat_a.to_string(),
330 pat_b: pat_b.to_string(),
331 }));
332 }
333 Ok(())
334 }
335
336 (&ty::Ref(r_a, _, mutbl_a), ty::Ref(r_b, _, mutbl_b))
337 if r_a == *r_b && mutbl_a == *mutbl_b =>
338 {
339 Ok(())
340 }
341 (&ty::RawPtr(_, a_mutbl), &ty::RawPtr(_, b_mutbl)) if a_mutbl == b_mutbl => Ok(()),
342 (&ty::Adt(def_a, args_a), &ty::Adt(def_b, args_b))
343 if def_a.is_struct() && def_b.is_struct() =>
344 {
345 if def_a != def_b {
346 let source_path = tcx.def_path_str(def_a.did());
347 let target_path = tcx.def_path_str(def_b.did());
348 return Err(tcx.dcx().emit_err(diagnostics::CoerceSameStruct {
349 span,
350 trait_name,
351 note: true,
352 source_path,
353 target_path,
354 }));
355 }
356
357 if def_a.repr().c() || def_a.repr().packed() {
358 return Err(tcx.dcx().emit_err(diagnostics::DispatchFromDynRepr { span }));
359 }
360
361 let fields = &def_a.non_enum_variant().fields;
362
363 let mut res = Ok(());
364 let coerced_fields = fields
365 .iter_enumerated()
366 .filter_map(|(i, field)| {
367 let unnormalized_ty = tcx.type_of(field.did).instantiate_identity();
369 if tcx
370 .try_normalize_erasing_regions(
371 ty::TypingEnv::non_body_analysis(tcx, def_a.did()),
372 unnormalized_ty,
373 )
374 .unwrap_or(unnormalized_ty.skip_norm_wip())
375 .is_phantom_data()
376 {
377 return None;
378 }
379
380 let ty_a = field.ty(tcx, args_a).skip_norm_wip();
381 let ty_b = field.ty(tcx, args_b).skip_norm_wip();
382
383 if ty_a == ty_b {
385 if let Ok(layout) =
390 tcx.layout_of(infcx.typing_env(param_env).as_query_input(ty_a))
391 && layout.is_1zst()
392 && !ty_a.has_non_region_param()
393 {
394 return None;
396 }
397
398 res = Err(tcx.dcx().emit_err(diagnostics::DispatchFromDynZST {
399 span,
400 name: field.ident(tcx),
401 ty: ty_a,
402 }));
403
404 None
405 } else {
406 Some((i, ty_a, ty_b, tcx.def_span(field.did)))
407 }
408 })
409 .collect::<Vec<_>>();
410 res?;
411
412 if coerced_fields.is_empty() {
413 return Err(tcx.dcx().emit_err(diagnostics::CoerceNoField {
414 span,
415 trait_name,
416 note: true,
417 }));
418 } else if let &[(_, ty_a, ty_b, field_span)] = &coerced_fields[..] {
419 let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
420 ocx.register_obligation(Obligation::new(
421 tcx,
422 cause.clone(),
423 param_env,
424 ty::TraitRef::new(tcx, trait_ref.def_id, [ty_a, ty_b]),
425 ));
426 let errors = ocx.evaluate_obligations_error_on_ambiguity();
427 if !errors.is_empty() {
428 if is_from_coerce_pointee_derive(tcx, span) {
429 return Err(tcx.dcx().emit_err(diagnostics::CoerceFieldValidity {
430 span,
431 trait_name,
432 ty: trait_ref.self_ty(),
433 field_span,
434 field_ty: ty_a,
435 }));
436 } else {
437 return Err(infcx.err_ctxt().report_fulfillment_errors(errors));
438 }
439 }
440
441 ocx.resolve_regions_and_report_errors(impl_did, param_env, [])?;
443
444 Ok(())
445 } else {
446 return Err(tcx.dcx().emit_err(diagnostics::CoerceMulti {
447 span,
448 trait_name,
449 number: coerced_fields.len(),
450 fields: coerced_fields.iter().map(|(_, _, _, s)| *s).collect::<Vec<_>>().into(),
451 }));
452 }
453 }
454 _ => Err(tcx.dcx().emit_err(diagnostics::CoerceUnsizedNonStruct { span, trait_name })),
455 }
456}
457
458pub(crate) fn reborrow_info<'tcx>(
459 tcx: TyCtxt<'tcx>,
460 impl_did: LocalDefId,
461) -> Result<(), ErrorGuaranteed> {
462 {
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:462",
"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(462u32),
::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);
463 let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
464 let span = tcx.def_span(impl_did);
465 let trait_name = "Reborrow";
466
467 let reborrow_trait = tcx.require_lang_item(LangItem::Reborrow, span);
468
469 let source = tcx.type_of(impl_did).instantiate_identity().skip_norm_wip();
470 let trait_ref = tcx.impl_trait_ref(impl_did).instantiate_identity().skip_norm_wip();
471
472 if trait_impl_lifetime_params_count(tcx, impl_did) != 1 {
473 return Err(tcx
474 .dcx()
475 .emit_err(diagnostics::CoerceSharedNotSingleLifetimeParam { span, trait_name }));
476 }
477
478 {
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);
479 let param_env = tcx.param_env(impl_did);
480 if !!source.has_escaping_bound_vars() {
::core::panicking::panic("assertion failed: !source.has_escaping_bound_vars()")
};assert!(!source.has_escaping_bound_vars());
481
482 let (def, args) = match source.kind() {
483 &ty::Adt(def, args) if def.is_struct() => (def, args),
484 _ => {
485 return Err(tcx
487 .dcx()
488 .emit_err(diagnostics::CoerceUnsizedNonStruct { span, trait_name }));
489 }
490 };
491
492 let lifetimes_count = generic_lifetime_params_count(args);
493 let data_fields = collect_struct_data_fields(tcx, def, args);
494
495 if lifetimes_count != 1 {
496 let item = tcx.hir_expect_item(impl_did);
497 let _span = if let ItemKind::Impl(hir::Impl { of_trait: Some(of_trait), .. }) = &item.kind {
498 of_trait.trait_ref.path.span
499 } else {
500 tcx.def_span(impl_did)
501 };
502
503 return Err(tcx.dcx().emit_err(diagnostics::CoerceSharedMulti { span, trait_name }));
504 }
505
506 if data_fields.is_empty() {
507 return Ok(());
508 }
509
510 let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
511 for (field, span) in data_fields {
513 let field = ocx
514 .deeply_normalize(&traits::ObligationCause::misc(span, impl_did), param_env, field)
515 .map_err(|errors| infcx.err_ctxt().report_fulfillment_errors(errors))?;
516 if assert_field_type_is_reborrow(
517 tcx,
518 &infcx,
519 reborrow_trait,
520 impl_did,
521 param_env,
522 field,
523 span,
524 )
525 .is_ok()
526 {
527 continue;
529 }
530
531 assert_field_type_is_copy(tcx, &infcx, impl_did, param_env, field, span)?;
533 }
534
535 Ok(())
536}
537
538fn assert_field_type_is_reborrow<'tcx>(
539 tcx: TyCtxt<'tcx>,
540 infcx: &InferCtxt<'tcx>,
541 reborrow_trait: DefId,
542 impl_did: LocalDefId,
543 param_env: ty::ParamEnv<'tcx>,
544 ty: Ty<'tcx>,
545 span: Span,
546) -> Result<(), Vec<FulfillmentError<'tcx>>> {
547 if ty.ref_mutability() == Some(ty::Mutability::Mut) {
548 return Ok(());
550 }
551 let ocx = ObligationCtxt::new_with_diagnostics(infcx);
552 let cause = traits::ObligationCause::misc(span, impl_did);
553 let obligation =
554 Obligation::new(tcx, cause, param_env, ty::TraitRef::new(tcx, reborrow_trait, [ty]));
555 ocx.register_obligation(obligation);
556 let errors = ocx.evaluate_obligations_error_on_ambiguity();
557
558 if !errors.is_empty() { Err(errors) } else { Ok(()) }
559}
560
561pub(crate) fn coerce_shared_info<'tcx>(
562 tcx: TyCtxt<'tcx>,
563 impl_did: LocalDefId,
564) -> Result<(), ErrorGuaranteed> {
565 {
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:565",
"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(565u32),
::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);
566 let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
567 let span = tcx.def_span(impl_did);
568 let trait_name = "CoerceShared";
569
570 let coerce_shared_trait = tcx.require_lang_item(LangItem::CoerceShared, span);
571
572 let source = tcx.type_of(impl_did).instantiate_identity().skip_norm_wip();
573 let trait_ref = tcx.impl_trait_ref(impl_did).instantiate_identity().skip_norm_wip();
574
575 if trait_impl_lifetime_params_count(tcx, impl_did) != 1 {
576 return Err(tcx
577 .dcx()
578 .emit_err(diagnostics::CoerceSharedNotSingleLifetimeParam { span, trait_name }));
579 }
580
581 {
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);
582 let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
583 let param_env = tcx.param_env(impl_did);
584 let (source, target) = ocx
585 .deeply_normalize(
586 &traits::ObligationCause::misc(span, impl_did),
587 param_env,
588 Unnormalized::new_wip((source, trait_ref.args.type_at(1))),
589 )
590 .map_err(|errors| infcx.err_ctxt().report_fulfillment_errors(errors))?;
591
592 if !!source.has_escaping_bound_vars() {
::core::panicking::panic("assertion failed: !source.has_escaping_bound_vars()")
};assert!(!source.has_escaping_bound_vars());
593
594 let data = match (source.kind(), target.kind()) {
595 (&ty::Adt(def_a, args_a), &ty::Adt(def_b, args_b))
596 if def_a.is_struct() && def_b.is_struct() =>
597 {
598 let a_lifetimes_count = generic_lifetime_params_count(args_a);
604 let a_data_fields = collect_struct_data_fields(tcx, def_a, args_a);
605 let b_lifetimes_count = generic_lifetime_params_count(args_b);
606 let b_data_fields = collect_struct_data_fields(tcx, def_b, args_b);
607
608 if a_lifetimes_count != 1
609 || b_lifetimes_count != 1
610 || a_data_fields.len() > 1
611 || b_data_fields.len() > 1
612 || a_data_fields.len() != b_data_fields.len()
613 {
614 let item = tcx.hir_expect_item(impl_did);
615 let span = if let ItemKind::Impl(hir::Impl { of_trait: Some(of_trait), .. }) =
616 &item.kind
617 {
618 of_trait.trait_ref.path.span
619 } else {
620 tcx.def_span(impl_did)
621 };
622
623 return Err(tcx
624 .dcx()
625 .emit_err(diagnostics::CoerceSharedMulti { span, trait_name }));
626 }
627
628 if a_data_fields.len() == 1 {
629 let (a, span_a) = a_data_fields[0];
632 let (b, span_b) = b_data_fields[0];
633 let a = ocx
634 .deeply_normalize(
635 &traits::ObligationCause::misc(span_a, impl_did),
636 param_env,
637 a,
638 )
639 .map_err(|errors| infcx.err_ctxt().report_fulfillment_errors(errors))?;
640 let b = ocx
641 .deeply_normalize(
642 &traits::ObligationCause::misc(span_b, impl_did),
643 param_env,
644 b,
645 )
646 .map_err(|errors| infcx.err_ctxt().report_fulfillment_errors(errors))?;
647
648 Some((a, b, coerce_shared_trait, span_a, span_b))
649 } else {
650 None
653 }
654 }
655
656 _ => {
657 return Err(tcx
659 .dcx()
660 .emit_err(diagnostics::CoerceUnsizedNonStruct { span, trait_name }));
661 }
662 };
663
664 if let Some((source, target, trait_def_id, source_field_span, _target_field_span)) = data {
666 if source.ref_mutability() == Some(ty::Mutability::Mut)
678 && target.ref_mutability() == Some(ty::Mutability::Not)
679 && infcx
680 .relate(
681 param_env,
682 source.peel_refs(),
683 ty::Variance::Invariant,
684 target.peel_refs(),
685 source_field_span,
686 )
687 .is_ok()
688 {
689 return Ok(());
691 }
692
693 if infcx
696 .relate(param_env, source, ty::Variance::Invariant, target, source_field_span)
697 .is_err()
698 {
699 let cause = traits::ObligationCause::misc(span, impl_did);
703 let obligation = Obligation::new(
704 tcx,
705 cause,
706 param_env,
707 ty::TraitRef::new(tcx, trait_def_id, [source, target]),
708 );
709 ocx.register_obligation(obligation);
710 let errors = ocx.evaluate_obligations_error_on_ambiguity();
711
712 if !errors.is_empty() {
713 return Err(infcx.err_ctxt().report_fulfillment_errors(errors));
714 }
715 ocx.resolve_regions_and_report_errors(impl_did, param_env, [])?;
717 } else {
718 assert_field_type_is_copy(tcx, &infcx, impl_did, param_env, source, source_field_span)?;
722 }
723 }
724
725 Ok(())
726}
727
728fn trait_impl_lifetime_params_count(tcx: TyCtxt<'_>, did: LocalDefId) -> usize {
729 tcx.generics_of(did)
730 .own_params
731 .iter()
732 .filter(|p| #[allow(non_exhaustive_omitted_patterns)] match p.kind {
ty::GenericParamDefKind::Lifetime => true,
_ => false,
}matches!(p.kind, ty::GenericParamDefKind::Lifetime))
733 .count()
734}
735
736fn generic_lifetime_params_count(args: &[ty::GenericArg<'_>]) -> usize {
737 args.iter().filter(|arg| arg.as_region().is_some()).count()
738}
739
740fn collect_struct_data_fields<'tcx>(
741 tcx: TyCtxt<'tcx>,
742 def: ty::AdtDef<'tcx>,
743 args: ty::GenericArgsRef<'tcx>,
744) -> Vec<(Unnormalized<'tcx, Ty<'tcx>>, Span)> {
745 def.non_enum_variant()
746 .fields
747 .iter()
748 .filter_map(|f| {
749 let ty = f.ty(tcx, args);
751 if ty.skip_norm_wip().is_phantom_data() {
754 return None;
755 }
756 Some((ty, tcx.def_span(f.did)))
757 })
758 .collect()
759}
760
761fn assert_field_type_is_copy<'tcx>(
762 tcx: TyCtxt<'tcx>,
763 infcx: &InferCtxt<'tcx>,
764 impl_did: LocalDefId,
765 param_env: ty::ParamEnv<'tcx>,
766 ty: Ty<'tcx>,
767 span: Span,
768) -> Result<(), ErrorGuaranteed> {
769 let copy_trait = tcx.require_lang_item(LangItem::Copy, span);
770 let ocx = ObligationCtxt::new_with_diagnostics(infcx);
771 let cause = traits::ObligationCause::misc(span, impl_did);
772 let obligation =
773 Obligation::new(tcx, cause, param_env, ty::TraitRef::new(tcx, copy_trait, [ty]));
774 ocx.register_obligation(obligation);
775 let errors = ocx.evaluate_obligations_error_on_ambiguity();
776
777 if !errors.is_empty() {
778 Err(infcx.err_ctxt().report_fulfillment_errors(errors))
779 } else {
780 Ok(())
781 }
782}
783
784pub(crate) fn coerce_unsized_info<'tcx>(
785 tcx: TyCtxt<'tcx>,
786 impl_did: LocalDefId,
787) -> Result<CoerceUnsizedInfo, ErrorGuaranteed> {
788 {
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:788",
"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(788u32),
::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);
789 let span = tcx.def_span(impl_did);
790 let trait_name = "CoerceUnsized";
791
792 let coerce_unsized_trait = tcx.require_lang_item(LangItem::CoerceUnsized, span);
793 let unsize_trait = tcx.require_lang_item(LangItem::Unsize, span);
794
795 let source = tcx.type_of(impl_did).instantiate_identity().skip_norm_wip();
796 let trait_ref = tcx.impl_trait_ref(impl_did).instantiate_identity().skip_norm_wip();
797
798 {
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);
799 let target = trait_ref.args.type_at(1);
800 {
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:800",
"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(800u32),
::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);
801
802 let param_env = tcx.param_env(impl_did);
803 if !!source.has_escaping_bound_vars() {
::core::panicking::panic("assertion failed: !source.has_escaping_bound_vars()")
};assert!(!source.has_escaping_bound_vars());
804
805 {
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:805",
"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(805u32),
::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);
806
807 let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
808 let cause = ObligationCause::misc(span, impl_did);
809 let check_mutbl = |mt_a: ty::TypeAndMut<'tcx>,
810 mt_b: ty::TypeAndMut<'tcx>,
811 mk_ptr: &dyn Fn(Ty<'tcx>) -> Ty<'tcx>| {
812 if mt_a.mutbl < mt_b.mutbl {
813 infcx
814 .err_ctxt()
815 .report_mismatched_types(
816 &cause,
817 param_env,
818 mk_ptr(mt_b.ty),
819 target,
820 ty::error::TypeError::Mutability,
821 )
822 .emit();
823 }
824 (mt_a.ty, mt_b.ty, unsize_trait, None, span)
825 };
826 let (source, target, trait_def_id, kind, field_span) = match (source.kind(), target.kind()) {
827 (&ty::Pat(ty_a, pat_a), &ty::Pat(ty_b, pat_b)) => {
828 if pat_a != pat_b {
829 return Err(tcx.dcx().emit_err(diagnostics::CoerceSamePatKind {
830 span,
831 trait_name,
832 pat_a: pat_a.to_string(),
833 pat_b: pat_b.to_string(),
834 }));
835 }
836 (ty_a, ty_b, coerce_unsized_trait, None, span)
837 }
838
839 (&ty::Ref(r_a, ty_a, mutbl_a), &ty::Ref(r_b, ty_b, mutbl_b)) => {
840 infcx.sub_regions(
841 SubregionOrigin::RelateObjectBound(span),
842 r_b,
843 r_a,
844 ty::VisibleForLeakCheck::Yes,
845 );
846 let mt_a = ty::TypeAndMut { ty: ty_a, mutbl: mutbl_a };
847 let mt_b = ty::TypeAndMut { ty: ty_b, mutbl: mutbl_b };
848 check_mutbl(mt_a, mt_b, &|ty| Ty::new_imm_ref(tcx, r_b, ty))
849 }
850
851 (&ty::Ref(_, ty_a, mutbl_a), &ty::RawPtr(ty_b, mutbl_b))
852 | (&ty::RawPtr(ty_a, mutbl_a), &ty::RawPtr(ty_b, mutbl_b)) => {
853 let mt_a = ty::TypeAndMut { ty: ty_a, mutbl: mutbl_a };
854 let mt_b = ty::TypeAndMut { ty: ty_b, mutbl: mutbl_b };
855 check_mutbl(mt_a, mt_b, &|ty| Ty::new_imm_ptr(tcx, ty))
856 }
857
858 (&ty::Adt(def_a, args_a), &ty::Adt(def_b, args_b))
859 if def_a.is_struct() && def_b.is_struct() =>
860 {
861 if def_a != def_b {
862 let source_path = tcx.def_path_str(def_a.did());
863 let target_path = tcx.def_path_str(def_b.did());
864 return Err(tcx.dcx().emit_err(diagnostics::CoerceSameStruct {
865 span,
866 trait_name,
867 note: true,
868 source_path,
869 target_path,
870 }));
871 }
872
873 let fields = &def_a.non_enum_variant().fields;
913 let diff_fields = fields
914 .iter_enumerated()
915 .filter_map(|(i, f)| {
916 let (a, b) =
917 (f.ty(tcx, args_a).skip_norm_wip(), f.ty(tcx, args_b).skip_norm_wip());
918
919 let unnormalized_ty = tcx.type_of(f.did).instantiate_identity();
921 if tcx
922 .try_normalize_erasing_regions(
923 ty::TypingEnv::non_body_analysis(tcx, def_a.did()),
924 unnormalized_ty,
925 )
926 .unwrap_or(unnormalized_ty.skip_norm_wip())
927 .is_phantom_data()
928 {
929 return None;
930 }
931
932 if a == b {
942 return None;
943 }
944
945 Some((i, a, b, tcx.def_span(f.did)))
948 })
949 .collect::<Vec<_>>();
950
951 if diff_fields.is_empty() {
952 return Err(tcx.dcx().emit_err(diagnostics::CoerceNoField {
953 span,
954 trait_name,
955 note: true,
956 }));
957 } else if diff_fields.len() > 1 {
958 let item = tcx.hir_expect_item(impl_did);
959 let span = if let ItemKind::Impl(hir::Impl { of_trait: Some(of_trait), .. }) =
960 &item.kind
961 {
962 of_trait.trait_ref.path.span
963 } else {
964 tcx.def_span(impl_did)
965 };
966
967 return Err(tcx.dcx().emit_err(diagnostics::CoerceMulti {
968 span,
969 trait_name,
970 number: diff_fields.len(),
971 fields: diff_fields.iter().map(|(_, _, _, s)| *s).collect::<Vec<_>>().into(),
972 }));
973 }
974
975 let (i, a, b, field_span) = diff_fields[0];
976 let kind = ty::adjustment::CustomCoerceUnsized::Struct(i);
977 (a, b, coerce_unsized_trait, Some(kind), field_span)
978 }
979
980 _ => {
981 return Err(tcx
982 .dcx()
983 .emit_err(diagnostics::CoerceUnsizedNonStruct { span, trait_name }));
984 }
985 };
986
987 let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
989 let cause = traits::ObligationCause::misc(span, impl_did);
990 let obligation = Obligation::new(
991 tcx,
992 cause,
993 param_env,
994 ty::TraitRef::new(tcx, trait_def_id, [source, target]),
995 );
996 ocx.register_obligation(obligation);
997 let errors = ocx.evaluate_obligations_error_on_ambiguity();
998
999 if !errors.is_empty() {
1000 if is_from_coerce_pointee_derive(tcx, span) {
1001 return Err(tcx.dcx().emit_err(diagnostics::CoerceFieldValidity {
1002 span,
1003 trait_name,
1004 ty: trait_ref.self_ty(),
1005 field_span,
1006 field_ty: source,
1007 }));
1008 } else {
1009 return Err(infcx.err_ctxt().report_fulfillment_errors(errors));
1010 }
1011 }
1012
1013 ocx.resolve_regions_and_report_errors(impl_did, param_env, [])?;
1015
1016 Ok(CoerceUnsizedInfo { custom_kind: kind })
1017}
1018
1019fn infringing_fields_error<'tcx>(
1020 tcx: TyCtxt<'tcx>,
1021 infringing_tys: impl Iterator<Item = (Span, Ty<'tcx>, InfringingFieldsReason<'tcx>)>,
1022 lang_item: LangItem,
1023 impl_did: LocalDefId,
1024 impl_span: Span,
1025) -> ErrorGuaranteed {
1026 let trait_did = tcx.require_lang_item(lang_item, impl_span);
1027
1028 let trait_name = tcx.def_path_str(trait_did);
1029
1030 let mut errors: BTreeMap<_, Vec<_>> = Default::default();
1033 let mut bounds = ::alloc::vec::Vec::new()vec![];
1034
1035 let mut seen_tys = FxHashSet::default();
1036
1037 let mut label_spans = Vec::new();
1038
1039 for (span, ty, reason) in infringing_tys {
1040 if !seen_tys.insert(ty) {
1042 continue;
1043 }
1044
1045 label_spans.push(span);
1046
1047 match reason {
1048 InfringingFieldsReason::Fulfill(fulfillment_errors) => {
1049 for error in fulfillment_errors {
1050 let error_predicate = error.obligation.predicate;
1051 if error_predicate != error.root_obligation.predicate {
1057 errors
1058 .entry((ty.to_string(), error_predicate.to_string()))
1059 .or_default()
1060 .push(error.obligation.cause.span);
1061 }
1062 if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(ty::TraitPredicate {
1063 trait_ref,
1064 polarity: ty::PredicatePolarity::Positive,
1065 ..
1066 })) = error_predicate.kind().skip_binder()
1067 {
1068 let ty = trait_ref.self_ty();
1069 if let ty::Param(_) = ty.kind() {
1070 bounds.push((
1071 ::alloc::__export::must_use({ ::alloc::fmt::format(format_args!("{0}", ty)) })format!("{ty}"),
1072 trait_ref.print_trait_sugared().to_string(),
1073 Some(trait_ref.def_id),
1074 ));
1075 }
1076 }
1077 }
1078 }
1079 InfringingFieldsReason::Regions(region_errors) => {
1080 for error in region_errors {
1081 let ty = ty.to_string();
1082 match error {
1083 RegionResolutionError::ConcreteFailure(origin, a, b) => {
1084 let predicate = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}: {1}", b, a))
})format!("{b}: {a}");
1085 errors
1086 .entry((ty.clone(), predicate.clone()))
1087 .or_default()
1088 .push(origin.span());
1089 if let ty::RegionKind::ReEarlyParam(ebr) = b.kind()
1090 && ebr.is_named()
1091 {
1092 bounds.push((b.to_string(), a.to_string(), None));
1093 }
1094 }
1095 RegionResolutionError::GenericBoundFailure(origin, a, b) => {
1096 let predicate = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}: {1}", a, b))
})format!("{a}: {b}");
1097 errors
1098 .entry((ty.clone(), predicate.clone()))
1099 .or_default()
1100 .push(origin.span());
1101 if let infer::region_constraints::GenericKind::Param(_) = a {
1102 bounds.push((a.to_string(), b.to_string(), None));
1103 }
1104 }
1105 _ => continue,
1106 }
1107 }
1108 }
1109 }
1110 }
1111 let mut notes = Vec::new();
1112 for ((ty, error_predicate), spans) in errors {
1113 let span: MultiSpan = spans.into();
1114 notes.push(diagnostics::ImplForTyRequires {
1115 span,
1116 error_predicate,
1117 trait_name: trait_name.clone(),
1118 ty,
1119 });
1120 }
1121
1122 let mut err = tcx.dcx().create_err(diagnostics::TraitCannotImplForTy {
1123 span: impl_span,
1124 trait_name,
1125 label_spans,
1126 notes,
1127 });
1128
1129 suggest_constraining_type_params(
1130 tcx,
1131 tcx.hir_get_generics(impl_did).expect("impls always have generics"),
1132 &mut err,
1133 bounds
1134 .iter()
1135 .map(|(param, constraint, def_id)| (param.as_str(), constraint.as_str(), *def_id)),
1136 None,
1137 );
1138
1139 err.emit()
1140}
1141
1142fn visit_implementation_of_coerce_pointee_validity(
1143 checker: &Checker<'_>,
1144) -> Result<(), ErrorGuaranteed> {
1145 let tcx = checker.tcx;
1146 let self_ty =
1147 tcx.impl_trait_ref(checker.impl_def_id).instantiate_identity().skip_norm_wip().self_ty();
1148 let span = tcx.def_span(checker.impl_def_id);
1149 if !tcx.is_builtin_derived(checker.impl_def_id.into()) {
1150 return Err(tcx.dcx().emit_err(diagnostics::CoercePointeeNoUserValidityAssertion { span }));
1151 }
1152 let ty::Adt(def, _args) = self_ty.kind() else {
1153 return Err(tcx.dcx().emit_err(diagnostics::CoercePointeeNotConcreteType { span }));
1154 };
1155 let did = def.did();
1156 let span = tcx.def_span(did);
1158 if !def.is_struct() {
1159 return Err(tcx
1160 .dcx()
1161 .emit_err(diagnostics::CoercePointeeNotStruct { span, kind: def.descr().into() }));
1162 }
1163 if !def.repr().transparent() {
1164 return Err(tcx.dcx().emit_err(diagnostics::CoercePointeeNotTransparent { span }));
1165 }
1166 if def.all_fields().next().is_none() {
1167 return Err(tcx.dcx().emit_err(diagnostics::CoercePointeeNoField { span }));
1168 }
1169 Ok(())
1170}