Skip to content

Commit f9ccc9a

Browse files
committed
Recognize type Alias = dyn Trait in fn return types
``` error[E0277]: the size for values of type `(dyn Debug + 'static)` cannot be known at compilation time --> $DIR/dyn-trait-type-alias-return-type.rs:4:11 | LL | fn f() -> T { loop {} } | ^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `(dyn Debug + 'static)` note: this type alias is unsized --> $DIR/dyn-trait-type-alias-return-type.rs:1:1 | LL | type T = dyn core::fmt::Debug; | ^^^^^^ = note: the return type of a function must have a statically known size ```
1 parent 349f572 commit f9ccc9a

File tree

6 files changed

+54
-44
lines changed

6 files changed

+54
-44
lines changed

compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1881,6 +1881,19 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
18811881
let ty::Dynamic(_, _) = trait_pred.self_ty().skip_binder().kind() else {
18821882
return false;
18831883
};
1884+
if let Node::Item(hir::Item { kind: hir::ItemKind::Fn { sig: fn_sig, .. }, .. }) =
1885+
self.tcx.hir_node_by_def_id(obligation.cause.body_id)
1886+
&& let hir::FnRetTy::Return(ty) = fn_sig.decl.output
1887+
&& let hir::TyKind::Path(qpath) = ty.kind
1888+
&& let hir::QPath::Resolved(None, path) = qpath
1889+
&& let Res::Def(DefKind::TyAlias, def_id) = path.res
1890+
{
1891+
// Do not suggest
1892+
// type T = dyn Trait;
1893+
// fn foo() -> impl T { .. }
1894+
err.span_note(self.tcx.def_span(def_id), "this type alias is unsized");
1895+
return false;
1896+
}
18841897

18851898
err.code(E0746);
18861899
err.primary_message("return type cannot be a trait object without pointer indirection");

src/tools/clippy/tests/ui/future_not_send.stderr

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
error: future cannot be sent between threads safely
2-
--> tests/ui/future_not_send.rs:8:1
2+
--> tests/ui/future_not_send.rs:8:62
33
|
44
LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `private_future` is not `Send`
5+
| ^^^^ future returned by `private_future` is not `Send`
66
|
77
note: future is not `Send` as this value is used across an await
88
--> tests/ui/future_not_send.rs:11:20
@@ -23,10 +23,10 @@ LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
2323
= help: to override `-D warnings` add `#[allow(clippy::future_not_send)]`
2424

2525
error: future cannot be sent between threads safely
26-
--> tests/ui/future_not_send.rs:14:1
26+
--> tests/ui/future_not_send.rs:14:41
2727
|
2828
LL | pub async fn public_future(rc: Rc<[u8]>) {
29-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `public_future` is not `Send`
29+
| ^ future returned by `public_future` is not `Send`
3030
|
3131
note: future is not `Send` as this value is used across an await
3232
--> tests/ui/future_not_send.rs:17:20
@@ -39,10 +39,10 @@ LL | async { true }.await;
3939
= note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send`
4040

4141
error: future cannot be sent between threads safely
42-
--> tests/ui/future_not_send.rs:24:1
42+
--> tests/ui/future_not_send.rs:24:63
4343
|
4444
LL | async fn private_future2(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
45-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `private_future2` is not `Send`
45+
| ^^^^ future returned by `private_future2` is not `Send`
4646
|
4747
note: captured value is not `Send`
4848
--> tests/ui/future_not_send.rs:24:26
@@ -58,10 +58,10 @@ LL | async fn private_future2(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
5858
= note: `std::cell::Cell<usize>` doesn't implement `std::marker::Sync`
5959

6060
error: future cannot be sent between threads safely
61-
--> tests/ui/future_not_send.rs:30:1
61+
--> tests/ui/future_not_send.rs:30:42
6262
|
6363
LL | pub async fn public_future2(rc: Rc<[u8]>) {}
64-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `public_future2` is not `Send`
64+
| ^ future returned by `public_future2` is not `Send`
6565
|
6666
note: captured value is not `Send`
6767
--> tests/ui/future_not_send.rs:30:29
@@ -71,10 +71,10 @@ LL | pub async fn public_future2(rc: Rc<[u8]>) {}
7171
= note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send`
7272

7373
error: future cannot be sent between threads safely
74-
--> tests/ui/future_not_send.rs:42:5
74+
--> tests/ui/future_not_send.rs:42:39
7575
|
7676
LL | async fn private_future(&self) -> usize {
77-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `private_future` is not `Send`
77+
| ^^^^^ future returned by `private_future` is not `Send`
7878
|
7979
note: future is not `Send` as this value is used across an await
8080
--> tests/ui/future_not_send.rs:45:24
@@ -87,10 +87,10 @@ LL | async { true }.await;
8787
= note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Sync`
8888

8989
error: future cannot be sent between threads safely
90-
--> tests/ui/future_not_send.rs:49:5
90+
--> tests/ui/future_not_send.rs:49:38
9191
|
9292
LL | pub async fn public_future(&self) {
93-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `public_future` is not `Send`
93+
| ^ future returned by `public_future` is not `Send`
9494
|
9595
note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync`
9696
--> tests/ui/future_not_send.rs:49:32
@@ -100,13 +100,10 @@ LL | pub async fn public_future(&self) {
100100
= note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Sync`
101101

102102
error: future cannot be sent between threads safely
103-
--> tests/ui/future_not_send.rs:61:1
103+
--> tests/ui/future_not_send.rs:61:37
104104
|
105-
LL | / async fn generic_future<T>(t: T) -> T
106-
LL | |
107-
LL | | where
108-
LL | | T: Send,
109-
| |____________^ future returned by `generic_future` is not `Send`
105+
LL | async fn generic_future<T>(t: T) -> T
106+
| ^ future returned by `generic_future` is not `Send`
110107
|
111108
note: future is not `Send` as this value is used across an await
112109
--> tests/ui/future_not_send.rs:67:20
@@ -118,10 +115,10 @@ LL | async { true }.await;
118115
= note: `T` doesn't implement `std::marker::Sync`
119116

120117
error: future cannot be sent between threads safely
121-
--> tests/ui/future_not_send.rs:83:1
118+
--> tests/ui/future_not_send.rs:83:51
122119
|
123120
LL | async fn generic_future_always_unsend<T>(_: Rc<T>) {
124-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `generic_future_always_unsend` is not `Send`
121+
| ^ future returned by `generic_future_always_unsend` is not `Send`
125122
|
126123
note: future is not `Send` as this value is used across an await
127124
--> tests/ui/future_not_send.rs:86:20
Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
type T = dyn core::fmt::Debug;
2-
2+
//~^ NOTE this type alias is unsized
3+
34
fn f() -> T { loop {} }
4-
//~^ ERROR return type cannot be a trait object without pointer indirection
5-
//~| HELP
6-
//~| HELP
5+
//~^ ERROR the size for values of type `(dyn Debug + 'static)` cannot be known at compilation time
6+
//~| HELP the trait `Sized` is not implemented for `(dyn Debug + 'static)`
7+
//~| NOTE doesn't have a size known at compile-time
8+
//~| NOTE the return type of a function must have a statically known size
79

810
fn main() {}
Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
1-
error[E0746]: return type cannot be a trait object without pointer indirection
2-
--> $DIR/dyn-trait-type-alias-return-type.rs:3:11
1+
error[E0277]: the size for values of type `(dyn Debug + 'static)` cannot be known at compilation time
2+
--> $DIR/dyn-trait-type-alias-return-type.rs:4:11
33
|
44
LL | fn f() -> T { loop {} }
55
| ^ doesn't have a size known at compile-time
66
|
7-
help: consider returning an `impl Trait` instead of a `dyn Trait`
7+
= help: the trait `Sized` is not implemented for `(dyn Debug + 'static)`
8+
note: this type alias is unsized
9+
--> $DIR/dyn-trait-type-alias-return-type.rs:1:1
810
|
9-
LL | fn f() -> impl T { loop {} }
10-
| ++++
11-
help: alternatively, box the return type, and wrap all of the returned values in `Box::new`
12-
|
13-
LL | fn f() -> Box<dyn T> { Box::new(loop {}) }
14-
| +++++++ + +++++++++ +
11+
LL | type T = dyn core::fmt::Debug;
12+
| ^^^^^^
13+
= note: the return type of a function must have a statically known size
1514

1615
error: aborting due to 1 previous error
1716

18-
For more information about this error, try `rustc --explain E0746`.
17+
For more information about this error, try `rustc --explain E0277`.

tests/ui/unsized/issue-91801.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ pub static ALL_VALIDATORS: &[(&'static str, &'static Validator)] =
66
&[("validate that credits and debits balance", &validate_something)];
77

88
fn or<'a>(first: &'static Validator<'a>, second: &'static Validator<'a>) -> Validator<'a> {
9-
//~^ ERROR return type cannot be a trait object without pointer indirection
9+
//~^ ERROR E0277
1010
return Box::new(move |something: &'_ Something| -> Result<(), ()> {
1111
first(something).or_else(|_| second(something))
1212
});
Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
1-
error[E0746]: return type cannot be a trait object without pointer indirection
1+
error[E0277]: the size for values of type `(dyn Fn(&'a Something) -> Result<(), ()> + Send + Sync + 'a)` cannot be known at compilation time
22
--> $DIR/issue-91801.rs:8:77
33
|
44
LL | fn or<'a>(first: &'static Validator<'a>, second: &'static Validator<'a>) -> Validator<'a> {
55
| ^^^^^^^^^^^^^ doesn't have a size known at compile-time
66
|
7-
help: consider returning an `impl Trait` instead of a `dyn Trait`
7+
= help: the trait `Sized` is not implemented for `(dyn Fn(&'a Something) -> Result<(), ()> + Send + Sync + 'a)`
8+
note: this type alias is unsized
9+
--> $DIR/issue-91801.rs:3:1
810
|
9-
LL | fn or<'a>(first: &'static Validator<'a>, second: &'static Validator<'a>) -> impl Validator<'a> {
10-
| ++++
11-
help: alternatively, box the return type, and wrap all of the returned values in `Box::new`
12-
|
13-
LL | fn or<'a>(first: &'static Validator<'a>, second: &'static Validator<'a>) -> Box<dyn Validator<'a>> {
14-
| +++++++ +
11+
LL | type Validator<'a> = dyn 'a + Send + Sync + Fn(&'a Something) -> Result<(), ()>;
12+
| ^^^^^^^^^^^^^^^^^^
13+
= note: the return type of a function must have a statically known size
1514

1615
error: aborting due to 1 previous error
1716

18-
For more information about this error, try `rustc --explain E0746`.
17+
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)