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 Ok(())
104}
105
106fn enforce_empty_impls_for_marker_traits(
109 tcx: TyCtxt<'_>,
110 impl_def_id: LocalDefId,
111 trait_def_id: DefId,
112 trait_def: &ty::TraitDef,
113) -> Result<(), ErrorGuaranteed> {
114 if !trait_def.is_marker {
115 return Ok(());
116 }
117
118 if tcx.associated_item_def_ids(trait_def_id).is_empty() {
119 return Ok(());
120 }
121
122 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!(
123 tcx.dcx(),
124 tcx.def_span(impl_def_id),
125 E0715,
126 "impls for marker traits cannot contain items"
127 )
128 .emit())
129}
130
131pub(crate) fn provide(providers: &mut Providers) {
133 use self::builtin::coerce_unsized_info;
134 use self::inherent_impls::{
135 crate_incoherent_impls, crate_inherent_impls, crate_inherent_impls_validity_check,
136 inherent_impls,
137 };
138 use self::inherent_impls_overlap::crate_inherent_impls_overlap_check;
139 use self::orphan::orphan_check_impl;
140
141 *providers = Providers {
142 coherent_trait,
143 crate_inherent_impls,
144 crate_incoherent_impls,
145 inherent_impls,
146 crate_inherent_impls_validity_check,
147 crate_inherent_impls_overlap_check,
148 coerce_unsized_info,
149 orphan_check_impl,
150 ..*providers
151 };
152}
153
154fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) -> Result<(), ErrorGuaranteed> {
155 let impls = tcx.local_trait_impls(def_id);
156 if impls.is_empty() {
159 return Ok(());
160 }
161 let mut res = tcx.ensure_ok().specialization_graph_of(def_id);
164
165 for &impl_def_id in impls {
166 let impl_header = tcx.impl_trait_header(impl_def_id);
167 let trait_ref = impl_header.trait_ref.instantiate_identity();
168 let trait_def = tcx.trait_def(trait_ref.def_id);
169
170 res = res
171 .and(check_impl(tcx, impl_def_id, trait_ref, trait_def, impl_header.polarity))
172 .and(check_object_overlap(tcx, impl_def_id, trait_ref))
173 .and(unsafety::check_item(tcx, impl_def_id, impl_header, trait_def))
174 .and(tcx.ensure_ok().orphan_check_impl(impl_def_id))
175 .and(builtin::check_trait(tcx, def_id, impl_def_id, impl_header));
176 }
177
178 res
179}
180
181fn check_object_overlap<'tcx>(
183 tcx: TyCtxt<'tcx>,
184 impl_def_id: LocalDefId,
185 trait_ref: ty::TraitRef<'tcx>,
186) -> Result<(), ErrorGuaranteed> {
187 let trait_def_id = trait_ref.def_id;
188
189 if let Err(guar) = trait_ref.error_reported() {
190 {
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:190",
"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(190u32),
::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);
191 return Err(guar);
192 }
193
194 if let ty::Dynamic(data, ..) = trait_ref.self_ty().kind() {
196 let component_def_ids = data.iter().flat_map(|predicate| {
200 match predicate.skip_binder() {
201 ty::ExistentialPredicate::Trait(tr) => Some(tr.def_id),
202 ty::ExistentialPredicate::AutoTrait(def_id) => Some(def_id),
203 ty::ExistentialPredicate::Projection(..) => None,
206 }
207 });
208
209 for component_def_id in component_def_ids {
210 if !tcx.is_dyn_compatible(component_def_id) {
211 } else {
213 let mut supertrait_def_ids = elaborate::supertrait_def_ids(tcx, component_def_id);
214 if supertrait_def_ids.any(|d| d == trait_def_id) {
215 let span = tcx.def_span(impl_def_id);
216 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!(
217 tcx.dcx(),
218 span,
219 E0371,
220 "the object type `{}` automatically implements the trait `{}`",
221 trait_ref.self_ty(),
222 tcx.def_path_str(trait_def_id)
223 )
224 .with_span_label(
225 span,
226 ::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!(
227 "`{}` automatically implements trait `{}`",
228 trait_ref.self_ty(),
229 tcx.def_path_str(trait_def_id)
230 ),
231 )
232 .emit());
233 }
234 }
235 }
236 }
237 Ok(())
238}