1 // Copyright 2012-2013 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.
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.
13 // The job of the coherence phase of typechecking is to ensure that each trait
14 // has at most one implementation for each type. Then we build a mapping from
15 // each trait in the system to its implementations.
18 use metadata::csearch::{each_impl, get_impl_trait, each_implementation_for_trait};
19 use metadata::csearch;
21 use middle::ty::{ImplContainer, lookup_item_type, subst};
22 use middle::ty::{substs, t, ty_bool, ty_char, ty_bot, ty_box, ty_enum, ty_err};
23 use middle::ty::{ty_str, ty_vec, ty_float, ty_infer, ty_int, ty_nil};
24 use middle::ty::{ty_param, ty_param_bounds_and_ty, ty_ptr};
25 use middle::ty::{ty_rptr, ty_self, ty_struct, ty_trait, ty_tup};
26 use middle::ty::{ty_uint, ty_uniq, ty_bare_fn, ty_closure};
27 use middle::ty::type_is_ty_var;
28 use middle::subst::Subst;
30 use middle::typeck::CrateCtxt;
31 use middle::typeck::infer::combine::Combine;
32 use middle::typeck::infer::InferCtxt;
33 use middle::typeck::infer::{new_infer_ctxt, resolve_ivar, resolve_type};
34 use middle::typeck::infer;
35 use util::ppaux::Repr;
36 use syntax::ast::{Crate, DefId, DefStruct, DefTy};
37 use syntax::ast::{Item, ItemEnum, ItemImpl, ItemMod, ItemStruct};
38 use syntax::ast::{LOCAL_CRATE, TraitRef, TyPath};
40 use syntax::ast_map::NodeItem;
42 use syntax::ast_util::{def_id_of_def, local_def};
43 use syntax::codemap::Span;
44 use syntax::owned_slice::OwnedSlice;
45 use syntax::parse::token;
48 use collections::HashSet;
49 use std::cell::RefCell;
52 struct UniversalQuantificationResult {
54 type_variables: Vec<ty::t> ,
55 type_param_defs: Rc<Vec<ty::TypeParameterDef> >
58 fn get_base_type(inference_context: &InferCtxt,
63 match resolve_type(inference_context,
66 Ok(resulting_type) if !type_is_ty_var(resulting_type) => {
67 resolved_type = resulting_type;
70 inference_context.tcx.sess.span_fatal(span,
71 "the type of this value must be known in order \
72 to determine the base type");
76 match get(resolved_type).sty {
77 ty_enum(..) | ty_trait(..) | ty_struct(..) => {
78 debug!("(getting base type) found base type");
82 ty_nil | ty_bot | ty_bool | ty_char | ty_int(..) | ty_uint(..) | ty_float(..) |
83 ty_str(..) | ty_vec(..) | ty_bare_fn(..) | ty_closure(..) | ty_tup(..) |
84 ty_infer(..) | ty_param(..) | ty_self(..) | ty_err |
85 ty_box(_) | ty_uniq(_) | ty_ptr(_) | ty_rptr(_, _) => {
86 debug!("(getting base type) no base type; found {:?}",
87 get(original_type).sty);
93 fn type_is_defined_in_local_crate(original_type: t) -> bool {
96 * For coherence, when we have `impl Trait for Type`, we need to
97 * guarantee that `Type` is "local" to the
98 * crate. For our purposes, this means that it must contain
99 * some nominal type defined in this crate.
102 let mut found_nominal = false;
103 ty::walk_ty(original_type, |t| {
106 ty_trait(box ty::TyTrait { def_id, .. }) |
107 ty_struct(def_id, _) => {
108 if def_id.krate == ast::LOCAL_CRATE {
109 found_nominal = true;
116 return found_nominal;
119 // Returns the def ID of the base type, if there is one.
120 fn get_base_type_def_id(inference_context: &InferCtxt,
124 match get_base_type(inference_context, span, original_type) {
129 match get(base_type).sty {
131 ty_struct(def_id, _) |
132 ty_trait(box ty::TyTrait { def_id, .. }) => {
136 fail!("get_base_type() returned a type that wasn't an \
137 enum, struct, or trait");
144 struct CoherenceChecker<'a> {
145 crate_context: &'a CrateCtxt<'a>,
146 inference_context: InferCtxt<'a>,
149 struct CoherenceCheckVisitor<'a> {
150 cc: &'a CoherenceChecker<'a>
153 impl<'a> visit::Visitor<()> for CoherenceCheckVisitor<'a> {
154 fn visit_item(&mut self, item: &Item, _: ()) {
156 //debug!("(checking coherence) item '{}'", token::get_ident(item.ident));
159 ItemImpl(_, ref opt_trait, _, _) => {
160 match opt_trait.clone() {
162 self.cc.check_implementation(item, [opt_trait]);
164 None => self.cc.check_implementation(item, [])
172 visit::walk_item(self, item, ());
176 struct PrivilegedScopeVisitor<'a> { cc: &'a CoherenceChecker<'a> }
178 impl<'a> visit::Visitor<()> for PrivilegedScopeVisitor<'a> {
179 fn visit_item(&mut self, item: &Item, _: ()) {
182 ItemMod(ref module_) => {
183 // Then visit the module items.
184 visit::walk_mod(self, module_, ());
186 ItemImpl(_, None, ast_ty, _) => {
187 if !self.cc.ast_type_is_defined_in_local_crate(ast_ty) {
189 let session = &self.cc.crate_context.tcx.sess;
190 session.span_err(item.span,
191 "cannot associate methods with a type outside the \
192 crate the type is defined in; define and implement \
193 a trait or new type instead");
196 ItemImpl(_, Some(ref trait_ref), _, _) => {
197 // `for_ty` is `Type` in `impl Trait for Type`
199 ty::node_id_to_type(self.cc.crate_context.tcx,
201 if !type_is_defined_in_local_crate(for_ty) {
202 // This implementation is not in scope of its base
203 // type. This still might be OK if the trait is
204 // defined in the same crate.
207 self.cc.trait_ref_to_trait_def_id(trait_ref);
209 if trait_def_id.krate != LOCAL_CRATE {
210 let session = &self.cc.crate_context.tcx.sess;
211 session.span_err(item.span,
212 "cannot provide an extension implementation \
213 where both trait and type are not defined in this crate");
217 visit::walk_item(self, item, ());
220 visit::walk_item(self, item, ());
226 impl<'a> CoherenceChecker<'a> {
227 fn check(&self, krate: &Crate) {
228 // Check implementations and traits. This populates the tables
229 // containing the inherent methods and extension methods. It also
230 // builds up the trait inheritance table.
231 let mut visitor = CoherenceCheckVisitor { cc: self };
232 visit::walk_crate(&mut visitor, krate, ());
234 // Check that there are no overlapping trait instances
235 self.check_implementation_coherence();
237 // Check whether traits with base types are in privileged scopes.
238 self.check_privileged_scopes(krate);
240 // Bring in external crates. It's fine for this to happen after the
241 // coherence checks, because we ensure by construction that no errors
242 // can happen at link time.
243 self.add_external_crates();
245 // Populate the table of destructors. It might seem a bit strange to
246 // do this here, but it's actually the most convenient place, since
247 // the coherence tables contain the trait -> type mappings.
248 self.populate_destructor_table();
251 fn check_implementation(&self, item: &Item,
252 associated_traits: &[TraitRef]) {
253 let tcx = self.crate_context.tcx;
254 let impl_did = local_def(item.id);
255 let self_type = ty::lookup_item_type(tcx, impl_did);
257 // If there are no traits, then this implementation must have a
260 if associated_traits.len() == 0 {
261 debug!("(checking implementation) no associated traits for item '{}'",
262 token::get_ident(item.ident));
264 match get_base_type_def_id(&self.inference_context,
268 let session = &self.crate_context.tcx.sess;
269 session.span_err(item.span,
270 "no base type found for inherent implementation; \
271 implement a trait or new type instead");
279 let impl_methods = self.create_impl_from_item(item);
281 for associated_trait in associated_traits.iter() {
282 let trait_ref = ty::node_id_to_trait_ref(
283 self.crate_context.tcx, associated_trait.ref_id);
284 debug!("(checking implementation) adding impl for trait '{}', item '{}'",
285 trait_ref.repr(self.crate_context.tcx),
286 token::get_ident(item.ident));
288 self.add_trait_impl(trait_ref.def_id, impl_did);
291 // Add the implementation to the mapping from implementation to base
292 // type def ID, if there is a base type for this implementation and
293 // the implementation does not have any associated traits.
294 match get_base_type_def_id(&self.inference_context,
300 Some(base_type_def_id) => {
301 // FIXME: Gather up default methods?
302 if associated_traits.len() == 0 {
303 self.add_inherent_impl(base_type_def_id, impl_did);
308 tcx.impl_methods.borrow_mut().insert(impl_did, impl_methods);
311 // Creates default method IDs and performs type substitutions for an impl
312 // and trait pair. Then, for each provided method in the trait, inserts a
313 // `ProvidedMethodInfo` instance into the `provided_method_sources` map.
314 fn instantiate_default_methods(&self, impl_id: DefId,
315 trait_ref: &ty::TraitRef,
316 all_methods: &mut Vec<DefId>) {
317 let tcx = self.crate_context.tcx;
318 debug!("instantiate_default_methods(impl_id={:?}, trait_ref={})",
319 impl_id, trait_ref.repr(tcx));
321 let impl_poly_type = ty::lookup_item_type(tcx, impl_id);
323 let prov = ty::provided_trait_methods(tcx, trait_ref.def_id);
324 for trait_method in prov.iter() {
326 let new_id = tcx.sess.next_node_id();
327 let new_did = local_def(new_id);
329 debug!("new_did={:?} trait_method={}", new_did, trait_method.repr(tcx));
331 // Create substitutions for the various trait parameters.
333 Rc::new(subst_receiver_types_in_method_ty(
339 Some(trait_method.def_id)));
341 debug!("new_method_ty={}", new_method_ty.repr(tcx));
342 all_methods.push(new_did);
344 // construct the polytype for the method based on the method_ty
345 let new_generics = ty::Generics {
347 Rc::new(Vec::from_slice(impl_poly_type.generics.type_param_defs()).append(
348 new_method_ty.generics.type_param_defs())),
350 Rc::new(Vec::from_slice(impl_poly_type.generics.region_param_defs()).append(
351 new_method_ty.generics.region_param_defs()))
353 let new_polytype = ty::ty_param_bounds_and_ty {
354 generics: new_generics,
355 ty: ty::mk_bare_fn(tcx, new_method_ty.fty.clone())
357 debug!("new_polytype={}", new_polytype.repr(tcx));
359 tcx.tcache.borrow_mut().insert(new_did, new_polytype);
360 tcx.methods.borrow_mut().insert(new_did, new_method_ty);
362 // Pair the new synthesized ID up with the
364 self.crate_context.tcx.provided_method_sources.borrow_mut()
365 .insert(new_did, trait_method.def_id);
369 fn add_inherent_impl(&self, base_def_id: DefId, impl_def_id: DefId) {
370 let tcx = self.crate_context.tcx;
371 match tcx.inherent_impls.borrow().find(&base_def_id) {
372 Some(implementation_list) => {
373 implementation_list.borrow_mut().push(impl_def_id);
379 tcx.inherent_impls.borrow_mut().insert(base_def_id,
380 Rc::new(RefCell::new(vec!(impl_def_id))));
383 fn add_trait_impl(&self, base_def_id: DefId, impl_def_id: DefId) {
384 ty::record_trait_implementation(self.crate_context.tcx,
389 fn check_implementation_coherence(&self) {
390 for &trait_id in self.crate_context.tcx.trait_impls.borrow().keys() {
391 self.check_implementation_coherence_of(trait_id);
395 fn check_implementation_coherence_of(&self, trait_def_id: DefId) {
396 // Unify pairs of polytypes.
397 self.iter_impls_of_trait_local(trait_def_id, |impl_a| {
399 self.get_self_type_for_implementation(impl_a);
401 // "We have an impl of trait <trait_def_id> for type <polytype_a>,
402 // and that impl is <impl_a>"
403 self.iter_impls_of_trait(trait_def_id, |impl_b| {
405 // An impl is coherent with itself
406 if impl_a != impl_b {
407 let polytype_b = self.get_self_type_for_implementation(
410 if self.polytypes_unify(polytype_a.clone(), polytype_b) {
411 let session = &self.crate_context.tcx.sess;
413 self.span_of_impl(impl_a),
414 format!("conflicting implementations for trait `{}`",
415 ty::item_path_str(self.crate_context.tcx,
417 if impl_b.krate == LOCAL_CRATE {
418 session.span_note(self.span_of_impl(impl_b),
419 "note conflicting implementation here");
421 let crate_store = &self.crate_context.tcx.sess.cstore;
422 let cdata = crate_store.get_crate_data(impl_b.krate);
424 "conflicting implementation in crate `" + cdata.name + "`");
432 fn iter_impls_of_trait(&self, trait_def_id: DefId, f: |DefId|) {
433 self.iter_impls_of_trait_local(trait_def_id, |x| f(x));
435 if trait_def_id.krate == LOCAL_CRATE {
439 let crate_store = &self.crate_context.tcx.sess.cstore;
440 csearch::each_implementation_for_trait(crate_store, trait_def_id, |impl_def_id| {
441 // Is this actually necessary?
442 let _ = lookup_item_type(self.crate_context.tcx, impl_def_id);
447 fn iter_impls_of_trait_local(&self, trait_def_id: DefId, f: |DefId|) {
448 match self.crate_context.tcx.trait_impls.borrow().find(&trait_def_id) {
450 for &impl_did in impls.borrow().iter() {
454 None => { /* no impls? */ }
458 fn polytypes_unify(&self,
459 polytype_a: ty_param_bounds_and_ty,
460 polytype_b: ty_param_bounds_and_ty)
462 let universally_quantified_a =
463 self.universally_quantify_polytype(polytype_a);
464 let universally_quantified_b =
465 self.universally_quantify_polytype(polytype_b);
467 return self.can_unify_universally_quantified(
468 &universally_quantified_a, &universally_quantified_b) ||
469 self.can_unify_universally_quantified(
470 &universally_quantified_b, &universally_quantified_a);
473 // Converts a polytype to a monotype by replacing all parameters with
474 // type variables. Returns the monotype and the type variables created.
475 fn universally_quantify_polytype(&self, polytype: ty_param_bounds_and_ty)
476 -> UniversalQuantificationResult {
477 let region_parameters =
478 polytype.generics.region_param_defs().iter()
479 .map(|d| self.inference_context.next_region_var(
480 infer::BoundRegionInCoherence(d.name)))
483 let bounds_count = polytype.generics.type_param_defs().len();
484 let type_parameters = self.inference_context.next_ty_vars(bounds_count);
486 let substitutions = substs {
487 regions: ty::NonerasedRegions(region_parameters),
491 let monotype = subst(self.crate_context.tcx,
495 UniversalQuantificationResult {
497 type_variables: substitutions.tps,
498 type_param_defs: polytype.generics.type_param_defs.clone()
502 fn can_unify_universally_quantified<'a>(&self,
503 a: &'a UniversalQuantificationResult,
504 b: &'a UniversalQuantificationResult)
506 infer::can_mk_subty(&self.inference_context,
511 fn get_self_type_for_implementation(&self, impl_did: DefId)
512 -> ty_param_bounds_and_ty {
513 self.crate_context.tcx.tcache.borrow().get_copy(&impl_did)
516 // Privileged scope checking
517 fn check_privileged_scopes(&self, krate: &Crate) {
518 let mut visitor = PrivilegedScopeVisitor{ cc: self };
519 visit::walk_crate(&mut visitor, krate, ());
522 fn trait_ref_to_trait_def_id(&self, trait_ref: &TraitRef) -> DefId {
523 let def_map = &self.crate_context.tcx.def_map;
524 let trait_def = def_map.borrow().get_copy(&trait_ref.ref_id);
525 let trait_id = def_id_of_def(trait_def);
529 /// For coherence, when we have `impl Type`, we need to guarantee that
530 /// `Type` is "local" to the crate. For our purposes, this means that it
531 /// must precisely name some nominal type defined in this crate.
532 fn ast_type_is_defined_in_local_crate(&self, original_type: &ast::Ty) -> bool {
533 match original_type.node {
534 TyPath(_, _, path_id) => {
535 match self.crate_context.tcx.def_map.borrow().get_copy(&path_id) {
536 DefTy(def_id) | DefStruct(def_id) => {
537 if def_id.krate != LOCAL_CRATE {
541 // Make sure that this type precisely names a nominal
543 match self.crate_context.tcx.map.find(def_id.node) {
545 self.crate_context.tcx.sess.span_bug(
547 "resolve didn't resolve this type?!");
549 Some(NodeItem(item)) => {
551 ItemStruct(..) | ItemEnum(..) => true,
565 // Converts an implementation in the AST to a vector of methods.
566 fn create_impl_from_item(&self, item: &Item) -> Vec<DefId> {
568 ItemImpl(_, ref trait_refs, _, ref ast_methods) => {
569 let mut methods: Vec<DefId> = ast_methods.iter().map(|ast_method| {
570 local_def(ast_method.id)
573 for trait_ref in trait_refs.iter() {
574 let ty_trait_ref = ty::node_id_to_trait_ref(
575 self.crate_context.tcx,
578 self.instantiate_default_methods(local_def(item.id),
586 self.crate_context.tcx.sess.span_bug(item.span,
587 "can't convert a non-impl to an impl");
592 fn span_of_impl(&self, impl_did: DefId) -> Span {
593 assert_eq!(impl_did.krate, LOCAL_CRATE);
594 self.crate_context.tcx.map.span(impl_did.node)
597 // External crate handling
599 fn add_external_impl(&self,
600 impls_seen: &mut HashSet<DefId>,
601 impl_def_id: DefId) {
602 let tcx = self.crate_context.tcx;
603 let methods = csearch::get_impl_methods(&tcx.sess.cstore, impl_def_id);
605 // Make sure we don't visit the same implementation multiple times.
606 if !impls_seen.insert(impl_def_id) {
612 let _ = lookup_item_type(tcx, impl_def_id);
613 let associated_traits = get_impl_trait(tcx, impl_def_id);
615 // Do a sanity check.
616 assert!(associated_traits.is_some());
618 // Record all the trait methods.
619 for trait_ref in associated_traits.iter() {
620 self.add_trait_impl(trait_ref.def_id, impl_def_id);
623 // For any methods that use a default implementation, add them to
624 // the map. This is a bit unfortunate.
625 for &method_def_id in methods.iter() {
626 for &source in ty::method(tcx, method_def_id).provided_source.iter() {
627 tcx.provided_method_sources.borrow_mut().insert(method_def_id, source);
631 tcx.impl_methods.borrow_mut().insert(impl_def_id, methods);
634 // Adds implementations and traits from external crates to the coherence
636 fn add_external_crates(&self) {
637 let mut impls_seen = HashSet::new();
639 let crate_store = &self.crate_context.tcx.sess.cstore;
640 crate_store.iter_crate_data(|crate_number, _crate_metadata| {
641 each_impl(crate_store, crate_number, |def_id| {
642 assert_eq!(crate_number, def_id.krate);
643 self.add_external_impl(&mut impls_seen, def_id)
652 fn populate_destructor_table(&self) {
653 let tcx = self.crate_context.tcx;
654 let drop_trait = match tcx.lang_items.drop_trait() {
655 Some(id) => id, None => { return }
658 let impl_methods = tcx.impl_methods.borrow();
659 let trait_impls = match tcx.trait_impls.borrow().find_copy(&drop_trait) {
660 None => return, // No types with (new-style) dtors present.
661 Some(found_impls) => found_impls
664 for &impl_did in trait_impls.borrow().iter() {
665 let methods = impl_methods.get(&impl_did);
666 if methods.len() < 1 {
667 // We'll error out later. For now, just don't ICE.
670 let method_def_id = *methods.get(0);
672 let self_type = self.get_self_type_for_implementation(impl_did);
673 match ty::get(self_type.ty).sty {
674 ty::ty_enum(type_def_id, _) |
675 ty::ty_struct(type_def_id, _) => {
676 tcx.destructor_for_type.borrow_mut().insert(type_def_id,
678 tcx.destructors.borrow_mut().insert(method_def_id);
681 // Destructors only work on nominal types.
682 if impl_did.krate == ast::LOCAL_CRATE {
684 match tcx.map.find(impl_did.node) {
685 Some(ast_map::NodeItem(item)) => {
686 tcx.sess.span_err((*item).span,
687 "the Drop trait may \
688 only be implemented \
692 tcx.sess.bug("didn't find impl in ast \
698 tcx.sess.bug("found external impl of Drop trait on \
699 something other than a struct");
707 pub fn make_substs_for_receiver_types(tcx: &ty::ctxt,
709 trait_ref: &ty::TraitRef,
713 * Substitutes the values for the receiver's type parameters
714 * that are found in method, leaving the method's type parameters
715 * intact. This is in fact a mildly complex operation,
716 * largely because of the hokey way that we concatenate the
717 * receiver and method generics.
720 let impl_polytype = ty::lookup_item_type(tcx, impl_id);
721 let num_impl_tps = impl_polytype.generics.type_param_defs().len();
722 let num_impl_regions = impl_polytype.generics.region_param_defs().len();
723 let meth_tps: Vec<ty::t> =
724 method.generics.type_param_defs().iter().enumerate()
725 .map(|(i, t)| ty::mk_param(tcx, i + num_impl_tps, t.def_id))
727 let meth_regions: Vec<ty::Region> =
728 method.generics.region_param_defs().iter().enumerate()
729 .map(|(i, l)| ty::ReEarlyBound(l.def_id.node, i + num_impl_regions, l.name))
731 let mut combined_tps = trait_ref.substs.tps.clone();
732 combined_tps.push_all_move(meth_tps);
733 let combined_regions = match &trait_ref.substs.regions {
734 &ty::ErasedRegions =>
735 fail!("make_substs_for_receiver_types: unexpected ErasedRegions"),
737 &ty::NonerasedRegions(ref rs) => {
738 let mut rs = rs.clone().into_vec();
739 rs.push_all_move(meth_regions);
740 ty::NonerasedRegions(OwnedSlice::from_vec(rs))
745 regions: combined_regions,
746 self_ty: trait_ref.substs.self_ty,
751 fn subst_receiver_types_in_method_ty(tcx: &ty::ctxt,
753 trait_ref: &ty::TraitRef,
754 new_def_id: ast::DefId,
756 provided_source: Option<ast::DefId>)
759 let combined_substs = make_substs_for_receiver_types(
760 tcx, impl_id, trait_ref, method);
765 // method types *can* appear in the generic bounds
766 method.generics.subst(tcx, &combined_substs),
768 // method types *can* appear in the fty
769 method.fty.subst(tcx, &combined_substs),
771 method.explicit_self,
774 ImplContainer(impl_id),
779 pub fn check_coherence(crate_context: &CrateCtxt, krate: &Crate) {
781 crate_context: crate_context,
782 inference_context: new_infer_ctxt(crate_context.tcx),