Skip to content

Commit

Permalink
Fix tuple element tys returned from
Browse files Browse the repository at this point in the history
Instead of returning the type of the last element we flip it around and
return types of all elements _except_ the last one. This matches the
the constraint on tuple types which says that only the last element
can be unsized.
  • Loading branch information
gurry committed Feb 28, 2024
1 parent dc00e8c commit 8652f5d
Show file tree
Hide file tree
Showing 17 changed files with 212 additions and 192 deletions.
11 changes: 8 additions & 3 deletions compiler/rustc_trait_selection/src/traits/select/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2116,9 +2116,14 @@ impl<'tcx> SelectionContext<'_, 'tcx> {

ty::Str | ty::Slice(_) | ty::Dynamic(..) | ty::Foreign(..) => None,

ty::Tuple(tys) => Where(
obligation.predicate.rebind(tys.last().map_or_else(Vec::new, |&last| vec![last])),
),
ty::Tuple(tys) => {
let tys_except_last = match tys.split_last() {
Some((_, t)) => t.to_owned(),
Option::None => Vec::new(),
};

Where(obligation.predicate.rebind(tys_except_last))
}

ty::Adt(def, args) => {
let sized_crit = def.sized_constraint(self.tcx());
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/dst/dst-bad-deep-2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ pub fn main() {
let f: ([isize; 3],) = ([5, 6, 7],);
let g: &([isize],) = &f;
let h: &(([isize],),) = &(*g,);
//~^ ERROR the size for values of type
//~^ ERROR cannot move out of
}
13 changes: 4 additions & 9 deletions tests/ui/dst/dst-bad-deep-2.stderr
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
error[E0277]: the size for values of type `[isize]` cannot be known at compilation time
--> $DIR/dst-bad-deep-2.rs:11:30
error[E0507]: cannot move out of `*g` which is behind a shared reference
--> $DIR/dst-bad-deep-2.rs:11:31
|
LL | let h: &(([isize],),) = &(*g,);
| ^^^^^ doesn't have a size known at compile-time
|
= help: within `(([isize],),)`, the trait `Sized` is not implemented for `[isize]`, which is required by `(([isize],),): Sized`
= note: required because it appears within the type `([isize],)`
= note: required because it appears within the type `(([isize],),)`
= note: tuples must have a statically known size to be initialized
| ^^ move occurs because `*g` has type `([isize],)`, which does not implement the `Copy` trait

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0277`.
For more information about this error, try `rustc --explain E0507`.
6 changes: 2 additions & 4 deletions tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,9 @@ impl Trait for Struct {}
impl Trait for u32 {}

fn fuz() -> (usize, Trait) { (42, Struct) }
//~^ ERROR E0277
//~| ERROR E0308
//~^ ERROR E0308
fn bar() -> (usize, dyn Trait) { (42, Struct) }
//~^ ERROR E0277
//~| ERROR E0308
//~^ ERROR E0308
fn bap() -> Trait { Struct }
//~^ ERROR E0746
fn ban() -> dyn Trait { Struct }
Expand Down
62 changes: 19 additions & 43 deletions tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,8 @@ LL | fn fuz() -> (usize, Trait) { (42, Struct) }
found struct `Struct`
= help: `Struct` implements `Trait` so you could box the found value and coerce it to the trait object `Box<dyn Trait>`, you will have to change the expected type as well

error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:7:13
|
LL | fn fuz() -> (usize, Trait) { (42, Struct) }
| ^^^^^^^^^^^^^^ ------------ this returned value is of type `(usize, (dyn Trait + 'static))`
| |
| doesn't have a size known at compile-time
|
= help: within `(usize, (dyn Trait + 'static))`, the trait `Sized` is not implemented for `(dyn Trait + 'static)`, which is required by `(usize, (dyn Trait + 'static)): Sized`
= note: required because it appears within the type `(usize, (dyn Trait + 'static))`
= note: the return type of a function must have a statically known size

error[E0308]: mismatched types
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:10:39
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:9:39
|
LL | fn bar() -> (usize, dyn Trait) { (42, Struct) }
| ^^^^^^ expected `dyn Trait`, found `Struct`
Expand All @@ -30,20 +18,8 @@ LL | fn bar() -> (usize, dyn Trait) { (42, Struct) }
found struct `Struct`
= help: `Struct` implements `Trait` so you could box the found value and coerce it to the trait object `Box<dyn Trait>`, you will have to change the expected type as well

error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:10:13
|
LL | fn bar() -> (usize, dyn Trait) { (42, Struct) }
| ^^^^^^^^^^^^^^^^^^ ------------ this returned value is of type `(usize, (dyn Trait + 'static))`
| |
| doesn't have a size known at compile-time
|
= help: within `(usize, (dyn Trait + 'static))`, the trait `Sized` is not implemented for `(dyn Trait + 'static)`, which is required by `(usize, (dyn Trait + 'static)): Sized`
= note: required because it appears within the type `(usize, (dyn Trait + 'static))`
= note: the return type of a function must have a statically known size

error[E0746]: return type cannot have an unboxed trait object
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:13:13
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:11:13
|
LL | fn bap() -> Trait { Struct }
| ^^^^^ doesn't have a size known at compile-time
Expand All @@ -54,7 +30,7 @@ LL | fn bap() -> Box<Trait> { Box::new(Struct) }
| ++++ + +++++++++ +

error[E0746]: return type cannot have an unboxed trait object
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:15:13
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:13:13
|
LL | fn ban() -> dyn Trait { Struct }
| ^^^^^^^^^ doesn't have a size known at compile-time
Expand All @@ -69,7 +45,7 @@ LL | fn ban() -> Box<dyn Trait> { Box::new(Struct) }
| ++++ + +++++++++ +

error[E0746]: return type cannot have an unboxed trait object
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:17:13
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:15:13
|
LL | fn bak() -> dyn Trait { unimplemented!() }
| ^^^^^^^^^ doesn't have a size known at compile-time
Expand All @@ -84,7 +60,7 @@ LL | fn bak() -> Box<dyn Trait> { Box::new(unimplemented!()) }
| ++++ + +++++++++ +

error[E0746]: return type cannot have an unboxed trait object
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:19:13
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:17:13
|
LL | fn bal() -> dyn Trait {
| ^^^^^^^^^ doesn't have a size known at compile-time
Expand All @@ -103,7 +79,7 @@ LL ~ Box::new(42)
|

error[E0746]: return type cannot have an unboxed trait object
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:25:13
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:23:13
|
LL | fn bax() -> dyn Trait {
| ^^^^^^^^^ doesn't have a size known at compile-time
Expand All @@ -122,7 +98,7 @@ LL ~ Box::new(42)
|

error[E0308]: mismatched types
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:34:16
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:32:16
|
LL | fn bam() -> Box<dyn Trait> {
| -------------- expected `Box<(dyn Trait + 'static)>` because of return type
Expand All @@ -139,7 +115,7 @@ LL | return Box::new(Struct);
| +++++++++ +

error[E0308]: mismatched types
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:36:5
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:34:5
|
LL | fn bam() -> Box<dyn Trait> {
| -------------- expected `Box<(dyn Trait + 'static)>` because of return type
Expand All @@ -156,7 +132,7 @@ LL | Box::new(42)
| +++++++++ +

error[E0308]: mismatched types
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:40:16
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:38:16
|
LL | fn baq() -> Box<dyn Trait> {
| -------------- expected `Box<(dyn Trait + 'static)>` because of return type
Expand All @@ -173,7 +149,7 @@ LL | return Box::new(0);
| +++++++++ +

error[E0308]: mismatched types
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:42:5
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:40:5
|
LL | fn baq() -> Box<dyn Trait> {
| -------------- expected `Box<(dyn Trait + 'static)>` because of return type
Expand All @@ -190,7 +166,7 @@ LL | Box::new(42)
| +++++++++ +

error[E0308]: mismatched types
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:46:9
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:44:9
|
LL | fn baz() -> Box<dyn Trait> {
| -------------- expected `Box<(dyn Trait + 'static)>` because of return type
Expand All @@ -207,7 +183,7 @@ LL | Box::new(Struct)
| +++++++++ +

error[E0308]: mismatched types
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:48:9
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:46:9
|
LL | fn baz() -> Box<dyn Trait> {
| -------------- expected `Box<(dyn Trait + 'static)>` because of return type
Expand All @@ -224,7 +200,7 @@ LL | Box::new(42)
| +++++++++ +

error[E0308]: mismatched types
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:53:9
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:51:9
|
LL | fn baw() -> Box<dyn Trait> {
| -------------- expected `Box<(dyn Trait + 'static)>` because of return type
Expand All @@ -241,7 +217,7 @@ LL | Box::new(0)
| +++++++++ +

error[E0308]: mismatched types
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:55:9
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:53:9
|
LL | fn baw() -> Box<dyn Trait> {
| -------------- expected `Box<(dyn Trait + 'static)>` because of return type
Expand All @@ -258,7 +234,7 @@ LL | Box::new(42)
| +++++++++ +

error[E0746]: return type cannot have an unboxed trait object
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:60:13
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:58:13
|
LL | fn bat() -> dyn Trait {
| ^^^^^^^^^ doesn't have a size known at compile-time
Expand All @@ -277,7 +253,7 @@ LL ~ Box::new(42)
|

error[E0746]: return type cannot have an unboxed trait object
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:66:13
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:64:13
|
LL | fn bay() -> dyn Trait {
| ^^^^^^^^^ doesn't have a size known at compile-time
Expand All @@ -295,7 +271,7 @@ LL | } else {
LL ~ Box::new(42)
|

error: aborting due to 19 previous errors
error: aborting due to 17 previous errors

Some errors have detailed explanations: E0277, E0308, E0746.
For more information about an error, try `rustc --explain E0277`.
Some errors have detailed explanations: E0308, E0746.
For more information about an error, try `rustc --explain E0308`.
1 change: 1 addition & 0 deletions tests/ui/layout/issue-84108.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ const BAR: (&Path, [u8], usize) = ("hello", [], 42);

static BAZ: ([u8], usize) = ([], 0);
//~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
//~| ERROR the size for values of type `[u8]` cannot be known at compilation time
//~| ERROR mismatched types
12 changes: 11 additions & 1 deletion tests/ui/layout/issue-84108.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,16 @@ LL | static BAZ: ([u8], usize) = ([], 0);
= help: the trait `Sized` is not implemented for `[u8]`
= note: only the last element of a tuple may have a dynamically sized type

error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
--> $DIR/issue-84108.rs:12:29
|
LL | static BAZ: ([u8], usize) = ([], 0);
| ^^^^^^^ doesn't have a size known at compile-time
|
= help: within `([u8], usize)`, the trait `Sized` is not implemented for `[u8]`, which is required by `([u8], usize): Sized`
= note: required because it appears within the type `([u8], usize)`
= note: constant expressions must have a statically known size

error[E0308]: mismatched types
--> $DIR/issue-84108.rs:12:30
|
Expand All @@ -38,7 +48,7 @@ LL | static BAZ: ([u8], usize) = ([], 0);
= note: expected slice `[u8]`
found array `[_; 0]`

error: aborting due to 4 previous errors
error: aborting due to 5 previous errors

Some errors have detailed explanations: E0277, E0308, E0412.
For more information about an error, try `rustc --explain E0277`.
16 changes: 16 additions & 0 deletions tests/ui/trait-bounds/ice-unsized-tuple-const-issue-121443.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Regression test for #121443
// Checks that no ICE occurs upon encountering
// a tuple with unsized element that is not
// the last element

type Fn = dyn FnOnce() -> u8;

const TEST: Fn = some_fn;
//~^ ERROR cannot find value `some_fn` in this scope
//~| ERROR the size for values of type `(dyn FnOnce() -> u8 + 'static)` cannot be known at compilation time
//~| ERROR the size for values of type `(dyn FnOnce() -> u8 + 'static)` cannot be known at compilation time
const TEST2: (Fn, u8) = (TEST, 0);
//~^ ERROR the size for values of type `(dyn FnOnce() -> u8 + 'static)` cannot be known at compilation time
//~| ERROR the size for values of type `(dyn FnOnce() -> u8 + 'static)` cannot be known at compilation time

fn main() {}
46 changes: 46 additions & 0 deletions tests/ui/trait-bounds/ice-unsized-tuple-const-issue-121443.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
error[E0425]: cannot find value `some_fn` in this scope
--> $DIR/ice-unsized-tuple-const-issue-121443.rs:8:18
|
LL | const TEST: Fn = some_fn;
| ^^^^^^^ not found in this scope

error[E0277]: the size for values of type `(dyn FnOnce() -> u8 + 'static)` cannot be known at compilation time
--> $DIR/ice-unsized-tuple-const-issue-121443.rs:8:13
|
LL | const TEST: Fn = some_fn;
| ^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `(dyn FnOnce() -> u8 + 'static)`

error[E0277]: the size for values of type `(dyn FnOnce() -> u8 + 'static)` cannot be known at compilation time
--> $DIR/ice-unsized-tuple-const-issue-121443.rs:8:18
|
LL | const TEST: Fn = some_fn;
| ^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `(dyn FnOnce() -> u8 + 'static)`
= note: constant expressions must have a statically known size

error[E0277]: the size for values of type `(dyn FnOnce() -> u8 + 'static)` cannot be known at compilation time
--> $DIR/ice-unsized-tuple-const-issue-121443.rs:12:14
|
LL | const TEST2: (Fn, u8) = (TEST, 0);
| ^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `(dyn FnOnce() -> u8 + 'static)`
= note: only the last element of a tuple may have a dynamically sized type

error[E0277]: the size for values of type `(dyn FnOnce() -> u8 + 'static)` cannot be known at compilation time
--> $DIR/ice-unsized-tuple-const-issue-121443.rs:12:25
|
LL | const TEST2: (Fn, u8) = (TEST, 0);
| ^^^^^^^^^ doesn't have a size known at compile-time
|
= help: within `((dyn FnOnce() -> u8 + 'static), u8)`, the trait `Sized` is not implemented for `(dyn FnOnce() -> u8 + 'static)`, which is required by `((dyn FnOnce() -> u8 + 'static), u8): Sized`
= note: required because it appears within the type `((dyn FnOnce() -> u8 + 'static), u8)`
= note: constant expressions must have a statically known size

error: aborting due to 5 previous errors

Some errors have detailed explanations: E0277, E0425.
For more information about an error, try `rustc --explain E0277`.
3 changes: 0 additions & 3 deletions tests/ui/trait-bounds/unsized-bound.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
trait Trait<A> {}
impl<A, B> Trait<(A, B)> for (A, B) where A: ?Sized, B: ?Sized, {}
//~^ ERROR E0277
//~| ERROR E0277
impl<A, B: ?Sized, C: ?Sized> Trait<(A, B, C)> for (A, B, C) where A: ?Sized, {}
//~^ ERROR E0277
//~| ERROR E0277
//~| ERROR E0277
trait Trait2<A> {}
impl<A: ?Sized, B: ?Sized> Trait2<(A, B)> for (A, B) {}
//~^ ERROR E0277
//~| ERROR E0277
trait Trait3<A> {}
impl<A> Trait3<A> for A where A: ?Sized {}
//~^ ERROR E0277
Expand Down
Loading

0 comments on commit 8652f5d

Please sign in to comment.