about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-09-05 01:09:48 +0000
committerbors <bors@rust-lang.org>2023-09-05 01:09:48 +0000
commit9c609ae158aab27f1e7df446de6f2c09414012a9 (patch)
tree2d66b2f8985fa6d88c6ed51fe2d85cbc9fb67175
parent04374cd74264b9d3b7d2d3df08ae38df8af4d020 (diff)
parent07fc6441327a02dd8aa8497b1e4e890f1801e8cf (diff)
Auto merge of #115467 - compiler-errors:assoc-ty-object-safety, r=oli-obk
Do not require associated types with Self: Sized to uphold bounds when confirming object candidate

RPITITs and associated types that have `Self: Sized` bounds are opted out of the `dyn Trait` well-formedness check that happens during confirmation. This ensures that we can actually *use* `dyn Trait`s that have associated types that, e.g., have GATs and RPITITs and other naughty things as long as those are opted-out of object safety via a `Self: Sized` bound.

Fixes #115464

This seems like a natural part of https://github.com/rust-lang/rust/pull/112319#issuecomment-1592574451, and I don't think needs re-litigation.

r? `@oli-obk`
-rw-r--r--compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs3
-rw-r--r--tests/ui/impl-trait/in-trait/issue-102140.stderr6
-rw-r--r--tests/ui/impl-trait/in-trait/object-safety-sized.rs23
-rw-r--r--tests/ui/object-safety/assoc_type_bounds_sized_used.rs6
-rw-r--r--tests/ui/object-safety/assoc_type_bounds_sized_used.stderr21
-rw-r--r--tests/ui/object-safety/call-when-assoc-ty-is-sized.rs25
7 files changed, 68 insertions, 22 deletions
diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
index c47767101a4..b61e02ba761 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
@@ -354,6 +354,12 @@ pub(in crate::solve) fn predicates_for_object_candidate<'tcx>(
         // FIXME(associated_const_equality): Also add associated consts to
         // the requirements here.
         if item.kind == ty::AssocKind::Type {
+            // associated types that require `Self: Sized` do not show up in the built-in
+            // implementation of `Trait for dyn Trait`, and can be dropped here.
+            if tcx.generics_require_sized_self(item.def_id) {
+                continue;
+            }
+
             requirements
                 .extend(tcx.item_bounds(item.def_id).iter_instantiated(tcx, trait_ref.args));
         }
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 8a24f96743a..eadac70057c 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -535,6 +535,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         let assoc_types: Vec<_> = tcx
             .associated_items(trait_predicate.def_id())
             .in_definition_order()
+            // Associated types that require `Self: Sized` do not show up in the built-in
+            // implementation of `Trait for dyn Trait`, and can be dropped here.
+            .filter(|item| !tcx.generics_require_sized_self(item.def_id))
             .filter_map(
                 |item| if item.kind == ty::AssocKind::Type { Some(item.def_id) } else { None },
             )
diff --git a/tests/ui/impl-trait/in-trait/issue-102140.stderr b/tests/ui/impl-trait/in-trait/issue-102140.stderr
index 5d55b9fa4f9..18bb63745d7 100644
--- a/tests/ui/impl-trait/in-trait/issue-102140.stderr
+++ b/tests/ui/impl-trait/in-trait/issue-102140.stderr
@@ -6,7 +6,11 @@ LL |         MyTrait::foo(&self)
    |         |
    |         required by a bound introduced by this call
    |
-   = help: the trait `MyTrait` is implemented for `Outer`
+help: consider removing the leading `&`-reference
+   |
+LL -         MyTrait::foo(&self)
+LL +         MyTrait::foo(self)
+   |
 
 error[E0277]: the trait bound `&dyn MyTrait: MyTrait` is not satisfied
   --> $DIR/issue-102140.rs:23:9
diff --git a/tests/ui/impl-trait/in-trait/object-safety-sized.rs b/tests/ui/impl-trait/in-trait/object-safety-sized.rs
new file mode 100644
index 00000000000..f221cfbb176
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/object-safety-sized.rs
@@ -0,0 +1,23 @@
+// check-pass
+// revisions: current next
+//[next] compile-flags: -Ztrait-solver=next
+
+#![feature(return_position_impl_trait_in_trait)]
+
+fn main() {
+    let vec: Vec<Box<dyn Trait>> = Vec::new();
+
+    for i in vec {
+        i.fn_2();
+    }
+}
+
+trait OtherTrait {}
+
+trait Trait {
+    fn fn_1(&self) -> impl OtherTrait
+    where
+        Self: Sized;
+
+    fn fn_2(&self) -> bool;
+}
diff --git a/tests/ui/object-safety/assoc_type_bounds_sized_used.rs b/tests/ui/object-safety/assoc_type_bounds_sized_used.rs
index cf5345b1c1d..d59fc1712ea 100644
--- a/tests/ui/object-safety/assoc_type_bounds_sized_used.rs
+++ b/tests/ui/object-safety/assoc_type_bounds_sized_used.rs
@@ -1,6 +1,5 @@
-//! This test checks that even if some associated types have
-//! `where Self: Sized` bounds, those without still need to be
-//! mentioned in trait objects.
+//! This test checks that associated types with `Self: Sized` cannot be projected
+//! from a `dyn Trait`.
 
 trait Bop {
     type Bar: Default
@@ -16,5 +15,4 @@ fn bop<T: Bop + ?Sized>() {
 
 fn main() {
     bop::<dyn Bop>();
-    //~^ ERROR: the size for values of type `dyn Bop` cannot be known at compilation time
 }
diff --git a/tests/ui/object-safety/assoc_type_bounds_sized_used.stderr b/tests/ui/object-safety/assoc_type_bounds_sized_used.stderr
index 6b5bc360349..224d33fb2da 100644
--- a/tests/ui/object-safety/assoc_type_bounds_sized_used.stderr
+++ b/tests/ui/object-safety/assoc_type_bounds_sized_used.stderr
@@ -1,5 +1,5 @@
 error[E0599]: the function or associated item `default` exists for associated type `<T as Bop>::Bar`, but its trait bounds were not satisfied
-  --> $DIR/assoc_type_bounds_sized_used.rs:12:30
+  --> $DIR/assoc_type_bounds_sized_used.rs:11:30
    |
 LL |     let _ = <T as Bop>::Bar::default();
    |                              ^^^^^^^ function or associated item cannot be called on `<T as Bop>::Bar` due to unsatisfied trait bounds
@@ -13,7 +13,7 @@ LL | fn bop<T: Bop + ?Sized>() where T: Sized {
    |                           ++++++++++++++
 
 error[E0277]: the size for values of type `T` cannot be known at compilation time
-  --> $DIR/assoc_type_bounds_sized_used.rs:12:14
+  --> $DIR/assoc_type_bounds_sized_used.rs:11:14
    |
 LL | fn bop<T: Bop + ?Sized>() {
    |        - this type parameter needs to be `Sized`
@@ -21,7 +21,7 @@ LL |     let _ = <T as Bop>::Bar::default();
    |              ^ doesn't have a size known at compile-time
    |
 note: required by a bound in `Bop::Bar`
-  --> $DIR/assoc_type_bounds_sized_used.rs:8:15
+  --> $DIR/assoc_type_bounds_sized_used.rs:7:15
    |
 LL |     type Bar: Default
    |          --- required by a bound in this associated type
@@ -34,20 +34,7 @@ LL - fn bop<T: Bop + ?Sized>() {
 LL + fn bop<T: Bop>() {
    |
 
-error[E0277]: the size for values of type `dyn Bop` cannot be known at compilation time
-  --> $DIR/assoc_type_bounds_sized_used.rs:18:11
-   |
-LL |     bop::<dyn Bop>();
-   |           ^^^^^^^ doesn't have a size known at compile-time
-   |
-   = help: the trait `Sized` is not implemented for `dyn Bop`
-note: required by a bound in `bop`
-  --> $DIR/assoc_type_bounds_sized_used.rs:11:11
-   |
-LL | fn bop<T: Bop + ?Sized>() {
-   |           ^^^ required by this bound in `bop`
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0277, E0599.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/object-safety/call-when-assoc-ty-is-sized.rs b/tests/ui/object-safety/call-when-assoc-ty-is-sized.rs
new file mode 100644
index 00000000000..0b30a88fdd4
--- /dev/null
+++ b/tests/ui/object-safety/call-when-assoc-ty-is-sized.rs
@@ -0,0 +1,25 @@
+// check-pass
+// revisions: current next
+//[next] compile-flags: -Ztrait-solver=next
+
+trait Foo {
+    type Bar<'a>
+    where
+        Self: Sized;
+
+    fn test(&self);
+}
+
+impl Foo for () {
+    type Bar<'a> = () where Self: Sized;
+
+    fn test(&self) {}
+}
+
+fn test(x: &dyn Foo) {
+    x.test();
+}
+
+fn main() {
+    test(&());
+}