]> git.lizzy.rs Git - rust.git/blob - src/librustc/traits/coherence.rs
2ca4628ab13f1c85378c3f68e3849d338854c6b7
[rust.git] / src / librustc / traits / coherence.rs
1 // Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 //! See `README.md` for high-level documentation
12
13 use hir::def_id::{DefId, LOCAL_CRATE};
14 use syntax_pos::DUMMY_SP;
15 use traits::{self, Normalized, SelectionContext, Obligation, ObligationCause, Reveal};
16 use traits::select::IntercrateAmbiguityCause;
17 use ty::{self, Ty, TyCtxt};
18 use ty::subst::Subst;
19
20 use infer::{InferCtxt, InferOk};
21
22 #[derive(Copy, Clone, Debug)]
23 enum InferIsLocal {
24     BrokenYes,
25     Yes,
26     No
27 }
28
29 #[derive(Debug, Copy, Clone)]
30 pub enum Conflict {
31     Upstream,
32     Downstream
33 }
34
35 pub struct OverlapResult<'tcx> {
36     pub impl_header: ty::ImplHeader<'tcx>,
37     pub intercrate_ambiguity_causes: Vec<IntercrateAmbiguityCause>,
38 }
39
40 /// If there are types that satisfy both impls, returns a suitably-freshened
41 /// `ImplHeader` with those types substituted
42 pub fn overlapping_impls<'cx, 'gcx, 'tcx>(infcx: &InferCtxt<'cx, 'gcx, 'tcx>,
43                                           impl1_def_id: DefId,
44                                           impl2_def_id: DefId)
45                                           -> Option<OverlapResult<'tcx>>
46 {
47     debug!("impl_can_satisfy(\
48            impl1_def_id={:?}, \
49            impl2_def_id={:?})",
50            impl1_def_id,
51            impl2_def_id);
52
53     let selcx = &mut SelectionContext::intercrate(infcx);
54     overlap(selcx, impl1_def_id, impl2_def_id)
55 }
56
57 fn with_fresh_ty_vars<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>,
58                                        param_env: ty::ParamEnv<'tcx>,
59                                        impl_def_id: DefId)
60                                        -> ty::ImplHeader<'tcx>
61 {
62     let tcx = selcx.tcx();
63     let impl_substs = selcx.infcx().fresh_substs_for_item(DUMMY_SP, impl_def_id);
64
65     let header = ty::ImplHeader {
66         impl_def_id,
67         self_ty: tcx.type_of(impl_def_id),
68         trait_ref: tcx.impl_trait_ref(impl_def_id),
69         predicates: tcx.predicates_of(impl_def_id).predicates
70     }.subst(tcx, impl_substs);
71
72     let Normalized { value: mut header, obligations } =
73         traits::normalize(selcx, param_env, ObligationCause::dummy(), &header);
74
75     header.predicates.extend(obligations.into_iter().map(|o| o.predicate));
76     header
77 }
78
79 /// Can both impl `a` and impl `b` be satisfied by a common type (including
80 /// `where` clauses)? If so, returns an `ImplHeader` that unifies the two impls.
81 fn overlap<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>,
82                             a_def_id: DefId,
83                             b_def_id: DefId)
84                             -> Option<OverlapResult<'tcx>>
85 {
86     debug!("overlap(a_def_id={:?}, b_def_id={:?})",
87            a_def_id,
88            b_def_id);
89
90     // For the purposes of this check, we don't bring any skolemized
91     // types into scope; instead, we replace the generic types with
92     // fresh type variables, and hence we do our evaluations in an
93     // empty environment.
94     let param_env = ty::ParamEnv::empty(Reveal::UserFacing);
95
96     let a_impl_header = with_fresh_ty_vars(selcx, param_env, a_def_id);
97     let b_impl_header = with_fresh_ty_vars(selcx, param_env, b_def_id);
98
99     debug!("overlap: a_impl_header={:?}", a_impl_header);
100     debug!("overlap: b_impl_header={:?}", b_impl_header);
101
102     // Do `a` and `b` unify? If not, no overlap.
103     let obligations = match selcx.infcx().at(&ObligationCause::dummy(), param_env)
104                                          .eq_impl_headers(&a_impl_header, &b_impl_header) {
105         Ok(InferOk { obligations, value: () }) => {
106             obligations
107         }
108         Err(_) => return None
109     };
110
111     debug!("overlap: unification check succeeded");
112
113     // Are any of the obligations unsatisfiable? If so, no overlap.
114     let infcx = selcx.infcx();
115     let opt_failing_obligation =
116         a_impl_header.predicates
117                      .iter()
118                      .chain(&b_impl_header.predicates)
119                      .map(|p| infcx.resolve_type_vars_if_possible(p))
120                      .map(|p| Obligation { cause: ObligationCause::dummy(),
121                                            param_env,
122                                            recursion_depth: 0,
123                                            predicate: p })
124                      .chain(obligations)
125                      .find(|o| !selcx.evaluate_obligation(o));
126
127     if let Some(failing_obligation) = opt_failing_obligation {
128         debug!("overlap: obligation unsatisfiable {:?}", failing_obligation);
129         return None
130     }
131
132     Some(OverlapResult {
133         impl_header: selcx.infcx().resolve_type_vars_if_possible(&a_impl_header),
134         intercrate_ambiguity_causes: selcx.intercrate_ambiguity_causes().to_vec(),
135     })
136 }
137
138 pub fn trait_ref_is_knowable<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
139                                              trait_ref: ty::TraitRef<'tcx>,
140                                              broken: bool)
141                                              -> Option<Conflict>
142 {
143     debug!("trait_ref_is_knowable(trait_ref={:?}, broken={:?})", trait_ref, broken);
144     let mode = if broken {
145         InferIsLocal::BrokenYes
146     } else {
147         InferIsLocal::Yes
148     };
149     if orphan_check_trait_ref(tcx, trait_ref, mode).is_ok() {
150         // A downstream or cousin crate is allowed to implement some
151         // substitution of this trait-ref.
152         debug!("trait_ref_is_knowable: downstream crate might implement");
153         return Some(Conflict::Downstream);
154     }
155
156     if trait_ref_is_local_or_fundamental(tcx, trait_ref) {
157         // This is a local or fundamental trait, so future-compatibility
158         // is no concern. We know that downstream/cousin crates are not
159         // allowed to implement a substitution of this trait ref, which
160         // means impls could only come from dependencies of this crate,
161         // which we already know about.
162         return None;
163     }
164     // This is a remote non-fundamental trait, so if another crate
165     // can be the "final owner" of a substitution of this trait-ref,
166     // they are allowed to implement it future-compatibly.
167     //
168     // However, if we are a final owner, then nobody else can be,
169     // and if we are an intermediate owner, then we don't care
170     // about future-compatibility, which means that we're OK if
171     // we are an owner.
172     if orphan_check_trait_ref(tcx, trait_ref, InferIsLocal::No).is_ok() {
173         debug!("trait_ref_is_knowable: orphan check passed");
174         return None;
175     } else {
176         debug!("trait_ref_is_knowable: nonlocal, nonfundamental, unowned");
177         return Some(Conflict::Upstream);
178     }
179 }
180
181 pub fn trait_ref_is_local_or_fundamental<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
182                                                          trait_ref: ty::TraitRef<'tcx>)
183                                                          -> bool {
184     trait_ref.def_id.krate == LOCAL_CRATE || tcx.has_attr(trait_ref.def_id, "fundamental")
185 }
186
187 pub enum OrphanCheckErr<'tcx> {
188     NoLocalInputType,
189     UncoveredTy(Ty<'tcx>),
190 }
191
192 /// Checks the coherence orphan rules. `impl_def_id` should be the
193 /// def-id of a trait impl. To pass, either the trait must be local, or else
194 /// two conditions must be satisfied:
195 ///
196 /// 1. All type parameters in `Self` must be "covered" by some local type constructor.
197 /// 2. Some local type must appear in `Self`.
198 pub fn orphan_check<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
199                                     impl_def_id: DefId)
200                                     -> Result<(), OrphanCheckErr<'tcx>>
201 {
202     debug!("orphan_check({:?})", impl_def_id);
203
204     // We only except this routine to be invoked on implementations
205     // of a trait, not inherent implementations.
206     let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
207     debug!("orphan_check: trait_ref={:?}", trait_ref);
208
209     // If the *trait* is local to the crate, ok.
210     if trait_ref.def_id.is_local() {
211         debug!("trait {:?} is local to current crate",
212                trait_ref.def_id);
213         return Ok(());
214     }
215
216     orphan_check_trait_ref(tcx, trait_ref, InferIsLocal::No)
217 }
218
219 fn orphan_check_trait_ref<'tcx>(tcx: TyCtxt,
220                                 trait_ref: ty::TraitRef<'tcx>,
221                                 infer_is_local: InferIsLocal)
222                                 -> Result<(), OrphanCheckErr<'tcx>>
223 {
224     debug!("orphan_check_trait_ref(trait_ref={:?}, infer_is_local={:?})",
225            trait_ref, infer_is_local);
226
227     // First, create an ordered iterator over all the type parameters to the trait, with the self
228     // type appearing first.
229     // Find the first input type that either references a type parameter OR
230     // some local type.
231     for input_ty in trait_ref.input_types() {
232         if ty_is_local(tcx, input_ty, infer_is_local) {
233             debug!("orphan_check_trait_ref: ty_is_local `{:?}`", input_ty);
234
235             // First local input type. Check that there are no
236             // uncovered type parameters.
237             let uncovered_tys = uncovered_tys(tcx, input_ty, infer_is_local);
238             for uncovered_ty in uncovered_tys {
239                 if let Some(param) = uncovered_ty.walk()
240                     .find(|t| is_possibly_remote_type(t, infer_is_local))
241                 {
242                     debug!("orphan_check_trait_ref: uncovered type `{:?}`", param);
243                     return Err(OrphanCheckErr::UncoveredTy(param));
244                 }
245             }
246
247             // OK, found local type, all prior types upheld invariant.
248             return Ok(());
249         }
250
251         // Otherwise, enforce invariant that there are no type
252         // parameters reachable.
253         if let Some(param) = input_ty.walk()
254             .find(|t| is_possibly_remote_type(t, infer_is_local))
255         {
256             debug!("orphan_check_trait_ref: uncovered type `{:?}`", param);
257             return Err(OrphanCheckErr::UncoveredTy(param));
258         }
259     }
260
261     // If we exit above loop, never found a local type.
262     debug!("orphan_check_trait_ref: no local type");
263     return Err(OrphanCheckErr::NoLocalInputType);
264 }
265
266 fn uncovered_tys<'tcx>(tcx: TyCtxt, ty: Ty<'tcx>, infer_is_local: InferIsLocal)
267                        -> Vec<Ty<'tcx>> {
268     if ty_is_local_constructor(ty, infer_is_local) {
269         vec![]
270     } else if fundamental_ty(tcx, ty) {
271         ty.walk_shallow()
272           .flat_map(|t| uncovered_tys(tcx, t, infer_is_local))
273           .collect()
274     } else {
275         vec![ty]
276     }
277 }
278
279 fn is_possibly_remote_type(ty: Ty, _infer_is_local: InferIsLocal) -> bool {
280     match ty.sty {
281         ty::TyProjection(..) | ty::TyParam(..) => true,
282         _ => false,
283     }
284 }
285
286 fn ty_is_local(tcx: TyCtxt, ty: Ty, infer_is_local: InferIsLocal) -> bool {
287     ty_is_local_constructor(ty, infer_is_local) ||
288         fundamental_ty(tcx, ty) && ty.walk_shallow().any(|t| ty_is_local(tcx, t, infer_is_local))
289 }
290
291 fn fundamental_ty(tcx: TyCtxt, ty: Ty) -> bool {
292     match ty.sty {
293         ty::TyRef(..) => true,
294         ty::TyAdt(def, _) => def.is_fundamental(),
295         ty::TyDynamic(ref data, ..) => {
296             data.principal().map_or(false, |p| tcx.has_attr(p.def_id(), "fundamental"))
297         }
298         _ => false
299     }
300 }
301
302 fn def_id_is_local(def_id: DefId, infer_is_local: InferIsLocal) -> bool {
303     match infer_is_local {
304         InferIsLocal::Yes => false,
305         InferIsLocal::No |
306         InferIsLocal::BrokenYes => def_id.is_local()
307     }
308 }
309
310 fn ty_is_local_constructor(ty: Ty, infer_is_local: InferIsLocal) -> bool {
311     debug!("ty_is_local_constructor({:?})", ty);
312
313     match ty.sty {
314         ty::TyBool |
315         ty::TyChar |
316         ty::TyInt(..) |
317         ty::TyUint(..) |
318         ty::TyFloat(..) |
319         ty::TyStr |
320         ty::TyFnDef(..) |
321         ty::TyFnPtr(_) |
322         ty::TyArray(..) |
323         ty::TySlice(..) |
324         ty::TyRawPtr(..) |
325         ty::TyRef(..) |
326         ty::TyNever |
327         ty::TyTuple(..) |
328         ty::TyParam(..) |
329         ty::TyProjection(..) => {
330             false
331         }
332
333         ty::TyInfer(..) => match infer_is_local {
334             InferIsLocal::No => false,
335             InferIsLocal::Yes |
336             InferIsLocal::BrokenYes => true
337         },
338
339         ty::TyAdt(def, _) => def_id_is_local(def.did, infer_is_local),
340         ty::TyForeign(did) => def_id_is_local(did, infer_is_local),
341
342         ty::TyDynamic(ref tt, ..) => {
343             tt.principal().map_or(false, |p| {
344                 def_id_is_local(p.def_id(), infer_is_local)
345             })
346         }
347
348         ty::TyError => {
349             true
350         }
351
352         ty::TyClosure(..) | ty::TyGenerator(..) | ty::TyAnon(..) => {
353             bug!("ty_is_local invoked on unexpected type: {:?}", ty)
354         }
355     }
356 }