Rollup merge of #108203 - compiler-errors:rpitit-fix-defaults-2, r=jackh726
Fix RPITITs in default trait methods (by assuming projection predicates in param-env) Instead of having special projection logic that allows us to turn `ProjectionTy(RPITIT, [Self#0, ...])` into `OpaqueTy(RPITIT, [Self#0, ...])`, we can instead augment the param-env of default trait method bodies to assume these as projection predicates. This should allow us to only project where we're allowed to! In order to make this work without introducing a bunch of cycle errors, we additionally tweak the `OpaqueTypeExpander` used by `ParamEnv::with_reveal_all_normalized` to not normalize the right-hand side of projection predicates. This should be fine, because if we use the projection predicate to normalize some other projection type, we'll continue to normalize the opaque that it gets projected to. This also makes it possible to support default trait methods with RPITITs in an associated-type based RPITIT lowering strategy without too much extra effort. Fixes #107002 Alternative to #108142
This commit is contained in:
commit
d2aef58eb5
6 changed files with 161 additions and 37 deletions
66
tests/ui/async-await/in-trait/async-default-fn-overridden.rs
Normal file
66
tests/ui/async-await/in-trait/async-default-fn-overridden.rs
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
// run-pass
|
||||
// edition:2021
|
||||
|
||||
#![feature(async_fn_in_trait)]
|
||||
//~^ WARN the feature `async_fn_in_trait` is incomplete and may not be safe to use
|
||||
|
||||
use std::future::Future;
|
||||
|
||||
trait AsyncTrait {
|
||||
async fn default_impl() {
|
||||
assert!(false);
|
||||
}
|
||||
|
||||
async fn call_default_impl() {
|
||||
Self::default_impl().await
|
||||
}
|
||||
}
|
||||
|
||||
struct AsyncType;
|
||||
|
||||
impl AsyncTrait for AsyncType {
|
||||
async fn default_impl() {
|
||||
// :)
|
||||
}
|
||||
}
|
||||
|
||||
async fn async_main() {
|
||||
// Should not assert false
|
||||
AsyncType::call_default_impl().await;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------- //
|
||||
// Implementation Details Below...
|
||||
|
||||
use std::pin::Pin;
|
||||
use std::task::*;
|
||||
|
||||
pub fn noop_waker() -> Waker {
|
||||
let raw = RawWaker::new(std::ptr::null(), &NOOP_WAKER_VTABLE);
|
||||
|
||||
// SAFETY: the contracts for RawWaker and RawWakerVTable are upheld
|
||||
unsafe { Waker::from_raw(raw) }
|
||||
}
|
||||
|
||||
const NOOP_WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new(noop_clone, noop, noop, noop);
|
||||
|
||||
unsafe fn noop_clone(_p: *const ()) -> RawWaker {
|
||||
RawWaker::new(std::ptr::null(), &NOOP_WAKER_VTABLE)
|
||||
}
|
||||
|
||||
unsafe fn noop(_p: *const ()) {}
|
||||
|
||||
fn main() {
|
||||
let mut fut = async_main();
|
||||
|
||||
// Poll loop, just to test the future...
|
||||
let waker = noop_waker();
|
||||
let ctx = &mut Context::from_waker(&waker);
|
||||
|
||||
loop {
|
||||
match unsafe { Pin::new_unchecked(&mut fut).poll(ctx) } {
|
||||
Poll::Pending => {}
|
||||
Poll::Ready(()) => break,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/async-default-fn-overridden.rs:4:12
|
||||
|
|
||||
LL | #![feature(async_fn_in_trait)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue