Skip to content

Commit 39ce238

Browse files
committed
Tweak wording and only suggest dyn Trait if Trait is object safe
1 parent 943ea75 commit 39ce238

File tree

37 files changed

+230
-518
lines changed

37 files changed

+230
-518
lines changed

compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs

Lines changed: 39 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
2020
) -> Option<ErrorGuaranteed> {
2121
let tcx = self.tcx();
2222

23-
let hir::TyKind::TraitObject([poly_trait_ref, ..], _, TraitObjectSyntax::None) =
24-
self_ty.kind
25-
else {
23+
let hir::TyKind::TraitObject(traits, _, TraitObjectSyntax::None) = self_ty.kind else {
24+
return None;
25+
};
26+
let [poly_trait_ref, ..] = traits else {
2627
return None;
2728
};
2829

@@ -36,6 +37,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
3637

3738
let is_global = poly_trait_ref.trait_ref.path.is_global();
3839

40+
let object_safe = traits.iter().all(|ptr| match ptr.trait_ref.path.res {
41+
Res::Def(DefKind::Trait, def_id) => tcx.object_safety_violations(def_id).is_empty(),
42+
_ => false,
43+
});
44+
3945
let mut sugg = vec![(
4046
self_ty.span.shrink_to_lo(),
4147
format!(
@@ -63,10 +69,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
6369
rustc_errors::struct_span_code_err!(tcx.dcx(), self_ty.span, E0782, "{}", msg);
6470
let mut downgrade = false;
6571
if self_ty.span.can_be_used_for_suggestions() {
66-
let (non_object_safe, should_downgrade) =
67-
self.maybe_suggest_impl_trait(self_ty, &mut diag);
72+
let should_downgrade = self.maybe_suggest_impl_trait(self_ty, &mut diag);
6873
downgrade = should_downgrade;
69-
if !non_object_safe {
74+
if object_safe {
7075
// Only emit this suggestion if the trait is object safe.
7176
diag.multipart_suggestion_verbose(
7277
label,
@@ -89,12 +94,27 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
8994
} else {
9095
tcx.node_span_lint(BARE_TRAIT_OBJECTS, self_ty.hir_id, self_ty.span, |lint| {
9196
lint.primary_message("trait objects without an explicit `dyn` are deprecated");
92-
if self_ty.span.can_be_used_for_suggestions() {
93-
lint.multipart_suggestion_verbose(
94-
"if this is an object-safe trait, use `dyn`",
95-
sugg,
96-
Applicability::MachineApplicable,
97-
);
97+
match (object_safe, self_ty.span.can_be_used_for_suggestions()) {
98+
(true, true) => {
99+
lint.multipart_suggestion_verbose(
100+
"as this is an \"object safe\" trait, write `dyn` in front of the \
101+
trait",
102+
sugg,
103+
Applicability::MachineApplicable,
104+
);
105+
}
106+
(true, false) => {
107+
lint.note(
108+
"as this is an \"object safe\" trait, you can write `dyn` in front of \
109+
the trait",
110+
);
111+
}
112+
(false, _) => {
113+
lint.note(
114+
"you can't use write a trait object here because the trait isn't \
115+
\"object safe\"",
116+
);
117+
}
98118
}
99119
self.maybe_suggest_blanket_trait_impl(self_ty, lint);
100120
});
@@ -170,7 +190,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
170190
/// Make sure that we are in the condition to suggest `impl Trait`.
171191
///
172192
/// Returns whether a suggestion was provided and whether the error itself should not be emitted
173-
fn maybe_suggest_impl_trait(&self, self_ty: &hir::Ty<'_>, diag: &mut Diag<'_>) -> (bool, bool) {
193+
fn maybe_suggest_impl_trait(&self, self_ty: &hir::Ty<'_>, diag: &mut Diag<'_>) -> bool {
174194
let tcx = self.tcx();
175195
let parent_id = tcx.hir().get_parent_item(self_ty.hir_id).def_id;
176196
// FIXME: If `type_alias_impl_trait` is enabled, also look for `Trait0<Ty = Trait1>`
@@ -185,10 +205,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
185205
owner_id,
186206
..
187207
}) => (sig, generics, Some(tcx.parent(owner_id.to_def_id()))),
188-
_ => return (false, false),
208+
_ => return false,
189209
};
190210
let Ok(trait_name) = tcx.sess.source_map().span_to_snippet(self_ty.span) else {
191-
return (false, false);
211+
return false;
192212
};
193213
let impl_sugg = vec![(self_ty.span.shrink_to_lo(), "impl ".to_string())];
194214
let mut is_downgradable = true;
@@ -201,7 +221,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
201221
// For recursive traits, don't downgrade the error. (#119652)
202222
is_downgradable = false;
203223
}
204-
tcx.check_is_object_safe(id)
224+
tcx.object_safety_violations(id).is_empty()
205225
}
206226
_ => false,
207227
})
@@ -234,7 +254,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
234254
// We'll emit the object safety error already, with a structured suggestion.
235255
downgrade = true;
236256
}
237-
return (true, downgrade);
257+
return downgrade;
238258
}
239259
for ty in sig.decl.inputs {
240260
if ty.hir_id != self_ty.hir_id {
@@ -279,9 +299,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
279299
Applicability::MachineApplicable,
280300
);
281301
}
282-
return (true, downgrade);
302+
return downgrade;
283303
}
284-
(false, downgrade)
304+
downgrade
285305
}
286306

287307
fn maybe_suggest_assoc_ty_bound(&self, self_ty: &hir::Ty<'_>, diag: &mut Diag<'_>) {

tests/ui/associated-type-bounds/suggest-assoc-ty-bound-on-eq-bound.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,10 @@
33

44
fn f(_: impl Trait<T = Copy>) {}
55
//~^ ERROR trait objects must include the `dyn` keyword
6-
//~| HELP add `dyn` keyword before this trait
76
//~| HELP you might have meant to write a bound here
87

98
fn g(_: impl Trait<T = std::fmt::Debug + Eq>) {}
109
//~^ ERROR trait objects must include the `dyn` keyword
11-
//~| HELP add `dyn` keyword before this trait
1210
//~| HELP you might have meant to write a bound here
1311

1412
fn h(_: impl Trait<T<> = 'static + for<'a> Fn(&'a ())>) {}
@@ -19,7 +17,6 @@ fn h(_: impl Trait<T<> = 'static + for<'a> Fn(&'a ())>) {}
1917
// Don't suggest assoc ty bound in trait object types, that's not valid:
2018
type Obj = dyn Trait<T = Clone>;
2119
//~^ ERROR trait objects must include the `dyn` keyword
22-
//~| HELP add `dyn` keyword before this trait
2320

2421
trait Trait { type T; }
2522

tests/ui/associated-type-bounds/suggest-assoc-ty-bound-on-eq-bound.stderr

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,32 +4,24 @@ error[E0782]: trait objects must include the `dyn` keyword
44
LL | fn f(_: impl Trait<T = Copy>) {}
55
| ^^^^
66
|
7-
help: add `dyn` keyword before this trait
8-
|
9-
LL | fn f(_: impl Trait<T = dyn Copy>) {}
10-
| +++
117
help: you might have meant to write a bound here
128
|
139
LL | fn f(_: impl Trait<T: Copy>) {}
1410
| ~
1511

1612
error[E0782]: trait objects must include the `dyn` keyword
17-
--> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:9:24
13+
--> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:8:24
1814
|
1915
LL | fn g(_: impl Trait<T = std::fmt::Debug + Eq>) {}
2016
| ^^^^^^^^^^^^^^^^^^^^
2117
|
22-
help: add `dyn` keyword before this trait
23-
|
24-
LL | fn g(_: impl Trait<T = dyn std::fmt::Debug + Eq>) {}
25-
| +++
2618
help: you might have meant to write a bound here
2719
|
2820
LL | fn g(_: impl Trait<T: std::fmt::Debug + Eq>) {}
2921
| ~
3022

3123
error[E0782]: trait objects must include the `dyn` keyword
32-
--> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:14:26
24+
--> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:12:26
3325
|
3426
LL | fn h(_: impl Trait<T<> = 'static + for<'a> Fn(&'a ())>) {}
3527
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -44,15 +36,10 @@ LL | fn h(_: impl Trait<T<>: 'static + for<'a> Fn(&'a ())>) {}
4436
| ~
4537

4638
error[E0782]: trait objects must include the `dyn` keyword
47-
--> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:20:26
39+
--> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:18:26
4840
|
4941
LL | type Obj = dyn Trait<T = Clone>;
5042
| ^^^^^
51-
|
52-
help: add `dyn` keyword before this trait
53-
|
54-
LL | type Obj = dyn Trait<T = dyn Clone>;
55-
| +++
5643

5744
error: aborting due to 4 previous errors
5845

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ LL | static FOO: Sync = AtomicUsize::new(0);
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: if this is an object-safe trait, use `dyn`
21+
help: as this is an "object safe" trait, write `dyn` in front of the trait
2222
|
2323
LL | static FOO: dyn Sync = AtomicUsize::new(0);
2424
| +++
@@ -32,7 +32,7 @@ LL | static FOO: Sync = AtomicUsize::new(0);
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: if this is an object-safe trait, use `dyn`
35+
help: as this is an "object safe" trait, write `dyn` in front of the trait
3636
|
3737
LL | static FOO: dyn Sync = AtomicUsize::new(0);
3838
| +++

tests/ui/did_you_mean/bad-assoc-ty.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ LL | type H = Fn(u8) -> (u8)::Output;
182182
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
183183
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
184184
= note: `#[warn(bare_trait_objects)]` on by default
185-
help: if this is an object-safe trait, use `dyn`
185+
help: as this is an "object safe" trait, write `dyn` in front of the trait
186186
|
187187
LL | type H = <dyn Fn(u8) -> (u8)>::Output;
188188
| ++++ +

tests/ui/dyn-keyword/dyn-2018-edition-lint.stderr

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ note: the lint level is defined here
1111
|
1212
LL | #[deny(bare_trait_objects)]
1313
| ^^^^^^^^^^^^^^^^^^
14-
help: if this is an object-safe trait, use `dyn`
14+
help: as this is an "object safe" trait, write `dyn` in front of the trait
1515
|
1616
LL | fn function(x: &dyn SomeTrait, y: Box<SomeTrait>) {
1717
| +++
@@ -24,7 +24,7 @@ LL | fn function(x: &SomeTrait, y: Box<SomeTrait>) {
2424
|
2525
= warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
2626
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
27-
help: if this is an object-safe trait, use `dyn`
27+
help: as this is an "object safe" trait, write `dyn` in front of the trait
2828
|
2929
LL | fn function(x: &SomeTrait, y: Box<dyn SomeTrait>) {
3030
| +++
@@ -37,7 +37,7 @@ LL | let _x: &SomeTrait = todo!();
3737
|
3838
= warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
3939
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
40-
help: if this is an object-safe trait, use `dyn`
40+
help: as this is an "object safe" trait, write `dyn` in front of the trait
4141
|
4242
LL | let _x: &dyn SomeTrait = todo!();
4343
| +++

tests/ui/dyn-keyword/dyn-angle-brackets.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ note: the lint level is defined here
1111
|
1212
LL | #![deny(bare_trait_objects)]
1313
| ^^^^^^^^^^^^^^^^^^
14-
help: if this is an object-safe trait, use `dyn`
14+
help: as this is an "object safe" trait, write `dyn` in front of the trait
1515
|
1616
LL | <dyn fmt::Debug>::fmt(self, f)
1717
| +++

tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.edition2018.stderr

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,8 @@ LL | let x: u32 = <Default>::default();
66
|
77
= warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
88
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
9+
= note: you can't use write a trait object here because the trait isn't "object safe"
910
= note: `#[warn(bare_trait_objects)]` on by default
10-
help: if this is an object-safe trait, use `dyn`
11-
|
12-
LL | let x: u32 = <dyn Default>::default();
13-
| +++
1411

1512
error[E0038]: the trait `Default` cannot be made into an object
1613
--> $DIR/trait-missing-dyn-in-qualified-path.rs:5:19

tests/ui/dyn-keyword/trait-missing-dyn-in-qualified-path.edition2021.stderr

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,6 @@ error[E0782]: trait objects must include the `dyn` keyword
33
|
44
LL | let x: u32 = <Default>::default();
55
| ^^^^^^^
6-
|
7-
help: add `dyn` keyword before this trait
8-
|
9-
LL | let x: u32 = <dyn Default>::default();
10-
| +++
116

127
error: aborting due to 1 previous error
138

tests/ui/impl-trait/fresh-lifetime-from-bare-trait-obj-114664.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ LL | fn ice() -> impl AsRef<Fn(&())> {
77
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
88
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
99
= note: `#[warn(bare_trait_objects)]` on by default
10-
help: if this is an object-safe trait, use `dyn`
10+
help: as this is an "object safe" trait, write `dyn` in front of the trait
1111
|
1212
LL | fn ice() -> impl AsRef<dyn Fn(&())> {
1313
| +++
@@ -21,7 +21,7 @@ LL | fn ice() -> impl AsRef<Fn(&())> {
2121
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
2222
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
2323
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
24-
help: if this is an object-safe trait, use `dyn`
24+
help: as this is an "object safe" trait, write `dyn` in front of the trait
2525
|
2626
LL | fn ice() -> impl AsRef<dyn Fn(&())> {
2727
| +++

tests/ui/issues/issue-28344.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ LL | let x: u8 = BitXor::bitor(0 as u8, 0 as u8);
77
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
88
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
99
= note: `#[warn(bare_trait_objects)]` on by default
10-
help: if this is an object-safe trait, use `dyn`
10+
help: as this is an "object safe" trait, write `dyn` in front of the trait
1111
|
1212
LL | let x: u8 = <dyn BitXor>::bitor(0 as u8, 0 as u8);
1313
| ++++ +
@@ -35,7 +35,7 @@ LL | let g = BitXor::bitor;
3535
|
3636
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
3737
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
38-
help: if this is an object-safe trait, use `dyn`
38+
help: as this is an "object safe" trait, write `dyn` in front of the trait
3939
|
4040
LL | let g = <dyn BitXor>::bitor;
4141
| ++++ +

tests/ui/issues/issue-58734.stderr

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,8 @@ LL | Trait::nonexistent(());
66
|
77
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
88
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
9+
= note: you can't use write a trait object here because the trait isn't "object safe"
910
= note: `#[warn(bare_trait_objects)]` on by default
10-
help: if this is an object-safe trait, use `dyn`
11-
|
12-
LL | <dyn Trait>::nonexistent(());
13-
| ++++ +
1411

1512
error[E0599]: no function or associated item named `nonexistent` found for trait object `dyn Trait` in the current scope
1613
--> $DIR/issue-58734.rs:20:12

tests/ui/issues/issue-86756.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ LL | eq::<dyn, Foo>
2121
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
2222
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
2323
= note: `#[warn(bare_trait_objects)]` on by default
24-
help: if this is an object-safe trait, use `dyn`
24+
help: as this is an "object safe" trait, write `dyn` in front of the trait
2525
|
2626
LL | eq::<dyn, dyn Foo>
2727
| +++

tests/ui/lint/bare-trait-objects-path.stderr

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ LL | let _: Dyn::Ty;
77
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
88
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
99
= note: `#[warn(bare_trait_objects)]` on by default
10-
help: if this is an object-safe trait, use `dyn`
10+
help: as this is an "object safe" trait, write `dyn` in front of the trait
1111
|
1212
LL | let _: <dyn Dyn>::Ty;
1313
| ++++ +
@@ -26,7 +26,7 @@ LL | Dyn::func();
2626
|
2727
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
2828
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
29-
help: if this is an object-safe trait, use `dyn`
29+
help: as this is an "object safe" trait, write `dyn` in front of the trait
3030
|
3131
LL | <dyn Dyn>::func();
3232
| ++++ +
@@ -39,7 +39,7 @@ LL | ::Dyn::func();
3939
|
4040
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
4141
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
42-
help: if this is an object-safe trait, use `dyn`
42+
help: as this is an "object safe" trait, write `dyn` in front of the trait
4343
|
4444
LL | <dyn (::Dyn)>::func();
4545
| ++++++ ++
@@ -52,7 +52,7 @@ LL | Dyn::CONST;
5252
|
5353
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
5454
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
55-
help: if this is an object-safe trait, use `dyn`
55+
help: as this is an "object safe" trait, write `dyn` in front of the trait
5656
|
5757
LL | <dyn Dyn>::CONST;
5858
| ++++ +

tests/ui/lint/force-warn/allowed-group-warn-by-default-lint.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ LL | pub fn function(_x: Box<SomeTrait>) {}
77
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
88
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
99
= note: requested on the command line with `--force-warn bare-trait-objects`
10-
help: if this is an object-safe trait, use `dyn`
10+
help: as this is an "object safe" trait, write `dyn` in front of the trait
1111
|
1212
LL | pub fn function(_x: Box<dyn SomeTrait>) {}
1313
| +++

tests/ui/lint/force-warn/cap-lints-allow.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ LL | pub fn function(_x: Box<SomeTrait>) {}
77
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
88
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
99
= note: requested on the command line with `--force-warn bare-trait-objects`
10-
help: if this is an object-safe trait, use `dyn`
10+
help: as this is an "object safe" trait, write `dyn` in front of the trait
1111
|
1212
LL | pub fn function(_x: Box<dyn SomeTrait>) {}
1313
| +++

0 commit comments

Comments
 (0)