Skip to content

Commit f75bcf3

Browse files
committed
Treat errors in signatures as an object safety violation
1 parent 25b706c commit f75bcf3

File tree

4 files changed

+62
-1
lines changed

4 files changed

+62
-1
lines changed

compiler/rustc_middle/src/traits/mod.rs

+6
Original file line numberDiff line numberDiff line change
@@ -820,6 +820,9 @@ impl ObjectSafetyViolation {
820820
) => {
821821
format!("method `{name}` references an `impl Trait` type in its return type").into()
822822
}
823+
ObjectSafetyViolation::Method(name, MethodViolationCode::AlreadyErrored, _) => {
824+
format!("method `{name}` has errors in its signature").into()
825+
}
823826
ObjectSafetyViolation::Method(name, MethodViolationCode::AsyncFn, _) => {
824827
format!("method `{name}` is `async`").into()
825828
}
@@ -974,6 +977,9 @@ pub enum MethodViolationCode {
974977

975978
/// the method's receiver (`self` argument) can't be dispatched on
976979
UndispatchableReceiver(Option<Span>),
980+
981+
/// The signature contained type errors, e.g. due to cycle errors
982+
AlreadyErrored,
977983
}
978984

979985
/// These are the error cases for `codegen_select_candidate`.

compiler/rustc_trait_selection/src/traits/object_safety.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,10 @@ fn virtual_call_violations_for_method<'tcx>(
419419
trait_def_id: DefId,
420420
method: ty::AssocItem,
421421
) -> Vec<MethodViolationCode> {
422-
let sig = tcx.fn_sig(method.def_id).instantiate_identity();
422+
let sig: ty::Binder<'_, ty::FnSig<'_>> = tcx.fn_sig(method.def_id).instantiate_identity();
423+
if sig.references_error() {
424+
return vec![MethodViolationCode::AlreadyErrored];
425+
}
423426

424427
// The method's first parameter must be named `self`
425428
if !method.fn_has_self_parameter {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
//! This is a regression test for an ICE.
2+
// edition: 2021
3+
4+
trait Foo {
5+
async fn foo(self: &Foo) {
6+
//~^ ERROR: `Foo` cannot be made into an object
7+
//~| ERROR invalid `self` parameter type: &dyn Foo
8+
//~| ERROR trait objects must include the `dyn` keyword
9+
todo!()
10+
}
11+
}
12+
13+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
error[E0038]: the trait `Foo` cannot be made into an object
2+
--> $DIR/inference_var_self_argument.rs:5:5
3+
|
4+
LL | async fn foo(self: &Foo) {
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object
6+
|
7+
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>
8+
--> $DIR/inference_var_self_argument.rs:5:14
9+
|
10+
LL | trait Foo {
11+
| --- this trait cannot be made into an object...
12+
LL | async fn foo(self: &Foo) {
13+
| ^^^ ...because method `foo` has errors in its signature
14+
= help: consider moving `foo` to another trait
15+
16+
error[E0307]: invalid `self` parameter type: &dyn Foo
17+
--> $DIR/inference_var_self_argument.rs:5:24
18+
|
19+
LL | async fn foo(self: &Foo) {
20+
| ^^^^
21+
|
22+
= note: type of `self` must be `Self` or a type that dereferences to it
23+
= help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
24+
25+
error[E0782]: trait objects must include the `dyn` keyword
26+
--> $DIR/inference_var_self_argument.rs:5:25
27+
|
28+
LL | async fn foo(self: &Foo) {
29+
| ^^^
30+
|
31+
help: add `dyn` keyword before this trait
32+
|
33+
LL | async fn foo(self: &dyn Foo) {
34+
| +++
35+
36+
error: aborting due to 3 previous errors
37+
38+
Some errors have detailed explanations: E0038, E0307, E0782.
39+
For more information about an error, try `rustc --explain E0038`.

0 commit comments

Comments
 (0)