Skip to content

Commit f617130

Browse files
committed
Avoid potential for ICE by not stashing delayed as bug error and silence more redundant errors
Instead of calling `dowgrade_to_delayed_bug` and then stashing a diagnostic, we either stash the diagnostic or we `delay_as_bug` it. Remove unnecessary restriction of silencing of knock down errors on bare trait objects in edition >=2021.
1 parent 8539a6a commit f617130

File tree

8 files changed

+51
-156
lines changed

8 files changed

+51
-156
lines changed

compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -61,16 +61,31 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
6161
let label = "add `dyn` keyword before this trait";
6262
let mut diag =
6363
rustc_errors::struct_span_code_err!(tcx.dcx(), self_ty.span, E0782, "{}", msg);
64-
if self_ty.span.can_be_used_for_suggestions()
65-
&& !self.maybe_suggest_impl_trait(self_ty, &mut diag)
66-
{
67-
// FIXME: Only emit this suggestion if the trait is object safe.
68-
diag.multipart_suggestion_verbose(label, sugg, Applicability::MachineApplicable);
64+
let mut downgrade = false;
65+
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);
68+
downgrade = should_downgrade;
69+
if !non_object_safe {
70+
// Only emit this suggestion if the trait is object safe.
71+
diag.multipart_suggestion_verbose(
72+
label,
73+
sugg,
74+
Applicability::MachineApplicable,
75+
);
76+
}
6977
}
7078
// Check if the impl trait that we are considering is an impl of a local trait.
7179
self.maybe_suggest_blanket_trait_impl(self_ty, &mut diag);
7280
self.maybe_suggest_assoc_ty_bound(self_ty, &mut diag);
73-
diag.stash(self_ty.span, StashKey::TraitMissingMethod)
81+
if downgrade {
82+
// FIXME: Delayed bugs and stashing are not compatible, so we paper over it here by
83+
// consuming the diagnostic without emitting it, instead of downgrading it.
84+
diag.delay_as_bug();
85+
None
86+
} else {
87+
diag.stash(self_ty.span, StashKey::TraitMissingMethod)
88+
}
7489
} else {
7590
tcx.node_span_lint(BARE_TRAIT_OBJECTS, self_ty.hir_id, self_ty.span, |lint| {
7691
lint.primary_message("trait objects without an explicit `dyn` are deprecated");
@@ -153,7 +168,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
153168
}
154169

155170
/// Make sure that we are in the condition to suggest `impl Trait`.
156-
fn maybe_suggest_impl_trait(&self, self_ty: &hir::Ty<'_>, diag: &mut Diag<'_>) -> bool {
171+
///
172+
/// 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) {
157174
let tcx = self.tcx();
158175
let parent_id = tcx.hir().get_parent_item(self_ty.hir_id).def_id;
159176
// FIXME: If `type_alias_impl_trait` is enabled, also look for `Trait0<Ty = Trait1>`
@@ -168,13 +185,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
168185
owner_id,
169186
..
170187
}) => (sig, generics, Some(tcx.parent(owner_id.to_def_id()))),
171-
_ => return false,
188+
_ => return (false, false),
172189
};
173190
let Ok(trait_name) = tcx.sess.source_map().span_to_snippet(self_ty.span) else {
174-
return false;
191+
return (false, false);
175192
};
176193
let impl_sugg = vec![(self_ty.span.shrink_to_lo(), "impl ".to_string())];
177194
let mut is_downgradable = true;
195+
let mut downgrade = false;
178196
let is_object_safe = match self_ty.kind {
179197
hir::TyKind::TraitObject(objects, ..) => {
180198
objects.iter().all(|o| match o.trait_ref.path.res {
@@ -214,9 +232,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
214232
);
215233
} else if is_downgradable {
216234
// We'll emit the object safety error already, with a structured suggestion.
217-
diag.downgrade_to_delayed_bug();
235+
downgrade = true;
218236
}
219-
return true;
237+
return (true, downgrade);
220238
}
221239
for ty in sig.decl.inputs {
222240
if ty.hir_id != self_ty.hir_id {
@@ -240,7 +258,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
240258
diag.note(format!("`{trait_name}` it is not object safe, so it can't be `dyn`"));
241259
if is_downgradable {
242260
// We'll emit the object safety error already, with a structured suggestion.
243-
diag.downgrade_to_delayed_bug();
261+
downgrade = true;
244262
}
245263
} else {
246264
let sugg = if let hir::TyKind::TraitObject([_, _, ..], _, _) = self_ty.kind {
@@ -261,9 +279,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
261279
Applicability::MachineApplicable,
262280
);
263281
}
264-
return true;
282+
return (true, downgrade);
265283
}
266-
false
284+
(false, downgrade)
267285
}
268286

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

compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2081,16 +2081,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
20812081
}
20822082
hir::TyKind::TraitObject(bounds, lifetime, repr) => {
20832083
if let Some(guard) = self.prohibit_or_lint_bare_trait_object_ty(hir_ty, in_path) {
2084-
if let hir::Node::Item(_) | hir::Node::TraitItem(_) | hir::Node::ImplItem(_) =
2085-
tcx.parent_hir_node(hir_ty.hir_id)
2086-
{
2087-
// `tests/ui/suggestions/issue-116434-2021.rs` and others would otherwise
2088-
// fail with no error beign emitted. We restrict the silencing only to
2089-
// expressions, as those *will* emit the error *and* also produce further
2090-
// knock-down errors.
2091-
} else {
2092-
return Ty::new_error(tcx, guard);
2093-
}
2084+
return Ty::new_error(tcx, guard);
20942085
}
20952086

20962087
let repr = match repr {

tests/ui/suggestions/object-unsafe-trait-should-use-self-2021-without-dyn.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,18 @@ trait A: Sized {
55
//~^ ERROR trait objects must include the `dyn` keyword
66
//~| ERROR trait objects must include the `dyn` keyword
77
//~| ERROR associated item referring to unboxed trait object for its own trait
8-
//~| ERROR the trait `A` cannot be made into an object
98
}
109
trait B {
1110
fn f(b: B) -> B;
1211
//~^ ERROR trait objects must include the `dyn` keyword
1312
//~| ERROR trait objects must include the `dyn` keyword
1413
//~| ERROR associated item referring to unboxed trait object for its own trait
15-
//~| ERROR the trait `B` cannot be made into an object
1614
}
1715
trait C {
1816
fn f(&self, c: C) -> C;
1917
//~^ ERROR trait objects must include the `dyn` keyword
2018
//~| ERROR trait objects must include the `dyn` keyword
2119
//~| ERROR associated item referring to unboxed trait object for its own trait
22-
//~| ERROR the trait `C` cannot be made into an object
2320
}
2421

2522
fn main() {}

tests/ui/suggestions/object-unsafe-trait-should-use-self-2021-without-dyn.stderr

Lines changed: 8 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,8 @@ help: you might have meant to use `Self` to refer to the implementing type
1111
LL | fn f(a: Self) -> Self;
1212
| ~~~~ ~~~~
1313

14-
error[E0038]: the trait `A` cannot be made into an object
15-
--> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:4:13
16-
|
17-
LL | fn f(a: A) -> A;
18-
| ^ `A` cannot be made into an object
19-
|
20-
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
21-
--> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:3:10
22-
|
23-
LL | trait A: Sized {
24-
| - ^^^^^ ...because it requires `Self: Sized`
25-
| |
26-
| this trait cannot be made into an object...
27-
2814
error: associated item referring to unboxed trait object for its own trait
29-
--> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:11:13
15+
--> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:10:13
3016
|
3117
LL | trait B {
3218
| - in this trait
@@ -38,30 +24,8 @@ help: you might have meant to use `Self` to refer to the implementing type
3824
LL | fn f(b: Self) -> Self;
3925
| ~~~~ ~~~~
4026

41-
error[E0038]: the trait `B` cannot be made into an object
42-
--> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:11:13
43-
|
44-
LL | fn f(b: B) -> B;
45-
| ^ `B` cannot be made into an object
46-
|
47-
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
48-
--> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:11:8
49-
|
50-
LL | trait B {
51-
| - this trait cannot be made into an object...
52-
LL | fn f(b: B) -> B;
53-
| ^ ...because associated function `f` has no `self` parameter
54-
help: consider turning `f` into a method by giving it a `&self` argument
55-
|
56-
LL | fn f(&self, b: B) -> B;
57-
| ++++++
58-
help: alternatively, consider constraining `f` so it does not apply to trait objects
59-
|
60-
LL | fn f(b: B) -> B where Self: Sized;
61-
| +++++++++++++++++
62-
6327
error: associated item referring to unboxed trait object for its own trait
64-
--> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:18:20
28+
--> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:16:20
6529
|
6630
LL | trait C {
6731
| - in this trait
@@ -73,22 +37,6 @@ help: you might have meant to use `Self` to refer to the implementing type
7337
LL | fn f(&self, c: Self) -> Self;
7438
| ~~~~ ~~~~
7539

76-
error[E0038]: the trait `C` cannot be made into an object
77-
--> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:18:20
78-
|
79-
LL | fn f(&self, c: C) -> C;
80-
| ----- ^ `C` cannot be made into an object
81-
| |
82-
| help: consider changing method `f`'s `self` parameter to be `&self` (notice the capitalization): `&Self`
83-
|
84-
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
85-
--> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:18:10
86-
|
87-
LL | trait C {
88-
| - this trait cannot be made into an object...
89-
LL | fn f(&self, c: C) -> C;
90-
| ^^^^^ ...because method `f`'s `self` parameter cannot be dispatched on
91-
9240
error[E0782]: trait objects must include the `dyn` keyword
9341
--> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:4:13
9442
|
@@ -117,7 +65,7 @@ LL | fn f(a: A) -> impl A;
11765
| ++++
11866

11967
error[E0782]: trait objects must include the `dyn` keyword
120-
--> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:11:13
68+
--> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:10:13
12169
|
12270
LL | fn f(b: B) -> B;
12371
| ^
@@ -133,7 +81,7 @@ LL | fn f(b: impl B) -> B;
13381
| ++++
13482

13583
error[E0782]: trait objects must include the `dyn` keyword
136-
--> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:11:19
84+
--> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:10:19
13785
|
13886
LL | fn f(b: B) -> B;
13987
| ^
@@ -144,7 +92,7 @@ LL | fn f(b: B) -> impl B;
14492
| ++++
14593

14694
error[E0782]: trait objects must include the `dyn` keyword
147-
--> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:18:20
95+
--> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:16:20
14896
|
14997
LL | fn f(&self, c: C) -> C;
15098
| ^
@@ -160,7 +108,7 @@ LL | fn f(&self, c: impl C) -> C;
160108
| ++++
161109

162110
error[E0782]: trait objects must include the `dyn` keyword
163-
--> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:18:26
111+
--> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:16:26
164112
|
165113
LL | fn f(&self, c: C) -> C;
166114
| ^
@@ -170,7 +118,6 @@ help: `C` is not object safe, use `impl C` to return an opaque type, as long as
170118
LL | fn f(&self, c: C) -> impl C;
171119
| ++++
172120

173-
error: aborting due to 12 previous errors
121+
error: aborting due to 9 previous errors
174122

175-
Some errors have detailed explanations: E0038, E0782.
176-
For more information about an error, try `rustc --explain E0038`.
123+
For more information about this error, try `rustc --explain E0782`.

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,10 @@ trait Foo {
77

88
fn foo(_x: Foo + Send) {
99
//~^ ERROR trait objects must include the `dyn` keyword
10-
//~| ERROR size for values of type
1110
}
1211
fn bar(x: Foo) -> Foo {
1312
//~^ ERROR trait objects must include the `dyn` keyword
1413
//~| ERROR trait objects must include the `dyn` keyword
15-
//~| ERROR size for values of type
1614
x
1715
}
1816

Lines changed: 4 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,3 @@
1-
error[E0277]: the size for values of type `(dyn Foo + Send + 'static)` cannot be known at compilation time
2-
--> $DIR/not-on-bare-trait-2021.rs:8:8
3-
|
4-
LL | fn foo(_x: Foo + Send) {
5-
| ^^ doesn't have a size known at compile-time
6-
|
7-
= help: the trait `Sized` is not implemented for `(dyn Foo + Send + 'static)`
8-
= help: unsized fn params are gated as an unstable feature
9-
help: you can use `impl Trait` as the argument type
10-
|
11-
LL | fn foo(_x: impl Foo + Send) {
12-
| ++++
13-
help: function arguments must have a statically known size, borrowed types always have a known size
14-
|
15-
LL | fn foo(_x: &(dyn Foo + Send)) {
16-
| +++++ +
17-
18-
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:8
20-
|
21-
LL | fn bar(x: Foo) -> Foo {
22-
| ^ doesn't have a size known at compile-time
23-
|
24-
= help: the trait `Sized` is not implemented for `(dyn Foo + 'static)`
25-
= help: unsized fn params are gated as an unstable feature
26-
help: you can use `impl Trait` as the argument type
27-
|
28-
LL | fn bar(x: impl Foo) -> Foo {
29-
| ++++
30-
help: function arguments must have a statically known size, borrowed types always have a known size
31-
|
32-
LL | fn bar(x: &dyn Foo) -> Foo {
33-
| ++++
34-
351
error[E0782]: trait objects must include the `dyn` keyword
362
--> $DIR/not-on-bare-trait-2021.rs:8:12
373
|
@@ -52,7 +18,7 @@ LL | fn foo(_x: &(dyn Foo + Send)) {
5218
| +++++ +
5319

5420
error[E0782]: trait objects must include the `dyn` keyword
55-
--> $DIR/not-on-bare-trait-2021.rs:12:11
21+
--> $DIR/not-on-bare-trait-2021.rs:11:11
5622
|
5723
LL | fn bar(x: Foo) -> Foo {
5824
| ^^^
@@ -71,7 +37,7 @@ LL | fn bar(x: &dyn Foo) -> Foo {
7137
| ++++
7238

7339
error[E0782]: trait objects must include the `dyn` keyword
74-
--> $DIR/not-on-bare-trait-2021.rs:12:19
40+
--> $DIR/not-on-bare-trait-2021.rs:11:19
7541
|
7642
LL | fn bar(x: Foo) -> Foo {
7743
| ^^^
@@ -85,7 +51,6 @@ help: alternatively, you can return an owned trait object
8551
LL | fn bar(x: Foo) -> Box<dyn Foo> {
8652
| +++++++ +
8753

88-
error: aborting due to 5 previous errors
54+
error: aborting due to 3 previous errors
8955

90-
Some errors have detailed explanations: E0277, E0782.
91-
For more information about an error, try `rustc --explain E0277`.
56+
For more information about this error, try `rustc --explain E0782`.

tests/ui/traits/issue-106072.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
#[derive(Clone)] //~ trait objects must include the `dyn` keyword
2-
//~^ ERROR: the size for values of type `(dyn Foo + 'static)` cannot be known
3-
//~| ERROR: return type cannot have an unboxed trait object
1+
#[derive(Clone)] //~ERROR trait objects must include the `dyn` keyword
42
struct Foo;
5-
trait Foo {} //~ the name `Foo` is defined multiple times
3+
trait Foo {} //~ERROR the name `Foo` is defined multiple times
64
fn main() {}

tests/ui/traits/issue-106072.stderr

Lines changed: 4 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0428]: the name `Foo` is defined multiple times
2-
--> $DIR/issue-106072.rs:5:1
2+
--> $DIR/issue-106072.rs:3:1
33
|
44
LL | struct Foo;
55
| ----------- previous definition of the type `Foo` here
@@ -8,25 +8,6 @@ LL | trait Foo {}
88
|
99
= note: `Foo` must be defined only once in the type namespace of this module
1010

11-
error[E0277]: the size for values of type `(dyn Foo + 'static)` cannot be known at compilation time
12-
--> $DIR/issue-106072.rs:1:10
13-
|
14-
LL | #[derive(Clone)]
15-
| ^^^^^ doesn't have a size known at compile-time
16-
|
17-
= help: the trait `Sized` is not implemented for `(dyn Foo + 'static)`
18-
note: required by a bound in `Clone`
19-
--> $SRC_DIR/core/src/clone.rs:LL:COL
20-
= note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
21-
22-
error[E0746]: return type cannot have an unboxed trait object
23-
--> $DIR/issue-106072.rs:1:10
24-
|
25-
LL | #[derive(Clone)]
26-
| ^^^^^ doesn't have a size known at compile-time
27-
|
28-
= note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
29-
3011
error[E0782]: trait objects must include the `dyn` keyword
3112
--> $DIR/issue-106072.rs:1:10
3213
|
@@ -35,7 +16,7 @@ LL | #[derive(Clone)]
3516
|
3617
= note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
3718

38-
error: aborting due to 4 previous errors
19+
error: aborting due to 2 previous errors
3920

40-
Some errors have detailed explanations: E0277, E0428, E0746, E0782.
41-
For more information about an error, try `rustc --explain E0277`.
21+
Some errors have detailed explanations: E0428, E0782.
22+
For more information about an error, try `rustc --explain E0428`.

0 commit comments

Comments
 (0)