Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 177d513

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

11 files changed

+553
-11
lines changed
 

‎compiler/rustc_hir_analysis/src/astconv/lint.rs

Lines changed: 21 additions & 11 deletions
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.
Lines changed: 9 additions & 0 deletions
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() {}
Lines changed: 50 additions & 0 deletions
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`.
Lines changed: 17 additions & 0 deletions
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() {}
Lines changed: 148 additions & 0 deletions
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`.
Lines changed: 6 additions & 0 deletions
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() {}
Lines changed: 29 additions & 0 deletions
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`.
Lines changed: 23 additions & 0 deletions
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() {}
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
error: associated item referring to unboxed trait object for its own trait
2+
--> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:4:13
3+
|
4+
LL | trait A: Sized {
5+
| - in this trait
6+
LL | fn f(a: A) -> A;
7+
| ^ ^
8+
|
9+
help: you might have meant to use `Self` to refer to the implementing type
10+
|
11+
LL | fn f(a: Self) -> Self;
12+
| ~~~~ ~~~~
13+
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+
28+
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
30+
|
31+
LL | trait B {
32+
| - in this trait
33+
LL | fn f(a: B) -> B;
34+
| ^ ^
35+
|
36+
help: you might have meant to use `Self` to refer to the implementing type
37+
|
38+
LL | fn f(a: Self) -> Self;
39+
| ~~~~ ~~~~
40+
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(a: 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(a: 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, a: B) -> B;
57+
| ++++++
58+
help: alternatively, consider constraining `f` so it does not apply to trait objects
59+
|
60+
LL | fn f(a: B) -> B where Self: Sized;
61+
| +++++++++++++++++
62+
63+
error[E0782]: trait objects must include the `dyn` keyword
64+
--> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:4:13
65+
|
66+
LL | fn f(a: A) -> A;
67+
| ^
68+
|
69+
help: use a new generic type parameter, constrained by `A`
70+
|
71+
LL | fn f<T: A>(a: T) -> A;
72+
| ++++++ ~
73+
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
74+
|
75+
LL | fn f(a: impl A) -> A;
76+
| ++++
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+
| ++++
81+
82+
error[E0782]: trait objects must include the `dyn` keyword
83+
--> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:4:19
84+
|
85+
LL | fn f(a: A) -> A;
86+
| ^
87+
|
88+
help: use `impl A` to return an opaque type, as long as you return a single underlying type
89+
|
90+
LL | fn f(a: A) -> impl A;
91+
| ++++
92+
help: alternatively, you can return an owned trait object
93+
|
94+
LL | fn f(a: A) -> Box<dyn A>;
95+
| +++++++ +
96+
97+
error[E0782]: trait objects must include the `dyn` keyword
98+
--> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:11:13
99+
|
100+
LL | fn f(a: B) -> B;
101+
| ^
102+
|
103+
help: use a new generic type parameter, constrained by `B`
104+
|
105+
LL | fn f<T: B>(a: T) -> B;
106+
| ++++++ ~
107+
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
108+
|
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;
114+
| ++++
115+
116+
error[E0782]: trait objects must include the `dyn` keyword
117+
--> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:11:19
118+
|
119+
LL | fn f(a: B) -> B;
120+
| ^
121+
|
122+
help: use `impl B` to return an opaque type, as long as you return a single underlying type
123+
|
124+
LL | fn f(a: B) -> impl B;
125+
| ++++
126+
help: alternatively, you can return an owned trait object
127+
|
128+
LL | fn f(a: B) -> Box<dyn B>;
129+
| +++++++ +
130+
131+
error[E0782]: trait objects must include the `dyn` keyword
132+
--> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:18:20
133+
|
134+
LL | fn f(&self, a: C) -> C;
135+
| ^
136+
|
137+
help: use a new generic type parameter, constrained by `C`
138+
|
139+
LL | fn f<T: C>(&self, a: T) -> C;
140+
| ++++++ ~
141+
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
142+
|
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;
148+
| ++++
149+
150+
error[E0782]: trait objects must include the `dyn` keyword
151+
--> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:18:26
152+
|
153+
LL | fn f(&self, a: C) -> C;
154+
| ^
155+
|
156+
help: use `impl C` to return an opaque type, as long as you return a single underlying type
157+
|
158+
LL | fn f(&self, a: C) -> impl C;
159+
| ++++
160+
help: alternatively, you can return an owned trait object
161+
|
162+
LL | fn f(&self, a: C) -> Box<dyn C>;
163+
| +++++++ +
164+
165+
error: aborting due to 10 previous errors
166+
167+
Some errors have detailed explanations: E0038, E0782.
168+
For more information about an error, try `rustc --explain E0038`.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// edition:2021
2+
#![allow(bare_trait_objects)]
3+
trait A: Sized {
4+
fn f(a: dyn A) -> dyn A;
5+
//~^ ERROR associated item referring to unboxed trait object for its own trait
6+
//~| ERROR the trait `A` cannot be made into an object
7+
}
8+
trait B {
9+
fn f(a: dyn B) -> dyn B;
10+
//~^ ERROR associated item referring to unboxed trait object for its own trait
11+
//~| ERROR the trait `B` cannot be made into an object
12+
}
13+
trait C {
14+
fn f(&self, a: dyn C) -> dyn C;
15+
}
16+
17+
fn main() {}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
error: associated item referring to unboxed trait object for its own trait
2+
--> $DIR/object-unsafe-trait-should-use-self-2021.rs:4:13
3+
|
4+
LL | trait A: Sized {
5+
| - in this trait
6+
LL | fn f(a: dyn A) -> dyn A;
7+
| ^^^^^ ^^^^^
8+
|
9+
help: you might have meant to use `Self` to refer to the implementing type
10+
|
11+
LL | fn f(a: Self) -> Self;
12+
| ~~~~ ~~~~
13+
14+
error[E0038]: the trait `A` cannot be made into an object
15+
--> $DIR/object-unsafe-trait-should-use-self-2021.rs:4:13
16+
|
17+
LL | fn f(a: dyn A) -> dyn 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.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+
28+
error: associated item referring to unboxed trait object for its own trait
29+
--> $DIR/object-unsafe-trait-should-use-self-2021.rs:9:13
30+
|
31+
LL | trait B {
32+
| - in this trait
33+
LL | fn f(a: dyn B) -> dyn B;
34+
| ^^^^^ ^^^^^
35+
|
36+
help: you might have meant to use `Self` to refer to the implementing type
37+
|
38+
LL | fn f(a: Self) -> Self;
39+
| ~~~~ ~~~~
40+
41+
error[E0038]: the trait `B` cannot be made into an object
42+
--> $DIR/object-unsafe-trait-should-use-self-2021.rs:9:13
43+
|
44+
LL | fn f(a: dyn B) -> dyn 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.rs:9:8
49+
|
50+
LL | trait B {
51+
| - this trait cannot be made into an object...
52+
LL | fn f(a: dyn B) -> dyn 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, a: dyn B) -> dyn B;
57+
| ++++++
58+
help: alternatively, consider constraining `f` so it does not apply to trait objects
59+
|
60+
LL | fn f(a: dyn B) -> dyn B where Self: Sized;
61+
| +++++++++++++++++
62+
63+
error: aborting due to 4 previous errors
64+
65+
For more information about this error, try `rustc --explain E0038`.

0 commit comments

Comments
 (0)
Please sign in to comment.