From 4c210afb19cd8b3a71a18f85dce80d3429f72667 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 29 Jan 2018 18:20:24 -0500 Subject: [PATCH] make `overlapping_impls` call closures instead of returning --- src/librustc/lib.rs | 1 + src/librustc/traits/coherence.rs | 27 +++++++---- .../traits/specialize/specialization_graph.rs | 47 ++++++++++--------- .../coherence/inherent_impls_overlap.rs | 46 +++++++++++------- 4 files changed, 73 insertions(+), 48 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, } -/// 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> +/// 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( + 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)); - } + 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)); + 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)) - } + 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, + ), + || (), + ); }); } }