1
Fork 0

make overlapping_impls call closures instead of returning

This commit is contained in:
Niko Matsakis 2018-01-29 18:20:24 -05:00
parent c48f46ba36
commit 4c210afb19
4 changed files with 73 additions and 48 deletions

View file

@ -65,6 +65,7 @@
#![feature(specialization)] #![feature(specialization)]
#![feature(unboxed_closures)] #![feature(unboxed_closures)]
#![feature(underscore_lifetimes)] #![feature(underscore_lifetimes)]
#![feature(universal_impl_trait)]
#![feature(trace_macros)] #![feature(trace_macros)]
#![feature(catch_expr)] #![feature(catch_expr)]
#![feature(test)] #![feature(test)]

View file

@ -40,13 +40,20 @@ pub struct OverlapResult<'tcx> {
pub intercrate_ambiguity_causes: Vec<IntercrateAmbiguityCause>, pub intercrate_ambiguity_causes: Vec<IntercrateAmbiguityCause>,
} }
/// If there are types that satisfy both impls, returns a suitably-freshened /// If there are types that satisfy both impls, invokes `on_overlap`
/// `ImplHeader` with those types substituted /// with a suitably-freshened `ImplHeader` with those types
pub fn overlapping_impls<'cx, 'gcx, 'tcx>(infcx: &InferCtxt<'cx, 'gcx, 'tcx>, /// substituted. Otherwise, invokes `no_overlap`.
impl1_def_id: DefId, pub fn overlapping_impls<F1, F2, R>(
impl2_def_id: DefId, infcx: &InferCtxt<'_, '_, '_>,
intercrate_mode: IntercrateMode) impl1_def_id: DefId,
-> Option<OverlapResult<'tcx>> 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(\ debug!("impl_can_satisfy(\
impl1_def_id={:?}, \ impl1_def_id={:?}, \
@ -57,7 +64,11 @@ pub fn overlapping_impls<'cx, 'gcx, 'tcx>(infcx: &InferCtxt<'cx, 'gcx, 'tcx>,
intercrate_mode); intercrate_mode);
let selcx = &mut SelectionContext::intercrate(infcx, 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>, fn with_fresh_ty_vars<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>,

View file

@ -134,26 +134,27 @@ impl<'a, 'gcx, 'tcx> Children {
let tcx = tcx.global_tcx(); let tcx = tcx.global_tcx();
let (le, ge) = tcx.infer_ctxt().enter(|infcx| { let (le, ge) = tcx.infer_ctxt().enter(|infcx| {
let overlap = traits::overlapping_impls(&infcx, traits::overlapping_impls(
possible_sibling, &infcx,
impl_def_id, possible_sibling,
traits::IntercrateMode::Issue43355); impl_def_id,
if let Some(overlap) = overlap { traits::IntercrateMode::Issue43355,
if tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling) { |overlap| {
return Ok((false, false)); 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 le = tcx.specializes((impl_def_id, possible_sibling));
let ge = tcx.specializes((possible_sibling, impl_def_id)); let ge = tcx.specializes((possible_sibling, impl_def_id));
if le == ge { if le == ge {
Err(overlap_error(overlap)) Err(overlap_error(overlap))
} else { } else {
Ok((le, ge)) Ok((le, ge))
} }
} else { },
Ok((false, false)) || Ok((false, false)),
} )
})?; })?;
if le && !ge { if le && !ge {
@ -172,14 +173,14 @@ impl<'a, 'gcx, 'tcx> Children {
} else { } else {
if !tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling) { if !tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling) {
tcx.infer_ctxt().enter(|infcx| { tcx.infer_ctxt().enter(|infcx| {
if let Some(overlap) = traits::overlapping_impls( traits::overlapping_impls(
&infcx, &infcx,
possible_sibling, possible_sibling,
impl_def_id, impl_def_id,
traits::IntercrateMode::Fixed) traits::IntercrateMode::Fixed,
{ |overlap| last_lint = Some(overlap_error(overlap)),
last_lint = Some(overlap_error(overlap)); || (),
} )
}); });
} }

View file

@ -83,27 +83,39 @@ impl<'a, 'tcx> InherentOverlapChecker<'a, 'tcx> {
for (i, &impl1_def_id) in impls.iter().enumerate() { for (i, &impl1_def_id) in impls.iter().enumerate() {
for &impl2_def_id in &impls[(i + 1)..] { for &impl2_def_id in &impls[(i + 1)..] {
let used_to_be_allowed = self.tcx.infer_ctxt().enter(|infcx| { let used_to_be_allowed = self.tcx.infer_ctxt().enter(|infcx| {
if let Some(overlap) = traits::overlapping_impls(
traits::overlapping_impls(&infcx, impl1_def_id, impl2_def_id, &infcx,
IntercrateMode::Issue43355) impl1_def_id,
{ impl2_def_id,
self.check_for_common_items_in_impls( IntercrateMode::Issue43355,
impl1_def_id, impl2_def_id, overlap, false); |overlap| {
false self.check_for_common_items_in_impls(
} else { impl1_def_id,
true impl2_def_id,
} overlap,
false,
);
false
},
|| true,
)
}); });
if used_to_be_allowed { if used_to_be_allowed {
self.tcx.infer_ctxt().enter(|infcx| { self.tcx.infer_ctxt().enter(|infcx| {
if let Some(overlap) = traits::overlapping_impls(
traits::overlapping_impls(&infcx, impl1_def_id, impl2_def_id, &infcx,
IntercrateMode::Fixed) impl1_def_id,
{ impl2_def_id,
self.check_for_common_items_in_impls( IntercrateMode::Fixed,
impl1_def_id, impl2_def_id, overlap, true); |overlap| self.check_for_common_items_in_impls(
} impl1_def_id,
impl2_def_id,
overlap,
true,
),
|| (),
);
}); });
} }
} }