mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
Fix ICE in next-solver dyn-compatibility check
The next solver treated error-containing dispatchability goals as proven and misclassified the trait as dyn compatible. Short-circuit receivers with type errors so object-method confirmation stays on the normal error path.
This commit is contained in:
@@ -603,6 +603,9 @@ fn receiver_for_self_ty<'tcx>(
|
||||
/// contained by the trait object, because the object that needs to be coerced is behind
|
||||
/// a pointer.
|
||||
///
|
||||
/// If lowering already produced an error in the receiver type, we conservatively treat it as
|
||||
/// undispatchable instead of asking the solver.
|
||||
///
|
||||
/// In practice, we cannot use `dyn Trait` explicitly in the obligation because it would result in
|
||||
/// a new check that `Trait` is dyn-compatible, creating a cycle.
|
||||
/// Instead, we emulate a placeholder by introducing a new type parameter `U` such that
|
||||
@@ -630,6 +633,10 @@ fn receiver_is_dispatchable<'tcx>(
|
||||
) -> bool {
|
||||
debug!("receiver_is_dispatchable: method = {:?}, receiver_ty = {:?}", method, receiver_ty);
|
||||
|
||||
if receiver_ty.references_error() {
|
||||
return false;
|
||||
}
|
||||
|
||||
let (Some(unsize_did), Some(dispatch_from_dyn_did)) =
|
||||
(tcx.lang_items().unsize_trait(), tcx.lang_items().dispatch_from_dyn_trait())
|
||||
else {
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
//! Regression test for <https://github.com/rust-lang/rust/issues/151311>
|
||||
//@ edition: 2024
|
||||
//@ compile-flags: -Znext-solver=globally
|
||||
|
||||
#![feature(unsafe_binders)]
|
||||
|
||||
use std::ops::Deref;
|
||||
|
||||
trait Foo: Deref<Target = unsafe<'a> &'a dyn Bar> {
|
||||
fn method(self: &unsafe<'ops> &'a Bar) {}
|
||||
//~^ ERROR expected a type, found a trait
|
||||
//~| ERROR use of undeclared lifetime name `'a`
|
||||
}
|
||||
|
||||
trait Bar {}
|
||||
|
||||
fn test(x: &dyn Foo) {
|
||||
//~^ ERROR the trait `Foo` is not dyn compatible
|
||||
x.method();
|
||||
//~^ ERROR no method named `method` found for reference `&dyn Foo`
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,62 @@
|
||||
error[E0261]: use of undeclared lifetime name `'a`
|
||||
--> $DIR/unsafe-binders-bare-trait-object-next-solver.rs:10:36
|
||||
|
|
||||
LL | fn method(self: &unsafe<'ops> &'a Bar) {}
|
||||
| ^^ undeclared lifetime
|
||||
|
|
||||
= note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
|
||||
help: consider making the type lifetime-generic with a new `'a` lifetime
|
||||
|
|
||||
LL | fn method(self: &unsafe<'a, 'ops> &'a Bar) {}
|
||||
| +++
|
||||
help: consider introducing lifetime `'a` here
|
||||
|
|
||||
LL | fn method<'a>(self: &unsafe<'ops> &'a Bar) {}
|
||||
| ++++
|
||||
help: consider introducing lifetime `'a` here
|
||||
|
|
||||
LL | trait Foo<'a>: Deref<Target = unsafe<'a> &'a dyn Bar> {
|
||||
| ++++
|
||||
|
||||
error[E0782]: expected a type, found a trait
|
||||
--> $DIR/unsafe-binders-bare-trait-object-next-solver.rs:10:39
|
||||
|
|
||||
LL | fn method(self: &unsafe<'ops> &'a Bar) {}
|
||||
| ^^^
|
||||
|
|
||||
help: you can add the `dyn` keyword if you want a trait object
|
||||
|
|
||||
LL | fn method(self: &unsafe<'ops> &'a dyn Bar) {}
|
||||
| +++
|
||||
|
||||
error[E0038]: the trait `Foo` is not dyn compatible
|
||||
--> $DIR/unsafe-binders-bare-trait-object-next-solver.rs:17:13
|
||||
|
|
||||
LL | fn method(self: &unsafe<'ops> &'a Bar) {}
|
||||
| --------------------- help: consider changing method `method`'s `self` parameter to be `&self`: `&Self`
|
||||
...
|
||||
LL | fn test(x: &dyn Foo) {
|
||||
| ^^^^^^^ `Foo` is not dyn compatible
|
||||
|
|
||||
note: for a trait to be dyn compatible it needs to allow building a vtable
|
||||
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
|
||||
--> $DIR/unsafe-binders-bare-trait-object-next-solver.rs:10:21
|
||||
|
|
||||
LL | trait Foo: Deref<Target = unsafe<'a> &'a dyn Bar> {
|
||||
| --- this trait is not dyn compatible...
|
||||
LL | fn method(self: &unsafe<'ops> &'a Bar) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ ...because method `method`'s `self` parameter cannot be dispatched on
|
||||
|
||||
error[E0599]: no method named `method` found for reference `&dyn Foo` in the current scope
|
||||
--> $DIR/unsafe-binders-bare-trait-object-next-solver.rs:19:7
|
||||
|
|
||||
LL | fn method(self: &unsafe<'ops> &'a Bar) {}
|
||||
| --------------------- the method might not be found because of this arbitrary self type
|
||||
...
|
||||
LL | x.method();
|
||||
| ^^^^^^ method not found in `&dyn Foo`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0038, E0261, E0599, E0782.
|
||||
For more information about an error, try `rustc --explain E0038`.
|
||||
Reference in New Issue
Block a user