rustc_hir_analysis/coherence/
mod.rs1use rustc_errors::codes::*;
9use rustc_errors::struct_span_code_err;
10use rustc_hir::LangItem;
11use rustc_hir::def_id::{DefId, LocalDefId};
12use rustc_middle::query::Providers;
13use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt, elaborate};
14use rustc_session::parse::feature_err;
15use rustc_span::{ErrorGuaranteed, sym};
16use tracing::debug;
17
18use crate::check::always_applicable;
19use crate::errors;
20
21mod builtin;
22mod inherent_impls;
23mod inherent_impls_overlap;
24mod orphan;
25mod unsafety;
26
27fn check_impl<'tcx>(
28 tcx: TyCtxt<'tcx>,
29 impl_def_id: LocalDefId,
30 trait_ref: ty::TraitRef<'tcx>,
31 trait_def: &'tcx ty::TraitDef,
32 polarity: ty::ImplPolarity,
33) -> Result<(), ErrorGuaranteed> {
34 {
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/mod.rs:34",
"rustc_hir_analysis::coherence", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_analysis/src/coherence/mod.rs"),
::tracing_core::__macro_support::Option::Some(34u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::coherence"),
::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!("(checking implementation) adding impl for trait \'{0:?}\', item \'{1}\'",
trait_ref, tcx.def_path_str(impl_def_id)) as &dyn Value))])
});
} else { ; }
};debug!(
35 "(checking implementation) adding impl for trait '{:?}', item '{}'",
36 trait_ref,
37 tcx.def_path_str(impl_def_id)
38 );
39
40 trait_ref.error_reported()?;
43
44 enforce_trait_manually_implementable(tcx, impl_def_id, trait_ref.def_id, trait_def)
45 .and(enforce_empty_impls_for_marker_traits(tcx, impl_def_id, trait_ref.def_id, trait_def))
46 .and(always_applicable::check_negative_auto_trait_impl(
47 tcx,
48 impl_def_id,
49 trait_ref,
50 polarity,
51 ))
52}
53
54fn enforce_trait_manually_implementable(
55 tcx: TyCtxt<'_>,
56 impl_def_id: LocalDefId,
57 trait_def_id: DefId,
58 trait_def: &ty::TraitDef,
59) -> Result<(), ErrorGuaranteed> {
60 let impl_header_span = tcx.def_span(impl_def_id);
61
62 if tcx.is_lang_item(trait_def_id, LangItem::Freeze) && !tcx.features().freeze_impls() {
63 feature_err(
64 &tcx.sess,
65 sym::freeze_impls,
66 impl_header_span,
67 "explicit impls for the `Freeze` trait are not permitted",
68 )
69 .with_span_label(impl_header_span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("impl of `Freeze` not allowed"))
})format!("impl of `Freeze` not allowed"))
70 .emit();
71 }
72
73 if trait_def.deny_explicit_impl {
75 let trait_name = tcx.item_name(trait_def_id);
76 let mut err = {
tcx.dcx().struct_span_err(impl_header_span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("explicit impls for the `{0}` trait are not permitted",
trait_name))
})).with_code(E0322)
}struct_span_code_err!(
77 tcx.dcx(),
78 impl_header_span,
79 E0322,
80 "explicit impls for the `{trait_name}` trait are not permitted"
81 );
82 err.span_label(impl_header_span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("impl of `{0}` not allowed",
trait_name))
})format!("impl of `{trait_name}` not allowed"));
83
84 if tcx.is_lang_item(trait_def_id, LangItem::Unsize) {
87 err.code(E0328);
88 }
89
90 return Err(err.emit());
91 }
92
93 if let ty::trait_def::TraitSpecializationKind::AlwaysApplicable = trait_def.specialization_kind
94 {
95 if !tcx.features().specialization()
96 && !tcx.features().min_specialization()
97 && !impl_header_span.allows_unstable(sym::specialization)
98 && !impl_header_span.allows_unstable(sym::min_specialization)
99 {
100 return Err(tcx.dcx().emit_err(errors::SpecializationTrait { span: impl_header_span }));
101 }
102 }
103
104 if !trait_def.impl_restriction.is_allowed_in(impl_def_id.to_def_id(), tcx) {
105 return Err(tcx.dcx().emit_err(errors::ImplOfRestrictedTrait {
106 impl_span: impl_header_span,
107 restriction_span: trait_def.impl_restriction.expect_span(),
108 restriction_path: trait_def.impl_restriction.restriction_path(tcx),
109 }));
110 }
111 Ok(())
112}
113
114fn enforce_empty_impls_for_marker_traits(
117 tcx: TyCtxt<'_>,
118 impl_def_id: LocalDefId,
119 trait_def_id: DefId,
120 trait_def: &ty::TraitDef,
121) -> Result<(), ErrorGuaranteed> {
122 if !trait_def.is_marker {
123 return Ok(());
124 }
125
126 if tcx.associated_item_def_ids(trait_def_id).is_empty() {
127 return Ok(());
128 }
129
130 Err({
tcx.dcx().struct_span_err(tcx.def_span(impl_def_id),
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("impls for marker traits cannot contain items"))
})).with_code(E0715)
}struct_span_code_err!(
131 tcx.dcx(),
132 tcx.def_span(impl_def_id),
133 E0715,
134 "impls for marker traits cannot contain items"
135 )
136 .emit())
137}
138
139pub(crate) fn provide(providers: &mut Providers) {
141 use self::builtin::coerce_unsized_info;
142 use self::inherent_impls::{
143 crate_incoherent_impls, crate_inherent_impls, crate_inherent_impls_validity_check,
144 inherent_impls,
145 };
146 use self::inherent_impls_overlap::crate_inherent_impls_overlap_check;
147 use self::orphan::orphan_check_impl;
148
149 *providers = Providers {
150 coherent_trait,
151 crate_inherent_impls,
152 crate_incoherent_impls,
153 inherent_impls,
154 crate_inherent_impls_validity_check,
155 crate_inherent_impls_overlap_check,
156 coerce_unsized_info,
157 orphan_check_impl,
158 ..*providers
159 };
160}
161
162fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) -> Result<(), ErrorGuaranteed> {
163 let impls = tcx.local_trait_impls(def_id);
164 if impls.is_empty() {
167 return Ok(());
168 }
169 let mut res = tcx.ensure_result().specialization_graph_of(def_id);
172
173 for &impl_def_id in impls {
174 let impl_header = tcx.impl_trait_header(impl_def_id);
175 let trait_ref = impl_header.trait_ref.instantiate_identity().skip_norm_wip();
176 let trait_def = tcx.trait_def(trait_ref.def_id);
177
178 res = res
179 .and(check_impl(tcx, impl_def_id, trait_ref, trait_def, impl_header.polarity))
180 .and(check_object_overlap(tcx, impl_def_id, trait_ref))
181 .and(unsafety::check_item(tcx, impl_def_id, impl_header, trait_def))
182 .and(tcx.ensure_result().orphan_check_impl(impl_def_id))
183 .and(builtin::check_trait(tcx, def_id, impl_def_id, impl_header));
184 }
185
186 res
187}
188
189fn check_object_overlap<'tcx>(
191 tcx: TyCtxt<'tcx>,
192 impl_def_id: LocalDefId,
193 trait_ref: ty::TraitRef<'tcx>,
194) -> Result<(), ErrorGuaranteed> {
195 let trait_def_id = trait_ref.def_id;
196
197 if let Err(guar) = trait_ref.error_reported() {
198 {
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/mod.rs:198",
"rustc_hir_analysis::coherence", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_analysis/src/coherence/mod.rs"),
::tracing_core::__macro_support::Option::Some(198u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::coherence"),
::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!("coherence: skipping impl {0:?} with error {1:?}",
impl_def_id, trait_ref) as &dyn Value))])
});
} else { ; }
};debug!("coherence: skipping impl {:?} with error {:?}", impl_def_id, trait_ref);
199 return Err(guar);
200 }
201
202 if let ty::Dynamic(data, ..) = trait_ref.self_ty().kind() {
204 let component_def_ids = data.iter().flat_map(|predicate| {
208 match predicate.skip_binder() {
209 ty::ExistentialPredicate::Trait(tr) => Some(tr.def_id),
210 ty::ExistentialPredicate::AutoTrait(def_id) => Some(def_id),
211 ty::ExistentialPredicate::Projection(..) => None,
214 }
215 });
216
217 for component_def_id in component_def_ids {
218 if !tcx.is_dyn_compatible(component_def_id) {
219 } else {
221 let mut supertrait_def_ids = elaborate::supertrait_def_ids(tcx, component_def_id);
222 if supertrait_def_ids.any(|d| d == trait_def_id) {
223 let span = tcx.def_span(impl_def_id);
224 return Err({
tcx.dcx().struct_span_err(span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("the object type `{0}` automatically implements the trait `{1}`",
trait_ref.self_ty(), tcx.def_path_str(trait_def_id)))
})).with_code(E0371)
}struct_span_code_err!(
225 tcx.dcx(),
226 span,
227 E0371,
228 "the object type `{}` automatically implements the trait `{}`",
229 trait_ref.self_ty(),
230 tcx.def_path_str(trait_def_id)
231 )
232 .with_span_label(
233 span,
234 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}` automatically implements trait `{1}`",
trait_ref.self_ty(), tcx.def_path_str(trait_def_id)))
})format!(
235 "`{}` automatically implements trait `{}`",
236 trait_ref.self_ty(),
237 tcx.def_path_str(trait_def_id)
238 ),
239 )
240 .emit());
241 }
242 }
243 }
244 }
245 Ok(())
246}