fudge infer vars in cause code intentionally
This commit is contained in:
parent
fb505a7985
commit
b111aed11f
6 changed files with 152 additions and 0 deletions
|
|
@ -37,6 +37,8 @@ use crate::infer::InferCtxt;
|
|||
#[derive(Clone, TypeFoldable, TypeVisitable)]
|
||||
pub struct Obligation<'tcx, T> {
|
||||
/// The reason we have to prove this thing.
|
||||
/// FIXME: we shouldn't ignore the cause but instead change the affected visitors
|
||||
/// to only visit predicates manually.
|
||||
#[type_foldable(identity)]
|
||||
#[type_visitable(ignore)]
|
||||
pub cause: ObligationCause<'tcx>,
|
||||
|
|
|
|||
|
|
@ -177,7 +177,11 @@ fn find_best_leaf_obligation<'tcx>(
|
|||
)
|
||||
.break_value()
|
||||
.ok_or(())
|
||||
// walk around the fact that the cause in `Obligation` is ignored by folders so that
|
||||
// we can properly fudge the infer vars in cause code.
|
||||
.map(|o| (o.cause.clone(), o))
|
||||
})
|
||||
.map(|(cause, o)| PredicateObligation { cause, ..o })
|
||||
.unwrap_or(obligation);
|
||||
deeply_normalize_for_diagnostics(infcx, obligation.param_env, obligation)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,43 @@
|
|||
//@ compile-flags: -Znext-solver
|
||||
//@ edition: 2024
|
||||
//
|
||||
// A regression test for the ICE variant in trait-system-refactor-initiative#245.
|
||||
// We'll meet regions that're already popped off when using parent predicate in cause code.
|
||||
// `cause` in `Obligation` is ignored by folders/visitors.
|
||||
// In this case, `fudge_inference_if_ok` doesn't fudge a region var in cause code.
|
||||
//
|
||||
// The old solver doesn't trigger ICE because regions in the predicate are replaced with
|
||||
// placeholders when checking generator witness. Besides, the old solver doesn't eagerly
|
||||
// resolves vars before canonicalizing the predicate in `predicate_must_hold_modulo_regions`.
|
||||
|
||||
trait AsyncFn: Send + 'static {
|
||||
type Fut: Future<Output = ()> + Send;
|
||||
|
||||
fn call(&self) -> Self::Fut;
|
||||
}
|
||||
|
||||
async fn wrap_call<P: AsyncFn + ?Sized>(filter: &P) {
|
||||
filter.call().await;
|
||||
}
|
||||
|
||||
fn get_boxed_fn() -> Box<DynAsyncFnBoxed> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
async fn cursed_fut() {
|
||||
wrap_call(get_boxed_fn().as_ref()).await;
|
||||
}
|
||||
|
||||
fn observe_fut_not_send() {
|
||||
assert_send(cursed_fut());
|
||||
//~^ ERROR: `dyn AsyncFn<Fut = Pin<Box<dyn Future<Output = ()> + Send>>>` cannot be shared between threads safely [E0277]
|
||||
}
|
||||
|
||||
fn assert_send<T: Send>(t: T) -> T {
|
||||
t
|
||||
}
|
||||
|
||||
pub type BoxFuture<'a, T> = std::pin::Pin<Box<dyn Future<Output = T> + Send + 'a>>;
|
||||
type DynAsyncFnBoxed = dyn AsyncFn<Fut = BoxFuture<'static, ()>>;
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
error[E0277]: `dyn AsyncFn<Fut = Pin<Box<dyn Future<Output = ()> + Send>>>` cannot be shared between threads safely
|
||||
--> $DIR/leaking-vars-in-cause-code-1.rs:32:17
|
||||
|
|
||||
LL | assert_send(cursed_fut());
|
||||
| ----------- ^^^^^^^^^^^^ `dyn AsyncFn<Fut = Pin<Box<dyn Future<Output = ()> + Send>>>` cannot be shared between threads safely
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= help: the trait `Sync` is not implemented for `dyn AsyncFn<Fut = Pin<Box<dyn Future<Output = ()> + Send>>>`
|
||||
= note: required for `&dyn AsyncFn<Fut = Pin<Box<dyn Future<Output = ()> + Send>>>` to implement `Send`
|
||||
note: required because it's used within this `async` fn body
|
||||
--> $DIR/leaking-vars-in-cause-code-1.rs:19:53
|
||||
|
|
||||
LL | async fn wrap_call<P: AsyncFn + ?Sized>(filter: &P) {
|
||||
| _____________________________________________________^
|
||||
LL | | filter.call().await;
|
||||
LL | | }
|
||||
| |_^
|
||||
note: required because it's used within this `async` fn body
|
||||
--> $DIR/leaking-vars-in-cause-code-1.rs:27:23
|
||||
|
|
||||
LL | async fn cursed_fut() {
|
||||
| _______________________^
|
||||
LL | | wrap_call(get_boxed_fn().as_ref()).await;
|
||||
LL | | }
|
||||
| |_^
|
||||
note: required by a bound in `assert_send`
|
||||
--> $DIR/leaking-vars-in-cause-code-1.rs:36:19
|
||||
|
|
||||
LL | fn assert_send<T: Send>(t: T) -> T {
|
||||
| ^^^^ required by this bound in `assert_send`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
//@ compile-flags: -Znext-solver
|
||||
|
||||
// The `cause` in `Obligation` is ignored by type folders. So infer vars in cause code is not
|
||||
// fudged.
|
||||
// Check the comments of
|
||||
// `leaking-vars-in-cause-code-1.rs` for more details.
|
||||
trait Trait<T> {}
|
||||
struct A<T>(T);
|
||||
struct B<T>(T);
|
||||
|
||||
trait IncompleteGuidance {}
|
||||
|
||||
impl<T> Trait<()> for A<T>
|
||||
where
|
||||
T: IncompleteGuidance,
|
||||
{
|
||||
}
|
||||
|
||||
impl<T, U> Trait<()> for B<T>
|
||||
//~^ ERROR: the type parameter `U` is not constrained by the impl trait, self type, or predicates
|
||||
where
|
||||
A<T>: Trait<U>,
|
||||
{
|
||||
}
|
||||
|
||||
fn impls_trait<T: Trait<()>>() {}
|
||||
|
||||
fn main() {
|
||||
impls_trait::<B<()>>();
|
||||
//~^ ERROR: the trait bound `(): IncompleteGuidance` is not satisfied
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates
|
||||
--> $DIR/leaking-vars-in-cause-code-2.rs:19:9
|
||||
|
|
||||
LL | impl<T, U> Trait<()> for B<T>
|
||||
| ^ unconstrained type parameter
|
||||
|
||||
error[E0277]: the trait bound `(): IncompleteGuidance` is not satisfied
|
||||
--> $DIR/leaking-vars-in-cause-code-2.rs:29:19
|
||||
|
|
||||
LL | impls_trait::<B<()>>();
|
||||
| ^^^^^ the trait `IncompleteGuidance` is not implemented for `()`
|
||||
|
|
||||
help: this trait has no implementations, consider adding one
|
||||
--> $DIR/leaking-vars-in-cause-code-2.rs:11:1
|
||||
|
|
||||
LL | trait IncompleteGuidance {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: required for `A<()>` to implement `Trait<()>`
|
||||
--> $DIR/leaking-vars-in-cause-code-2.rs:13:9
|
||||
|
|
||||
LL | impl<T> Trait<()> for A<T>
|
||||
| ^^^^^^^^^ ^^^^
|
||||
LL | where
|
||||
LL | T: IncompleteGuidance,
|
||||
| ------------------ unsatisfied trait bound introduced here
|
||||
= note: 1 redundant requirement hidden
|
||||
= note: required for `B<()>` to implement `Trait<()>`
|
||||
note: required by a bound in `impls_trait`
|
||||
--> $DIR/leaking-vars-in-cause-code-2.rs:26:19
|
||||
|
|
||||
LL | fn impls_trait<T: Trait<()>>() {}
|
||||
| ^^^^^^^^^ required by this bound in `impls_trait`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0207, E0277.
|
||||
For more information about an error, try `rustc --explain E0207`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue