Skip to content

Commit 1974f5c

Browse files
authored
Rollup merge of #118649 - compiler-errors:coherence-ambig, r=lcnr
Make inductive cycles in coherence ambiguous always Logical conclusion of #114040 One step after #116493 cc rust-lang/trait-system-refactor-initiative#20 r? lcnr to kick off the FCP after review... maybe we should wait until 1.75 is landed? In that case, I'd still like to get the FCP boxes checked sooner since that'll be near the holidays which means everyone's away.
2 parents 9e4843e + 8abf133 commit 1974f5c

File tree

6 files changed

+27
-155
lines changed

6 files changed

+27
-155
lines changed

compiler/rustc_lint/src/lib.rs

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

518523
fn register_internals(store: &mut LintStore) {

compiler/rustc_lint_defs/src/builtin.rs

-40
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ declare_lint_pass! {
2626
BYTE_SLICE_IN_PACKED_STRUCT_WITH_DERIVE,
2727
CENUM_IMPL_DROP_CAST,
2828
COHERENCE_LEAK_CHECK,
29-
COINDUCTIVE_OVERLAP_IN_COHERENCE,
3029
CONFLICTING_REPR_HINTS,
3130
CONST_EVALUATABLE_UNCHECKED,
3231
CONST_ITEM_MUTATION,
@@ -4367,45 +4366,6 @@ declare_lint! {
43674366
@feature_gate = sym::type_privacy_lints;
43684367
}
43694368

4370-
declare_lint! {
4371-
/// The `coinductive_overlap_in_coherence` lint detects impls which are currently
4372-
/// considered not overlapping, but may be considered to overlap if support for
4373-
/// coinduction is added to the trait solver.
4374-
///
4375-
/// ### Example
4376-
///
4377-
/// ```rust,compile_fail
4378-
/// #![deny(coinductive_overlap_in_coherence)]
4379-
///
4380-
/// trait CyclicTrait {}
4381-
/// impl<T: CyclicTrait> CyclicTrait for T {}
4382-
///
4383-
/// trait Trait {}
4384-
/// impl<T: CyclicTrait> Trait for T {}
4385-
/// // conflicting impl with the above
4386-
/// impl Trait for u8 {}
4387-
/// ```
4388-
///
4389-
/// {{produces}}
4390-
///
4391-
/// ### Explanation
4392-
///
4393-
/// We have two choices for impl which satisfy `u8: Trait`: the blanket impl
4394-
/// for generic `T`, and the direct impl for `u8`. These two impls nominally
4395-
/// overlap, since we can infer `T = u8` in the former impl, but since the where
4396-
/// clause `u8: CyclicTrait` would end up resulting in a cycle (since it depends
4397-
/// on itself), the blanket impl is not considered to hold for `u8`. This will
4398-
/// change in a future release.
4399-
pub COINDUCTIVE_OVERLAP_IN_COHERENCE,
4400-
Deny,
4401-
"impls that are not considered to overlap may be considered to \
4402-
overlap in the future",
4403-
@future_incompatible = FutureIncompatibleInfo {
4404-
reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
4405-
reference: "issue #114040 <https://github.com/rust-lang/rust/issues/114040>",
4406-
};
4407-
}
4408-
44094369
declare_lint! {
44104370
/// The `unknown_or_malformed_diagnostic_attributes` lint detects unrecognized or otherwise malformed
44114371
/// diagnostic attributes.

compiler/rustc_trait_selection/src/traits/coherence.rs

+6-58
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use crate::solve::inspect::{InspectGoal, ProofTreeInferCtxtExt, ProofTreeVisitor
1010
use crate::solve::{deeply_normalize_for_diagnostics, inspect};
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,61 +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_trait_sugared(),
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-
},
277-
);
278-
}
279-
280-
return None;
281-
}
226+
if let Some(_failing_obligation) =
227+
impl_intersection_has_impossible_obligation(selcx, &obligations)
228+
{
229+
return None;
282230
}
283231
}
284232

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 -- currently inductive -- 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)