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.
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
14 // each trait has at most one implementation for each type. This is
15 // done by the orphan and overlap modules. Then we build up various
16 // mappings. That mapping code resides here.
18 use hir::def_id::DefId;
19 use rustc::ty::{self, TyCtxt, TypeFoldable};
20 use rustc::ty::{Ty, TyBool, TyChar, TyError};
21 use rustc::ty::{TyParam, TyRawPtr};
22 use rustc::ty::{TyRef, TyAdt, TyDynamic, TyNever, TyTuple};
23 use rustc::ty::{TyStr, TyArray, TySlice, TyFloat, TyInfer, TyInt};
24 use rustc::ty::{TyUint, TyClosure, TyBox, TyFnDef, TyFnPtr};
25 use rustc::ty::{TyProjection, TyAnon};
28 use rustc::dep_graph::DepNode;
29 use rustc::hir::itemlikevisit::ItemLikeVisitor;
30 use rustc::hir::{Item, ItemImpl};
38 struct CoherenceChecker<'a, 'tcx: 'a> {
39 tcx: TyCtxt<'a, 'tcx, 'tcx>,
42 impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for CoherenceChecker<'a, 'tcx> {
43 fn visit_item(&mut self, item: &Item) {
44 if let ItemImpl(..) = item.node {
45 self.check_implementation(item)
49 fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
52 fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
56 impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
57 // Returns the def ID of the base type, if there is one.
58 fn get_base_type_def_id(&self, span: Span, ty: Ty<'tcx>) -> Option<DefId> {
60 TyAdt(def, _) => Some(def.did),
62 TyDynamic(ref t, ..) => t.principal().map(|p| p.def_id()),
64 TyBox(_) => self.tcx.lang_items.owned_box(),
66 TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) | TyStr | TyArray(..) |
67 TySlice(..) | TyFnDef(..) | TyFnPtr(_) | TyTuple(..) | TyParam(..) | TyError |
68 TyNever | TyRawPtr(_) | TyRef(..) | TyProjection(..) => None,
70 TyInfer(..) | TyClosure(..) | TyAnon(..) => {
71 // `ty` comes from a user declaration so we should only expect types
72 // that the user can type
74 "coherence encountered unexpected type searching for base type: {}",
81 // Check implementations and traits. This populates the tables
82 // containing the inherent methods and extension methods. It also
83 // builds up the trait inheritance table.
84 self.tcx.visit_all_item_likes_in_krate(DepNode::CoherenceCheckImpl, self);
87 fn check_implementation(&self, item: &Item) {
89 let impl_did = tcx.hir.local_def_id(item.id);
90 let self_type = tcx.item_type(impl_did);
92 // If there are no traits, then this implementation must have a
95 if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_did) {
96 debug!("(checking implementation) adding impl for trait '{:?}', item '{}'",
100 // Skip impls where one of the self type is an error type.
101 // This occurs with e.g. resolve failures (#30589).
102 if trait_ref.references_error() {
106 enforce_trait_manually_implementable(self.tcx, item.span, trait_ref.def_id);
107 self.add_trait_impl(trait_ref, impl_did);
109 // Skip inherent impls where the self type is an error
110 // type. This occurs with e.g. resolve failures (#30589).
111 if self_type.references_error() {
115 // Add the implementation to the mapping from implementation to base
116 // type def ID, if there is a base type for this implementation and
117 // the implementation does not have any associated traits.
118 if let Some(base_def_id) = self.get_base_type_def_id(item.span, self_type) {
119 self.add_inherent_impl(base_def_id, impl_did);
124 fn add_inherent_impl(&self, base_def_id: DefId, impl_def_id: DefId) {
125 self.tcx.inherent_impls.borrow_mut().push(base_def_id, impl_def_id);
128 fn add_trait_impl(&self, impl_trait_ref: ty::TraitRef<'tcx>, impl_def_id: DefId) {
129 debug!("add_trait_impl: impl_trait_ref={:?} impl_def_id={:?}",
132 let trait_def = self.tcx.lookup_trait_def(impl_trait_ref.def_id);
133 trait_def.record_local_impl(self.tcx, impl_def_id, impl_trait_ref);
137 fn enforce_trait_manually_implementable(tcx: TyCtxt, sp: Span, trait_def_id: DefId) {
138 if tcx.sess.features.borrow().unboxed_closures {
139 // the feature gate allows all of them
142 let did = Some(trait_def_id);
143 let li = &tcx.lang_items;
145 let trait_name = if did == li.fn_trait() {
147 } else if did == li.fn_mut_trait() {
149 } else if did == li.fn_once_trait() {
152 return; // everything OK
154 let mut err = struct_span_err!(tcx.sess,
157 "manual implementations of `{}` are experimental",
160 "add `#![feature(unboxed_closures)]` to the crate attributes to enable");
164 pub fn check_coherence(ccx: &CrateCtxt) {
165 let _task = ccx.tcx.dep_graph.in_task(DepNode::Coherence);
166 CoherenceChecker { tcx: ccx.tcx }.check();
167 unsafety::check(ccx.tcx);
168 orphan::check(ccx.tcx);
169 overlap::check(ccx.tcx);
170 builtin::check(ccx.tcx);