Skip to content

Commit 2c194e7

Browse files
authored
Unrolled build for #136520
Rollup merge of #136520 - compiler-errors:redundant-layout-assert, r=lcnr Remove unnecessary layout assertions for object-safe receivers The soundness of `DispatchFromDyn` relies on the fact that, like all other built-in marker-like layout traits (e.g. `Sized`, `CoerceUnsized`), the guarantees that they enforce in *generic* code via traits will result in assumptions that we can rely on in codegen. Specifically, `DispatchFromDyn` ensures that we end up with a receiver that is a valid pointer type, and its implementation validity recursively ensures that the ABI of that pointer type upholds the `Scalar` or `ScalarPair` representation for sized and unsized pointees, respectively. The check that this layout guarantee holds for arbitrary, possibly generic receiver types that also may exist in possibly impossible-to-instantiate where clauses is overkill IMO, and leads to several ICEs due to the fact that computing layouts before monomorphization is going to be fallible at best. This PR removes the check altogether, since it just exists as a sanity check from very long ago, 6f2a161. Fixes #125810 Fixes #90110 This PR is an alternative to #136195. cc `@adetaylor.` I didn't realize in that PR that the layout checks that were being modified were simply *sanity checks*, rather than being actually necessary for soundness.
2 parents 3f33b30 + 0b26dc0 commit 2c194e7

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)