]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_typeck/src/coherence/mod.rs
Auto merge of #102189 - davidtwco:translation-derive-enums, r=compiler-errors
[rust.git] / compiler / rustc_typeck / src / coherence / mod.rs
1 // Coherence phase
2 //
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.
7
8 use rustc_errors::struct_span_err;
9 use rustc_hir::def_id::{DefId, LocalDefId};
10 use rustc_middle::ty::query::Providers;
11 use rustc_middle::ty::{self, TyCtxt, TypeVisitable};
12 use rustc_trait_selection::traits;
13
14 mod builtin;
15 mod inherent_impls;
16 mod inherent_impls_overlap;
17 mod orphan;
18 mod unsafety;
19
20 fn check_impl(tcx: TyCtxt<'_>, impl_def_id: LocalDefId, trait_ref: ty::TraitRef<'_>) {
21     debug!(
22         "(checking implementation) adding impl for trait '{:?}', item '{}'",
23         trait_ref,
24         tcx.def_path_str(impl_def_id.to_def_id())
25     );
26
27     // Skip impls where one of the self type is an error type.
28     // This occurs with e.g., resolve failures (#30589).
29     if trait_ref.references_error() {
30         return;
31     }
32
33     enforce_trait_manually_implementable(tcx, impl_def_id, trait_ref.def_id);
34     enforce_empty_impls_for_marker_traits(tcx, impl_def_id, trait_ref.def_id);
35 }
36
37 fn enforce_trait_manually_implementable(
38     tcx: TyCtxt<'_>,
39     impl_def_id: LocalDefId,
40     trait_def_id: DefId,
41 ) {
42     let did = Some(trait_def_id);
43     let li = tcx.lang_items();
44     let impl_header_span = tcx.def_span(impl_def_id);
45
46     // Disallow *all* explicit impls of `Pointee`, `DiscriminantKind`, `Sized` and `Unsize` for now.
47     if did == li.pointee_trait() {
48         struct_span_err!(
49             tcx.sess,
50             impl_header_span,
51             E0322,
52             "explicit impls for the `Pointee` trait are not permitted"
53         )
54         .span_label(impl_header_span, "impl of `Pointee` not allowed")
55         .emit();
56         return;
57     }
58
59     if did == li.discriminant_kind_trait() {
60         struct_span_err!(
61             tcx.sess,
62             impl_header_span,
63             E0322,
64             "explicit impls for the `DiscriminantKind` trait are not permitted"
65         )
66         .span_label(impl_header_span, "impl of `DiscriminantKind` not allowed")
67         .emit();
68         return;
69     }
70
71     if did == li.sized_trait() {
72         struct_span_err!(
73             tcx.sess,
74             impl_header_span,
75             E0322,
76             "explicit impls for the `Sized` trait are not permitted"
77         )
78         .span_label(impl_header_span, "impl of `Sized` not allowed")
79         .emit();
80         return;
81     }
82
83     if did == li.unsize_trait() {
84         struct_span_err!(
85             tcx.sess,
86             impl_header_span,
87             E0328,
88             "explicit impls for the `Unsize` trait are not permitted"
89         )
90         .span_label(impl_header_span, "impl of `Unsize` not allowed")
91         .emit();
92         return;
93     }
94
95     if tcx.features().unboxed_closures {
96         // the feature gate allows all Fn traits
97         return;
98     }
99
100     if let ty::trait_def::TraitSpecializationKind::AlwaysApplicable =
101         tcx.trait_def(trait_def_id).specialization_kind
102     {
103         if !tcx.features().specialization && !tcx.features().min_specialization {
104             tcx.sess
105                 .struct_span_err(
106                     impl_header_span,
107                     "implementing `rustc_specialization_trait` traits is unstable",
108                 )
109                 .help("add `#![feature(min_specialization)]` to the crate attributes to enable")
110                 .emit();
111             return;
112         }
113     }
114 }
115
116 /// We allow impls of marker traits to overlap, so they can't override impls
117 /// as that could make it ambiguous which associated item to use.
118 fn enforce_empty_impls_for_marker_traits(
119     tcx: TyCtxt<'_>,
120     impl_def_id: LocalDefId,
121     trait_def_id: DefId,
122 ) {
123     if !tcx.trait_def(trait_def_id).is_marker {
124         return;
125     }
126
127     if tcx.associated_item_def_ids(trait_def_id).is_empty() {
128         return;
129     }
130
131     struct_span_err!(
132         tcx.sess,
133         tcx.def_span(impl_def_id),
134         E0715,
135         "impls for marker traits cannot contain items"
136     )
137     .emit();
138 }
139
140 pub fn provide(providers: &mut Providers) {
141     use self::builtin::coerce_unsized_info;
142     use self::inherent_impls::{crate_incoherent_impls, crate_inherent_impls, inherent_impls};
143     use self::inherent_impls_overlap::crate_inherent_impls_overlap_check;
144     use self::orphan::orphan_check_impl;
145
146     *providers = Providers {
147         coherent_trait,
148         crate_inherent_impls,
149         crate_incoherent_impls,
150         inherent_impls,
151         crate_inherent_impls_overlap_check,
152         coerce_unsized_info,
153         orphan_check_impl,
154         ..*providers
155     };
156 }
157
158 fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) {
159     // Trigger building the specialization graph for the trait. This will detect and report any
160     // overlap errors.
161     tcx.ensure().specialization_graph_of(def_id);
162
163     let impls = tcx.hir().trait_impls(def_id);
164     for &impl_def_id in impls {
165         let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
166
167         check_impl(tcx, impl_def_id, trait_ref);
168         check_object_overlap(tcx, impl_def_id, trait_ref);
169
170         tcx.sess.time("unsafety_checking", || unsafety::check_item(tcx, impl_def_id));
171         tcx.sess.time("orphan_checking", || tcx.ensure().orphan_check_impl(impl_def_id));
172     }
173
174     builtin::check_trait(tcx, def_id);
175 }
176
177 /// Checks whether an impl overlaps with the automatic `impl Trait for dyn Trait`.
178 fn check_object_overlap<'tcx>(
179     tcx: TyCtxt<'tcx>,
180     impl_def_id: LocalDefId,
181     trait_ref: ty::TraitRef<'tcx>,
182 ) {
183     let trait_def_id = trait_ref.def_id;
184
185     if trait_ref.references_error() {
186         debug!("coherence: skipping impl {:?} with error {:?}", impl_def_id, trait_ref);
187         return;
188     }
189
190     // check for overlap with the automatic `impl Trait for dyn Trait`
191     if let ty::Dynamic(data, ..) = trait_ref.self_ty().kind() {
192         // This is something like impl Trait1 for Trait2. Illegal
193         // if Trait1 is a supertrait of Trait2 or Trait2 is not object safe.
194
195         let component_def_ids = data.iter().flat_map(|predicate| {
196             match predicate.skip_binder() {
197                 ty::ExistentialPredicate::Trait(tr) => Some(tr.def_id),
198                 ty::ExistentialPredicate::AutoTrait(def_id) => Some(def_id),
199                 // An associated type projection necessarily comes with
200                 // an additional `Trait` requirement.
201                 ty::ExistentialPredicate::Projection(..) => None,
202             }
203         });
204
205         for component_def_id in component_def_ids {
206             if !tcx.is_object_safe(component_def_id) {
207                 // Without the 'object_safe_for_dispatch' feature this is an error
208                 // which will be reported by wfcheck.  Ignore it here.
209                 // This is tested by `coherence-impl-trait-for-trait-object-safe.rs`.
210                 // With the feature enabled, the trait is not implemented automatically,
211                 // so this is valid.
212             } else {
213                 let mut supertrait_def_ids = traits::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                     struct_span_err!(
217                         tcx.sess,
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                     .span_label(
225                         span,
226                         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 }