about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-03-23 12:36:53 -0700
committerbors <bors@rust-lang.org>2013-03-23 12:36:53 -0700
commita56ec8c1342453a88be79e192a11501844375d40 (patch)
tree438faffceaa44ab4ddeb23c6fbfa6eb920082a8c
parent8aee0a6a2972f0c62777cb757184c01042513973 (diff)
parenta1b4afe0670fb1603b056f317a301ed527064ef5 (diff)
downloadrust-a56ec8c1342453a88be79e192a11501844375d40.tar.gz
rust-a56ec8c1342453a88be79e192a11501844375d40.zip
auto merge of #5515 : nikomatsakis/rust/issue-5514-flexible-coherence-rules, r=pcwalton
See issue #5514

r? @pcwalton
-rw-r--r--src/librustc/middle/typeck/coherence.rs95
1 files changed, 49 insertions, 46 deletions
diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs
index 824ac594e74..0b3eca7c07d 100644
--- a/src/librustc/middle/typeck/coherence.rs
+++ b/src/librustc/middle/typeck/coherence.rs
@@ -104,6 +104,32 @@ pub fn get_base_type(inference_context: @mut InferCtxt,
     }
 }
 
+pub fn type_is_defined_in_local_crate(original_type: t) -> bool {
+    /*!
+     *
+     * For coherence, when we have `impl Trait for Type`, we need to
+     * guarantee that `Type` is "local" to the
+     * crate.  For our purposes, this means that it must contain
+     * some nominal type defined in this crate.
+     */
+
+    let mut found_nominal = false;
+    do ty::walk_ty(original_type) |t| {
+        match get(t).sty {
+            ty_enum(def_id, _) |
+            ty_trait(def_id, _, _) |
+            ty_struct(def_id, _) => {
+                if def_id.crate == ast::local_crate {
+                    found_nominal = true;
+                }
+            }
+
+            _ => { }
+        }
+    }
+    return found_nominal;
+}
+
 // Returns the def ID of the base type, if there is one.
 pub fn get_base_type_def_id(inference_context: @mut InferCtxt,
                             span: span,
@@ -161,8 +187,7 @@ pub fn CoherenceChecker(crate_context: @mut CrateCtxt) -> CoherenceChecker {
         crate_context: crate_context,
         inference_context: new_infer_ctxt(crate_context.tcx),
 
-        base_type_def_ids: HashMap(),
-        privileged_implementations: HashMap()
+        base_type_def_ids: HashMap()
     }
 }
 
@@ -174,11 +199,6 @@ pub struct CoherenceChecker {
     // definition ID.
 
     base_type_def_ids: HashMap<def_id,def_id>,
-
-    // A set of implementations in privileged scopes; i.e. those
-    // implementations that are defined in the same scope as their base types.
-
-    privileged_implementations: HashMap<node_id,()>,
 }
 
 pub impl CoherenceChecker {
@@ -615,27 +635,11 @@ pub impl CoherenceChecker {
                         visit_mod(module_, item.span, item.id, (), visitor);
                     }
                     item_impl(_, opt_trait, _, _) => {
-                        let mut ok = false;
-                        match self.base_type_def_ids.find(
-                            &local_def(item.id)) {
-
-                            None => {
-                                // Nothing to do.
-                            }
-                            Some(base_type_def_id) => {
-                                // Check to see whether the implementation is
-                                // in the same crate as its base type.
-
-                                if base_type_def_id.crate == local_crate {
-                                    // Record that this implementation is OK.
-                                    self.privileged_implementations.insert
-                                        (item.id, ());
-                                    ok = true;
-                                }
-                            }
-                        }
-
-                        if !ok {
+                        // `for_ty` is `Type` in `impl Trait for Type`
+                        let for_ty =
+                            ty::node_id_to_type(self.crate_context.tcx,
+                                                item.id);
+                        if !type_is_defined_in_local_crate(for_ty) {
                             // This implementation is not in scope of its base
                             // type. This still might be OK if the trait is
                             // defined in the same crate.
@@ -655,25 +659,24 @@ pub impl CoherenceChecker {
                                                       implement a trait or \
                                                       new type instead");
                                 }
-                                _ => ()
-                          }
 
-                          for opt_trait.each |trait_ref| {
-                                // This is OK if and only if the trait was
-                                // defined in this crate.
-
-                                let trait_def_id =
-                                    self.trait_ref_to_trait_def_id(
-                                        *trait_ref);
-
-                                if trait_def_id.crate != local_crate {
-                                    let session = self.crate_context.tcx.sess;
-                                    session.span_err(item.span,
-                                                     ~"cannot provide an \
-                                                       extension \
-                                                       implementation for a \
-                                                       trait not defined in \
-                                                       this crate");
+                                Some(trait_ref) => {
+                                    // This is OK if and only if the trait was
+                                    // defined in this crate.
+
+                                    let trait_def_id =
+                                        self.trait_ref_to_trait_def_id(
+                                            trait_ref);
+
+                                    if trait_def_id.crate != local_crate {
+                                        let session = self.crate_context.tcx.sess;
+                                        session.span_err(item.span,
+                                                         ~"cannot provide an \
+                                                           extension \
+                                                           implementation for a \
+                                                           trait not defined in \
+                                                           this crate");
+                                    }
                                 }
                             }
                         }