Move overlap_mode into trait level attribute + feature flag
This commit is contained in:
parent
427eba2f0b
commit
a9bfb5d837
17 changed files with 121 additions and 75 deletions
|
@ -161,6 +161,9 @@ declare_features! (
|
||||||
(active, staged_api, "1.0.0", None, None),
|
(active, staged_api, "1.0.0", None, None),
|
||||||
/// Added for testing E0705; perma-unstable.
|
/// Added for testing E0705; perma-unstable.
|
||||||
(active, test_2018_feature, "1.31.0", None, Some(Edition::Edition2018)),
|
(active, test_2018_feature, "1.31.0", None, Some(Edition::Edition2018)),
|
||||||
|
/// Use for stable + negative coherence and strict coherence depending on trait's
|
||||||
|
/// rustc_strict_coherence value.
|
||||||
|
(active, with_negative_coherence, "1.60.0", None, None),
|
||||||
// !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!!
|
// !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!!
|
||||||
// Features are listed in alphabetical order. Tidy will fail if you don't keep it this way.
|
// Features are listed in alphabetical order. Tidy will fail if you don't keep it this way.
|
||||||
// !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!!
|
// !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!!
|
||||||
|
|
|
@ -697,7 +697,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
||||||
rustc_attr!(TEST, rustc_capture_analysis, Normal, template!(Word), WarnFollowing),
|
rustc_attr!(TEST, rustc_capture_analysis, Normal, template!(Word), WarnFollowing),
|
||||||
rustc_attr!(TEST, rustc_insignificant_dtor, Normal, template!(Word), WarnFollowing),
|
rustc_attr!(TEST, rustc_insignificant_dtor, Normal, template!(Word), WarnFollowing),
|
||||||
rustc_attr!(TEST, rustc_strict_coherence, Normal, template!(Word), WarnFollowing),
|
rustc_attr!(TEST, rustc_strict_coherence, Normal, template!(Word), WarnFollowing),
|
||||||
rustc_attr!(TEST, rustc_with_negative_coherence, Normal, template!(Word), WarnFollowing),
|
|
||||||
rustc_attr!(TEST, rustc_variance, Normal, template!(Word), WarnFollowing),
|
rustc_attr!(TEST, rustc_variance, Normal, template!(Word), WarnFollowing),
|
||||||
rustc_attr!(TEST, rustc_layout, Normal, template!(List: "field1, field2, ..."), WarnFollowing),
|
rustc_attr!(TEST, rustc_layout, Normal, template!(List: "field1, field2, ..."), WarnFollowing),
|
||||||
rustc_attr!(TEST, rustc_regions, Normal, template!(Word), WarnFollowing),
|
rustc_attr!(TEST, rustc_regions, Normal, template!(Word), WarnFollowing),
|
||||||
|
|
|
@ -4,6 +4,7 @@ use crate::ty::{self, TyCtxt};
|
||||||
use rustc_data_structures::fx::FxIndexMap;
|
use rustc_data_structures::fx::FxIndexMap;
|
||||||
use rustc_errors::ErrorReported;
|
use rustc_errors::ErrorReported;
|
||||||
use rustc_hir::def_id::{DefId, DefIdMap};
|
use rustc_hir::def_id::{DefId, DefIdMap};
|
||||||
|
use rustc_span::symbol::sym;
|
||||||
|
|
||||||
/// A per-trait graph of impls in specialization order. At the moment, this
|
/// A per-trait graph of impls in specialization order. At the moment, this
|
||||||
/// graph forms a tree rooted with the trait itself, with all other nodes
|
/// graph forms a tree rooted with the trait itself, with all other nodes
|
||||||
|
@ -31,11 +32,23 @@ pub struct Graph {
|
||||||
|
|
||||||
/// Whether an error was emitted while constructing the graph.
|
/// Whether an error was emitted while constructing the graph.
|
||||||
pub has_errored: bool,
|
pub has_errored: bool,
|
||||||
|
|
||||||
|
/// Overlap mode to be used
|
||||||
|
pub overlap_mode: OverlapMode,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Graph {
|
impl Graph {
|
||||||
pub fn new() -> Graph {
|
pub fn new() -> Graph {
|
||||||
Graph { parent: Default::default(), children: Default::default(), has_errored: false }
|
Graph {
|
||||||
|
parent: Default::default(),
|
||||||
|
children: Default::default(),
|
||||||
|
has_errored: false,
|
||||||
|
overlap_mode: OverlapMode::Stable,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_overlap_mode(&mut self, overlap_mode: OverlapMode) {
|
||||||
|
self.overlap_mode = overlap_mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The parent of a given impl, which is the `DefId` of the trait when the
|
/// The parent of a given impl, which is the `DefId` of the trait when the
|
||||||
|
@ -45,6 +58,41 @@ impl Graph {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// What kind of overlap check are we doing -- this exists just for testing and feature-gating
|
||||||
|
/// purposes.
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable, Debug, TyEncodable, TyDecodable)]
|
||||||
|
pub enum OverlapMode {
|
||||||
|
/// The 1.0 rules (either types fail to unify, or where clauses are not implemented for crate-local types)
|
||||||
|
Stable,
|
||||||
|
/// Feature-gated test: Stable, *or* there is an explicit negative impl that rules out one of the where-clauses.
|
||||||
|
WithNegative,
|
||||||
|
/// Just check for negative impls, not for "where clause not implemented": used for testing.
|
||||||
|
Strict,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OverlapMode {
|
||||||
|
pub fn get<'tcx>(tcx: TyCtxt<'tcx>, trait_id: DefId) -> OverlapMode {
|
||||||
|
let with_negative_coherence = tcx.features().with_negative_coherence;
|
||||||
|
let strict_coherence = tcx.has_attr(trait_id, sym::rustc_strict_coherence);
|
||||||
|
|
||||||
|
if with_negative_coherence {
|
||||||
|
if strict_coherence { OverlapMode::Strict } else { OverlapMode::WithNegative }
|
||||||
|
} else if strict_coherence {
|
||||||
|
bug!("To use strict_coherence you need to set with_negative_coherence feature flag");
|
||||||
|
} else {
|
||||||
|
OverlapMode::Stable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn use_negative_impl(&self) -> bool {
|
||||||
|
*self == OverlapMode::Strict || *self == OverlapMode::WithNegative
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn use_implicit_negative(&self) -> bool {
|
||||||
|
*self == OverlapMode::Stable || *self == OverlapMode::WithNegative
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Children of a given impl, grouped into blanket/non-blanket varieties as is
|
/// Children of a given impl, grouped into blanket/non-blanket varieties as is
|
||||||
/// done in `TraitDef`.
|
/// done in `TraitDef`.
|
||||||
#[derive(Default, TyEncodable, TyDecodable, Debug, HashStable)]
|
#[derive(Default, TyEncodable, TyDecodable, Debug, HashStable)]
|
||||||
|
|
|
@ -1205,7 +1205,6 @@ symbols! {
|
||||||
rustc_trivial_field_reads,
|
rustc_trivial_field_reads,
|
||||||
rustc_unsafe_specialization_marker,
|
rustc_unsafe_specialization_marker,
|
||||||
rustc_variance,
|
rustc_variance,
|
||||||
rustc_with_negative_coherence,
|
|
||||||
rustdoc,
|
rustdoc,
|
||||||
rustdoc_internals,
|
rustdoc_internals,
|
||||||
rustfmt,
|
rustfmt,
|
||||||
|
@ -1489,6 +1488,7 @@ symbols! {
|
||||||
width,
|
width,
|
||||||
windows,
|
windows,
|
||||||
windows_subsystem,
|
windows_subsystem,
|
||||||
|
with_negative_coherence,
|
||||||
wrapping_add,
|
wrapping_add,
|
||||||
wrapping_mul,
|
wrapping_mul,
|
||||||
wrapping_sub,
|
wrapping_sub,
|
||||||
|
|
|
@ -13,8 +13,8 @@ use crate::traits::{
|
||||||
self, FulfillmentContext, Normalized, Obligation, ObligationCause, PredicateObligation,
|
self, FulfillmentContext, Normalized, Obligation, ObligationCause, PredicateObligation,
|
||||||
PredicateObligations, SelectionContext,
|
PredicateObligations, SelectionContext,
|
||||||
};
|
};
|
||||||
use rustc_ast::Attribute;
|
|
||||||
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
|
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
|
||||||
|
use rustc_middle::traits::specialization_graph::OverlapMode;
|
||||||
use rustc_middle::ty::fast_reject::{self, SimplifyParams, StripReferences};
|
use rustc_middle::ty::fast_reject::{self, SimplifyParams, StripReferences};
|
||||||
use rustc_middle::ty::fold::TypeFoldable;
|
use rustc_middle::ty::fold::TypeFoldable;
|
||||||
use rustc_middle::ty::subst::Subst;
|
use rustc_middle::ty::subst::Subst;
|
||||||
|
@ -62,6 +62,7 @@ pub fn overlapping_impls<F1, F2, R>(
|
||||||
impl1_def_id: DefId,
|
impl1_def_id: DefId,
|
||||||
impl2_def_id: DefId,
|
impl2_def_id: DefId,
|
||||||
skip_leak_check: SkipLeakCheck,
|
skip_leak_check: SkipLeakCheck,
|
||||||
|
overlap_mode: OverlapMode,
|
||||||
on_overlap: F1,
|
on_overlap: F1,
|
||||||
no_overlap: F2,
|
no_overlap: F2,
|
||||||
) -> R
|
) -> R
|
||||||
|
@ -99,7 +100,7 @@ where
|
||||||
|
|
||||||
let overlaps = tcx.infer_ctxt().enter(|infcx| {
|
let overlaps = tcx.infer_ctxt().enter(|infcx| {
|
||||||
let selcx = &mut SelectionContext::intercrate(&infcx);
|
let selcx = &mut SelectionContext::intercrate(&infcx);
|
||||||
overlap(selcx, skip_leak_check, impl1_def_id, impl2_def_id).is_some()
|
overlap(selcx, skip_leak_check, impl1_def_id, impl2_def_id, overlap_mode).is_some()
|
||||||
});
|
});
|
||||||
|
|
||||||
if !overlaps {
|
if !overlaps {
|
||||||
|
@ -112,7 +113,9 @@ where
|
||||||
tcx.infer_ctxt().enter(|infcx| {
|
tcx.infer_ctxt().enter(|infcx| {
|
||||||
let selcx = &mut SelectionContext::intercrate(&infcx);
|
let selcx = &mut SelectionContext::intercrate(&infcx);
|
||||||
selcx.enable_tracking_intercrate_ambiguity_causes();
|
selcx.enable_tracking_intercrate_ambiguity_causes();
|
||||||
on_overlap(overlap(selcx, skip_leak_check, impl1_def_id, impl2_def_id).unwrap())
|
on_overlap(
|
||||||
|
overlap(selcx, skip_leak_check, impl1_def_id, impl2_def_id, overlap_mode).unwrap(),
|
||||||
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,56 +141,6 @@ fn with_fresh_ty_vars<'cx, 'tcx>(
|
||||||
header
|
header
|
||||||
}
|
}
|
||||||
|
|
||||||
/// What kind of overlap check are we doing -- this exists just for testing and feature-gating
|
|
||||||
/// purposes.
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
|
||||||
enum OverlapMode {
|
|
||||||
/// The 1.0 rules (either types fail to unify, or where clauses are not implemented for crate-local types)
|
|
||||||
Stable,
|
|
||||||
/// Feature-gated test: Stable, *or* there is an explicit negative impl that rules out one of the where-clauses.
|
|
||||||
WithNegative,
|
|
||||||
/// Just check for negative impls, not for "where clause not implemented": used for testing.
|
|
||||||
Strict,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl OverlapMode {
|
|
||||||
fn use_negative_impl(&self) -> bool {
|
|
||||||
*self == OverlapMode::Strict || *self == OverlapMode::WithNegative
|
|
||||||
}
|
|
||||||
|
|
||||||
fn use_implicit_negative(&self) -> bool {
|
|
||||||
*self == OverlapMode::Stable || *self == OverlapMode::WithNegative
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn overlap_mode<'tcx>(tcx: TyCtxt<'tcx>, impl1_def_id: DefId, impl2_def_id: DefId) -> OverlapMode {
|
|
||||||
// Find the possible coherence mode override opt-in attributes for each `DefId`
|
|
||||||
let find_coherence_attr = |attr: &Attribute| {
|
|
||||||
let name = attr.name_or_empty();
|
|
||||||
match name {
|
|
||||||
sym::rustc_with_negative_coherence | sym::rustc_strict_coherence => Some(name),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let impl1_coherence_mode = tcx.get_attrs(impl1_def_id).iter().find_map(find_coherence_attr);
|
|
||||||
let impl2_coherence_mode = tcx.get_attrs(impl2_def_id).iter().find_map(find_coherence_attr);
|
|
||||||
|
|
||||||
// If there are any (that currently happens in tests), they need to match. Otherwise, the
|
|
||||||
// default 1.0 rules are used.
|
|
||||||
match (impl1_coherence_mode, impl2_coherence_mode) {
|
|
||||||
(None, None) => OverlapMode::Stable,
|
|
||||||
(Some(sym::rustc_with_negative_coherence), Some(sym::rustc_with_negative_coherence)) => {
|
|
||||||
OverlapMode::WithNegative
|
|
||||||
}
|
|
||||||
(Some(sym::rustc_strict_coherence), Some(sym::rustc_strict_coherence)) => {
|
|
||||||
OverlapMode::Strict
|
|
||||||
}
|
|
||||||
(Some(mode), _) | (_, Some(mode)) => {
|
|
||||||
bug!("Use the same coherence mode on both impls: {}", mode)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Can both impl `a` and impl `b` be satisfied by a common type (including
|
/// Can both impl `a` and impl `b` be satisfied by a common type (including
|
||||||
/// where-clauses)? If so, returns an `ImplHeader` that unifies the two impls.
|
/// where-clauses)? If so, returns an `ImplHeader` that unifies the two impls.
|
||||||
fn overlap<'cx, 'tcx>(
|
fn overlap<'cx, 'tcx>(
|
||||||
|
@ -195,11 +148,19 @@ fn overlap<'cx, 'tcx>(
|
||||||
skip_leak_check: SkipLeakCheck,
|
skip_leak_check: SkipLeakCheck,
|
||||||
impl1_def_id: DefId,
|
impl1_def_id: DefId,
|
||||||
impl2_def_id: DefId,
|
impl2_def_id: DefId,
|
||||||
|
overlap_mode: OverlapMode,
|
||||||
) -> Option<OverlapResult<'tcx>> {
|
) -> Option<OverlapResult<'tcx>> {
|
||||||
debug!("overlap(impl1_def_id={:?}, impl2_def_id={:?})", impl1_def_id, impl2_def_id);
|
debug!("overlap(impl1_def_id={:?}, impl2_def_id={:?})", impl1_def_id, impl2_def_id);
|
||||||
|
|
||||||
selcx.infcx().probe_maybe_skip_leak_check(skip_leak_check.is_yes(), |snapshot| {
|
selcx.infcx().probe_maybe_skip_leak_check(skip_leak_check.is_yes(), |snapshot| {
|
||||||
overlap_within_probe(selcx, skip_leak_check, impl1_def_id, impl2_def_id, snapshot)
|
overlap_within_probe(
|
||||||
|
selcx,
|
||||||
|
skip_leak_check,
|
||||||
|
impl1_def_id,
|
||||||
|
impl2_def_id,
|
||||||
|
overlap_mode,
|
||||||
|
snapshot,
|
||||||
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,12 +169,10 @@ fn overlap_within_probe<'cx, 'tcx>(
|
||||||
skip_leak_check: SkipLeakCheck,
|
skip_leak_check: SkipLeakCheck,
|
||||||
impl1_def_id: DefId,
|
impl1_def_id: DefId,
|
||||||
impl2_def_id: DefId,
|
impl2_def_id: DefId,
|
||||||
|
overlap_mode: OverlapMode,
|
||||||
snapshot: &CombinedSnapshot<'_, 'tcx>,
|
snapshot: &CombinedSnapshot<'_, 'tcx>,
|
||||||
) -> Option<OverlapResult<'tcx>> {
|
) -> Option<OverlapResult<'tcx>> {
|
||||||
let infcx = selcx.infcx();
|
let infcx = selcx.infcx();
|
||||||
let tcx = infcx.tcx;
|
|
||||||
|
|
||||||
let overlap_mode = overlap_mode(tcx, impl1_def_id, impl2_def_id);
|
|
||||||
|
|
||||||
if overlap_mode.use_negative_impl() {
|
if overlap_mode.use_negative_impl() {
|
||||||
if negative_impl(selcx, impl1_def_id, impl2_def_id)
|
if negative_impl(selcx, impl1_def_id, impl2_def_id)
|
||||||
|
|
|
@ -257,6 +257,7 @@ pub(super) fn specialization_graph_provider(
|
||||||
trait_id: DefId,
|
trait_id: DefId,
|
||||||
) -> specialization_graph::Graph {
|
) -> specialization_graph::Graph {
|
||||||
let mut sg = specialization_graph::Graph::new();
|
let mut sg = specialization_graph::Graph::new();
|
||||||
|
sg.set_overlap_mode(specialization_graph::OverlapMode::get(tcx, trait_id));
|
||||||
|
|
||||||
let mut trait_impls: Vec<_> = tcx.all_impls(trait_id).collect();
|
let mut trait_impls: Vec<_> = tcx.all_impls(trait_id).collect();
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,7 @@ trait ChildrenExt<'tcx> {
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
impl_def_id: DefId,
|
impl_def_id: DefId,
|
||||||
simplified_self: Option<SimplifiedType>,
|
simplified_self: Option<SimplifiedType>,
|
||||||
|
overlap_mode: OverlapMode,
|
||||||
) -> Result<Inserted, OverlapError>;
|
) -> Result<Inserted, OverlapError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,6 +93,7 @@ impl ChildrenExt<'_> for Children {
|
||||||
tcx: TyCtxt<'_>,
|
tcx: TyCtxt<'_>,
|
||||||
impl_def_id: DefId,
|
impl_def_id: DefId,
|
||||||
simplified_self: Option<SimplifiedType>,
|
simplified_self: Option<SimplifiedType>,
|
||||||
|
overlap_mode: OverlapMode,
|
||||||
) -> Result<Inserted, OverlapError> {
|
) -> Result<Inserted, OverlapError> {
|
||||||
let mut last_lint = None;
|
let mut last_lint = None;
|
||||||
let mut replace_children = Vec::new();
|
let mut replace_children = Vec::new();
|
||||||
|
@ -142,6 +144,7 @@ impl ChildrenExt<'_> for Children {
|
||||||
possible_sibling,
|
possible_sibling,
|
||||||
impl_def_id,
|
impl_def_id,
|
||||||
traits::SkipLeakCheck::default(),
|
traits::SkipLeakCheck::default(),
|
||||||
|
overlap_mode,
|
||||||
|_| true,
|
|_| true,
|
||||||
|| false,
|
|| false,
|
||||||
);
|
);
|
||||||
|
@ -166,6 +169,7 @@ impl ChildrenExt<'_> for Children {
|
||||||
possible_sibling,
|
possible_sibling,
|
||||||
impl_def_id,
|
impl_def_id,
|
||||||
traits::SkipLeakCheck::Yes,
|
traits::SkipLeakCheck::Yes,
|
||||||
|
overlap_mode,
|
||||||
|overlap| {
|
|overlap| {
|
||||||
if let Some(overlap_kind) =
|
if let Some(overlap_kind) =
|
||||||
tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling)
|
tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling)
|
||||||
|
@ -327,8 +331,12 @@ impl GraphExt for Graph {
|
||||||
loop {
|
loop {
|
||||||
use self::Inserted::*;
|
use self::Inserted::*;
|
||||||
|
|
||||||
let insert_result =
|
let insert_result = self.children.entry(parent).or_default().insert(
|
||||||
self.children.entry(parent).or_default().insert(tcx, impl_def_id, simplified)?;
|
tcx,
|
||||||
|
impl_def_id,
|
||||||
|
simplified,
|
||||||
|
self.overlap_mode,
|
||||||
|
)?;
|
||||||
|
|
||||||
match insert_result {
|
match insert_result {
|
||||||
BecameNewSibling(opt_lint) => {
|
BecameNewSibling(opt_lint) => {
|
||||||
|
|
|
@ -4,6 +4,7 @@ use rustc_hir as hir;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_hir::itemlikevisit::ItemLikeVisitor;
|
use rustc_hir::itemlikevisit::ItemLikeVisitor;
|
||||||
use rustc_index::vec::IndexVec;
|
use rustc_index::vec::IndexVec;
|
||||||
|
use rustc_middle::traits::specialization_graph::OverlapMode;
|
||||||
use rustc_middle::ty::{self, TyCtxt};
|
use rustc_middle::ty::{self, TyCtxt};
|
||||||
use rustc_span::Symbol;
|
use rustc_span::Symbol;
|
||||||
use rustc_trait_selection::traits::{self, SkipLeakCheck};
|
use rustc_trait_selection::traits::{self, SkipLeakCheck};
|
||||||
|
@ -99,7 +100,12 @@ impl<'tcx> InherentOverlapChecker<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_for_overlapping_inherent_impls(&self, impl1_def_id: DefId, impl2_def_id: DefId) {
|
fn check_for_overlapping_inherent_impls(
|
||||||
|
&self,
|
||||||
|
overlap_mode: OverlapMode,
|
||||||
|
impl1_def_id: DefId,
|
||||||
|
impl2_def_id: DefId,
|
||||||
|
) {
|
||||||
traits::overlapping_impls(
|
traits::overlapping_impls(
|
||||||
self.tcx,
|
self.tcx,
|
||||||
impl1_def_id,
|
impl1_def_id,
|
||||||
|
@ -107,6 +113,7 @@ impl<'tcx> InherentOverlapChecker<'tcx> {
|
||||||
// We go ahead and just skip the leak check for
|
// We go ahead and just skip the leak check for
|
||||||
// inherent impls without warning.
|
// inherent impls without warning.
|
||||||
SkipLeakCheck::Yes,
|
SkipLeakCheck::Yes,
|
||||||
|
overlap_mode,
|
||||||
|overlap| {
|
|overlap| {
|
||||||
self.check_for_common_items_in_impls(impl1_def_id, impl2_def_id, overlap);
|
self.check_for_common_items_in_impls(impl1_def_id, impl2_def_id, overlap);
|
||||||
false
|
false
|
||||||
|
@ -131,6 +138,8 @@ impl<'tcx> ItemLikeVisitor<'_> for InherentOverlapChecker<'tcx> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let overlap_mode = OverlapMode::get(self.tcx, item.def_id.to_def_id());
|
||||||
|
|
||||||
let impls_items = impls
|
let impls_items = impls
|
||||||
.iter()
|
.iter()
|
||||||
.map(|impl_def_id| (impl_def_id, self.tcx.associated_items(*impl_def_id)))
|
.map(|impl_def_id| (impl_def_id, self.tcx.associated_items(*impl_def_id)))
|
||||||
|
@ -145,6 +154,7 @@ impl<'tcx> ItemLikeVisitor<'_> for InherentOverlapChecker<'tcx> {
|
||||||
for &(&impl2_def_id, impl_items2) in &impls_items[(i + 1)..] {
|
for &(&impl2_def_id, impl_items2) in &impls_items[(i + 1)..] {
|
||||||
if self.impls_have_common_items(impl_items1, impl_items2) {
|
if self.impls_have_common_items(impl_items1, impl_items2) {
|
||||||
self.check_for_overlapping_inherent_impls(
|
self.check_for_overlapping_inherent_impls(
|
||||||
|
overlap_mode,
|
||||||
impl1_def_id,
|
impl1_def_id,
|
||||||
impl2_def_id,
|
impl2_def_id,
|
||||||
);
|
);
|
||||||
|
@ -288,6 +298,7 @@ impl<'tcx> ItemLikeVisitor<'_> for InherentOverlapChecker<'tcx> {
|
||||||
let &(&impl2_def_id, impl_items2) = &impls_items[impl2_items_idx];
|
let &(&impl2_def_id, impl_items2) = &impls_items[impl2_items_idx];
|
||||||
if self.impls_have_common_items(impl_items1, impl_items2) {
|
if self.impls_have_common_items(impl_items1, impl_items2) {
|
||||||
self.check_for_overlapping_inherent_impls(
|
self.check_for_overlapping_inherent_impls(
|
||||||
|
overlap_mode,
|
||||||
impl1_def_id,
|
impl1_def_id,
|
||||||
impl2_def_id,
|
impl2_def_id,
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#![crate_type = "lib"]
|
#![crate_type = "lib"]
|
||||||
#![feature(negative_impls)]
|
#![feature(negative_impls)]
|
||||||
#![feature(rustc_attrs)]
|
#![feature(rustc_attrs)]
|
||||||
|
#![feature(with_negative_coherence)]
|
||||||
|
|
||||||
pub trait Future {}
|
pub trait Future {}
|
||||||
|
|
||||||
#[rustc_with_negative_coherence]
|
|
||||||
impl<E> !Future for Option<E> where E: Sized {}
|
impl<E> !Future for Option<E> where E: Sized {}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#![feature(negative_impls)]
|
#![feature(negative_impls)]
|
||||||
#![feature(rustc_attrs)]
|
#![feature(rustc_attrs)]
|
||||||
#![feature(trait_alias)]
|
#![feature(trait_alias)]
|
||||||
|
#![feature(with_negative_coherence)]
|
||||||
|
|
||||||
trait A {}
|
trait A {}
|
||||||
trait B {}
|
trait B {}
|
||||||
|
@ -8,10 +9,9 @@ trait AB = A + B;
|
||||||
|
|
||||||
impl !A for u32 {}
|
impl !A for u32 {}
|
||||||
|
|
||||||
|
#[rustc_strict_coherence]
|
||||||
trait C {}
|
trait C {}
|
||||||
#[rustc_strict_coherence]
|
|
||||||
impl<T: AB> C for T {}
|
impl<T: AB> C for T {}
|
||||||
#[rustc_strict_coherence]
|
|
||||||
impl C for u32 {}
|
impl C for u32 {}
|
||||||
//~^ ERROR: conflicting implementations of trait `C` for type `u32` [E0119]
|
//~^ ERROR: conflicting implementations of trait `C` for type `u32` [E0119]
|
||||||
// FIXME this should work, we should implement an `assemble_neg_candidates` fn
|
// FIXME this should work, we should implement an `assemble_neg_candidates` fn
|
||||||
|
|
|
@ -3,7 +3,6 @@ error[E0119]: conflicting implementations of trait `C` for type `u32`
|
||||||
|
|
|
|
||||||
LL | impl<T: AB> C for T {}
|
LL | impl<T: AB> C for T {}
|
||||||
| ------------------- first implementation here
|
| ------------------- first implementation here
|
||||||
LL | #[rustc_strict_coherence]
|
|
||||||
LL | impl C for u32 {}
|
LL | impl C for u32 {}
|
||||||
| ^^^^^^^^^^^^^^ conflicting implementation for `u32`
|
| ^^^^^^^^^^^^^^ conflicting implementation for `u32`
|
||||||
|
|
||||||
|
|
|
@ -3,16 +3,16 @@
|
||||||
#![feature(negative_impls)]
|
#![feature(negative_impls)]
|
||||||
#![feature(rustc_attrs)]
|
#![feature(rustc_attrs)]
|
||||||
#![feature(trait_alias)]
|
#![feature(trait_alias)]
|
||||||
|
#![feature(with_negative_coherence)]
|
||||||
|
|
||||||
trait A {}
|
trait A {}
|
||||||
trait B {}
|
trait B {}
|
||||||
|
|
||||||
impl !A for u32 {}
|
impl !A for u32 {}
|
||||||
|
|
||||||
|
#[rustc_strict_coherence]
|
||||||
trait C {}
|
trait C {}
|
||||||
#[rustc_strict_coherence]
|
|
||||||
impl<T: A + B> C for T {}
|
impl<T: A + B> C for T {}
|
||||||
#[rustc_strict_coherence]
|
|
||||||
impl C for u32 {}
|
impl C for u32 {}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -4,15 +4,14 @@
|
||||||
// Check that if we promise to not impl what would overlap it doesn't actually overlap
|
// Check that if we promise to not impl what would overlap it doesn't actually overlap
|
||||||
|
|
||||||
#![feature(rustc_attrs)]
|
#![feature(rustc_attrs)]
|
||||||
|
#![feature(with_negative_coherence)]
|
||||||
|
|
||||||
extern crate option_future as lib;
|
extern crate option_future as lib;
|
||||||
use lib::Future;
|
use lib::Future;
|
||||||
|
|
||||||
trait Termination {}
|
trait Termination {}
|
||||||
|
|
||||||
#[rustc_with_negative_coherence]
|
|
||||||
impl<E> Termination for Option<E> where E: Sized {}
|
impl<E> Termination for Option<E> where E: Sized {}
|
||||||
#[rustc_with_negative_coherence]
|
|
||||||
impl<F> Termination for F where F: Future + Sized {}
|
impl<F> Termination for F where F: Future + Sized {}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#![feature(rustc_attrs)]
|
#![feature(rustc_attrs)]
|
||||||
#![feature(trait_alias)]
|
#![feature(trait_alias)]
|
||||||
|
#![feature(with_negative_coherence)]
|
||||||
|
|
||||||
trait A {}
|
trait A {}
|
||||||
trait B {}
|
trait B {}
|
||||||
|
@ -8,10 +9,9 @@ trait AB = A + B;
|
||||||
impl A for u32 {}
|
impl A for u32 {}
|
||||||
impl B for u32 {}
|
impl B for u32 {}
|
||||||
|
|
||||||
|
#[rustc_strict_coherence]
|
||||||
trait C {}
|
trait C {}
|
||||||
#[rustc_strict_coherence]
|
|
||||||
impl<T: AB> C for T {}
|
impl<T: AB> C for T {}
|
||||||
#[rustc_strict_coherence]
|
|
||||||
impl C for u32 {}
|
impl C for u32 {}
|
||||||
//~^ ERROR
|
//~^ ERROR
|
||||||
// FIXME it's giving an ungreat error but unsure if we care given that it's using an internal rustc
|
// FIXME it's giving an ungreat error but unsure if we care given that it's using an internal rustc
|
||||||
|
|
|
@ -5,11 +5,10 @@ LL | impl C for u32 {}
|
||||||
| ^ cannot infer type for type `u32`
|
| ^ cannot infer type for type `u32`
|
||||||
|
|
|
|
||||||
note: multiple `impl`s satisfying `u32: C` found
|
note: multiple `impl`s satisfying `u32: C` found
|
||||||
--> $DIR/coherence-overlap-trait-alias.rs:13:1
|
--> $DIR/coherence-overlap-trait-alias.rs:14:1
|
||||||
|
|
|
|
||||||
LL | impl<T: AB> C for T {}
|
LL | impl<T: AB> C for T {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^
|
||||||
LL | #[rustc_strict_coherence]
|
|
||||||
LL | impl C for u32 {}
|
LL | impl C for u32 {}
|
||||||
| ^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
trait Foo { }
|
||||||
|
|
||||||
|
impl<T: std::ops::DerefMut> Foo for T { }
|
||||||
|
|
||||||
|
impl<T> Foo for &T { }
|
||||||
|
//~^ ERROR conflicting implementations of trait `Foo` for type `&_` [E0119]
|
||||||
|
|
||||||
|
fn main() { }
|
|
@ -0,0 +1,12 @@
|
||||||
|
error[E0119]: conflicting implementations of trait `Foo` for type `&_`
|
||||||
|
--> $DIR/feature-gate-with_negative_coherence.rs:5:1
|
||||||
|
|
|
||||||
|
LL | impl<T: std::ops::DerefMut> Foo for T { }
|
||||||
|
| ------------------------------------- first implementation here
|
||||||
|
LL |
|
||||||
|
LL | impl<T> Foo for &T { }
|
||||||
|
| ^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_`
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0119`.
|
Loading…
Add table
Add a link
Reference in a new issue