Further update with response to feedback
This commit is contained in:
parent
ddcca79d25
commit
c81c958e98
|
@ -1736,7 +1736,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
if other.evaluation == EvaluatedToOk {
|
||||
if let ImplCandidate(victim_def) = victim.candidate {
|
||||
let tcx = self.tcx().global_tcx();
|
||||
return traits::specializes(tcx, other_def, victim_def);
|
||||
return traits::specializes(tcx, other_def, victim_def) ||
|
||||
tcx.impls_are_allowed_to_overlap(other_def, victim_def);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -155,11 +155,6 @@ pub fn specializes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
return r;
|
||||
}
|
||||
|
||||
if tcx.impl_always_allowed_to_overlap(impl1_def_id)
|
||||
&& tcx.impl_always_allowed_to_overlap(impl2_def_id) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// The feature gate should prevent introducing new specializations, but not
|
||||
// taking advantage of upstream ones.
|
||||
if !tcx.sess.features.borrow().specialization &&
|
||||
|
|
|
@ -113,9 +113,8 @@ impl<'a, 'gcx, 'tcx> Children {
|
|||
possible_sibling,
|
||||
impl_def_id);
|
||||
if let Some(impl_header) = overlap {
|
||||
if tcx.impl_always_allowed_to_overlap(impl_def_id)
|
||||
&& tcx.impl_always_allowed_to_overlap(possible_sibling) {
|
||||
return Ok((true, true));
|
||||
if tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling) {
|
||||
return Ok((false, false));
|
||||
}
|
||||
|
||||
let le = specializes(tcx, impl_def_id, possible_sibling);
|
||||
|
|
|
@ -2227,14 +2227,20 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
queries::impl_trait_ref::get(self, DUMMY_SP, id)
|
||||
}
|
||||
|
||||
/// Returns true if the impl is positive and is for a trait which contains
|
||||
/// no items
|
||||
pub fn impl_always_allowed_to_overlap(self, def_id: DefId) -> bool {
|
||||
self.trait_impl_polarity(def_id) == hir::ImplPolarity::Positive
|
||||
&& self.impl_trait_ref(def_id)
|
||||
.map_or(false, |trait_ref| {
|
||||
self.associated_item_def_ids(trait_ref.def_id).is_empty()
|
||||
})
|
||||
/// Returns true if the impls are the same polarity and are implementing
|
||||
/// a trait which contains no items
|
||||
pub fn impls_are_allowed_to_overlap(self, def_id1: DefId, def_id2: DefId) -> bool {
|
||||
let trait1_is_empty = self.impl_trait_ref(def_id1)
|
||||
.map_or(false, |trait_ref| {
|
||||
self.associated_item_def_ids(trait_ref.def_id).is_empty()
|
||||
});
|
||||
let trait2_is_empty = self.impl_trait_ref(def_id2)
|
||||
.map_or(false, |trait_ref| {
|
||||
self.associated_item_def_ids(trait_ref.def_id).is_empty()
|
||||
});
|
||||
self.trait_impl_polarity(def_id1) == self.trait_impl_polarity(def_id2)
|
||||
&& trait1_is_empty
|
||||
&& trait2_is_empty
|
||||
}
|
||||
|
||||
// Returns `ty::VariantDef` if `def` refers to a struct,
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
// except according to those terms.
|
||||
|
||||
pub trait Foo {
|
||||
fn foo() {}
|
||||
}
|
||||
|
||||
impl Foo for isize {
|
||||
|
|
Loading…
Reference in New Issue