Skip to content

Commit 88ccfa4

Browse files
committed
Account for static and const in suggestion
When encountering `static FOO: Trait = ...`, if `Trait` is object safe, suggest `static FOO: Box<dyn Trait> = ...`.
1 parent 05bffa0 commit 88ccfa4

File tree

4 files changed

+107
-31
lines changed

4 files changed

+107
-31
lines changed

compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs

Lines changed: 53 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -64,24 +64,40 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
6464
));
6565
}
6666

67+
let parent = tcx.parent_hir_node(self_ty.hir_id);
6768
if self_ty.span.edition().at_least_rust_2021() {
6869
let msg = "trait objects must include the `dyn` keyword";
6970
let label = "add `dyn` keyword before this trait";
7071
let mut diag =
7172
rustc_errors::struct_span_code_err!(tcx.dcx(), self_ty.span, E0782, "{}", msg);
7273
if self_ty.span.can_be_used_for_suggestions() {
7374
if !self.maybe_suggest_impl_trait(self_ty, &mut diag) && object_safe {
74-
// Only emit this suggestion if the trait is object safe.
75-
diag.multipart_suggestion_verbose(
76-
label,
77-
sugg,
78-
Applicability::MachineApplicable,
79-
);
75+
if let hir::Node::Item(hir::Item {
76+
kind: hir::ItemKind::Static(..) | hir::ItemKind::Const(..),
77+
..
78+
}) = parent
79+
{
80+
// Statics can't be unsized, so we suggest `Box<dyn Trait>` instead.
81+
diag.multipart_suggestion_verbose(
82+
"`static` can't be unsized; use a boxed trait object",
83+
vec![
84+
(self_ty.span.shrink_to_lo(), "Box<dyn ".to_string()),
85+
(self_ty.span.shrink_to_hi(), ">".to_string()),
86+
],
87+
Applicability::MachineApplicable,
88+
);
89+
} else {
90+
// Only emit this suggestion if the trait is object safe.
91+
diag.multipart_suggestion_verbose(
92+
label,
93+
sugg,
94+
Applicability::MachineApplicable,
95+
);
96+
}
8097
}
8198
}
8299

83100
if !object_safe && self_ty.span.can_be_used_for_suggestions() {
84-
let parent = tcx.parent_hir_node(self_ty.hir_id);
85101
suggest_path_on_bare_trait(tcx, &mut diag, parent);
86102
}
87103

@@ -112,22 +128,46 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
112128
} else {
113129
tcx.node_span_lint(BARE_TRAIT_OBJECTS, self_ty.hir_id, self_ty.span, |lint| {
114130
lint.primary_message("trait objects without an explicit `dyn` are deprecated");
115-
match (object_safe, self_ty.span.can_be_used_for_suggestions()) {
116-
(true, true) => {
131+
match (object_safe, self_ty.span.can_be_used_for_suggestions(), parent) {
132+
(
133+
true,
134+
true,
135+
hir::Node::Item(hir::Item {
136+
kind: hir::ItemKind::Static(..) | hir::ItemKind::Const(..),
137+
..
138+
}),
139+
) => {
140+
// Statics can't be unsized, so we suggest `Box<dyn Trait>` instead.
141+
lint.multipart_suggestion_verbose(
142+
"`static` can't be unsized; use a boxed trait object",
143+
vec![
144+
(self_ty.span.shrink_to_lo(), "Box<dyn ".to_string()),
145+
(self_ty.span.shrink_to_hi(), ">".to_string()),
146+
],
147+
Applicability::MachineApplicable,
148+
);
149+
}
150+
(true, true, _) => {
117151
lint.multipart_suggestion_verbose(
118152
"as this is an \"object safe\" trait, write `dyn` in front of the \
119153
trait",
120154
sugg,
121155
Applicability::MachineApplicable,
122156
);
123157
}
124-
(true, false) => {
158+
(
159+
true,
160+
false,
161+
hir::Node::Item(hir::Item { kind: hir::ItemKind::Static(..), .. }),
162+
) => {
125163
lint.note(
126-
"as this is an \"object safe\" trait, you can write `dyn` in front of \
127-
the trait",
164+
"as this is an \"object safe\" trait, you can write `Box<dyn Trait>`",
128165
);
129166
}
130-
(false, _) => {
167+
(true, false, _) => {
168+
lint.note("as this is an \"object safe\" trait, you can write `dyn Trait`");
169+
}
170+
(false, _, _) => {
131171
lint.note(
132172
"you can't use write a trait object here because the trait isn't \
133173
\"object safe\"",

tests/ui/consts/const_refs_to_static-ice-121413.stderr renamed to tests/ui/consts/const_refs_to_static-ice-121413.edition2015.stderr

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0433]: failed to resolve: use of undeclared type `AtomicUsize`
2-
--> $DIR/const_refs_to_static-ice-121413.rs:8:24
2+
--> $DIR/const_refs_to_static-ice-121413.rs:11:24
33
|
44
LL | static FOO: Sync = AtomicUsize::new(0);
55
| ^^^^^^^^^^^ use of undeclared type `AtomicUsize`
@@ -10,43 +10,43 @@ LL + use std::sync::atomic::AtomicUsize;
1010
|
1111

1212
warning: trait objects without an explicit `dyn` are deprecated
13-
--> $DIR/const_refs_to_static-ice-121413.rs:8:17
13+
--> $DIR/const_refs_to_static-ice-121413.rs:11:17
1414
|
1515
LL | static FOO: Sync = AtomicUsize::new(0);
1616
| ^^^^
1717
|
1818
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
1919
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
2020
= note: `#[warn(bare_trait_objects)]` on by default
21-
help: as this is an "object safe" trait, write `dyn` in front of the trait
21+
help: `static` can't be unsized; use a boxed trait object
2222
|
23-
LL | static FOO: dyn Sync = AtomicUsize::new(0);
24-
| +++
23+
LL | static FOO: Box<dyn Sync> = AtomicUsize::new(0);
24+
| +++++++ +
2525

2626
warning: trait objects without an explicit `dyn` are deprecated
27-
--> $DIR/const_refs_to_static-ice-121413.rs:8:17
27+
--> $DIR/const_refs_to_static-ice-121413.rs:11:17
2828
|
2929
LL | static FOO: Sync = AtomicUsize::new(0);
3030
| ^^^^
3131
|
3232
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
3333
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
3434
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
35-
help: as this is an "object safe" trait, write `dyn` in front of the trait
35+
help: `static` can't be unsized; use a boxed trait object
3636
|
37-
LL | static FOO: dyn Sync = AtomicUsize::new(0);
38-
| +++
37+
LL | static FOO: Box<dyn Sync> = AtomicUsize::new(0);
38+
| +++++++ +
3939

4040
error[E0277]: the size for values of type `(dyn Sync + 'static)` cannot be known at compilation time
41-
--> $DIR/const_refs_to_static-ice-121413.rs:8:17
41+
--> $DIR/const_refs_to_static-ice-121413.rs:11:17
4242
|
4343
LL | static FOO: Sync = AtomicUsize::new(0);
4444
| ^^^^ doesn't have a size known at compile-time
4545
|
4646
= help: the trait `Sized` is not implemented for `(dyn Sync + 'static)`
4747

4848
error[E0277]: the size for values of type `(dyn Sync + 'static)` cannot be known at compilation time
49-
--> $DIR/const_refs_to_static-ice-121413.rs:8:24
49+
--> $DIR/const_refs_to_static-ice-121413.rs:11:24
5050
|
5151
LL | static FOO: Sync = AtomicUsize::new(0);
5252
| ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
error[E0433]: failed to resolve: use of undeclared type `AtomicUsize`
2+
--> $DIR/const_refs_to_static-ice-121413.rs:11:24
3+
|
4+
LL | static FOO: Sync = AtomicUsize::new(0);
5+
| ^^^^^^^^^^^ use of undeclared type `AtomicUsize`
6+
|
7+
help: consider importing one of these items
8+
|
9+
LL + use core::sync::atomic::AtomicUsize;
10+
|
11+
LL + use std::sync::atomic::AtomicUsize;
12+
|
13+
14+
error[E0782]: trait objects must include the `dyn` keyword
15+
--> $DIR/const_refs_to_static-ice-121413.rs:11:17
16+
|
17+
LL | static FOO: Sync = AtomicUsize::new(0);
18+
| ^^^^
19+
|
20+
help: `static` can't be unsized; use a boxed trait object
21+
|
22+
LL | static FOO: Box<dyn Sync> = AtomicUsize::new(0);
23+
| +++++++ +
24+
25+
error: aborting due to 2 previous errors
26+
27+
Some errors have detailed explanations: E0433, E0782.
28+
For more information about an error, try `rustc --explain E0433`.

tests/ui/consts/const_refs_to_static-ice-121413.rs

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,25 @@
22
// or with -Zextra-const-ub-checks: expected wide pointer extra data (e.g. slice length or trait object vtable)
33
// issue: rust-lang/rust#121413
44
//@ compile-flags: -Zextra-const-ub-checks
5-
// ignore-tidy-linelength
5+
//@ revisions: edition2015 edition2021
6+
//@[edition2021] edition:2021
67
#![feature(const_refs_to_static)]
78
const REF_INTERIOR_MUT: &usize = {
9+
//[edition2015]~^ HELP consider importing this struct
10+
//[edition2021]~^^ HELP consider importing one of these items
811
static FOO: Sync = AtomicUsize::new(0);
912
//~^ ERROR failed to resolve: use of undeclared type `AtomicUsize`
10-
//~| WARN trait objects without an explicit `dyn` are deprecated
11-
//~| WARN trait objects without an explicit `dyn` are deprecated
12-
//~| ERROR the size for values of type `(dyn Sync + 'static)` cannot be known at compilation time
13-
//~| ERROR the size for values of type `(dyn Sync + 'static)` cannot be known at compilation time
14-
//~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
15-
//~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
13+
//~| HELP `static` can't be unsized; use a boxed trait object
14+
//[edition2021]~^^^ ERROR trait objects must include the `dyn` keyword
15+
//[edition2015]~^^^^ WARN trait objects without an explicit `dyn` are deprecated
16+
//[edition2015]~| WARN trait objects without an explicit `dyn` are deprecated
17+
//[edition2015]~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
18+
//[edition2015]~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
19+
//[edition2015]~| HELP the trait `Sized` is not implemented for `(dyn Sync + 'static)
20+
//[edition2015]~| HELP the trait `Sized` is not implemented for `(dyn Sync + 'static)
21+
//[edition2015]~| ERROR the size for values of type `(dyn Sync + 'static)` cannot be known at compilation time
22+
//[edition2015]~| ERROR the size for values of type `(dyn Sync + 'static)` cannot be known at compilation time
23+
//[edition2015]~| HELP `static` can't be unsized; use a boxed trait object
1624
unsafe { &*(&FOO as *const _ as *const usize) }
1725
};
1826
pub fn main() {}

0 commit comments

Comments
 (0)