mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
Make inductive cycles in coherence ambiguous always
This commit is contained in:
parent
0ee9cfd54d
commit
8abf133c4b
@ -513,6 +513,11 @@ fn register_builtins(store: &mut LintStore) {
|
|||||||
"converted into hard error, see PR #117984 \
|
"converted into hard error, see PR #117984 \
|
||||||
<https://github.com/rust-lang/rust/pull/117984> for more information",
|
<https://github.com/rust-lang/rust/pull/117984> for more information",
|
||||||
);
|
);
|
||||||
|
store.register_removed(
|
||||||
|
"coinductive_overlap_in_coherence",
|
||||||
|
"converted into hard error, see PR #118649 \
|
||||||
|
<https://github.com/rust-lang/rust/pull/118649> for more information",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn register_internals(store: &mut LintStore) {
|
fn register_internals(store: &mut LintStore) {
|
||||||
|
@ -26,7 +26,6 @@ declare_lint_pass! {
|
|||||||
BYTE_SLICE_IN_PACKED_STRUCT_WITH_DERIVE,
|
BYTE_SLICE_IN_PACKED_STRUCT_WITH_DERIVE,
|
||||||
CENUM_IMPL_DROP_CAST,
|
CENUM_IMPL_DROP_CAST,
|
||||||
COHERENCE_LEAK_CHECK,
|
COHERENCE_LEAK_CHECK,
|
||||||
COINDUCTIVE_OVERLAP_IN_COHERENCE,
|
|
||||||
CONFLICTING_REPR_HINTS,
|
CONFLICTING_REPR_HINTS,
|
||||||
CONST_EVALUATABLE_UNCHECKED,
|
CONST_EVALUATABLE_UNCHECKED,
|
||||||
CONST_ITEM_MUTATION,
|
CONST_ITEM_MUTATION,
|
||||||
@ -4367,45 +4366,6 @@ declare_lint! {
|
|||||||
@feature_gate = sym::type_privacy_lints;
|
@feature_gate = sym::type_privacy_lints;
|
||||||
}
|
}
|
||||||
|
|
||||||
declare_lint! {
|
|
||||||
/// The `coinductive_overlap_in_coherence` lint detects impls which are currently
|
|
||||||
/// considered not overlapping, but may be considered to overlap if support for
|
|
||||||
/// coinduction is added to the trait solver.
|
|
||||||
///
|
|
||||||
/// ### Example
|
|
||||||
///
|
|
||||||
/// ```rust,compile_fail
|
|
||||||
/// #![deny(coinductive_overlap_in_coherence)]
|
|
||||||
///
|
|
||||||
/// trait CyclicTrait {}
|
|
||||||
/// impl<T: CyclicTrait> CyclicTrait for T {}
|
|
||||||
///
|
|
||||||
/// trait Trait {}
|
|
||||||
/// impl<T: CyclicTrait> Trait for T {}
|
|
||||||
/// // conflicting impl with the above
|
|
||||||
/// impl Trait for u8 {}
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// {{produces}}
|
|
||||||
///
|
|
||||||
/// ### Explanation
|
|
||||||
///
|
|
||||||
/// We have two choices for impl which satisfy `u8: Trait`: the blanket impl
|
|
||||||
/// for generic `T`, and the direct impl for `u8`. These two impls nominally
|
|
||||||
/// overlap, since we can infer `T = u8` in the former impl, but since the where
|
|
||||||
/// clause `u8: CyclicTrait` would end up resulting in a cycle (since it depends
|
|
||||||
/// on itself), the blanket impl is not considered to hold for `u8`. This will
|
|
||||||
/// change in a future release.
|
|
||||||
pub COINDUCTIVE_OVERLAP_IN_COHERENCE,
|
|
||||||
Deny,
|
|
||||||
"impls that are not considered to overlap may be considered to \
|
|
||||||
overlap in the future",
|
|
||||||
@future_incompatible = FutureIncompatibleInfo {
|
|
||||||
reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
|
|
||||||
reference: "issue #114040 <https://github.com/rust-lang/rust/issues/114040>",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
declare_lint! {
|
declare_lint! {
|
||||||
/// The `unknown_or_malformed_diagnostic_attributes` lint detects unrecognized or otherwise malformed
|
/// The `unknown_or_malformed_diagnostic_attributes` lint detects unrecognized or otherwise malformed
|
||||||
/// diagnostic attributes.
|
/// diagnostic attributes.
|
||||||
|
@ -10,7 +10,7 @@ use crate::solve::inspect::{InspectGoal, ProofTreeInferCtxtExt, ProofTreeVisitor
|
|||||||
use crate::solve::{deeply_normalize_for_diagnostics, inspect};
|
use crate::solve::{deeply_normalize_for_diagnostics, inspect};
|
||||||
use crate::traits::engine::TraitEngineExt;
|
use crate::traits::engine::TraitEngineExt;
|
||||||
use crate::traits::query::evaluate_obligation::InferCtxtExt;
|
use crate::traits::query::evaluate_obligation::InferCtxtExt;
|
||||||
use crate::traits::select::{IntercrateAmbiguityCause, TreatInductiveCycleAs};
|
use crate::traits::select::IntercrateAmbiguityCause;
|
||||||
use crate::traits::structural_normalize::StructurallyNormalizeExt;
|
use crate::traits::structural_normalize::StructurallyNormalizeExt;
|
||||||
use crate::traits::NormalizeExt;
|
use crate::traits::NormalizeExt;
|
||||||
use crate::traits::SkipLeakCheck;
|
use crate::traits::SkipLeakCheck;
|
||||||
@ -31,7 +31,6 @@ use rustc_middle::traits::DefiningAnchor;
|
|||||||
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
|
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
|
||||||
use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt};
|
use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt};
|
||||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor};
|
use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor};
|
||||||
use rustc_session::lint::builtin::COINDUCTIVE_OVERLAP_IN_COHERENCE;
|
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
use rustc_span::DUMMY_SP;
|
use rustc_span::DUMMY_SP;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
@ -197,7 +196,7 @@ fn overlap<'tcx>(
|
|||||||
.intercrate(true)
|
.intercrate(true)
|
||||||
.with_next_trait_solver(tcx.next_trait_solver_in_coherence())
|
.with_next_trait_solver(tcx.next_trait_solver_in_coherence())
|
||||||
.build();
|
.build();
|
||||||
let selcx = &mut SelectionContext::new(&infcx);
|
let selcx = &mut SelectionContext::with_treat_inductive_cycle_as_ambig(&infcx);
|
||||||
if track_ambiguity_causes.is_yes() {
|
if track_ambiguity_causes.is_yes() {
|
||||||
selcx.enable_tracking_intercrate_ambiguity_causes();
|
selcx.enable_tracking_intercrate_ambiguity_causes();
|
||||||
}
|
}
|
||||||
@ -224,61 +223,10 @@ fn overlap<'tcx>(
|
|||||||
);
|
);
|
||||||
|
|
||||||
if overlap_mode.use_implicit_negative() {
|
if overlap_mode.use_implicit_negative() {
|
||||||
for mode in [TreatInductiveCycleAs::Ambig, TreatInductiveCycleAs::Recur] {
|
if let Some(_failing_obligation) =
|
||||||
if let Some(failing_obligation) = selcx.with_treat_inductive_cycle_as(mode, |selcx| {
|
impl_intersection_has_impossible_obligation(selcx, &obligations)
|
||||||
impl_intersection_has_impossible_obligation(selcx, &obligations)
|
{
|
||||||
}) {
|
return None;
|
||||||
if matches!(mode, TreatInductiveCycleAs::Recur) {
|
|
||||||
let first_local_impl = impl1_header
|
|
||||||
.impl_def_id
|
|
||||||
.as_local()
|
|
||||||
.or(impl2_header.impl_def_id.as_local())
|
|
||||||
.expect("expected one of the impls to be local");
|
|
||||||
infcx.tcx.struct_span_lint_hir(
|
|
||||||
COINDUCTIVE_OVERLAP_IN_COHERENCE,
|
|
||||||
infcx.tcx.local_def_id_to_hir_id(first_local_impl),
|
|
||||||
infcx.tcx.def_span(first_local_impl),
|
|
||||||
format!(
|
|
||||||
"implementations {} will conflict in the future",
|
|
||||||
match impl1_header.trait_ref {
|
|
||||||
Some(trait_ref) => {
|
|
||||||
let trait_ref = infcx.resolve_vars_if_possible(trait_ref);
|
|
||||||
format!(
|
|
||||||
"of `{}` for `{}`",
|
|
||||||
trait_ref.print_trait_sugared(),
|
|
||||||
trait_ref.self_ty()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
None => format!(
|
|
||||||
"for `{}`",
|
|
||||||
infcx.resolve_vars_if_possible(impl1_header.self_ty)
|
|
||||||
),
|
|
||||||
},
|
|
||||||
),
|
|
||||||
|lint| {
|
|
||||||
lint.note(
|
|
||||||
"impls that are not considered to overlap may be considered to \
|
|
||||||
overlap in the future",
|
|
||||||
)
|
|
||||||
.span_label(
|
|
||||||
infcx.tcx.def_span(impl1_header.impl_def_id),
|
|
||||||
"the first impl is here",
|
|
||||||
)
|
|
||||||
.span_label(
|
|
||||||
infcx.tcx.def_span(impl2_header.impl_def_id),
|
|
||||||
"the second impl is here",
|
|
||||||
);
|
|
||||||
lint.note(format!(
|
|
||||||
"`{}` may be considered to hold in future releases, \
|
|
||||||
causing the impls to overlap",
|
|
||||||
infcx.resolve_vars_if_possible(failing_obligation.predicate)
|
|
||||||
));
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -239,20 +239,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets the `TreatInductiveCycleAs` mode temporarily in the selection context
|
pub fn with_treat_inductive_cycle_as_ambig(
|
||||||
pub fn with_treat_inductive_cycle_as<T>(
|
infcx: &'cx InferCtxt<'tcx>,
|
||||||
&mut self,
|
) -> SelectionContext<'cx, 'tcx> {
|
||||||
treat_inductive_cycle: TreatInductiveCycleAs,
|
|
||||||
f: impl FnOnce(&mut Self) -> T,
|
|
||||||
) -> T {
|
|
||||||
// Should be executed in a context where caching is disabled,
|
// Should be executed in a context where caching is disabled,
|
||||||
// otherwise the cache is poisoned with the temporary result.
|
// otherwise the cache is poisoned with the temporary result.
|
||||||
assert!(self.is_intercrate());
|
assert!(infcx.intercrate);
|
||||||
let treat_inductive_cycle =
|
SelectionContext {
|
||||||
std::mem::replace(&mut self.treat_inductive_cycle, treat_inductive_cycle);
|
treat_inductive_cycle: TreatInductiveCycleAs::Ambig,
|
||||||
let value = f(self);
|
..SelectionContext::new(infcx)
|
||||||
self.treat_inductive_cycle = treat_inductive_cycle;
|
}
|
||||||
value
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_query_mode(
|
pub fn with_query_mode(
|
||||||
|
@ -1,18 +1,15 @@
|
|||||||
#![deny(coinductive_overlap_in_coherence)]
|
|
||||||
|
|
||||||
use std::borrow::Borrow;
|
use std::borrow::Borrow;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
#[derive(PartialEq, Default)]
|
#[derive(PartialEq, Default)]
|
||||||
|
//~^ ERROR conflicting implementations of trait `PartialEq<Interval<_>>` for type `Interval<_>`
|
||||||
pub(crate) struct Interval<T>(PhantomData<T>);
|
pub(crate) struct Interval<T>(PhantomData<T>);
|
||||||
|
|
||||||
// This impl overlaps with the `derive` unless we reject the nested
|
// This impl overlaps with the `derive` unless we reject the nested
|
||||||
// `Interval<?1>: PartialOrd<Interval<?1>>` candidate which results
|
// `Interval<?1>: PartialOrd<Interval<?1>>` candidate which results
|
||||||
// in a - currently inductive - cycle.
|
// in a -- currently inductive -- cycle.
|
||||||
impl<T, Q> PartialEq<Q> for Interval<T>
|
impl<T, Q> PartialEq<Q> for Interval<T>
|
||||||
//~^ ERROR implementations of `PartialEq<Interval<_>>` for `Interval<_>` will conflict in the future
|
|
||||||
//~| WARN this was previously accepted by the compiler but is being phased out
|
|
||||||
where
|
where
|
||||||
T: Borrow<Q>,
|
T: Borrow<Q>,
|
||||||
Q: ?Sized + PartialOrd,
|
Q: ?Sized + PartialOrd,
|
||||||
|
@ -1,51 +1,17 @@
|
|||||||
error: implementations of `PartialEq<Interval<_>>` for `Interval<_>` will conflict in the future
|
error[E0119]: conflicting implementations of trait `PartialEq<Interval<_>>` for type `Interval<_>`
|
||||||
--> $DIR/warn-when-cycle-is-error-in-coherence.rs:13:1
|
--> $DIR/warn-when-cycle-is-error-in-coherence.rs:5:10
|
||||||
|
|
|
|
||||||
LL | #[derive(PartialEq, Default)]
|
LL | #[derive(PartialEq, Default)]
|
||||||
| --------- the second impl is here
|
| ^^^^^^^^^ conflicting implementation for `Interval<_>`
|
||||||
...
|
...
|
||||||
LL | / impl<T, Q> PartialEq<Q> for Interval<T>
|
LL | / impl<T, Q> PartialEq<Q> for Interval<T>
|
||||||
LL | |
|
|
||||||
LL | |
|
|
||||||
LL | | where
|
LL | | where
|
||||||
LL | | T: Borrow<Q>,
|
LL | | T: Borrow<Q>,
|
||||||
LL | | Q: ?Sized + PartialOrd,
|
LL | | Q: ?Sized + PartialOrd,
|
||||||
| |___________________________^ the first impl is here
|
| |___________________________- first implementation here
|
||||||
|
|
|
|
||||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
= note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
= note: for more information, see issue #114040 <https://github.com/rust-lang/rust/issues/114040>
|
|
||||||
= note: impls that are not considered to overlap may be considered to overlap in the future
|
|
||||||
= note: `Interval<_>: PartialOrd` may be considered to hold in future releases, causing the impls to overlap
|
|
||||||
note: the lint level is defined here
|
|
||||||
--> $DIR/warn-when-cycle-is-error-in-coherence.rs:1:9
|
|
||||||
|
|
|
||||||
LL | #![deny(coinductive_overlap_in_coherence)]
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
Future incompatibility report: Future breakage diagnostic:
|
For more information about this error, try `rustc --explain E0119`.
|
||||||
error: implementations of `PartialEq<Interval<_>>` for `Interval<_>` will conflict in the future
|
|
||||||
--> $DIR/warn-when-cycle-is-error-in-coherence.rs:13:1
|
|
||||||
|
|
|
||||||
LL | #[derive(PartialEq, Default)]
|
|
||||||
| --------- the second impl is here
|
|
||||||
...
|
|
||||||
LL | / impl<T, Q> PartialEq<Q> for Interval<T>
|
|
||||||
LL | |
|
|
||||||
LL | |
|
|
||||||
LL | | where
|
|
||||||
LL | | T: Borrow<Q>,
|
|
||||||
LL | | Q: ?Sized + PartialOrd,
|
|
||||||
| |___________________________^ the first impl is here
|
|
||||||
|
|
|
||||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
|
||||||
= note: for more information, see issue #114040 <https://github.com/rust-lang/rust/issues/114040>
|
|
||||||
= note: impls that are not considered to overlap may be considered to overlap in the future
|
|
||||||
= note: `Interval<_>: PartialOrd` may be considered to hold in future releases, causing the impls to overlap
|
|
||||||
note: the lint level is defined here
|
|
||||||
--> $DIR/warn-when-cycle-is-error-in-coherence.rs:1:9
|
|
||||||
|
|
|
||||||
LL | #![deny(coinductive_overlap_in_coherence)]
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user