Skip to content

Commit

Permalink
Treat errors in signatures as an object safety violation
Browse files Browse the repository at this point in the history
  • Loading branch information
oli-obk committed Jan 17, 2024
1 parent 25b706c commit f75bcf3
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 1 deletion.
6 changes: 6 additions & 0 deletions compiler/rustc_middle/src/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -820,6 +820,9 @@ impl ObjectSafetyViolation {
) => {
format!("method `{name}` references an `impl Trait` type in its return type").into()
}
ObjectSafetyViolation::Method(name, MethodViolationCode::AlreadyErrored, _) => {
format!("method `{name}` has errors in its signature").into()
}
ObjectSafetyViolation::Method(name, MethodViolationCode::AsyncFn, _) => {
format!("method `{name}` is `async`").into()
}
Expand Down Expand Up @@ -974,6 +977,9 @@ pub enum MethodViolationCode {

/// the method's receiver (`self` argument) can't be dispatched on
UndispatchableReceiver(Option<Span>),

/// The signature contained type errors, e.g. due to cycle errors
AlreadyErrored,
}

/// These are the error cases for `codegen_select_candidate`.
Expand Down
5 changes: 4 additions & 1 deletion compiler/rustc_trait_selection/src/traits/object_safety.rs
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,10 @@ fn virtual_call_violations_for_method<'tcx>(
trait_def_id: DefId,
method: ty::AssocItem,
) -> Vec<MethodViolationCode> {
let sig = tcx.fn_sig(method.def_id).instantiate_identity();
let sig: ty::Binder<'_, ty::FnSig<'_>> = tcx.fn_sig(method.def_id).instantiate_identity();
if sig.references_error() {
return vec![MethodViolationCode::AlreadyErrored];
}

// The method's first parameter must be named `self`
if !method.fn_has_self_parameter {
Expand Down
13 changes: 13 additions & 0 deletions tests/ui/async-await/inference_var_self_argument.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//! This is a regression test for an ICE.
// edition: 2021

trait Foo {
async fn foo(self: &Foo) {
//~^ ERROR: `Foo` cannot be made into an object
//~| ERROR invalid `self` parameter type: &dyn Foo
//~| ERROR trait objects must include the `dyn` keyword
todo!()
}
}

fn main() {}
39 changes: 39 additions & 0 deletions tests/ui/async-await/inference_var_self_argument.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
error[E0038]: the trait `Foo` cannot be made into an object
--> $DIR/inference_var_self_argument.rs:5:5
|
LL | async fn foo(self: &Foo) {
| ^^^^^^^^^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object
|
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>
--> $DIR/inference_var_self_argument.rs:5:14
|
LL | trait Foo {
| --- this trait cannot be made into an object...
LL | async fn foo(self: &Foo) {
| ^^^ ...because method `foo` has errors in its signature
= help: consider moving `foo` to another trait

error[E0307]: invalid `self` parameter type: &dyn Foo
--> $DIR/inference_var_self_argument.rs:5:24
|
LL | async fn foo(self: &Foo) {
| ^^^^
|
= note: type of `self` must be `Self` or a type that dereferences to it
= 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`)

error[E0782]: trait objects must include the `dyn` keyword
--> $DIR/inference_var_self_argument.rs:5:25
|
LL | async fn foo(self: &Foo) {
| ^^^
|
help: add `dyn` keyword before this trait
|
LL | async fn foo(self: &dyn Foo) {
| +++

error: aborting due to 3 previous errors

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

0 comments on commit f75bcf3

Please sign in to comment.