about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2018-01-29 18:20:24 -0500
committerNiko Matsakis <niko@alum.mit.edu>2018-01-30 13:43:41 -0500
commit4c210afb19cd8b3a71a18f85dce80d3429f72667 (patch)
tree288f5009c7c1a5d3b8482ceb7ad17767b35243f1
parentc48f46ba368a5ae77acb0db46843a3e432ff87d3 (diff)
downloadrust-4c210afb19cd8b3a71a18f85dce80d3429f72667.tar.gz
rust-4c210afb19cd8b3a71a18f85dce80d3429f72667.zip
make `overlapping_impls` call closures instead of returning
-rw-r--r--src/librustc/lib.rs1
-rw-r--r--src/librustc/traits/coherence.rs27
-rw-r--r--src/librustc/traits/specialize/specialization_graph.rs51
-rw-r--r--src/librustc_typeck/coherence/inherent_impls_overlap.rs46
4 files changed, 75 insertions, 50 deletions
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index 075ee0b8c7c..0e371e0130a 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -65,6 +65,7 @@
 #![feature(specialization)]
 #![feature(unboxed_closures)]
 #![feature(underscore_lifetimes)]
+#![feature(universal_impl_trait)]
 #![feature(trace_macros)]
 #![feature(catch_expr)]
 #![feature(test)]
diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs
index 7d1f3b31bfc..77bb78e4ee0 100644
--- a/src/librustc/traits/coherence.rs
+++ b/src/librustc/traits/coherence.rs
@@ -40,13 +40,20 @@ pub struct OverlapResult<'tcx> {
     pub intercrate_ambiguity_causes: Vec<IntercrateAmbiguityCause>,
 }
 
-/// If there are types that satisfy both impls, returns a suitably-freshened
-/// `ImplHeader` with those types substituted
-pub fn overlapping_impls<'cx, 'gcx, 'tcx>(infcx: &InferCtxt<'cx, 'gcx, 'tcx>,
-                                          impl1_def_id: DefId,
-                                          impl2_def_id: DefId,
-                                          intercrate_mode: IntercrateMode)
-                                          -> Option<OverlapResult<'tcx>>
+/// If there are types that satisfy both impls, invokes `on_overlap`
+/// with a suitably-freshened `ImplHeader` with those types
+/// substituted. Otherwise, invokes `no_overlap`.
+pub fn overlapping_impls<F1, F2, R>(
+    infcx: &InferCtxt<'_, '_, '_>,
+    impl1_def_id: DefId,
+    impl2_def_id: DefId,
+    intercrate_mode: IntercrateMode,
+    on_overlap: F1,
+    no_overlap: F2,
+) -> R
+where
+    F1: FnOnce(OverlapResult<'_>) -> R,
+    F2: FnOnce() -> R,
 {
     debug!("impl_can_satisfy(\
            impl1_def_id={:?}, \
@@ -57,7 +64,11 @@ pub fn overlapping_impls<'cx, 'gcx, 'tcx>(infcx: &InferCtxt<'cx, 'gcx, 'tcx>,
            intercrate_mode);
 
     let selcx = &mut SelectionContext::intercrate(infcx, intercrate_mode);
-    overlap(selcx, impl1_def_id, impl2_def_id)
+    if let Some(r) = overlap(selcx, impl1_def_id, impl2_def_id) {
+        on_overlap(r)
+    } else {
+        no_overlap()
+    }
 }
 
 fn with_fresh_ty_vars<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>,
diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs
index 834389e5d00..4ad2a4955e9 100644
--- a/src/librustc/traits/specialize/specialization_graph.rs
+++ b/src/librustc/traits/specialize/specialization_graph.rs
@@ -134,26 +134,27 @@ impl<'a, 'gcx, 'tcx> Children {
 
             let tcx = tcx.global_tcx();
             let (le, ge) = tcx.infer_ctxt().enter(|infcx| {
-                let overlap = traits::overlapping_impls(&infcx,
-                                                        possible_sibling,
-                                                        impl_def_id,
-                                                        traits::IntercrateMode::Issue43355);
-                if let Some(overlap) = overlap {
-                    if tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling) {
-                        return Ok((false, false));
-                    }
-
-                    let le = tcx.specializes((impl_def_id, possible_sibling));
-                    let ge = tcx.specializes((possible_sibling, impl_def_id));
-
-                    if le == ge {
-                        Err(overlap_error(overlap))
-                    } else {
-                        Ok((le, ge))
-                    }
-                } else {
-                    Ok((false, false))
-                }
+                traits::overlapping_impls(
+                    &infcx,
+                    possible_sibling,
+                    impl_def_id,
+                    traits::IntercrateMode::Issue43355,
+                    |overlap| {
+                        if tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling) {
+                            return Ok((false, false));
+                        }
+
+                        let le = tcx.specializes((impl_def_id, possible_sibling));
+                        let ge = tcx.specializes((possible_sibling, impl_def_id));
+
+                        if le == ge {
+                            Err(overlap_error(overlap))
+                        } else {
+                            Ok((le, ge))
+                        }
+                    },
+                    || Ok((false, false)),
+                )
             })?;
 
             if le && !ge {
@@ -172,14 +173,14 @@ impl<'a, 'gcx, 'tcx> Children {
             } else {
                 if !tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling) {
                     tcx.infer_ctxt().enter(|infcx| {
-                        if let Some(overlap) = traits::overlapping_impls(
+                        traits::overlapping_impls(
                             &infcx,
                             possible_sibling,
                             impl_def_id,
-                            traits::IntercrateMode::Fixed)
-                        {
-                            last_lint = Some(overlap_error(overlap));
-                        }
+                            traits::IntercrateMode::Fixed,
+                            |overlap| last_lint = Some(overlap_error(overlap)),
+                            || (),
+                        )
                     });
                 }
 
diff --git a/src/librustc_typeck/coherence/inherent_impls_overlap.rs b/src/librustc_typeck/coherence/inherent_impls_overlap.rs
index 07d5f813cbb..c8a37c01094 100644
--- a/src/librustc_typeck/coherence/inherent_impls_overlap.rs
+++ b/src/librustc_typeck/coherence/inherent_impls_overlap.rs
@@ -83,27 +83,39 @@ impl<'a, 'tcx> InherentOverlapChecker<'a, 'tcx> {
         for (i, &impl1_def_id) in impls.iter().enumerate() {
             for &impl2_def_id in &impls[(i + 1)..] {
                 let used_to_be_allowed = self.tcx.infer_ctxt().enter(|infcx| {
-                    if let Some(overlap) =
-                        traits::overlapping_impls(&infcx, impl1_def_id, impl2_def_id,
-                                                  IntercrateMode::Issue43355)
-                    {
-                        self.check_for_common_items_in_impls(
-                            impl1_def_id, impl2_def_id, overlap, false);
-                        false
-                    } else {
-                        true
-                    }
+                    traits::overlapping_impls(
+                        &infcx,
+                        impl1_def_id,
+                        impl2_def_id,
+                        IntercrateMode::Issue43355,
+                        |overlap| {
+                            self.check_for_common_items_in_impls(
+                                impl1_def_id,
+                                impl2_def_id,
+                                overlap,
+                                false,
+                            );
+                            false
+                        },
+                        || true,
+                    )
                 });
 
                 if used_to_be_allowed {
                     self.tcx.infer_ctxt().enter(|infcx| {
-                        if let Some(overlap) =
-                            traits::overlapping_impls(&infcx, impl1_def_id, impl2_def_id,
-                                                      IntercrateMode::Fixed)
-                        {
-                            self.check_for_common_items_in_impls(
-                                impl1_def_id, impl2_def_id, overlap, true);
-                        }
+                        traits::overlapping_impls(
+                            &infcx,
+                            impl1_def_id,
+                            impl2_def_id,
+                            IntercrateMode::Fixed,
+                            |overlap| self.check_for_common_items_in_impls(
+                                impl1_def_id,
+                                impl2_def_id,
+                                overlap,
+                                true,
+                            ),
+                            || (),
+                        );
                     });
                 }
             }