Skip to content

Commit 8f6b184

Browse files
committed
Turn order dependent trait objects future incompat warning into a hard error
1 parent eeb9035 commit 8f6b184

File tree

13 files changed

+38
-330
lines changed

13 files changed

+38
-330
lines changed

Diff for: compiler/rustc_lint_defs/src/builtin.rs

-37
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@ declare_lint_pass! {
7373
NEVER_TYPE_FALLBACK_FLOWING_INTO_UNSAFE,
7474
NON_CONTIGUOUS_RANGE_ENDPOINTS,
7575
NON_EXHAUSTIVE_OMITTED_PATTERNS,
76-
ORDER_DEPENDENT_TRAIT_OBJECTS,
7776
OUT_OF_SCOPE_MACRO_CALLS,
7877
OVERLAPPING_RANGE_ENDPOINTS,
7978
PATTERNS_IN_FNS_WITHOUT_BODY,
@@ -1502,42 +1501,6 @@ declare_lint! {
15021501
};
15031502
}
15041503

1505-
declare_lint! {
1506-
/// The `order_dependent_trait_objects` lint detects a trait coherency
1507-
/// violation that would allow creating two trait impls for the same
1508-
/// dynamic trait object involving marker traits.
1509-
///
1510-
/// ### Example
1511-
///
1512-
/// ```rust,compile_fail
1513-
/// pub trait Trait {}
1514-
///
1515-
/// impl Trait for dyn Send + Sync { }
1516-
/// impl Trait for dyn Sync + Send { }
1517-
/// ```
1518-
///
1519-
/// {{produces}}
1520-
///
1521-
/// ### Explanation
1522-
///
1523-
/// A previous bug caused the compiler to interpret traits with different
1524-
/// orders (such as `Send + Sync` and `Sync + Send`) as distinct types
1525-
/// when they were intended to be treated the same. This allowed code to
1526-
/// define separate trait implementations when there should be a coherence
1527-
/// error. This is a [future-incompatible] lint to transition this to a
1528-
/// hard error in the future. See [issue #56484] for more details.
1529-
///
1530-
/// [issue #56484]: https://github.com/rust-lang/rust/issues/56484
1531-
/// [future-incompatible]: ../index.md#future-incompatible-lints
1532-
pub ORDER_DEPENDENT_TRAIT_OBJECTS,
1533-
Deny,
1534-
"trait-object types were treated as different depending on marker-trait order",
1535-
@future_incompatible = FutureIncompatibleInfo {
1536-
reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
1537-
reference: "issue #56484 <https://github.com/rust-lang/rust/issues/56484>",
1538-
};
1539-
}
1540-
15411504
declare_lint! {
15421505
/// The `coherence_leak_check` lint detects conflicting implementations of
15431506
/// a trait that are only distinguished by the old leak-check code.

Diff for: compiler/rustc_middle/src/query/mod.rs

-6
Original file line numberDiff line numberDiff line change
@@ -985,12 +985,6 @@ rustc_queries! {
985985
separate_provide_extern
986986
}
987987

988-
query self_ty_of_trait_impl_enabling_order_dep_trait_object_hack(
989-
key: DefId
990-
) -> Option<ty::EarlyBinder<'tcx, ty::Ty<'tcx>>> {
991-
desc { |tcx| "computing self type wrt issue #33140 `{}`", tcx.def_path_str(key) }
992-
}
993-
994988
/// Maps a `DefId` of a type to a list of its inherent impls.
995989
/// Contains implementations of methods that are inherent to a type.
996990
/// Methods in these implementations don't need to be exported.

Diff for: compiler/rustc_middle/src/ty/mod.rs

+1-46
Original file line numberDiff line numberDiff line change
@@ -1424,39 +1424,6 @@ pub enum ImplOverlapKind {
14241424
/// Whether or not the impl is permitted due to the trait being a `#[marker]` trait
14251425
marker: bool,
14261426
},
1427-
/// These impls are allowed to overlap, but that raises an
1428-
/// issue #33140 future-compatibility warning (tracked in #56484).
1429-
///
1430-
/// Some background: in Rust 1.0, the trait-object types `Send + Sync` (today's
1431-
/// `dyn Send + Sync`) and `Sync + Send` (now `dyn Sync + Send`) were different.
1432-
///
1433-
/// The widely-used version 0.1.0 of the crate `traitobject` had accidentally relied on
1434-
/// that difference, doing what reduces to the following set of impls:
1435-
///
1436-
/// ```compile_fail,(E0119)
1437-
/// trait Trait {}
1438-
/// impl Trait for dyn Send + Sync {}
1439-
/// impl Trait for dyn Sync + Send {}
1440-
/// ```
1441-
///
1442-
/// Obviously, once we made these types be identical, that code causes a coherence
1443-
/// error and a fairly big headache for us. However, luckily for us, the trait
1444-
/// `Trait` used in this case is basically a marker trait, and therefore having
1445-
/// overlapping impls for it is sound.
1446-
///
1447-
/// To handle this, we basically regard the trait as a marker trait, with an additional
1448-
/// future-compatibility warning. To avoid accidentally "stabilizing" this feature,
1449-
/// it has the following restrictions:
1450-
///
1451-
/// 1. The trait must indeed be a marker-like trait (i.e., no items), and must be
1452-
/// positive impls.
1453-
/// 2. The trait-ref of both impls must be equal.
1454-
/// 3. The trait-ref of both impls must be a trait object type consisting only of
1455-
/// marker traits.
1456-
/// 4. Neither of the impls can have any where-clauses.
1457-
///
1458-
/// Once `traitobject` 0.1.0 is no longer an active concern, this hack can be removed.
1459-
FutureCompatOrderDepTraitObjects,
14601427
}
14611428

14621429
/// Useful source information about where a desugared associated type for an
@@ -1629,7 +1596,7 @@ impl<'tcx> TyCtxt<'tcx> {
16291596
})
16301597
}
16311598

1632-
/// Returns `true` if the impls are the same polarity and the trait either
1599+
/// Returns `Some` if the impls are the same polarity and the trait either
16331600
/// has no items or is annotated `#[marker]` and prevents item overrides.
16341601
#[instrument(level = "debug", skip(self), ret)]
16351602
pub fn impls_are_allowed_to_overlap(
@@ -1670,18 +1637,6 @@ impl<'tcx> TyCtxt<'tcx> {
16701637
return Some(ImplOverlapKind::Permitted { marker: true });
16711638
}
16721639

1673-
if let Some(self_ty1) =
1674-
self.self_ty_of_trait_impl_enabling_order_dep_trait_object_hack(def_id1)
1675-
&& let Some(self_ty2) =
1676-
self.self_ty_of_trait_impl_enabling_order_dep_trait_object_hack(def_id2)
1677-
{
1678-
if self_ty1 == self_ty2 {
1679-
return Some(ImplOverlapKind::FutureCompatOrderDepTraitObjects);
1680-
} else {
1681-
debug!("found {self_ty1:?} != {self_ty2:?}");
1682-
}
1683-
}
1684-
16851640
None
16861641
}
16871642

Diff for: compiler/rustc_trait_selection/src/traits/select/mod.rs

+3-11
Original file line numberDiff line numberDiff line change
@@ -1920,9 +1920,9 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
19201920
let mut impl_candidate = None;
19211921
for c in impls {
19221922
if let Some(prev) = impl_candidate.replace(c) {
1923-
if self.prefer_lhs_over_victim(has_non_region_infer, c, prev) {
1923+
if self.prefer_lhs_over_victim(has_non_region_infer, c, prev.0) {
19241924
// Ok, prefer `c` over the previous entry
1925-
} else if self.prefer_lhs_over_victim(has_non_region_infer, prev, c) {
1925+
} else if self.prefer_lhs_over_victim(has_non_region_infer, prev, c.0) {
19261926
// Ok, keep `prev` instead of the new entry
19271927
impl_candidate = Some(prev);
19281928
} else {
@@ -1981,7 +1981,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
19811981
&self,
19821982
has_non_region_infer: bool,
19831983
(lhs, lhs_evaluation): (DefId, EvaluationResult),
1984-
(victim, victim_evaluation): (DefId, EvaluationResult),
1984+
victim: DefId,
19851985
) -> bool {
19861986
let tcx = self.tcx();
19871987
// See if we can toss out `victim` based on specialization.
@@ -1997,14 +1997,6 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
19971997
}
19981998

19991999
match tcx.impls_are_allowed_to_overlap(lhs, victim) {
2000-
// For #33140 the impl headers must be exactly equal, the trait must not have
2001-
// any associated items and there are no where-clauses.
2002-
//
2003-
// We can just arbitrarily drop one of the impls.
2004-
Some(ty::ImplOverlapKind::FutureCompatOrderDepTraitObjects) => {
2005-
assert_eq!(lhs_evaluation, victim_evaluation);
2006-
true
2007-
}
20082000
// For candidates which already reference errors it doesn't really
20092001
// matter what we do 🤷
20102002
Some(ty::ImplOverlapKind::Permitted { marker: false }) => {

Diff for: compiler/rustc_trait_selection/src/traits/specialize/mod.rs

+2-7
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use rustc_middle::bug;
2020
use rustc_middle::query::LocalCrate;
2121
use rustc_middle::ty::print::PrintTraitRefExt as _;
2222
use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt, TypingMode};
23-
use rustc_session::lint::builtin::{COHERENCE_LEAK_CHECK, ORDER_DEPENDENT_TRAIT_OBJECTS};
23+
use rustc_session::lint::builtin::COHERENCE_LEAK_CHECK;
2424
use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, sym};
2525
use rustc_type_ir::solve::NoSolution;
2626
use specialization_graph::GraphExt;
@@ -557,13 +557,9 @@ fn report_conflicting_impls<'tcx>(
557557

558558
let msg = || {
559559
format!(
560-
"conflicting implementations of trait `{}`{}{}",
560+
"conflicting implementations of trait `{}`{}",
561561
overlap.trait_ref.print_trait_sugared(),
562562
overlap.self_ty.map_or_else(String::new, |ty| format!(" for type `{ty}`")),
563-
match used_to_be_allowed {
564-
Some(FutureCompatOverlapErrorKind::OrderDepTraitObjects) => ": (E0119)",
565-
_ => "",
566-
}
567563
)
568564
};
569565

@@ -588,7 +584,6 @@ fn report_conflicting_impls<'tcx>(
588584
}
589585
Some(kind) => {
590586
let lint = match kind {
591-
FutureCompatOverlapErrorKind::OrderDepTraitObjects => ORDER_DEPENDENT_TRAIT_OBJECTS,
592587
FutureCompatOverlapErrorKind::LeakCheck => COHERENCE_LEAK_CHECK,
593588
};
594589
tcx.node_span_lint(lint, tcx.local_def_id_to_hir_id(impl_def_id), impl_span, |err| {

Diff for: compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs

-7
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ use crate::traits;
1212

1313
#[derive(Copy, Clone, Debug)]
1414
pub enum FutureCompatOverlapErrorKind {
15-
OrderDepTraitObjects,
1615
LeakCheck,
1716
}
1817

@@ -151,12 +150,6 @@ impl<'tcx> Children {
151150
{
152151
match overlap_kind {
153152
ty::ImplOverlapKind::Permitted { marker: _ } => {}
154-
ty::ImplOverlapKind::FutureCompatOrderDepTraitObjects => {
155-
*last_lint_mut = Some(FutureCompatOverlapError {
156-
error: create_overlap_error(overlap),
157-
kind: FutureCompatOverlapErrorKind::OrderDepTraitObjects,
158-
});
159-
}
160153
}
161154

162155
return Ok((false, false));

Diff for: compiler/rustc_ty_utils/src/ty.rs

+2-56
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,11 @@ use rustc_index::bit_set::DenseBitSet;
66
use rustc_middle::bug;
77
use rustc_middle::query::Providers;
88
use rustc_middle::ty::fold::fold_regions;
9-
use rustc_middle::ty::{
10-
self, EarlyBinder, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, Upcast,
11-
};
9+
use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, Upcast};
1210
use rustc_span::DUMMY_SP;
1311
use rustc_span::def_id::{CRATE_DEF_ID, DefId, LocalDefId};
1412
use rustc_trait_selection::traits;
15-
use tracing::{debug, instrument};
13+
use tracing::instrument;
1614

1715
#[instrument(level = "debug", skip(tcx), ret)]
1816
fn sized_constraint_for_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
@@ -257,57 +255,6 @@ fn param_env_normalized_for_post_analysis(tcx: TyCtxt<'_>, def_id: DefId) -> ty:
257255
typing_env.with_post_analysis_normalized(tcx).param_env
258256
}
259257

260-
/// If the given trait impl enables exploiting the former order dependence of trait objects,
261-
/// returns its self type; otherwise, returns `None`.
262-
///
263-
/// See [`ty::ImplOverlapKind::FutureCompatOrderDepTraitObjects`] for more details.
264-
#[instrument(level = "debug", skip(tcx))]
265-
fn self_ty_of_trait_impl_enabling_order_dep_trait_object_hack(
266-
tcx: TyCtxt<'_>,
267-
def_id: DefId,
268-
) -> Option<EarlyBinder<'_, Ty<'_>>> {
269-
let impl_ =
270-
tcx.impl_trait_header(def_id).unwrap_or_else(|| bug!("called on inherent impl {def_id:?}"));
271-
272-
let trait_ref = impl_.trait_ref.skip_binder();
273-
debug!(?trait_ref);
274-
275-
let is_marker_like = impl_.polarity == ty::ImplPolarity::Positive
276-
&& tcx.associated_item_def_ids(trait_ref.def_id).is_empty();
277-
278-
// Check whether these impls would be ok for a marker trait.
279-
if !is_marker_like {
280-
debug!("not marker-like!");
281-
return None;
282-
}
283-
284-
// impl must be `impl Trait for dyn Marker1 + Marker2 + ...`
285-
if trait_ref.args.len() != 1 {
286-
debug!("impl has args!");
287-
return None;
288-
}
289-
290-
let predicates = tcx.predicates_of(def_id);
291-
if predicates.parent.is_some() || !predicates.predicates.is_empty() {
292-
debug!(?predicates, "impl has predicates!");
293-
return None;
294-
}
295-
296-
let self_ty = trait_ref.self_ty();
297-
let self_ty_matches = match self_ty.kind() {
298-
ty::Dynamic(data, re, _) if re.is_static() => data.principal().is_none(),
299-
_ => false,
300-
};
301-
302-
if self_ty_matches {
303-
debug!("MATCHES!");
304-
Some(EarlyBinder::bind(self_ty))
305-
} else {
306-
debug!("non-matching self type");
307-
None
308-
}
309-
}
310-
311258
/// Check if a function is async.
312259
fn asyncness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Asyncness {
313260
let node = tcx.hir_node_by_def_id(def_id);
@@ -367,7 +314,6 @@ pub(crate) fn provide(providers: &mut Providers) {
367314
adt_sized_constraint,
368315
param_env,
369316
param_env_normalized_for_post_analysis,
370-
self_ty_of_trait_impl_enabling_order_dep_trait_object_hack,
371317
defaultness,
372318
unsizing_params_for_adt,
373319
..*providers

Diff for: tests/ui/lint/lint-incoherent-auto-trait-objects.rs

-3
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,13 @@ impl Foo for dyn Send {}
44

55
impl Foo for dyn Send + Send {}
66
//~^ ERROR conflicting implementations
7-
//~| hard error
87

98
impl Foo for dyn Send + Sync {}
109

1110
impl Foo for dyn Sync + Send {}
1211
//~^ ERROR conflicting implementations
13-
//~| hard error
1412

1513
impl Foo for dyn Send + Sync + Send {}
1614
//~^ ERROR conflicting implementations
17-
//~| hard error
1815

1916
fn main() {}

0 commit comments

Comments
 (0)