Skip to content

Commit 7a4f862

Browse files
Make inductive cycles in coherence ambiguous always
1 parent 8a7b203 commit 7a4f862

File tree

6 files changed

+27
-156
lines changed

6 files changed

+27
-156
lines changed

compiler/rustc_lint/src/lib.rs

+5
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,11 @@ fn register_builtins(store: &mut LintStore) {
512512
"converted into hard error, see PR #104616 \
513513
<https://github.com/rust-lang/rust/pull/104616> for more information",
514514
);
515+
store.register_removed(
516+
"coinductive_overlap_in_coherence",
517+
"converted into hard error, see PR #118649 \
518+
<https://github.com/rust-lang/rust/pull/118649> for more information",
519+
);
515520
}
516521

517522
fn register_internals(store: &mut LintStore) {

compiler/rustc_lint_defs/src/builtin.rs

-40
Original file line numberDiff line numberDiff line change
@@ -3366,7 +3366,6 @@ declare_lint_pass! {
33663366
BYTE_SLICE_IN_PACKED_STRUCT_WITH_DERIVE,
33673367
CENUM_IMPL_DROP_CAST,
33683368
COHERENCE_LEAK_CHECK,
3369-
COINDUCTIVE_OVERLAP_IN_COHERENCE,
33703369
CONFLICTING_REPR_HINTS,
33713370
CONST_EVALUATABLE_UNCHECKED,
33723371
CONST_ITEM_MUTATION,
@@ -4429,45 +4428,6 @@ declare_lint! {
44294428
@feature_gate = sym::type_privacy_lints;
44304429
}
44314430

4432-
declare_lint! {
4433-
/// The `coinductive_overlap_in_coherence` lint detects impls which are currently
4434-
/// considered not overlapping, but may be considered to overlap if support for
4435-
/// coinduction is added to the trait solver.
4436-
///
4437-
/// ### Example
4438-
///
4439-
/// ```rust,compile_fail
4440-
/// #![deny(coinductive_overlap_in_coherence)]
4441-
///
4442-
/// trait CyclicTrait {}
4443-
/// impl<T: CyclicTrait> CyclicTrait for T {}
4444-
///
4445-
/// trait Trait {}
4446-
/// impl<T: CyclicTrait> Trait for T {}
4447-
/// // conflicting impl with the above
4448-
/// impl Trait for u8 {}
4449-
/// ```
4450-
///
4451-
/// {{produces}}
4452-
///
4453-
/// ### Explanation
4454-
///
4455-
/// We have two choices for impl which satisfy `u8: Trait`: the blanket impl
4456-
/// for generic `T`, and the direct impl for `u8`. These two impls nominally
4457-
/// overlap, since we can infer `T = u8` in the former impl, but since the where
4458-
/// clause `u8: CyclicTrait` would end up resulting in a cycle (since it depends
4459-
/// on itself), the blanket impl is not considered to hold for `u8`. This will
4460-
/// change in a future release.
4461-
pub COINDUCTIVE_OVERLAP_IN_COHERENCE,
4462-
Deny,
4463-
"impls that are not considered to overlap may be considered to \
4464-
overlap in the future",
4465-
@future_incompatible = FutureIncompatibleInfo {
4466-
reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
4467-
reference: "issue #114040 <https://github.com/rust-lang/rust/issues/114040>",
4468-
};
4469-
}
4470-
44714431
declare_lint! {
44724432
/// The `unknown_or_malformed_diagnostic_attributes` lint detects unrecognized or otherwise malformed
44734433
/// diagnostic attributes.

compiler/rustc_trait_selection/src/traits/coherence.rs

+6-59
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use crate::solve::inspect;
1010
use crate::solve::inspect::{InspectGoal, ProofTreeInferCtxtExt, ProofTreeVisitor};
1111
use crate::traits::engine::TraitEngineExt;
1212
use crate::traits::query::evaluate_obligation::InferCtxtExt;
13-
use crate::traits::select::{IntercrateAmbiguityCause, TreatInductiveCycleAs};
13+
use crate::traits::select::IntercrateAmbiguityCause;
1414
use crate::traits::structural_normalize::StructurallyNormalizeExt;
1515
use crate::traits::NormalizeExt;
1616
use crate::traits::SkipLeakCheck;
@@ -31,7 +31,6 @@ use rustc_middle::traits::DefiningAnchor;
3131
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
3232
use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt};
3333
use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor};
34-
use rustc_session::lint::builtin::COINDUCTIVE_OVERLAP_IN_COHERENCE;
3534
use rustc_span::symbol::sym;
3635
use rustc_span::DUMMY_SP;
3736
use std::fmt::Debug;
@@ -197,7 +196,7 @@ fn overlap<'tcx>(
197196
.intercrate(true)
198197
.with_next_trait_solver(tcx.next_trait_solver_in_coherence())
199198
.build();
200-
let selcx = &mut SelectionContext::new(&infcx);
199+
let selcx = &mut SelectionContext::with_treat_inductive_cycle_as_ambig(&infcx);
201200
if track_ambiguity_causes.is_yes() {
202201
selcx.enable_tracking_intercrate_ambiguity_causes();
203202
}
@@ -224,62 +223,10 @@ fn overlap<'tcx>(
224223
);
225224

226225
if overlap_mode.use_implicit_negative() {
227-
for mode in [TreatInductiveCycleAs::Ambig, TreatInductiveCycleAs::Recur] {
228-
if let Some(failing_obligation) = selcx.with_treat_inductive_cycle_as(mode, |selcx| {
229-
impl_intersection_has_impossible_obligation(selcx, &obligations)
230-
}) {
231-
if matches!(mode, TreatInductiveCycleAs::Recur) {
232-
let first_local_impl = impl1_header
233-
.impl_def_id
234-
.as_local()
235-
.or(impl2_header.impl_def_id.as_local())
236-
.expect("expected one of the impls to be local");
237-
infcx.tcx.struct_span_lint_hir(
238-
COINDUCTIVE_OVERLAP_IN_COHERENCE,
239-
infcx.tcx.local_def_id_to_hir_id(first_local_impl),
240-
infcx.tcx.def_span(first_local_impl),
241-
format!(
242-
"implementations {} will conflict in the future",
243-
match impl1_header.trait_ref {
244-
Some(trait_ref) => {
245-
let trait_ref = infcx.resolve_vars_if_possible(trait_ref);
246-
format!(
247-
"of `{}` for `{}`",
248-
trait_ref.print_only_trait_path(),
249-
trait_ref.self_ty()
250-
)
251-
}
252-
None => format!(
253-
"for `{}`",
254-
infcx.resolve_vars_if_possible(impl1_header.self_ty)
255-
),
256-
},
257-
),
258-
|lint| {
259-
lint.note(
260-
"impls that are not considered to overlap may be considered to \
261-
overlap in the future",
262-
)
263-
.span_label(
264-
infcx.tcx.def_span(impl1_header.impl_def_id),
265-
"the first impl is here",
266-
)
267-
.span_label(
268-
infcx.tcx.def_span(impl2_header.impl_def_id),
269-
"the second impl is here",
270-
);
271-
lint.note(format!(
272-
"`{}` may be considered to hold in future releases, \
273-
causing the impls to overlap",
274-
infcx.resolve_vars_if_possible(failing_obligation.predicate)
275-
));
276-
lint
277-
},
278-
);
279-
}
280-
281-
return None;
282-
}
226+
if let Some(_failing_obligation) =
227+
impl_intersection_has_impossible_obligation(selcx, &obligations)
228+
{
229+
return None;
283230
}
284231
}
285232

compiler/rustc_trait_selection/src/traits/select/mod.rs

+8-12
Original file line numberDiff line numberDiff line change
@@ -239,20 +239,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
239239
}
240240
}
241241

242-
// Sets the `TreatInductiveCycleAs` mode temporarily in the selection context
243-
pub fn with_treat_inductive_cycle_as<T>(
244-
&mut self,
245-
treat_inductive_cycle: TreatInductiveCycleAs,
246-
f: impl FnOnce(&mut Self) -> T,
247-
) -> T {
242+
pub fn with_treat_inductive_cycle_as_ambig(
243+
infcx: &'cx InferCtxt<'tcx>,
244+
) -> SelectionContext<'cx, 'tcx> {
248245
// Should be executed in a context where caching is disabled,
249246
// otherwise the cache is poisoned with the temporary result.
250-
assert!(self.is_intercrate());
251-
let treat_inductive_cycle =
252-
std::mem::replace(&mut self.treat_inductive_cycle, treat_inductive_cycle);
253-
let value = f(self);
254-
self.treat_inductive_cycle = treat_inductive_cycle;
255-
value
247+
assert!(infcx.intercrate);
248+
SelectionContext {
249+
treat_inductive_cycle: TreatInductiveCycleAs::Ambig,
250+
..SelectionContext::new(infcx)
251+
}
256252
}
257253

258254
pub fn with_query_mode(

tests/ui/coherence/warn-when-cycle-is-error-in-coherence.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,15 @@
1-
#![deny(coinductive_overlap_in_coherence)]
2-
31
use std::borrow::Borrow;
42
use std::cmp::Ordering;
53
use std::marker::PhantomData;
64

75
#[derive(PartialEq, Default)]
6+
//~^ ERROR conflicting implementations of trait `PartialEq<Interval<_>>` for type `Interval<_>`
87
pub(crate) struct Interval<T>(PhantomData<T>);
98

109
// This impl overlaps with the `derive` unless we reject the nested
1110
// `Interval<?1>: PartialOrd<Interval<?1>>` candidate which results
12-
// in a - currently inductive - cycle.
11+
// in a cycle.
1312
impl<T, Q> PartialEq<Q> for Interval<T>
14-
//~^ ERROR implementations of `PartialEq<Interval<_>>` for `Interval<_>` will conflict in the future
15-
//~| WARN this was previously accepted by the compiler but is being phased out
1613
where
1714
T: Borrow<Q>,
1815
Q: ?Sized + PartialOrd,
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,17 @@
1-
error: implementations of `PartialEq<Interval<_>>` for `Interval<_>` will conflict in the future
2-
--> $DIR/warn-when-cycle-is-error-in-coherence.rs:13:1
1+
error[E0119]: conflicting implementations of trait `PartialEq<Interval<_>>` for type `Interval<_>`
2+
--> $DIR/warn-when-cycle-is-error-in-coherence.rs:5:10
33
|
44
LL | #[derive(PartialEq, Default)]
5-
| --------- the second impl is here
5+
| ^^^^^^^^^ conflicting implementation for `Interval<_>`
66
...
77
LL | / impl<T, Q> PartialEq<Q> for Interval<T>
8-
LL | |
9-
LL | |
108
LL | | where
119
LL | | T: Borrow<Q>,
1210
LL | | Q: ?Sized + PartialOrd,
13-
| |___________________________^ the first impl is here
11+
| |___________________________- first implementation here
1412
|
15-
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
16-
= note: for more information, see issue #114040 <https://github.com/rust-lang/rust/issues/114040>
17-
= note: impls that are not considered to overlap may be considered to overlap in the future
18-
= note: `Interval<_>: PartialOrd` may be considered to hold in future releases, causing the impls to overlap
19-
note: the lint level is defined here
20-
--> $DIR/warn-when-cycle-is-error-in-coherence.rs:1:9
21-
|
22-
LL | #![deny(coinductive_overlap_in_coherence)]
23-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
13+
= note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
2414

2515
error: aborting due to 1 previous error
2616

27-
Future incompatibility report: Future breakage diagnostic:
28-
error: implementations of `PartialEq<Interval<_>>` for `Interval<_>` will conflict in the future
29-
--> $DIR/warn-when-cycle-is-error-in-coherence.rs:13:1
30-
|
31-
LL | #[derive(PartialEq, Default)]
32-
| --------- the second impl is here
33-
...
34-
LL | / impl<T, Q> PartialEq<Q> for Interval<T>
35-
LL | |
36-
LL | |
37-
LL | | where
38-
LL | | T: Borrow<Q>,
39-
LL | | Q: ?Sized + PartialOrd,
40-
| |___________________________^ the first impl is here
41-
|
42-
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
43-
= note: for more information, see issue #114040 <https://github.com/rust-lang/rust/issues/114040>
44-
= note: impls that are not considered to overlap may be considered to overlap in the future
45-
= note: `Interval<_>: PartialOrd` may be considered to hold in future releases, causing the impls to overlap
46-
note: the lint level is defined here
47-
--> $DIR/warn-when-cycle-is-error-in-coherence.rs:1:9
48-
|
49-
LL | #![deny(coinductive_overlap_in_coherence)]
50-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
51-
17+
For more information about this error, try `rustc --explain E0119`.

0 commit comments

Comments
 (0)