3 // The job of the coherence phase of typechecking is to ensure that
4 // each trait has at most one implementation for each type. This is
5 // done by the orphan and overlap modules. Then we build up various
6 // mappings. That mapping code resides here.
8 use rustc_errors
::struct_span_err
;
9 use rustc_hir
::def_id
::{DefId, LocalDefId, LOCAL_CRATE}
;
10 use rustc_middle
::ty
::query
::Providers
;
11 use rustc_middle
::ty
::{self, TyCtxt, TypeFoldable}
;
13 use rustc_trait_selection
::traits
;
17 mod inherent_impls_overlap
;
21 /// Obtains the span of just the impl header of `impl_def_id`.
22 fn impl_header_span(tcx
: TyCtxt
<'_
>, impl_def_id
: LocalDefId
) -> Span
{
23 tcx
.sess
.source_map().guess_head_span(tcx
.span_of_impl(impl_def_id
.to_def_id()).unwrap())
26 fn check_impl(tcx
: TyCtxt
<'_
>, impl_def_id
: LocalDefId
, trait_ref
: ty
::TraitRef
<'_
>) {
28 "(checking implementation) adding impl for trait '{:?}', item '{}'",
30 tcx
.def_path_str(impl_def_id
.to_def_id())
33 // Skip impls where one of the self type is an error type.
34 // This occurs with e.g., resolve failures (#30589).
35 if trait_ref
.references_error() {
39 enforce_trait_manually_implementable(tcx
, impl_def_id
, trait_ref
.def_id
);
40 enforce_empty_impls_for_marker_traits(tcx
, impl_def_id
, trait_ref
.def_id
);
43 fn enforce_trait_manually_implementable(
45 impl_def_id
: LocalDefId
,
48 let did
= Some(trait_def_id
);
49 let li
= tcx
.lang_items();
51 // Disallow *all* explicit impls of `DiscriminantKind`, `Sized` and `Unsize` for now.
52 if did
== li
.discriminant_kind_trait() {
53 let span
= impl_header_span(tcx
, impl_def_id
);
58 "explicit impls for the `DiscriminantKind` trait are not permitted"
60 .span_label(span
, "impl of 'DiscriminantKind' not allowed")
65 if did
== li
.sized_trait() {
66 let span
= impl_header_span(tcx
, impl_def_id
);
71 "explicit impls for the `Sized` trait are not permitted"
73 .span_label(span
, "impl of 'Sized' not allowed")
78 if did
== li
.unsize_trait() {
79 let span
= impl_header_span(tcx
, impl_def_id
);
84 "explicit impls for the `Unsize` trait are not permitted"
86 .span_label(span
, "impl of `Unsize` not allowed")
91 if tcx
.features().unboxed_closures
{
92 // the feature gate allows all Fn traits
96 if let ty
::trait_def
::TraitSpecializationKind
::AlwaysApplicable
=
97 tcx
.trait_def(trait_def_id
).specialization_kind
99 if !tcx
.features().specialization
&& !tcx
.features().min_specialization
{
100 let span
= impl_header_span(tcx
, impl_def_id
);
104 "implementing `rustc_specialization_trait` traits is unstable",
106 .help("add `#![feature(min_specialization)]` to the crate attributes to enable")
112 let trait_name
= if did
== li
.fn_trait() {
114 } else if did
== li
.fn_mut_trait() {
116 } else if did
== li
.fn_once_trait() {
119 return; // everything OK
122 let span
= impl_header_span(tcx
, impl_def_id
);
127 "manual implementations of `{}` are experimental",
130 .span_label(span
, format
!("manual implementations of `{}` are experimental", trait_name
))
131 .help("add `#![feature(unboxed_closures)]` to the crate attributes to enable")
135 /// We allow impls of marker traits to overlap, so they can't override impls
136 /// as that could make it ambiguous which associated item to use.
137 fn enforce_empty_impls_for_marker_traits(
139 impl_def_id
: LocalDefId
,
142 if !tcx
.trait_def(trait_def_id
).is_marker
{
146 if tcx
.associated_item_def_ids(trait_def_id
).is_empty() {
150 let span
= impl_header_span(tcx
, impl_def_id
);
151 struct_span_err
!(tcx
.sess
, span
, E0715
, "impls for marker traits cannot contain items").emit();
154 pub fn provide(providers
: &mut Providers
) {
155 use self::builtin
::coerce_unsized_info
;
156 use self::inherent_impls
::{crate_inherent_impls, inherent_impls}
;
157 use self::inherent_impls_overlap
::crate_inherent_impls_overlap_check
;
159 *providers
= Providers
{
161 crate_inherent_impls
,
163 crate_inherent_impls_overlap_check
,
169 fn coherent_trait(tcx
: TyCtxt
<'_
>, def_id
: DefId
) {
170 // Trigger building the specialization graph for the trait. This will detect and report any
172 tcx
.ensure().specialization_graph_of(def_id
);
174 let impls
= tcx
.hir().trait_impls(def_id
);
175 for &hir_id
in impls
{
176 let impl_def_id
= tcx
.hir().local_def_id(hir_id
);
177 let trait_ref
= tcx
.impl_trait_ref(impl_def_id
).unwrap();
179 check_impl(tcx
, impl_def_id
, trait_ref
);
180 check_object_overlap(tcx
, impl_def_id
, trait_ref
);
182 builtin
::check_trait(tcx
, def_id
);
185 pub fn check_coherence(tcx
: TyCtxt
<'_
>) {
186 for &trait_def_id
in tcx
.hir().krate().trait_impls
.keys() {
187 tcx
.ensure().coherent_trait(trait_def_id
);
190 tcx
.sess
.time("unsafety_checking", || unsafety
::check(tcx
));
191 tcx
.sess
.time("orphan_checking", || orphan
::check(tcx
));
193 // these queries are executed for side-effects (error reporting):
194 tcx
.ensure().crate_inherent_impls(LOCAL_CRATE
);
195 tcx
.ensure().crate_inherent_impls_overlap_check(LOCAL_CRATE
);
198 /// Checks whether an impl overlaps with the automatic `impl Trait for dyn Trait`.
199 fn check_object_overlap
<'tcx
>(
201 impl_def_id
: LocalDefId
,
202 trait_ref
: ty
::TraitRef
<'tcx
>,
204 let trait_def_id
= trait_ref
.def_id
;
206 if trait_ref
.references_error() {
207 debug
!("coherence: skipping impl {:?} with error {:?}", impl_def_id
, trait_ref
);
211 // check for overlap with the automatic `impl Trait for dyn Trait`
212 if let ty
::Dynamic(ref data
, ..) = trait_ref
.self_ty().kind
{
213 // This is something like impl Trait1 for Trait2. Illegal
214 // if Trait1 is a supertrait of Trait2 or Trait2 is not object safe.
216 let component_def_ids
= data
.iter().flat_map(|predicate
| {
217 match predicate
.skip_binder() {
218 ty
::ExistentialPredicate
::Trait(tr
) => Some(tr
.def_id
),
219 ty
::ExistentialPredicate
::AutoTrait(def_id
) => Some(def_id
),
220 // An associated type projection necessarily comes with
221 // an additional `Trait` requirement.
222 ty
::ExistentialPredicate
::Projection(..) => None
,
226 for component_def_id
in component_def_ids
{
227 if !tcx
.is_object_safe(component_def_id
) {
228 // Without the 'object_safe_for_dispatch' feature this is an error
229 // which will be reported by wfcheck. Ignore it here.
230 // This is tested by `coherence-impl-trait-for-trait-object-safe.rs`.
231 // With the feature enabled, the trait is not implemented automatically,
234 let mut supertrait_def_ids
= traits
::supertrait_def_ids(tcx
, component_def_id
);
235 if supertrait_def_ids
.any(|d
| d
== trait_def_id
) {
236 let span
= impl_header_span(tcx
, impl_def_id
);
241 "the object type `{}` automatically implements the trait `{}`",
243 tcx
.def_path_str(trait_def_id
)
248 "`{}` automatically implements trait `{}`",
250 tcx
.def_path_str(trait_def_id
)