diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index baa94ead9d489..617bc87a9d23c 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -4,19 +4,16 @@ //! //! [^1]: Formerly known as "object safety". -use std::iter; use std::ops::ControlFlow; -use rustc_abi::BackendRepr; use rustc_errors::FatalError; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_middle::bug; use rustc_middle::query::Providers; use rustc_middle::ty::{ - self, EarlyBinder, ExistentialPredicateStableCmpExt as _, GenericArgs, Ty, TyCtxt, - TypeFoldable, TypeFolder, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, - TypeVisitableExt, TypeVisitor, TypingMode, Upcast, + self, EarlyBinder, GenericArgs, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, + TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, Upcast, }; use rustc_span::Span; use rustc_type_ir::elaborate; @@ -109,14 +106,6 @@ fn dyn_compatibility_violations_for_trait( violations.push(DynCompatibilityViolation::SupertraitNonLifetimeBinder(spans)); } - if violations.is_empty() { - for item in tcx.associated_items(trait_def_id).in_definition_order() { - if let ty::AssocKind::Fn = item.kind { - check_receiver_correct(tcx, trait_def_id, *item); - } - } - } - violations } @@ -499,55 +488,6 @@ fn virtual_call_violations_for_method<'tcx>( errors } -/// This code checks that `receiver_is_dispatchable` is correctly implemented. -/// -/// This check is outlined from the dyn-compatibility check to avoid cycles with -/// layout computation, which relies on knowing whether methods are dyn-compatible. -fn check_receiver_correct<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId, method: ty::AssocItem) { - if !is_vtable_safe_method(tcx, trait_def_id, method) { - return; - } - - let method_def_id = method.def_id; - let sig = tcx.fn_sig(method_def_id).instantiate_identity(); - let typing_env = ty::TypingEnv::non_body_analysis(tcx, method_def_id); - let receiver_ty = tcx.liberate_late_bound_regions(method_def_id, sig.input(0)); - - if receiver_ty == tcx.types.self_param { - // Assumed OK, may change later if unsized_locals permits `self: Self` as dispatchable. - return; - } - - // e.g., `Rc<()>` - let unit_receiver_ty = receiver_for_self_ty(tcx, receiver_ty, tcx.types.unit, method_def_id); - match tcx.layout_of(typing_env.as_query_input(unit_receiver_ty)).map(|l| l.backend_repr) { - Ok(BackendRepr::Scalar(..)) => (), - abi => { - tcx.dcx().span_delayed_bug( - tcx.def_span(method_def_id), - format!("receiver {unit_receiver_ty:?} when `Self = ()` should have a Scalar ABI; found {abi:?}"), - ); - } - } - - let trait_object_ty = object_ty_for_trait(tcx, trait_def_id, tcx.lifetimes.re_static); - - // e.g., `Rc` - let trait_object_receiver = - receiver_for_self_ty(tcx, receiver_ty, trait_object_ty, method_def_id); - match tcx.layout_of(typing_env.as_query_input(trait_object_receiver)).map(|l| l.backend_repr) { - Ok(BackendRepr::ScalarPair(..)) => (), - abi => { - tcx.dcx().span_delayed_bug( - tcx.def_span(method_def_id), - format!( - "receiver {trait_object_receiver:?} when `Self = {trait_object_ty}` should have a ScalarPair ABI; found {abi:?}" - ), - ); - } - } -} - /// Performs a type instantiation to produce the version of `receiver_ty` when `Self = self_ty`. /// For example, for `receiver_ty = Rc` and `self_ty = Foo`, returns `Rc`. fn receiver_for_self_ty<'tcx>( @@ -569,49 +509,6 @@ fn receiver_for_self_ty<'tcx>( result } -/// Creates the object type for the current trait. For example, -/// if the current trait is `Deref`, then this will be -/// `dyn Deref + 'static`. -#[instrument(level = "trace", skip(tcx), ret)] -fn object_ty_for_trait<'tcx>( - tcx: TyCtxt<'tcx>, - trait_def_id: DefId, - lifetime: ty::Region<'tcx>, -) -> Ty<'tcx> { - let trait_ref = ty::TraitRef::identity(tcx, trait_def_id); - debug!(?trait_ref); - - let trait_predicate = ty::Binder::dummy(ty::ExistentialPredicate::Trait( - ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref), - )); - debug!(?trait_predicate); - - let pred: ty::Predicate<'tcx> = trait_ref.upcast(tcx); - let mut elaborated_predicates: Vec<_> = elaborate(tcx, [pred]) - .filter_map(|pred| { - debug!(?pred); - let pred = pred.as_projection_clause()?; - Some(pred.map_bound(|p| { - ty::ExistentialPredicate::Projection(ty::ExistentialProjection::erase_self_ty( - tcx, p, - )) - })) - }) - .collect(); - // NOTE: Since #37965, the existential predicates list has depended on the - // list of predicates to be sorted. This is mostly to enforce that the primary - // predicate comes first. - elaborated_predicates.sort_by(|a, b| a.skip_binder().stable_cmp(tcx, &b.skip_binder())); - elaborated_predicates.dedup(); - - let existential_predicates = tcx.mk_poly_existential_predicates_from_iter( - iter::once(trait_predicate).chain(elaborated_predicates), - ); - debug!(?existential_predicates); - - Ty::new_dynamic(tcx, existential_predicates, lifetime, ty::Dyn) -} - /// Checks the method's receiver (the `self` argument) can be dispatched on when `Self` is a /// trait object. We require that `DispatchableFromDyn` be implemented for the receiver type /// in the following way: diff --git a/tests/crashes/125810.rs b/tests/crashes/125810.rs deleted file mode 100644 index 4a152da8ddf34..0000000000000 --- a/tests/crashes/125810.rs +++ /dev/null @@ -1,10 +0,0 @@ -//@ known-bug: rust-lang/rust#125810 -#![feature(arbitrary_self_types, dispatch_from_dyn)] - -use std::ops::{Deref, DispatchFromDyn}; - -trait Trait + DispatchFromDyn> { - fn MONO_BUF(self: T) -> dyn Trait; -} - -fn main() {} diff --git a/tests/crashes/90110.rs b/tests/crashes/90110.rs deleted file mode 100644 index a27a1f42b7af3..0000000000000 --- a/tests/crashes/90110.rs +++ /dev/null @@ -1,57 +0,0 @@ -//@ known-bug: #90110 - -use std::fs::File; -use std::io::{BufReader, BufRead}; -use std::str::Split; -use std::path::Path; - -pub trait Parser -where dyn Parser: Sized -{ - fn new(split_header: Split<&str>) -> Self where Self: Sized; - fn parse_line(&self, split_line: &Split<&str>) -> D; -} - - -pub struct CsvReader { - parser: Box>, - - reader: BufReader, - buf: String, // Buffer we will read into. Avoids re-allocation on each line. - path: String, // Record this so we can return more informative error messages. - line: usize, // Same motivation for this. -} - -impl CsvReader -where dyn Parser: Sized -{ - fn new(path: &str, make_parser: F) -> CsvReader - where F: Fn(Split) -> dyn Parser { - let file = match File::open(Path::new(path)) { - Err(err) => panic!("Couldn't read {}: {}", path, err), - Ok(file) => file, - }; - - let mut reader = BufReader::new(file); - - let mut buf = String::new(); - - let parser = Box::new(match reader.read_line(&mut buf) { - Err(err) => panic!("Failed to read the header line from {}: {}", path, err), - Ok(_) => { - let split_header = buf.split(','); - make_parser(split_header) - }, - }); - - CsvReader { - parser: parser, - reader, - buf, - path: path.to_string(), - line: 2, - } - } -} - -pub fn main() {} diff --git a/tests/ui/self/dispatch-from-dyn-layout-2.rs b/tests/ui/self/dispatch-from-dyn-layout-2.rs new file mode 100644 index 0000000000000..cd52f060dc83c --- /dev/null +++ b/tests/ui/self/dispatch-from-dyn-layout-2.rs @@ -0,0 +1,16 @@ +//@ check-pass +// Regression test for #90110. + +// Make sure that object safety checking doesn't freak out when +// we have impossible-to-satisfy `Sized` predicates. + +trait Parser +where + for<'a> (dyn Parser + 'a): Sized, +{ + fn parse_line(&self); +} + +fn foo(_: &dyn Parser) {} + +fn main() {} diff --git a/tests/ui/self/dispatch-from-dyn-layout-3.rs b/tests/ui/self/dispatch-from-dyn-layout-3.rs new file mode 100644 index 0000000000000..6878a4f4ac271 --- /dev/null +++ b/tests/ui/self/dispatch-from-dyn-layout-3.rs @@ -0,0 +1,19 @@ +//@ check-pass + +// Make sure that object safety checking doesn't freak out when +// we have impossible-to-satisfy `DispatchFromDyn` predicates. + +#![feature(dispatch_from_dyn)] +#![feature(arbitrary_self_types)] + +use std::ops::Deref; +use std::ops::DispatchFromDyn; + +trait Trait> +where + for<'a> &'a T: DispatchFromDyn<&'a T>, +{ + fn foo(self: &T) -> Box>; +} + +fn main() {} diff --git a/tests/crashes/57276.rs b/tests/ui/self/dispatch-from-dyn-layout.rs similarity index 54% rename from tests/crashes/57276.rs rename to tests/ui/self/dispatch-from-dyn-layout.rs index f70be4fba6d8b..468dc89a73e61 100644 --- a/tests/crashes/57276.rs +++ b/tests/ui/self/dispatch-from-dyn-layout.rs @@ -1,4 +1,8 @@ -//@ known-bug: #57276 +//@ check-pass +// Regression test for #57276. + +// Make sure that object safety checking doesn't freak out when +// we have impossible-to-satisfy `DispatchFromDyn` predicates. #![feature(arbitrary_self_types, dispatch_from_dyn)]