Skip to content

Commit f60ded9

Browse files
committed
Silence "missing dyn" error if "!Sized type" error is already emitted
1 parent d159e6c commit f60ded9

File tree

5 files changed

+231
-45
lines changed

5 files changed

+231
-45
lines changed

compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,8 +132,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
132132
],
133133
Applicability::MachineApplicable,
134134
);
135-
} else if is_downgradable {
136-
// We'll emit the object safety error already, with a structured suggestion.
135+
}
136+
if is_downgradable
137+
&& (matches!(self_ty.kind, hir::TyKind::TraitObject(_, _, TraitObjectSyntax::None))
138+
|| !is_object_safe)
139+
{
140+
// We'll emit the object safety or `!Sized` error already, with a structured
141+
// suggestion.
137142
diag.downgrade_to_delayed_bug();
138143
}
139144
return true;
@@ -163,6 +168,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
163168
diag.downgrade_to_delayed_bug();
164169
}
165170
} else {
171+
if let hir::TyKind::TraitObject(.., TraitObjectSyntax::None) = self_ty.kind
172+
&& is_downgradable
173+
{
174+
// We'll emit a `Sized` error already, with a structured suggestion.
175+
diag.downgrade_to_delayed_bug();
176+
}
166177
let sugg = if let hir::TyKind::TraitObject([_, _, ..], _, _) = self_ty.kind {
167178
// There are more than one trait bound, we need surrounding parentheses.
168179
vec![

tests/ui/traits/bound/not-on-bare-trait-2021.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,25 @@ trait Foo {
66
// This should emit the less confusing error, not the more confusing one.
77

88
fn foo(_x: Foo + Send) {
9-
//~^ ERROR trait objects must include the `dyn` keyword
10-
//~| ERROR size for values of type
9+
//~^ ERROR size for values of type
1110
}
1211
fn bar(x: Foo) -> Foo {
12+
//~^ ERROR size for values of type
13+
x
14+
}
15+
fn bat(x: &Foo) -> Foo {
16+
//~^ ERROR return type cannot have an unboxed trait object
17+
//~| ERROR trait objects must include the `dyn` keyword
18+
x
19+
}
20+
fn bae(x: &Foo) -> &Foo {
1321
//~^ ERROR trait objects must include the `dyn` keyword
1422
//~| ERROR trait objects must include the `dyn` keyword
15-
//~| ERROR size for values of type
1623
x
1724
}
25+
fn qux() -> Foo {
26+
//~^ ERROR return type cannot have an unboxed trait object
27+
todo!()
28+
}
1829

1930
fn main() {}

tests/ui/traits/bound/not-on-bare-trait-2021.stderr

Lines changed: 57 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ LL | fn foo(_x: &(dyn Foo + Send)) {
1616
| +++++ +
1717

1818
error[E0277]: the size for values of type `(dyn Foo + 'static)` cannot be known at compilation time
19-
--> $DIR/not-on-bare-trait-2021.rs:12:11
19+
--> $DIR/not-on-bare-trait-2021.rs:11:11
2020
|
2121
LL | fn bar(x: Foo) -> Foo {
2222
| ^^^ doesn't have a size known at compile-time
@@ -32,60 +32,79 @@ help: function arguments must have a statically known size, borrowed types alway
3232
LL | fn bar(x: &dyn Foo) -> Foo {
3333
| ++++
3434

35-
error[E0782]: trait objects must include the `dyn` keyword
36-
--> $DIR/not-on-bare-trait-2021.rs:8:12
35+
error[E0746]: return type cannot have an unboxed trait object
36+
--> $DIR/not-on-bare-trait-2021.rs:15:20
3737
|
38-
LL | fn foo(_x: Foo + Send) {
39-
| ^^^^^^^^^^
38+
LL | fn bat(x: &Foo) -> Foo {
39+
| ^^^ doesn't have a size known at compile-time
4040
|
41-
help: use a new generic type parameter, constrained by `Foo + Send`
41+
help: return an `impl Trait` instead of a `dyn Trait`
4242
|
43-
LL | fn foo<T: Foo + Send>(_x: T) {
44-
| +++++++++++++++ ~
45-
help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference
43+
LL | fn bat(x: &Foo) -> impl Foo {
44+
| ++++
45+
help: alternatively, box the return type to make a boxed trait object, and wrap all of the returned values in `Box::new`
4646
|
47-
LL | fn foo(_x: impl Foo + Send) {
48-
| ++++
49-
help: alternatively, use a trait object to accept any type that implements `Foo + Send`, accessing its methods at runtime using dynamic dispatch
47+
LL ~ fn bat(x: &Foo) -> Box<dyn Foo> {
48+
LL |
49+
LL |
50+
LL ~ Box::new(x)
5051
|
51-
LL | fn foo(_x: &(dyn Foo + Send)) {
52-
| +++++ +
52+
help: finally, you might be able to borrow from the function's argument
53+
|
54+
LL | fn bat(x: &Foo) -> &dyn Foo {
55+
| ++++
5356

54-
error[E0782]: trait objects must include the `dyn` keyword
55-
--> $DIR/not-on-bare-trait-2021.rs:12:11
57+
error[E0746]: return type cannot have an unboxed trait object
58+
--> $DIR/not-on-bare-trait-2021.rs:25:13
5659
|
57-
LL | fn bar(x: Foo) -> Foo {
58-
| ^^^
60+
LL | fn qux() -> Foo {
61+
| ^^^ doesn't have a size known at compile-time
5962
|
60-
help: use a new generic type parameter, constrained by `Foo`
63+
help: return an `impl Trait` instead of a `dyn Trait`
6164
|
62-
LL | fn bar<T: Foo>(x: T) -> Foo {
63-
| ++++++++ ~
64-
help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference
65+
LL | fn qux() -> impl Foo {
66+
| ++++
67+
help: alternatively, box the return type to make a boxed trait object, and wrap all of the returned values in `Box::new`
6568
|
66-
LL | fn bar(x: impl Foo) -> Foo {
67-
| ++++
68-
help: alternatively, use a trait object to accept any type that implements `Foo`, accessing its methods at runtime using dynamic dispatch
69+
LL ~ fn qux() -> Box<dyn Foo> {
70+
LL |
71+
LL ~ Box::new(todo!())
6972
|
70-
LL | fn bar(x: &dyn Foo) -> Foo {
71-
| ++++
7273

7374
error[E0782]: trait objects must include the `dyn` keyword
74-
--> $DIR/not-on-bare-trait-2021.rs:12:19
75+
--> $DIR/not-on-bare-trait-2021.rs:15:12
7576
|
76-
LL | fn bar(x: Foo) -> Foo {
77-
| ^^^
77+
LL | fn bat(x: &Foo) -> Foo {
78+
| ^^^
79+
|
80+
help: add `dyn` keyword before this trait
81+
|
82+
LL | fn bat(x: &dyn Foo) -> Foo {
83+
| +++
84+
85+
error[E0782]: trait objects must include the `dyn` keyword
86+
--> $DIR/not-on-bare-trait-2021.rs:20:12
87+
|
88+
LL | fn bae(x: &Foo) -> &Foo {
89+
| ^^^
90+
|
91+
help: add `dyn` keyword before this trait
92+
|
93+
LL | fn bae(x: &dyn Foo) -> &Foo {
94+
| +++
95+
96+
error[E0782]: trait objects must include the `dyn` keyword
97+
--> $DIR/not-on-bare-trait-2021.rs:20:21
7898
|
79-
help: use `impl Foo` to return an opaque type, as long as you return a single underlying type
99+
LL | fn bae(x: &Foo) -> &Foo {
100+
| ^^^
80101
|
81-
LL | fn bar(x: Foo) -> impl Foo {
82-
| ++++
83-
help: alternatively, you can return a boxed trait object
102+
help: add `dyn` keyword before this trait
84103
|
85-
LL | fn bar(x: Foo) -> Box<dyn Foo> {
86-
| +++++++ +
104+
LL | fn bae(x: &Foo) -> &dyn Foo {
105+
| +++
87106

88-
error: aborting due to 5 previous errors
107+
error: aborting due to 7 previous errors
89108

90-
Some errors have detailed explanations: E0277, E0782.
109+
Some errors have detailed explanations: E0277, E0746, E0782.
91110
For more information about an error, try `rustc --explain E0277`.

tests/ui/traits/bound/not-on-bare-trait.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,28 @@ fn foo(_x: Foo + Send) {
1212
fn bar(_x: (dyn Foo + Send)) {
1313
//~^ ERROR the size for values of type
1414
}
15+
fn bat(x: &Foo) -> Foo {
16+
//~^ ERROR return type cannot have an unboxed trait object
17+
//~| WARN trait objects without an explicit `dyn` are deprecated
18+
//~| WARN trait objects without an explicit `dyn` are deprecated
19+
//~| WARN trait objects without an explicit `dyn` are deprecated
20+
//~| WARN this is accepted in the current edition
21+
//~| WARN this is accepted in the current edition
22+
//~| WARN this is accepted in the current edition
23+
x
24+
}
25+
fn bae(x: &Foo) -> &Foo {
26+
//~^ WARN trait objects without an explicit `dyn` are deprecated
27+
//~| WARN trait objects without an explicit `dyn` are deprecated
28+
//~| WARN this is accepted in the current edition
29+
//~| WARN this is accepted in the current edition
30+
x
31+
}
32+
fn qux() -> Foo {
33+
//~^ ERROR return type cannot have an unboxed trait object
34+
//~| WARN trait objects without an explicit `dyn` are deprecated
35+
//~| WARN this is accepted in the current edition
36+
todo!()
37+
}
1538

1639
fn main() {}

tests/ui/traits/bound/not-on-bare-trait.stderr

Lines changed: 124 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,71 @@ help: if this is an object-safe trait, use `dyn`
1212
LL | fn foo(_x: dyn Foo + Send) {
1313
| +++
1414

15+
warning: trait objects without an explicit `dyn` are deprecated
16+
--> $DIR/not-on-bare-trait.rs:15:12
17+
|
18+
LL | fn bat(x: &Foo) -> Foo {
19+
| ^^^
20+
|
21+
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
22+
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
23+
help: if this is an object-safe trait, use `dyn`
24+
|
25+
LL | fn bat(x: &dyn Foo) -> Foo {
26+
| +++
27+
28+
warning: trait objects without an explicit `dyn` are deprecated
29+
--> $DIR/not-on-bare-trait.rs:15:20
30+
|
31+
LL | fn bat(x: &Foo) -> Foo {
32+
| ^^^
33+
|
34+
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
35+
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
36+
help: if this is an object-safe trait, use `dyn`
37+
|
38+
LL | fn bat(x: &Foo) -> dyn Foo {
39+
| +++
40+
41+
warning: trait objects without an explicit `dyn` are deprecated
42+
--> $DIR/not-on-bare-trait.rs:25:12
43+
|
44+
LL | fn bae(x: &Foo) -> &Foo {
45+
| ^^^
46+
|
47+
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
48+
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
49+
help: if this is an object-safe trait, use `dyn`
50+
|
51+
LL | fn bae(x: &dyn Foo) -> &Foo {
52+
| +++
53+
54+
warning: trait objects without an explicit `dyn` are deprecated
55+
--> $DIR/not-on-bare-trait.rs:25:21
56+
|
57+
LL | fn bae(x: &Foo) -> &Foo {
58+
| ^^^
59+
|
60+
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
61+
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
62+
help: if this is an object-safe trait, use `dyn`
63+
|
64+
LL | fn bae(x: &Foo) -> &dyn Foo {
65+
| +++
66+
67+
warning: trait objects without an explicit `dyn` are deprecated
68+
--> $DIR/not-on-bare-trait.rs:32:13
69+
|
70+
LL | fn qux() -> Foo {
71+
| ^^^
72+
|
73+
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
74+
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
75+
help: if this is an object-safe trait, use `dyn`
76+
|
77+
LL | fn qux() -> dyn Foo {
78+
| +++
79+
1580
error[E0277]: the size for values of type `(dyn Foo + Send + 'static)` cannot be known at compilation time
1681
--> $DIR/not-on-bare-trait.rs:7:12
1782
|
@@ -46,6 +111,63 @@ help: function arguments must have a statically known size, borrowed types alway
46111
LL | fn bar(_x: (&(dyn Foo + Send))) {
47112
| ++ +
48113

49-
error: aborting due to 2 previous errors; 1 warning emitted
114+
warning: trait objects without an explicit `dyn` are deprecated
115+
--> $DIR/not-on-bare-trait.rs:15:20
116+
|
117+
LL | fn bat(x: &Foo) -> Foo {
118+
| ^^^
119+
|
120+
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
121+
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
122+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
123+
help: if this is an object-safe trait, use `dyn`
124+
|
125+
LL | fn bat(x: &Foo) -> dyn Foo {
126+
| +++
127+
128+
error[E0746]: return type cannot have an unboxed trait object
129+
--> $DIR/not-on-bare-trait.rs:15:20
130+
|
131+
LL | fn bat(x: &Foo) -> Foo {
132+
| ^^^ doesn't have a size known at compile-time
133+
|
134+
help: return an `impl Trait` instead of a `dyn Trait`
135+
|
136+
LL | fn bat(x: &Foo) -> impl Foo {
137+
| ++++
138+
help: alternatively, box the return type to make a boxed trait object, and wrap all of the returned values in `Box::new`
139+
|
140+
LL ~ fn bat(x: &Foo) -> Box<dyn Foo> {
141+
LL |
142+
...
143+
LL |
144+
LL ~ Box::new(x)
145+
|
146+
help: finally, you might be able to borrow from the function's argument
147+
|
148+
LL | fn bat(x: &Foo) -> &dyn Foo {
149+
| ++++
150+
151+
error[E0746]: return type cannot have an unboxed trait object
152+
--> $DIR/not-on-bare-trait.rs:32:13
153+
|
154+
LL | fn qux() -> Foo {
155+
| ^^^ doesn't have a size known at compile-time
156+
|
157+
help: return an `impl Trait` instead of a `dyn Trait`
158+
|
159+
LL | fn qux() -> impl Foo {
160+
| ++++
161+
help: alternatively, box the return type to make a boxed trait object, and wrap all of the returned values in `Box::new`
162+
|
163+
LL ~ fn qux() -> Box<dyn Foo> {
164+
LL |
165+
LL |
166+
LL |
167+
LL ~ Box::new(todo!())
168+
|
169+
170+
error: aborting due to 4 previous errors; 7 warnings emitted
50171

51-
For more information about this error, try `rustc --explain E0277`.
172+
Some errors have detailed explanations: E0277, E0746.
173+
For more information about an error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)