Skip to content

Commit 177d513

Browse files
authored
Rollup merge of rust-lang#119752 - estebank:ice-ice, r=fmease
Avoid ICEs in trait names without `dyn` Check diagnostic is error before downgrading. Fix rust-lang#119633. Account for traits using self-trait by name without `dyn`. Fix rust-lang#119652.
2 parents 2de5ca2 + 7edbc95 commit 177d513

11 files changed

+553
-11
lines changed

compiler/rustc_hir_analysis/src/astconv/lint.rs

+21-11
Original file line numberDiff line numberDiff line change
@@ -78,14 +78,17 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
7878
fn maybe_lint_impl_trait(&self, self_ty: &hir::Ty<'_>, diag: &mut Diagnostic) -> bool {
7979
let tcx = self.tcx();
8080
let parent_id = tcx.hir().get_parent_item(self_ty.hir_id).def_id;
81-
let (hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, generics, _), .. })
82-
| hir::Node::TraitItem(hir::TraitItem {
83-
kind: hir::TraitItemKind::Fn(sig, _),
84-
generics,
85-
..
86-
})) = tcx.hir_node_by_def_id(parent_id)
87-
else {
88-
return false;
81+
let (sig, generics, owner) = match tcx.hir_node_by_def_id(parent_id) {
82+
hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, generics, _), .. }) => {
83+
(sig, generics, None)
84+
}
85+
hir::Node::TraitItem(hir::TraitItem {
86+
kind: hir::TraitItemKind::Fn(sig, _),
87+
generics,
88+
owner_id,
89+
..
90+
}) => (sig, generics, Some(tcx.parent(owner_id.to_def_id()))),
91+
_ => return false,
8992
};
9093
let Ok(trait_name) = tcx.sess.source_map().span_to_snippet(self_ty.span) else {
9194
return false;
@@ -94,6 +97,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
9497
let is_object_safe = match self_ty.kind {
9598
hir::TyKind::TraitObject(objects, ..) => {
9699
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
104+
}
97105
Res::Def(DefKind::Trait, id) => tcx.check_is_object_safe(id),
98106
_ => false,
99107
})
@@ -122,7 +130,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
122130
],
123131
Applicability::MachineApplicable,
124132
);
125-
} else {
133+
} else if diag.is_error() {
126134
// We'll emit the object safety error already, with a structured suggestion.
127135
diag.downgrade_to_delayed_bug();
128136
}
@@ -148,8 +156,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
148156
}
149157
if !is_object_safe {
150158
diag.note(format!("`{trait_name}` it is not object safe, so it can't be `dyn`"));
151-
// We'll emit the object safety error already, with a structured suggestion.
152-
diag.downgrade_to_delayed_bug();
159+
if diag.is_error() {
160+
// We'll emit the object safety error already, with a structured suggestion.
161+
diag.downgrade_to_delayed_bug();
162+
}
153163
} else {
154164
let sugg = if let hir::TyKind::TraitObject([_, _, ..], _, _) = self_ty.kind {
155165
// There are more than one trait bound, we need surrounding parentheses.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
fn id<F>(f: Copy) -> usize {
2+
//~^ WARN trait objects without an explicit `dyn` are deprecated
3+
//~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
4+
//~| WARN trait objects without an explicit `dyn` are deprecated
5+
//~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
6+
//~| ERROR the trait `Copy` cannot be made into an object
7+
f()
8+
}
9+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
warning: trait objects without an explicit `dyn` are deprecated
2+
--> $DIR/avoid-ice-on-warning-2.rs:1:13
3+
|
4+
LL | fn id<F>(f: Copy) -> usize {
5+
| ^^^^
6+
|
7+
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
8+
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
9+
= note: `Copy` it is not object safe, so it can't be `dyn`
10+
= note: `#[warn(bare_trait_objects)]` on by default
11+
help: use a new generic type parameter, constrained by `Copy`
12+
|
13+
LL | fn id<F, T: Copy>(f: T) -> usize {
14+
| +++++++++ ~
15+
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
16+
|
17+
LL | fn id<F>(f: impl Copy) -> usize {
18+
| ++++
19+
20+
warning: trait objects without an explicit `dyn` are deprecated
21+
--> $DIR/avoid-ice-on-warning-2.rs:1:13
22+
|
23+
LL | fn id<F>(f: Copy) -> usize {
24+
| ^^^^
25+
|
26+
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
27+
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
28+
= note: `Copy` it is not object safe, so it can't be `dyn`
29+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
30+
help: use a new generic type parameter, constrained by `Copy`
31+
|
32+
LL | fn id<F, T: Copy>(f: T) -> usize {
33+
| +++++++++ ~
34+
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
35+
|
36+
LL | fn id<F>(f: impl Copy) -> usize {
37+
| ++++
38+
39+
error[E0038]: the trait `Copy` cannot be made into an object
40+
--> $DIR/avoid-ice-on-warning-2.rs:1:13
41+
|
42+
LL | fn id<F>(f: Copy) -> usize {
43+
| ^^^^ `Copy` cannot be made into an object
44+
|
45+
= note: the trait cannot be made into an object because it requires `Self: Sized`
46+
= 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>
47+
48+
error: aborting due to 1 previous error; 2 warnings emitted
49+
50+
For more information about this error, try `rustc --explain E0038`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
trait B { fn f(a: A) -> A; }
2+
//~^ WARN trait objects without an explicit `dyn` are deprecated
3+
//~| WARN trait objects without an explicit `dyn` are deprecated
4+
//~| WARN trait objects without an explicit `dyn` are deprecated
5+
//~| WARN this is accepted in the current edition
6+
//~| WARN this is accepted in the current edition
7+
//~| WARN this is accepted in the current edition
8+
//~| ERROR the trait `A` cannot be made into an object
9+
trait A { fn g(b: B) -> B; }
10+
//~^ WARN trait objects without an explicit `dyn` are deprecated
11+
//~| WARN trait objects without an explicit `dyn` are deprecated
12+
//~| WARN trait objects without an explicit `dyn` are deprecated
13+
//~| WARN this is accepted in the current edition
14+
//~| WARN this is accepted in the current edition
15+
//~| WARN this is accepted in the current edition
16+
//~| ERROR the trait `B` cannot be made into an object
17+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
warning: trait objects without an explicit `dyn` are deprecated
2+
--> $DIR/avoid-ice-on-warning-3.rs:9:19
3+
|
4+
LL | trait A { fn g(b: B) -> B; }
5+
| ^
6+
|
7+
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
8+
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
9+
= note: `B` it is not object safe, so it can't be `dyn`
10+
= note: `#[warn(bare_trait_objects)]` on by default
11+
help: use a new generic type parameter, constrained by `B`
12+
|
13+
LL | trait A { fn g<T: B>(b: T) -> B; }
14+
| ++++++ ~
15+
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
16+
|
17+
LL | trait A { fn g(b: impl B) -> B; }
18+
| ++++
19+
20+
warning: trait objects without an explicit `dyn` are deprecated
21+
--> $DIR/avoid-ice-on-warning-3.rs:9:25
22+
|
23+
LL | trait A { fn g(b: B) -> B; }
24+
| ^
25+
|
26+
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
27+
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
28+
help: `B` is not object safe, use `impl B` to return an opaque type, as long as you return a single underlying type
29+
|
30+
LL | trait A { fn g(b: B) -> impl B; }
31+
| ++++
32+
33+
warning: trait objects without an explicit `dyn` are deprecated
34+
--> $DIR/avoid-ice-on-warning-3.rs:1:19
35+
|
36+
LL | trait B { fn f(a: A) -> A; }
37+
| ^
38+
|
39+
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
40+
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
41+
= note: `A` it is not object safe, so it can't be `dyn`
42+
help: use a new generic type parameter, constrained by `A`
43+
|
44+
LL | trait B { fn f<T: A>(a: T) -> A; }
45+
| ++++++ ~
46+
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
47+
|
48+
LL | trait B { fn f(a: impl A) -> A; }
49+
| ++++
50+
51+
warning: trait objects without an explicit `dyn` are deprecated
52+
--> $DIR/avoid-ice-on-warning-3.rs:1:25
53+
|
54+
LL | trait B { fn f(a: A) -> A; }
55+
| ^
56+
|
57+
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
58+
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
59+
help: `A` is not object safe, use `impl A` to return an opaque type, as long as you return a single underlying type
60+
|
61+
LL | trait B { fn f(a: A) -> impl A; }
62+
| ++++
63+
64+
warning: trait objects without an explicit `dyn` are deprecated
65+
--> $DIR/avoid-ice-on-warning-3.rs:1:19
66+
|
67+
LL | trait B { fn f(a: A) -> A; }
68+
| ^
69+
|
70+
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
71+
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
72+
= note: `A` it is not object safe, so it can't be `dyn`
73+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
74+
help: use a new generic type parameter, constrained by `A`
75+
|
76+
LL | trait B { fn f<T: A>(a: T) -> A; }
77+
| ++++++ ~
78+
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
79+
|
80+
LL | trait B { fn f(a: impl A) -> A; }
81+
| ++++
82+
83+
error[E0038]: the trait `A` cannot be made into an object
84+
--> $DIR/avoid-ice-on-warning-3.rs:1:19
85+
|
86+
LL | trait B { fn f(a: A) -> A; }
87+
| ^ `A` cannot be made into an object
88+
|
89+
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>
90+
--> $DIR/avoid-ice-on-warning-3.rs:9:14
91+
|
92+
LL | trait A { fn g(b: B) -> B; }
93+
| - ^ ...because associated function `g` has no `self` parameter
94+
| |
95+
| this trait cannot be made into an object...
96+
help: consider turning `g` into a method by giving it a `&self` argument
97+
|
98+
LL | trait A { fn g(&self, b: B) -> B; }
99+
| ++++++
100+
help: alternatively, consider constraining `g` so it does not apply to trait objects
101+
|
102+
LL | trait A { fn g(b: B) -> B where Self: Sized; }
103+
| +++++++++++++++++
104+
105+
warning: trait objects without an explicit `dyn` are deprecated
106+
--> $DIR/avoid-ice-on-warning-3.rs:9:19
107+
|
108+
LL | trait A { fn g(b: B) -> B; }
109+
| ^
110+
|
111+
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
112+
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
113+
= note: `B` it is not object safe, so it can't be `dyn`
114+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
115+
help: use a new generic type parameter, constrained by `B`
116+
|
117+
LL | trait A { fn g<T: B>(b: T) -> B; }
118+
| ++++++ ~
119+
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
120+
|
121+
LL | trait A { fn g(b: impl B) -> B; }
122+
| ++++
123+
124+
error[E0038]: the trait `B` cannot be made into an object
125+
--> $DIR/avoid-ice-on-warning-3.rs:9:19
126+
|
127+
LL | trait A { fn g(b: B) -> B; }
128+
| ^ `B` cannot be made into an object
129+
|
130+
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>
131+
--> $DIR/avoid-ice-on-warning-3.rs:1:14
132+
|
133+
LL | trait B { fn f(a: A) -> A; }
134+
| - ^ ...because associated function `f` has no `self` parameter
135+
| |
136+
| this trait cannot be made into an object...
137+
help: consider turning `f` into a method by giving it a `&self` argument
138+
|
139+
LL | trait B { fn f(&self, a: A) -> A; }
140+
| ++++++
141+
help: alternatively, consider constraining `f` so it does not apply to trait objects
142+
|
143+
LL | trait B { fn f(a: A) -> A where Self: Sized; }
144+
| +++++++++++++++++
145+
146+
error: aborting due to 2 previous errors; 6 warnings emitted
147+
148+
For more information about this error, try `rustc --explain E0038`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
fn call_this<F>(f: F) : Fn(&str) + call_that {}
2+
//~^ ERROR return types are denoted using `->`
3+
//~| ERROR cannot find trait `call_that` in this scope
4+
//~| WARN trait objects without an explicit `dyn` are deprecated
5+
//~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
6+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
error: return types are denoted using `->`
2+
--> $DIR/avoid-ice-on-warning.rs:1:23
3+
|
4+
LL | fn call_this<F>(f: F) : Fn(&str) + call_that {}
5+
| ^ help: use `->` instead
6+
7+
error[E0405]: cannot find trait `call_that` in this scope
8+
--> $DIR/avoid-ice-on-warning.rs:1:36
9+
|
10+
LL | fn call_this<F>(f: F) : Fn(&str) + call_that {}
11+
| ^^^^^^^^^ not found in this scope
12+
13+
warning: trait objects without an explicit `dyn` are deprecated
14+
--> $DIR/avoid-ice-on-warning.rs:1:25
15+
|
16+
LL | fn call_this<F>(f: F) : Fn(&str) + call_that {}
17+
| ^^^^^^^^^^^^^^^^^^^^
18+
|
19+
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
20+
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
21+
= note: `#[warn(bare_trait_objects)]` on by default
22+
help: `Fn(&str) + call_that` is not object safe, use `impl Fn(&str) + call_that` to return an opaque type, as long as you return a single underlying type
23+
|
24+
LL | fn call_this<F>(f: F) : impl Fn(&str) + call_that {}
25+
| ++++
26+
27+
error: aborting due to 2 previous errors; 1 warning emitted
28+
29+
For more information about this error, try `rustc --explain E0405`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// edition:2021
2+
#![allow(bare_trait_objects)]
3+
trait A: Sized {
4+
fn f(a: A) -> A;
5+
//~^ ERROR trait objects must include the `dyn` keyword
6+
//~| ERROR trait objects must include the `dyn` keyword
7+
//~| ERROR associated item referring to unboxed trait object for its own trait
8+
//~| ERROR the trait `A` cannot be made into an object
9+
}
10+
trait B {
11+
fn f(a: B) -> B;
12+
//~^ ERROR trait objects must include the `dyn` keyword
13+
//~| ERROR trait objects must include the `dyn` keyword
14+
//~| ERROR associated item referring to unboxed trait object for its own trait
15+
//~| ERROR the trait `B` cannot be made into an object
16+
}
17+
trait C {
18+
fn f(&self, a: C) -> C;
19+
//~^ ERROR trait objects must include the `dyn` keyword
20+
//~| ERROR trait objects must include the `dyn` keyword
21+
}
22+
23+
fn main() {}

0 commit comments

Comments
 (0)