Skip to content

Commit 90d6255

Browse files
committed
Auto merge of rust-lang#125380 - compiler-errors:wc-obj-safety, r=oli-obk
Make `WHERE_CLAUSES_OBJECT_SAFETY` a regular object safety violation #### The issue In rust-lang#50781, we have known about unsound `where` clauses in function arguments: ```rust trait Impossible {} trait Foo { fn impossible(&self) where Self: Impossible; } impl Foo for &() { fn impossible(&self) where Self: Impossible, {} } // `where` clause satisfied for the object, meaning that the function now *looks* callable. impl Impossible for dyn Foo {} fn main() { let x: &dyn Foo = &&(); x.impossible(); } ``` ... which currently segfaults at runtime because we try to call a method in the vtable that doesn't exist. :( #### What did u change This PR removes the `WHERE_CLAUSES_OBJECT_SAFETY` lint and instead makes it a regular object safety violation. I choose to make this into a hard error immediately rather than a `deny` because of the time that has passed since this lint was authored, and the single (1) regression (see below). That means that it's OK to mention `where Self: Trait` where clauses in your trait, but making such a trait into a `dyn Trait` object will report an object safety violation just like `where Self: Sized`, etc. ```rust trait Impossible {} trait Foo { fn impossible(&self) where Self: Impossible; // <~ This definition is valid, just not object-safe. } impl Foo for &() { fn impossible(&self) where Self: Impossible, {} } fn main() { let x: &dyn Foo = &&(); // <~ THIS is where we emit an error. } ``` #### Regressions From a recent crater run, there's only one crate that relies on this behavior: rust-lang#124305 (comment). The crate looks unmaintained and there seems to be no dependents. #### Further We may later choose to relax this (e.g. when the where clause is implied by the supertraits of the trait or something), but this is not something I propose to do in this FCP. For example, given: ``` trait Tr { fn f(&self) where Self: Blanket; } impl<T: ?Sized> Blanket for T {} ``` Proving that some placeholder `S` implements `S: Blanket` would be sufficient to prove that the same (blanket) impl applies for both `Concerete: Blanket` and `dyn Trait: Blanket`. Repeating here that I don't think we need to implement this behavior right now. ---- r? lcnr
2 parents 1689a5a + 511f1cf commit 90d6255

File tree

28 files changed

+92
-209
lines changed

28 files changed

+92
-209
lines changed

compiler/rustc_hir_analysis/src/check/wfcheck.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -881,7 +881,7 @@ fn check_object_unsafe_self_trait_by_name(tcx: TyCtxt<'_>, item: &hir::TraitItem
881881
_ => {}
882882
}
883883
if !trait_should_be_self.is_empty() {
884-
if tcx.check_is_object_safe(trait_def_id) {
884+
if tcx.is_object_safe(trait_def_id) {
885885
return;
886886
}
887887
let sugg = trait_should_be_self.iter().map(|span| (*span, "Self".to_string())).collect();

compiler/rustc_hir_analysis/src/coherence/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ fn check_object_overlap<'tcx>(
191191
});
192192

193193
for component_def_id in component_def_ids {
194-
if !tcx.check_is_object_safe(component_def_id) {
194+
if !tcx.is_object_safe(component_def_id) {
195195
// Without the 'object_safe_for_dispatch' feature this is an error
196196
// which will be reported by wfcheck. Ignore it here.
197197
// This is tested by `coherence-impl-trait-for-trait-object-safe.rs`.

compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
182182
// For recursive traits, don't downgrade the error. (#119652)
183183
is_downgradable = false;
184184
}
185-
tcx.check_is_object_safe(id)
185+
tcx.is_object_safe(id)
186186
}
187187
_ => false,
188188
})

compiler/rustc_interface/src/passes.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -832,7 +832,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
832832
let traits = tcx.traits(LOCAL_CRATE);
833833

834834
for &tr in traits {
835-
if !tcx.check_is_object_safe(tr) {
835+
if !tcx.is_object_safe(tr) {
836836
continue;
837837
}
838838

compiler/rustc_lint/src/multiple_supertrait_upcastable.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,10 @@ declare_lint_pass!(MultipleSupertraitUpcastable => [MULTIPLE_SUPERTRAIT_UPCASTAB
3838
impl<'tcx> LateLintPass<'tcx> for MultipleSupertraitUpcastable {
3939
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
4040
let def_id = item.owner_id.to_def_id();
41-
// NOTE(nbdd0121): use `object_safety_violations` instead of `check_is_object_safe` because
41+
// NOTE(nbdd0121): use `object_safety_violations` instead of `is_object_safe` because
4242
// the latter will report `where_clause_object_safety` lint.
4343
if let hir::ItemKind::Trait(_, _, _, _, _) = item.kind
44-
&& cx.tcx.object_safety_violations(def_id).is_empty()
44+
&& cx.tcx.is_object_safe(def_id)
4545
{
4646
let direct_super_traits_iter = cx
4747
.tcx

compiler/rustc_lint_defs/src/builtin.rs

Lines changed: 0 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,6 @@ declare_lint_pass! {
136136
USELESS_DEPRECATED,
137137
WARNINGS,
138138
WASM_C_ABI,
139-
WHERE_CLAUSES_OBJECT_SAFETY,
140139
WRITES_THROUGH_IMMUTABLE_POINTER,
141140
// tidy-alphabetical-end
142141
]
@@ -2093,47 +2092,6 @@ declare_lint! {
20932092
"detects labels that are never used"
20942093
}
20952094

2096-
declare_lint! {
2097-
/// The `where_clauses_object_safety` lint detects for [object safety] of
2098-
/// [where clauses].
2099-
///
2100-
/// [object safety]: https://doc.rust-lang.org/reference/items/traits.html#object-safety
2101-
/// [where clauses]: https://doc.rust-lang.org/reference/items/generics.html#where-clauses
2102-
///
2103-
/// ### Example
2104-
///
2105-
/// ```rust,no_run
2106-
/// trait Trait {}
2107-
///
2108-
/// trait X { fn foo(&self) where Self: Trait; }
2109-
///
2110-
/// impl X for () { fn foo(&self) {} }
2111-
///
2112-
/// impl Trait for dyn X {}
2113-
///
2114-
/// // Segfault at opt-level 0, SIGILL otherwise.
2115-
/// pub fn main() { <dyn X as X>::foo(&()); }
2116-
/// ```
2117-
///
2118-
/// {{produces}}
2119-
///
2120-
/// ### Explanation
2121-
///
2122-
/// The compiler previously allowed these object-unsafe bounds, which was
2123-
/// incorrect. This is a [future-incompatible] lint to transition this to
2124-
/// a hard error in the future. See [issue #51443] for more details.
2125-
///
2126-
/// [issue #51443]: https://github.com/rust-lang/rust/issues/51443
2127-
/// [future-incompatible]: ../index.md#future-incompatible-lints
2128-
pub WHERE_CLAUSES_OBJECT_SAFETY,
2129-
Warn,
2130-
"checks the object safety of where clauses",
2131-
@future_incompatible = FutureIncompatibleInfo {
2132-
reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
2133-
reference: "issue #51443 <https://github.com/rust-lang/rust/issues/51443>",
2134-
};
2135-
}
2136-
21372095
declare_lint! {
21382096
/// The `proc_macro_derive_resolution_fallback` lint detects proc macro
21392097
/// derives using inaccessible names from parent modules.

compiler/rustc_middle/src/query/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1309,7 +1309,7 @@ rustc_queries! {
13091309
query object_safety_violations(trait_id: DefId) -> &'tcx [ObjectSafetyViolation] {
13101310
desc { |tcx| "determining object safety of trait `{}`", tcx.def_path_str(trait_id) }
13111311
}
1312-
query check_is_object_safe(trait_id: DefId) -> bool {
1312+
query is_object_safe(trait_id: DefId) -> bool {
13131313
desc { |tcx| "checking if trait `{}` is object safe", tcx.def_path_str(trait_id) }
13141314
}
13151315

compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,7 @@ pub fn transform_instance<'tcx>(
367367
let trait_method = tcx.associated_item(method_id);
368368
let trait_id = trait_ref.skip_binder().def_id;
369369
if traits::is_vtable_safe_method(tcx, trait_id, trait_method)
370-
&& tcx.object_safety_violations(trait_id).is_empty()
370+
&& tcx.is_object_safe(trait_id)
371371
{
372372
// Trait methods will have a Self polymorphic parameter, where the concreteized
373373
// implementatation will not. We need to walk back to the more general trait method

compiler/rustc_trait_selection/src/solve/assembly/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -714,7 +714,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
714714
};
715715

716716
// Do not consider built-in object impls for non-object-safe types.
717-
if bounds.principal_def_id().is_some_and(|def_id| !tcx.check_is_object_safe(def_id)) {
717+
if bounds.principal_def_id().is_some_and(|def_id| !tcx.is_object_safe(def_id)) {
718718
return;
719719
}
720720

compiler/rustc_trait_selection/src/solve/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> {
133133
}
134134

135135
fn compute_object_safe_goal(&mut self, trait_def_id: DefId) -> QueryResult<'tcx> {
136-
if self.interner().check_is_object_safe(trait_def_id) {
136+
if self.interner().is_object_safe(trait_def_id) {
137137
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
138138
} else {
139139
Err(NoSolution)

0 commit comments

Comments
 (0)