Skip to content

Commit 6e4933f

Browse files
authored
Rollup merge of rust-lang#120164 - trevyn:is_downgradable, r=compiler-errors
`maybe_lint_impl_trait`: separate `is_downgradable` from `is_object_safe` rust-lang#119752 leveraged and overloaded `is_object_safe` to prevent an ICE, but accurate object safety information is needed for precise suggestions. This separates out `is_downgradable`, used for the ICE prevention, and `is_object_safe`, which returns to its original meaning.
2 parents a12e2ff + b58a8a9 commit 6e4933f

File tree

3 files changed

+65
-53
lines changed

3 files changed

+65
-53
lines changed

compiler/rustc_hir_analysis/src/astconv/lint.rs

+9-7
Original file line numberDiff line numberDiff line change
@@ -94,15 +94,17 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
9494
return false;
9595
};
9696
let impl_sugg = vec![(self_ty.span.shrink_to_lo(), "impl ".to_string())];
97+
let mut is_downgradable = true;
9798
let is_object_safe = match self_ty.kind {
9899
hir::TyKind::TraitObject(objects, ..) => {
99100
objects.iter().all(|o| match o.trait_ref.path.res {
100-
Res::Def(DefKind::Trait, id) if Some(id) == owner => {
101-
// When we're dealing with a recursive trait, we don't want to downgrade
102-
// the error, so we consider them to be object safe always. (#119652)
103-
true
101+
Res::Def(DefKind::Trait, id) => {
102+
if Some(id) == owner {
103+
// For recursive traits, don't downgrade the error. (#119652)
104+
is_downgradable = false;
105+
}
106+
tcx.check_is_object_safe(id)
104107
}
105-
Res::Def(DefKind::Trait, id) => tcx.check_is_object_safe(id),
106108
_ => false,
107109
})
108110
}
@@ -130,7 +132,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
130132
],
131133
Applicability::MachineApplicable,
132134
);
133-
} else if diag.is_error() {
135+
} else if diag.is_error() && is_downgradable {
134136
// We'll emit the object safety error already, with a structured suggestion.
135137
diag.downgrade_to_delayed_bug();
136138
}
@@ -156,7 +158,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
156158
}
157159
if !is_object_safe {
158160
diag.note(format!("`{trait_name}` it is not object safe, so it can't be `dyn`"));
159-
if diag.is_error() {
161+
if diag.is_error() && is_downgradable {
160162
// We'll emit the object safety error already, with a structured suggestion.
161163
diag.downgrade_to_delayed_bug();
162164
}

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

+4-2
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,18 @@ trait A: Sized {
88
//~| ERROR the trait `A` cannot be made into an object
99
}
1010
trait B {
11-
fn f(a: B) -> B;
11+
fn f(b: B) -> B;
1212
//~^ ERROR trait objects must include the `dyn` keyword
1313
//~| ERROR trait objects must include the `dyn` keyword
1414
//~| ERROR associated item referring to unboxed trait object for its own trait
1515
//~| ERROR the trait `B` cannot be made into an object
1616
}
1717
trait C {
18-
fn f(&self, a: C) -> C;
18+
fn f(&self, c: C) -> C;
1919
//~^ ERROR trait objects must include the `dyn` keyword
2020
//~| ERROR trait objects must include the `dyn` keyword
21+
//~| ERROR associated item referring to unboxed trait object for its own trait
22+
//~| ERROR the trait `C` cannot be made into an object
2123
}
2224

2325
fn main() {}

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

+52-44
Original file line numberDiff line numberDiff line change
@@ -30,42 +30,72 @@ error: associated item referring to unboxed trait object for its own trait
3030
|
3131
LL | trait B {
3232
| - in this trait
33-
LL | fn f(a: B) -> B;
33+
LL | fn f(b: B) -> B;
3434
| ^ ^
3535
|
3636
help: you might have meant to use `Self` to refer to the implementing type
3737
|
38-
LL | fn f(a: Self) -> Self;
38+
LL | fn f(b: Self) -> Self;
3939
| ~~~~ ~~~~
4040

4141
error[E0038]: the trait `B` cannot be made into an object
4242
--> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:11:13
4343
|
44-
LL | fn f(a: B) -> B;
44+
LL | fn f(b: B) -> B;
4545
| ^ `B` cannot be made into an object
4646
|
4747
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>
4848
--> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:11:8
4949
|
5050
LL | trait B {
5151
| - this trait cannot be made into an object...
52-
LL | fn f(a: B) -> B;
52+
LL | fn f(b: B) -> B;
5353
| ^ ...because associated function `f` has no `self` parameter
5454
help: consider turning `f` into a method by giving it a `&self` argument
5555
|
56-
LL | fn f(&self, a: B) -> B;
56+
LL | fn f(&self, b: B) -> B;
5757
| ++++++
5858
help: alternatively, consider constraining `f` so it does not apply to trait objects
5959
|
60-
LL | fn f(a: B) -> B where Self: Sized;
60+
LL | fn f(b: B) -> B where Self: Sized;
6161
| +++++++++++++++++
6262

63+
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
65+
|
66+
LL | trait C {
67+
| - in this trait
68+
LL | fn f(&self, c: C) -> C;
69+
| ^ ^
70+
|
71+
help: you might have meant to use `Self` to refer to the implementing type
72+
|
73+
LL | fn f(&self, c: Self) -> Self;
74+
| ~~~~ ~~~~
75+
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+
6392
error[E0782]: trait objects must include the `dyn` keyword
6493
--> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:4:13
6594
|
6695
LL | fn f(a: A) -> A;
6796
| ^
6897
|
98+
= note: `A` it is not object safe, so it can't be `dyn`
6999
help: use a new generic type parameter, constrained by `A`
70100
|
71101
LL | fn f<T: A>(a: T) -> A;
@@ -74,95 +104,73 @@ help: you can also use an opaque type, but users won't be able to specify the ty
74104
|
75105
LL | fn f(a: impl A) -> A;
76106
| ++++
77-
help: alternatively, use a trait object to accept any type that implements `A`, accessing its methods at runtime using dynamic dispatch
78-
|
79-
LL | fn f(a: &dyn A) -> A;
80-
| ++++
81107

82108
error[E0782]: trait objects must include the `dyn` keyword
83109
--> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:4:19
84110
|
85111
LL | fn f(a: A) -> A;
86112
| ^
87113
|
88-
help: use `impl A` to return an opaque type, as long as you return a single underlying type
114+
help: `A` is not object safe, use `impl A` to return an opaque type, as long as you return a single underlying type
89115
|
90116
LL | fn f(a: A) -> impl A;
91117
| ++++
92-
help: alternatively, you can return an owned trait object
93-
|
94-
LL | fn f(a: A) -> Box<dyn A>;
95-
| +++++++ +
96118

97119
error[E0782]: trait objects must include the `dyn` keyword
98120
--> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:11:13
99121
|
100-
LL | fn f(a: B) -> B;
122+
LL | fn f(b: B) -> B;
101123
| ^
102124
|
125+
= note: `B` it is not object safe, so it can't be `dyn`
103126
help: use a new generic type parameter, constrained by `B`
104127
|
105-
LL | fn f<T: B>(a: T) -> B;
128+
LL | fn f<T: B>(b: T) -> B;
106129
| ++++++ ~
107130
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
108131
|
109-
LL | fn f(a: impl B) -> B;
110-
| ++++
111-
help: alternatively, use a trait object to accept any type that implements `B`, accessing its methods at runtime using dynamic dispatch
112-
|
113-
LL | fn f(a: &dyn B) -> B;
132+
LL | fn f(b: impl B) -> B;
114133
| ++++
115134

116135
error[E0782]: trait objects must include the `dyn` keyword
117136
--> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:11:19
118137
|
119-
LL | fn f(a: B) -> B;
138+
LL | fn f(b: B) -> B;
120139
| ^
121140
|
122-
help: use `impl B` to return an opaque type, as long as you return a single underlying type
141+
help: `B` is not object safe, use `impl B` to return an opaque type, as long as you return a single underlying type
123142
|
124-
LL | fn f(a: B) -> impl B;
143+
LL | fn f(b: B) -> impl B;
125144
| ++++
126-
help: alternatively, you can return an owned trait object
127-
|
128-
LL | fn f(a: B) -> Box<dyn B>;
129-
| +++++++ +
130145

131146
error[E0782]: trait objects must include the `dyn` keyword
132147
--> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:18:20
133148
|
134-
LL | fn f(&self, a: C) -> C;
149+
LL | fn f(&self, c: C) -> C;
135150
| ^
136151
|
152+
= note: `C` it is not object safe, so it can't be `dyn`
137153
help: use a new generic type parameter, constrained by `C`
138154
|
139-
LL | fn f<T: C>(&self, a: T) -> C;
155+
LL | fn f<T: C>(&self, c: T) -> C;
140156
| ++++++ ~
141157
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
142158
|
143-
LL | fn f(&self, a: impl C) -> C;
144-
| ++++
145-
help: alternatively, use a trait object to accept any type that implements `C`, accessing its methods at runtime using dynamic dispatch
146-
|
147-
LL | fn f(&self, a: &dyn C) -> C;
159+
LL | fn f(&self, c: impl C) -> C;
148160
| ++++
149161

150162
error[E0782]: trait objects must include the `dyn` keyword
151163
--> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:18:26
152164
|
153-
LL | fn f(&self, a: C) -> C;
165+
LL | fn f(&self, c: C) -> C;
154166
| ^
155167
|
156-
help: use `impl C` to return an opaque type, as long as you return a single underlying type
168+
help: `C` is not object safe, use `impl C` to return an opaque type, as long as you return a single underlying type
157169
|
158-
LL | fn f(&self, a: C) -> impl C;
170+
LL | fn f(&self, c: C) -> impl C;
159171
| ++++
160-
help: alternatively, you can return an owned trait object
161-
|
162-
LL | fn f(&self, a: C) -> Box<dyn C>;
163-
| +++++++ +
164172

165-
error: aborting due to 10 previous errors
173+
error: aborting due to 12 previous errors
166174

167175
Some errors have detailed explanations: E0038, E0782.
168176
For more information about an error, try `rustc --explain E0038`.

0 commit comments

Comments
 (0)