]> git.lizzy.rs Git - rust.git/blob - src/librustc/middle/typeck/coherence.rs
librustc: Fix errors arising from the automated `~[T]` conversion
[rust.git] / src / librustc / middle / typeck / coherence.rs
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.
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 // Coherence phase
12 //
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.
16
17
18 use metadata::csearch::{each_impl, get_impl_trait, each_implementation_for_trait};
19 use metadata::csearch;
20 use middle::ty::get;
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::{ty_unboxed_vec, type_is_ty_var};
28 use middle::subst::Subst;
29 use middle::ty;
30 use middle::ty::{Impl, Method};
31 use middle::typeck::CrateCtxt;
32 use middle::typeck::infer::combine::Combine;
33 use middle::typeck::infer::InferCtxt;
34 use middle::typeck::infer::{new_infer_ctxt, resolve_ivar, resolve_type};
35 use middle::typeck::infer;
36 use util::ppaux::Repr;
37 use syntax::ast::{Crate, DefId, DefStruct, DefTy};
38 use syntax::ast::{Item, ItemEnum, ItemImpl, ItemMod, ItemStruct};
39 use syntax::ast::{LOCAL_CRATE, TraitRef, TyPath};
40 use syntax::ast;
41 use syntax::ast_map::NodeItem;
42 use syntax::ast_map;
43 use syntax::ast_util::{def_id_of_def, local_def};
44 use syntax::codemap::Span;
45 use syntax::opt_vec;
46 use syntax::parse::token;
47 use syntax::visit;
48
49 use std::cell::RefCell;
50 use collections::HashSet;
51 use std::rc::Rc;
52 use std::vec;
53
54 struct UniversalQuantificationResult {
55     monotype: t,
56     type_variables: ~[ty::t],
57     type_param_defs: Rc<~[ty::TypeParameterDef]>
58 }
59
60 fn get_base_type(inference_context: &InferCtxt,
61                  span: Span,
62                  original_type: t)
63                  -> Option<t> {
64     let resolved_type;
65     match resolve_type(inference_context,
66                        original_type,
67                        resolve_ivar) {
68         Ok(resulting_type) if !type_is_ty_var(resulting_type) => {
69             resolved_type = resulting_type;
70         }
71         _ => {
72             inference_context.tcx.sess.span_fatal(span,
73                                                   "the type of this value must be known in order \
74                                                    to determine the base type");
75         }
76     }
77
78     match get(resolved_type).sty {
79         ty_enum(..) | ty_trait(..) | ty_struct(..) => {
80             debug!("(getting base type) found base type");
81             Some(resolved_type)
82         }
83
84         ty_nil | ty_bot | ty_bool | ty_char | ty_int(..) | ty_uint(..) | ty_float(..) |
85         ty_str(..) | ty_vec(..) | ty_bare_fn(..) | ty_closure(..) | ty_tup(..) |
86         ty_infer(..) | ty_param(..) | ty_self(..) |
87         ty_unboxed_vec(..) | ty_err | ty_box(_) |
88         ty_uniq(_) | ty_ptr(_) | ty_rptr(_, _) => {
89             debug!("(getting base type) no base type; found {:?}",
90                    get(original_type).sty);
91             None
92         }
93     }
94 }
95
96 fn type_is_defined_in_local_crate(original_type: t) -> bool {
97     /*!
98      *
99      * For coherence, when we have `impl Trait for Type`, we need to
100      * guarantee that `Type` is "local" to the
101      * crate.  For our purposes, this means that it must contain
102      * some nominal type defined in this crate.
103      */
104
105     let mut found_nominal = false;
106     ty::walk_ty(original_type, |t| {
107         match get(t).sty {
108             ty_enum(def_id, _) |
109             ty_trait(def_id, _, _, _, _) |
110             ty_struct(def_id, _) => {
111                 if def_id.krate == ast::LOCAL_CRATE {
112                     found_nominal = true;
113                 }
114             }
115
116             _ => { }
117         }
118     });
119     return found_nominal;
120 }
121
122 // Returns the def ID of the base type, if there is one.
123 fn get_base_type_def_id(inference_context: &InferCtxt,
124                         span: Span,
125                         original_type: t)
126                         -> Option<DefId> {
127     match get_base_type(inference_context, span, original_type) {
128         None => {
129             return None;
130         }
131         Some(base_type) => {
132             match get(base_type).sty {
133                 ty_enum(def_id, _) |
134                 ty_struct(def_id, _) |
135                 ty_trait(def_id, _, _, _, _) => {
136                     return Some(def_id);
137                 }
138                 _ => {
139                     fail!("get_base_type() returned a type that wasn't an \
140                            enum, struct, or trait");
141                 }
142             }
143         }
144     }
145 }
146
147 struct CoherenceChecker {
148     crate_context: @CrateCtxt,
149     inference_context: InferCtxt,
150 }
151
152 struct CoherenceCheckVisitor<'a> {
153     cc: &'a CoherenceChecker
154 }
155
156 impl<'a> visit::Visitor<()> for CoherenceCheckVisitor<'a> {
157     fn visit_item(&mut self, item: &Item, _: ()) {
158
159         //debug!("(checking coherence) item '{}'", token::get_ident(item.ident));
160
161         match item.node {
162             ItemImpl(_, ref opt_trait, _, _) => {
163                 match opt_trait.clone() {
164                     Some(opt_trait) => {
165                         self.cc.check_implementation(item, [opt_trait]);
166                     }
167                     None => self.cc.check_implementation(item, [])
168                 }
169             }
170             _ => {
171                 // Nothing to do.
172             }
173         };
174
175         visit::walk_item(self, item, ());
176     }
177 }
178
179 struct PrivilegedScopeVisitor<'a> { cc: &'a CoherenceChecker }
180
181 impl<'a> visit::Visitor<()> for PrivilegedScopeVisitor<'a> {
182     fn visit_item(&mut self, item: &Item, _: ()) {
183
184         match item.node {
185             ItemMod(ref module_) => {
186                 // Then visit the module items.
187                 visit::walk_mod(self, module_, ());
188             }
189             ItemImpl(_, None, ast_ty, _) => {
190                 if !self.cc.ast_type_is_defined_in_local_crate(ast_ty) {
191                     // This is an error.
192                     let session = self.cc.crate_context.tcx.sess;
193                     session.span_err(item.span,
194                                      "cannot associate methods with a type outside the \
195                                      crate the type is defined in; define and implement \
196                                      a trait or new type instead");
197                 }
198             }
199             ItemImpl(_, Some(ref trait_ref), _, _) => {
200                 // `for_ty` is `Type` in `impl Trait for Type`
201                 let for_ty =
202                     ty::node_id_to_type(self.cc.crate_context.tcx,
203                                         item.id);
204                 if !type_is_defined_in_local_crate(for_ty) {
205                     // This implementation is not in scope of its base
206                     // type. This still might be OK if the trait is
207                     // defined in the same crate.
208
209                     let trait_def_id =
210                         self.cc.trait_ref_to_trait_def_id(trait_ref);
211
212                     if trait_def_id.krate != LOCAL_CRATE {
213                         let session = self.cc.crate_context.tcx.sess;
214                         session.span_err(item.span,
215                                 "cannot provide an extension implementation \
216                                 where both trait and type are not defined in this crate");
217                     }
218                 }
219
220                 visit::walk_item(self, item, ());
221             }
222             _ => {
223                 visit::walk_item(self, item, ());
224             }
225         }
226     }
227 }
228
229 impl CoherenceChecker {
230     fn new(crate_context: @CrateCtxt) -> CoherenceChecker {
231         CoherenceChecker {
232             crate_context: crate_context,
233             inference_context: new_infer_ctxt(crate_context.tcx),
234         }
235     }
236
237     fn check(&self, krate: &Crate) {
238         // Check implementations and traits. This populates the tables
239         // containing the inherent methods and extension methods. It also
240         // builds up the trait inheritance table.
241         let mut visitor = CoherenceCheckVisitor { cc: self };
242         visit::walk_crate(&mut visitor, krate, ());
243
244         // Check that there are no overlapping trait instances
245         self.check_implementation_coherence();
246
247         // Check whether traits with base types are in privileged scopes.
248         self.check_privileged_scopes(krate);
249
250         // Bring in external crates. It's fine for this to happen after the
251         // coherence checks, because we ensure by construction that no errors
252         // can happen at link time.
253         self.add_external_crates();
254
255         // Populate the table of destructors. It might seem a bit strange to
256         // do this here, but it's actually the most convenient place, since
257         // the coherence tables contain the trait -> type mappings.
258         self.populate_destructor_table();
259     }
260
261     fn check_implementation(&self, item: &Item,
262                             associated_traits: &[TraitRef]) {
263         let tcx = self.crate_context.tcx;
264         let self_type = ty::lookup_item_type(tcx, local_def(item.id));
265
266         // If there are no traits, then this implementation must have a
267         // base type.
268
269         if associated_traits.len() == 0 {
270             debug!("(checking implementation) no associated traits for item '{}'",
271                    token::get_ident(item.ident));
272
273             match get_base_type_def_id(&self.inference_context,
274                                        item.span,
275                                        self_type.ty) {
276                 None => {
277                     let session = self.crate_context.tcx.sess;
278                     session.span_err(item.span,
279                                      "no base type found for inherent implementation; \
280                                       implement a trait or new type instead");
281                 }
282                 Some(_) => {
283                     // Nothing to do.
284                 }
285             }
286         }
287
288         let implementation = self.create_impl_from_item(item);
289
290         for associated_trait in associated_traits.iter() {
291             let trait_ref = ty::node_id_to_trait_ref(
292                 self.crate_context.tcx, associated_trait.ref_id);
293             debug!("(checking implementation) adding impl for trait '{}', item '{}'",
294                    trait_ref.repr(self.crate_context.tcx),
295                    token::get_ident(item.ident));
296
297             self.add_trait_impl(trait_ref.def_id, implementation);
298         }
299
300         // Add the implementation to the mapping from implementation to base
301         // type def ID, if there is a base type for this implementation and
302         // the implementation does not have any associated traits.
303         match get_base_type_def_id(&self.inference_context,
304                                    item.span,
305                                    self_type.ty) {
306             None => {
307                 // Nothing to do.
308             }
309             Some(base_type_def_id) => {
310                 // FIXME: Gather up default methods?
311                 if associated_traits.len() == 0 {
312                     self.add_inherent_impl(base_type_def_id, implementation);
313                 }
314             }
315         }
316
317         let mut impls = tcx.impls.borrow_mut();
318         impls.get().insert(implementation.did, implementation);
319     }
320
321     // Creates default method IDs and performs type substitutions for an impl
322     // and trait pair. Then, for each provided method in the trait, inserts a
323     // `ProvidedMethodInfo` instance into the `provided_method_sources` map.
324     fn instantiate_default_methods(&self, impl_id: ast::DefId,
325                                    trait_ref: &ty::TraitRef,
326                                    all_methods: &mut ~[@Method]) {
327         let tcx = self.crate_context.tcx;
328         debug!("instantiate_default_methods(impl_id={:?}, trait_ref={})",
329                impl_id, trait_ref.repr(tcx));
330
331         let impl_poly_type = ty::lookup_item_type(tcx, impl_id);
332
333         let prov = ty::provided_trait_methods(tcx, trait_ref.def_id);
334         for trait_method in prov.iter() {
335             // Synthesize an ID.
336             let new_id = tcx.sess.next_node_id();
337             let new_did = local_def(new_id);
338
339             debug!("new_did={:?} trait_method={}", new_did, trait_method.repr(tcx));
340
341             // Create substitutions for the various trait parameters.
342             let new_method_ty =
343                 @subst_receiver_types_in_method_ty(
344                     tcx,
345                     impl_id,
346                     trait_ref,
347                     new_did,
348                     *trait_method,
349                     Some(trait_method.def_id));
350
351             debug!("new_method_ty={}", new_method_ty.repr(tcx));
352             all_methods.push(new_method_ty);
353
354             // construct the polytype for the method based on the method_ty
355             let new_generics = ty::Generics {
356                 type_param_defs:
357                     Rc::new(vec::append(
358                         impl_poly_type.generics.type_param_defs().to_owned(),
359                             new_method_ty.generics.type_param_defs())),
360                 region_param_defs:
361                     impl_poly_type.generics.region_param_defs.clone()
362             };
363             let new_polytype = ty::ty_param_bounds_and_ty {
364                 generics: new_generics,
365                 ty: ty::mk_bare_fn(tcx, new_method_ty.fty.clone())
366             };
367             debug!("new_polytype={}", new_polytype.repr(tcx));
368
369             {
370                 let mut tcache = tcx.tcache.borrow_mut();
371                 tcache.get().insert(new_did, new_polytype);
372             }
373
374             let mut methods = tcx.methods.borrow_mut();
375             methods.get().insert(new_did, new_method_ty);
376
377             // Pair the new synthesized ID up with the
378             // ID of the method.
379             let mut provided_method_sources =
380                 self.crate_context.tcx.provided_method_sources.borrow_mut();
381             provided_method_sources.get().insert(new_did,
382                                                  trait_method.def_id);
383         }
384     }
385
386     fn add_inherent_impl(&self, base_def_id: DefId,
387                          implementation: @Impl) {
388         let tcx = self.crate_context.tcx;
389         let implementation_list;
390         let mut inherent_impls = tcx.inherent_impls.borrow_mut();
391         match inherent_impls.get().find(&base_def_id) {
392             None => {
393                 implementation_list = @RefCell::new(~[]);
394                 inherent_impls.get().insert(base_def_id, implementation_list);
395             }
396             Some(&existing_implementation_list) => {
397                 implementation_list = existing_implementation_list;
398             }
399         }
400
401         let mut implementation_list = implementation_list.borrow_mut();
402         implementation_list.get().push(implementation);
403     }
404
405     fn add_trait_impl(&self, base_def_id: DefId,
406                       implementation: @Impl) {
407         let tcx = self.crate_context.tcx;
408         let implementation_list;
409         let mut trait_impls = tcx.trait_impls.borrow_mut();
410         match trait_impls.get().find(&base_def_id) {
411             None => {
412                 implementation_list = @RefCell::new(~[]);
413                 trait_impls.get().insert(base_def_id, implementation_list);
414             }
415             Some(&existing_implementation_list) => {
416                 implementation_list = existing_implementation_list;
417             }
418         }
419
420         let mut implementation_list = implementation_list.borrow_mut();
421         implementation_list.get().push(implementation);
422     }
423
424     fn check_implementation_coherence(&self) {
425         let trait_impls = self.crate_context.tcx.trait_impls.borrow();
426         for &trait_id in trait_impls.get().keys() {
427             self.check_implementation_coherence_of(trait_id);
428         }
429     }
430
431     fn check_implementation_coherence_of(&self, trait_def_id: DefId) {
432         // Unify pairs of polytypes.
433         self.iter_impls_of_trait_local(trait_def_id, |a| {
434             let implementation_a = a;
435             let polytype_a =
436                 self.get_self_type_for_implementation(implementation_a);
437
438             // "We have an impl of trait <trait_def_id> for type <polytype_a>,
439             // and that impl is <implementation_a>"
440             self.iter_impls_of_trait(trait_def_id, |b| {
441                 let implementation_b = b;
442
443                 // An impl is coherent with itself
444                 if a.did != b.did {
445                     let polytype_b = self.get_self_type_for_implementation(
446                             implementation_b);
447
448                     if self.polytypes_unify(polytype_a.clone(), polytype_b) {
449                         let session = self.crate_context.tcx.sess;
450                         session.span_err(
451                             self.span_of_impl(implementation_a),
452                             format!("conflicting implementations for trait `{}`",
453                                  ty::item_path_str(self.crate_context.tcx,
454                                                    trait_def_id)));
455                         if implementation_b.did.krate == LOCAL_CRATE {
456                             session.span_note(self.span_of_impl(implementation_b),
457                                               "note conflicting implementation here");
458                         } else {
459                             let crate_store = self.crate_context.tcx.sess.cstore;
460                             let cdata = crate_store.get_crate_data(implementation_b.did.krate);
461                             session.note(
462                                 "conflicting implementation in crate `" + cdata.name + "`");
463                         }
464                     }
465                 }
466             })
467         })
468     }
469
470     fn iter_impls_of_trait(&self, trait_def_id: DefId, f: |@Impl|) {
471         self.iter_impls_of_trait_local(trait_def_id, |x| f(x));
472
473         if trait_def_id.krate == LOCAL_CRATE {
474             return;
475         }
476
477         let crate_store = self.crate_context.tcx.sess.cstore;
478         csearch::each_implementation_for_trait(crate_store, trait_def_id, |impl_def_id| {
479             let implementation = @csearch::get_impl(self.crate_context.tcx, impl_def_id);
480             let _ = lookup_item_type(self.crate_context.tcx, implementation.did);
481             f(implementation);
482         });
483     }
484
485     fn iter_impls_of_trait_local(&self, trait_def_id: DefId, f: |@Impl|) {
486         let trait_impls = self.crate_context.tcx.trait_impls.borrow();
487         match trait_impls.get().find(&trait_def_id) {
488             Some(impls) => {
489                 let impls = impls.borrow();
490                 for &im in impls.get().iter() {
491                     f(im);
492                 }
493             }
494             None => { /* no impls? */ }
495         }
496     }
497
498     fn polytypes_unify(&self,
499                        polytype_a: ty_param_bounds_and_ty,
500                        polytype_b: ty_param_bounds_and_ty)
501                        -> bool {
502         let universally_quantified_a =
503             self.universally_quantify_polytype(polytype_a);
504         let universally_quantified_b =
505             self.universally_quantify_polytype(polytype_b);
506
507         return self.can_unify_universally_quantified(
508             &universally_quantified_a, &universally_quantified_b) ||
509             self.can_unify_universally_quantified(
510             &universally_quantified_b, &universally_quantified_a);
511     }
512
513     // Converts a polytype to a monotype by replacing all parameters with
514     // type variables. Returns the monotype and the type variables created.
515     fn universally_quantify_polytype(&self, polytype: ty_param_bounds_and_ty)
516                                      -> UniversalQuantificationResult {
517         let region_parameter_count = polytype.generics.region_param_defs().len();
518         let region_parameters =
519             self.inference_context.next_region_vars(
520                 infer::BoundRegionInCoherence,
521                 region_parameter_count);
522
523         let bounds_count = polytype.generics.type_param_defs().len();
524         let type_parameters = self.inference_context.next_ty_vars(bounds_count);
525
526         let substitutions = substs {
527             regions: ty::NonerasedRegions(opt_vec::from(
528                              region_parameters.move_iter().collect())),
529             self_ty: None,
530             tps: type_parameters
531         };
532         let monotype = subst(self.crate_context.tcx,
533                              &substitutions,
534                              polytype.ty);
535
536         UniversalQuantificationResult {
537             monotype: monotype,
538             type_variables: substitutions.tps,
539             type_param_defs: polytype.generics.type_param_defs.clone()
540         }
541     }
542
543     fn can_unify_universally_quantified<'a>(&self,
544                                             a: &'a UniversalQuantificationResult,
545                                             b: &'a UniversalQuantificationResult)
546                                             -> bool {
547         infer::can_mk_subty(&self.inference_context,
548                             a.monotype,
549                             b.monotype).is_ok()
550     }
551
552     fn get_self_type_for_implementation(&self, implementation: @Impl)
553                                         -> ty_param_bounds_and_ty {
554         let tcache = self.crate_context.tcx.tcache.borrow();
555         return tcache.get().get_copy(&implementation.did);
556     }
557
558     // Privileged scope checking
559     fn check_privileged_scopes(&self, krate: &Crate) {
560         let mut visitor = PrivilegedScopeVisitor{ cc: self };
561         visit::walk_crate(&mut visitor, krate, ());
562     }
563
564     fn trait_ref_to_trait_def_id(&self, trait_ref: &TraitRef) -> DefId {
565         let def_map = self.crate_context.tcx.def_map;
566         let def_map = def_map.borrow();
567         let trait_def = def_map.get().get_copy(&trait_ref.ref_id);
568         let trait_id = def_id_of_def(trait_def);
569         return trait_id;
570     }
571
572     /// For coherence, when we have `impl Type`, we need to guarantee that
573     /// `Type` is "local" to the crate. For our purposes, this means that it
574     /// must precisely name some nominal type defined in this crate.
575     fn ast_type_is_defined_in_local_crate(&self, original_type: &ast::Ty) -> bool {
576         match original_type.node {
577             TyPath(_, _, path_id) => {
578                 let def_map = self.crate_context.tcx.def_map.borrow();
579                 match def_map.get().get_copy(&path_id) {
580                     DefTy(def_id) | DefStruct(def_id) => {
581                         if def_id.krate != LOCAL_CRATE {
582                             return false;
583                         }
584
585                         // Make sure that this type precisely names a nominal
586                         // type.
587                         match self.crate_context.tcx.map.find(def_id.node) {
588                             None => {
589                                 self.crate_context.tcx.sess.span_bug(
590                                     original_type.span,
591                                     "resolve didn't resolve this type?!");
592                             }
593                             Some(NodeItem(item)) => {
594                                 match item.node {
595                                     ItemStruct(..) | ItemEnum(..) => true,
596                                     _ => false,
597                                 }
598                             }
599                             Some(_) => false,
600                         }
601                     }
602                     _ => false
603                 }
604             }
605             _ => false
606         }
607     }
608
609     // Converts an implementation in the AST to an Impl structure.
610     fn create_impl_from_item(&self, item: &Item) -> @Impl {
611         let tcx = self.crate_context.tcx;
612         match item.node {
613             ItemImpl(_, ref trait_refs, _, ref ast_methods) => {
614                 let mut methods = ~[];
615                 for ast_method in ast_methods.iter() {
616                     methods.push(ty::method(tcx, local_def(ast_method.id)));
617                 }
618
619                 for trait_ref in trait_refs.iter() {
620                     let ty_trait_ref = ty::node_id_to_trait_ref(
621                         self.crate_context.tcx,
622                         trait_ref.ref_id);
623
624                     self.instantiate_default_methods(local_def(item.id),
625                                                      ty_trait_ref,
626                                                      &mut methods);
627                 }
628
629                 return @Impl {
630                     did: local_def(item.id),
631                     ident: item.ident,
632                     methods: methods
633                 };
634             }
635             _ => {
636                 self.crate_context.tcx.sess.span_bug(item.span,
637                                                      "can't convert a non-impl to an impl");
638             }
639         }
640     }
641
642     fn span_of_impl(&self, implementation: @Impl) -> Span {
643         assert_eq!(implementation.did.krate, LOCAL_CRATE);
644         self.crate_context.tcx.map.span(implementation.did.node)
645     }
646
647     // External crate handling
648
649     fn add_external_impl(&self,
650                          impls_seen: &mut HashSet<DefId>,
651                          impl_def_id: DefId) {
652         let tcx = self.crate_context.tcx;
653         let implementation = @csearch::get_impl(tcx, impl_def_id);
654
655         // Make sure we don't visit the same implementation multiple times.
656         if !impls_seen.insert(implementation.did) {
657             // Skip this one.
658             return
659         }
660         // Good. Continue.
661
662         let _ = lookup_item_type(tcx, implementation.did);
663         let associated_traits = get_impl_trait(tcx, implementation.did);
664
665         // Do a sanity check.
666         assert!(associated_traits.is_some());
667
668         // Record all the trait methods.
669         for trait_ref in associated_traits.iter() {
670               self.add_trait_impl(trait_ref.def_id, implementation);
671         }
672
673         // For any methods that use a default implementation, add them to
674         // the map. This is a bit unfortunate.
675         for method in implementation.methods.iter() {
676             for source in method.provided_source.iter() {
677                 let mut provided_method_sources = tcx.provided_method_sources
678                                                      .borrow_mut();
679                 provided_method_sources.get().insert(method.def_id, *source);
680             }
681         }
682
683         let mut impls = tcx.impls.borrow_mut();
684         impls.get().insert(implementation.did, implementation);
685     }
686
687     // Adds implementations and traits from external crates to the coherence
688     // info.
689     fn add_external_crates(&self) {
690         let mut impls_seen = HashSet::new();
691
692         let crate_store = self.crate_context.tcx.sess.cstore;
693         crate_store.iter_crate_data(|crate_number, _crate_metadata| {
694             each_impl(crate_store, crate_number, |def_id| {
695                 assert_eq!(crate_number, def_id.krate);
696                 self.add_external_impl(&mut impls_seen, def_id)
697             })
698         })
699     }
700
701     //
702     // Destructors
703     //
704
705     fn populate_destructor_table(&self) {
706         let tcx = self.crate_context.tcx;
707         let drop_trait = match tcx.lang_items.drop_trait() {
708             Some(id) => id, None => { return }
709         };
710
711         let trait_impls = tcx.trait_impls.borrow();
712         let impls_opt = trait_impls.get().find(&drop_trait);
713         let impls;
714         match impls_opt {
715             None => return, // No types with (new-style) dtors present.
716             Some(found_impls) => impls = found_impls
717         }
718
719         let impls = impls.borrow();
720         for impl_info in impls.get().iter() {
721             if impl_info.methods.len() < 1 {
722                 // We'll error out later. For now, just don't ICE.
723                 continue;
724             }
725             let method_def_id = impl_info.methods[0].def_id;
726
727             let self_type = self.get_self_type_for_implementation(*impl_info);
728             match ty::get(self_type.ty).sty {
729                 ty::ty_enum(type_def_id, _) |
730                 ty::ty_struct(type_def_id, _) => {
731                     let mut destructor_for_type = tcx.destructor_for_type
732                                                      .borrow_mut();
733                     destructor_for_type.get().insert(type_def_id,
734                                                      method_def_id);
735                     let mut destructors = tcx.destructors.borrow_mut();
736                     destructors.get().insert(method_def_id);
737                 }
738                 _ => {
739                     // Destructors only work on nominal types.
740                     if impl_info.did.krate == ast::LOCAL_CRATE {
741                         {
742                             match tcx.map.find(impl_info.did.node) {
743                                 Some(ast_map::NodeItem(item)) => {
744                                     tcx.sess.span_err((*item).span,
745                                                       "the Drop trait may \
746                                                        only be implemented \
747                                                        on structures");
748                                 }
749                                 _ => {
750                                     tcx.sess.bug("didn't find impl in ast \
751                                                   map");
752                                 }
753                             }
754                         }
755                     } else {
756                         tcx.sess.bug("found external impl of Drop trait on \
757                                       something other than a struct");
758                     }
759                 }
760             }
761         }
762     }
763 }
764
765 pub fn make_substs_for_receiver_types(tcx: ty::ctxt,
766                                       impl_id: ast::DefId,
767                                       trait_ref: &ty::TraitRef,
768                                       method: &ty::Method)
769                                       -> ty::substs {
770     /*!
771      * Substitutes the values for the receiver's type parameters
772      * that are found in method, leaving the method's type parameters
773      * intact.  This is in fact a mildly complex operation,
774      * largely because of the hokey way that we concatenate the
775      * receiver and method generics.
776      */
777
778     // determine how many type parameters were declared on the impl
779     let num_impl_type_parameters = {
780         let impl_polytype = ty::lookup_item_type(tcx, impl_id);
781         impl_polytype.generics.type_param_defs().len()
782     };
783
784     // determine how many type parameters appear on the trait
785     let num_trait_type_parameters = trait_ref.substs.tps.len();
786
787     // the current method type has the type parameters from the trait + method
788     let num_method_type_parameters =
789         num_trait_type_parameters + method.generics.type_param_defs().len();
790
791     // the new method type will have the type parameters from the impl + method
792     let combined_tps = vec::from_fn(num_method_type_parameters, |i| {
793         if i < num_trait_type_parameters {
794             // replace type parameters that come from trait with new value
795             trait_ref.substs.tps[i]
796         } else {
797             // replace type parameters that belong to method with another
798             // type parameter, this time with the index adjusted
799             let method_index = i - num_trait_type_parameters;
800             let type_param_def = &method.generics.type_param_defs()[method_index];
801             let new_index = num_impl_type_parameters + method_index;
802             ty::mk_param(tcx, new_index, type_param_def.def_id)
803         }
804     });
805
806     return ty::substs {
807         regions: trait_ref.substs.regions.clone(),
808         self_ty: trait_ref.substs.self_ty,
809         tps: combined_tps
810     };
811 }
812
813 fn subst_receiver_types_in_method_ty(tcx: ty::ctxt,
814                                      impl_id: ast::DefId,
815                                      trait_ref: &ty::TraitRef,
816                                      new_def_id: ast::DefId,
817                                      method: &ty::Method,
818                                      provided_source: Option<ast::DefId>)
819                                      -> ty::Method {
820
821     let combined_substs = make_substs_for_receiver_types(
822         tcx, impl_id, trait_ref, method);
823
824     ty::Method::new(
825         method.ident,
826
827         // method types *can* appear in the generic bounds
828         method.generics.subst(tcx, &combined_substs),
829
830         // method types *can* appear in the fty
831         method.fty.subst(tcx, &combined_substs),
832
833         method.explicit_self,
834         method.vis,
835         new_def_id,
836         ImplContainer(impl_id),
837         provided_source
838     )
839 }
840
841 pub fn check_coherence(crate_context: @CrateCtxt, krate: &Crate) {
842     CoherenceChecker::new(crate_context).check(krate);
843 }