Skip to content

Commit 0b26dc0

Browse files
Remove unnecessary layout assertions for object-safe receivers
1 parent f2c4ccd commit 0b26dc0

File tree

6 files changed

+42
-173
lines changed

6 files changed

+42
-173
lines changed

compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs

+2-105
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,16 @@
44
//!
55
//! [^1]: Formerly known as "object safety".
66
7-
use std::iter;
87
use std::ops::ControlFlow;
98

10-
use rustc_abi::BackendRepr;
119
use rustc_errors::FatalError;
1210
use rustc_hir as hir;
1311
use rustc_hir::def_id::DefId;
1412
use rustc_middle::bug;
1513
use rustc_middle::query::Providers;
1614
use rustc_middle::ty::{
17-
self, EarlyBinder, ExistentialPredicateStableCmpExt as _, GenericArgs, Ty, TyCtxt,
18-
TypeFoldable, TypeFolder, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable,
19-
TypeVisitableExt, TypeVisitor, TypingMode, Upcast,
15+
self, EarlyBinder, GenericArgs, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
16+
TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, Upcast,
2017
};
2118
use rustc_span::Span;
2219
use rustc_type_ir::elaborate;
@@ -109,14 +106,6 @@ fn dyn_compatibility_violations_for_trait(
109106
violations.push(DynCompatibilityViolation::SupertraitNonLifetimeBinder(spans));
110107
}
111108

112-
if violations.is_empty() {
113-
for item in tcx.associated_items(trait_def_id).in_definition_order() {
114-
if let ty::AssocKind::Fn = item.kind {
115-
check_receiver_correct(tcx, trait_def_id, *item);
116-
}
117-
}
118-
}
119-
120109
violations
121110
}
122111

@@ -499,55 +488,6 @@ fn virtual_call_violations_for_method<'tcx>(
499488
errors
500489
}
501490

502-
/// This code checks that `receiver_is_dispatchable` is correctly implemented.
503-
///
504-
/// This check is outlined from the dyn-compatibility check to avoid cycles with
505-
/// layout computation, which relies on knowing whether methods are dyn-compatible.
506-
fn check_receiver_correct<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId, method: ty::AssocItem) {
507-
if !is_vtable_safe_method(tcx, trait_def_id, method) {
508-
return;
509-
}
510-
511-
let method_def_id = method.def_id;
512-
let sig = tcx.fn_sig(method_def_id).instantiate_identity();
513-
let typing_env = ty::TypingEnv::non_body_analysis(tcx, method_def_id);
514-
let receiver_ty = tcx.liberate_late_bound_regions(method_def_id, sig.input(0));
515-
516-
if receiver_ty == tcx.types.self_param {
517-
// Assumed OK, may change later if unsized_locals permits `self: Self` as dispatchable.
518-
return;
519-
}
520-
521-
// e.g., `Rc<()>`
522-
let unit_receiver_ty = receiver_for_self_ty(tcx, receiver_ty, tcx.types.unit, method_def_id);
523-
match tcx.layout_of(typing_env.as_query_input(unit_receiver_ty)).map(|l| l.backend_repr) {
524-
Ok(BackendRepr::Scalar(..)) => (),
525-
abi => {
526-
tcx.dcx().span_delayed_bug(
527-
tcx.def_span(method_def_id),
528-
format!("receiver {unit_receiver_ty:?} when `Self = ()` should have a Scalar ABI; found {abi:?}"),
529-
);
530-
}
531-
}
532-
533-
let trait_object_ty = object_ty_for_trait(tcx, trait_def_id, tcx.lifetimes.re_static);
534-
535-
// e.g., `Rc<dyn Trait>`
536-
let trait_object_receiver =
537-
receiver_for_self_ty(tcx, receiver_ty, trait_object_ty, method_def_id);
538-
match tcx.layout_of(typing_env.as_query_input(trait_object_receiver)).map(|l| l.backend_repr) {
539-
Ok(BackendRepr::ScalarPair(..)) => (),
540-
abi => {
541-
tcx.dcx().span_delayed_bug(
542-
tcx.def_span(method_def_id),
543-
format!(
544-
"receiver {trait_object_receiver:?} when `Self = {trait_object_ty}` should have a ScalarPair ABI; found {abi:?}"
545-
),
546-
);
547-
}
548-
}
549-
}
550-
551491
/// Performs a type instantiation to produce the version of `receiver_ty` when `Self = self_ty`.
552492
/// For example, for `receiver_ty = Rc<Self>` and `self_ty = Foo`, returns `Rc<Foo>`.
553493
fn receiver_for_self_ty<'tcx>(
@@ -569,49 +509,6 @@ fn receiver_for_self_ty<'tcx>(
569509
result
570510
}
571511

572-
/// Creates the object type for the current trait. For example,
573-
/// if the current trait is `Deref`, then this will be
574-
/// `dyn Deref<Target = Self::Target> + 'static`.
575-
#[instrument(level = "trace", skip(tcx), ret)]
576-
fn object_ty_for_trait<'tcx>(
577-
tcx: TyCtxt<'tcx>,
578-
trait_def_id: DefId,
579-
lifetime: ty::Region<'tcx>,
580-
) -> Ty<'tcx> {
581-
let trait_ref = ty::TraitRef::identity(tcx, trait_def_id);
582-
debug!(?trait_ref);
583-
584-
let trait_predicate = ty::Binder::dummy(ty::ExistentialPredicate::Trait(
585-
ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref),
586-
));
587-
debug!(?trait_predicate);
588-
589-
let pred: ty::Predicate<'tcx> = trait_ref.upcast(tcx);
590-
let mut elaborated_predicates: Vec<_> = elaborate(tcx, [pred])
591-
.filter_map(|pred| {
592-
debug!(?pred);
593-
let pred = pred.as_projection_clause()?;
594-
Some(pred.map_bound(|p| {
595-
ty::ExistentialPredicate::Projection(ty::ExistentialProjection::erase_self_ty(
596-
tcx, p,
597-
))
598-
}))
599-
})
600-
.collect();
601-
// NOTE: Since #37965, the existential predicates list has depended on the
602-
// list of predicates to be sorted. This is mostly to enforce that the primary
603-
// predicate comes first.
604-
elaborated_predicates.sort_by(|a, b| a.skip_binder().stable_cmp(tcx, &b.skip_binder()));
605-
elaborated_predicates.dedup();
606-
607-
let existential_predicates = tcx.mk_poly_existential_predicates_from_iter(
608-
iter::once(trait_predicate).chain(elaborated_predicates),
609-
);
610-
debug!(?existential_predicates);
611-
612-
Ty::new_dynamic(tcx, existential_predicates, lifetime, ty::Dyn)
613-
}
614-
615512
/// Checks the method's receiver (the `self` argument) can be dispatched on when `Self` is a
616513
/// trait object. We require that `DispatchableFromDyn` be implemented for the receiver type
617514
/// in the following way:

tests/crashes/125810.rs

-10
This file was deleted.

tests/crashes/90110.rs

-57
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//@ check-pass
2+
// Regression test for #90110.
3+
4+
// Make sure that object safety checking doesn't freak out when
5+
// we have impossible-to-satisfy `Sized` predicates.
6+
7+
trait Parser
8+
where
9+
for<'a> (dyn Parser + 'a): Sized,
10+
{
11+
fn parse_line(&self);
12+
}
13+
14+
fn foo(_: &dyn Parser) {}
15+
16+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//@ check-pass
2+
3+
// Make sure that object safety checking doesn't freak out when
4+
// we have impossible-to-satisfy `DispatchFromDyn` predicates.
5+
6+
#![feature(dispatch_from_dyn)]
7+
#![feature(arbitrary_self_types)]
8+
9+
use std::ops::Deref;
10+
use std::ops::DispatchFromDyn;
11+
12+
trait Trait<T: Deref<Target = Self>>
13+
where
14+
for<'a> &'a T: DispatchFromDyn<&'a T>,
15+
{
16+
fn foo(self: &T) -> Box<dyn Trait<T>>;
17+
}
18+
19+
fn main() {}

tests/crashes/57276.rs tests/ui/self/dispatch-from-dyn-layout.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
//@ known-bug: #57276
1+
//@ check-pass
2+
// Regression test for #57276.
3+
4+
// Make sure that object safety checking doesn't freak out when
5+
// we have impossible-to-satisfy `DispatchFromDyn` predicates.
26

37
#![feature(arbitrary_self_types, dispatch_from_dyn)]
48

0 commit comments

Comments
 (0)