From 04348c68628ef8f881c86526aacd94d030ab653d Mon Sep 17 00:00:00 2001 From: yvt Date: Thu, 10 Nov 2022 12:45:27 +0900 Subject: [PATCH] refactor(core): remove the work-around for `[ref:opaque_type_extraneous_capture]` and `[ref:rust_99793_tait]` `[ref:opaque_type_extraneous_capture]` has been resolved by [rust-lang/rust#95474][1]. TAIT in associated types seems unaffected by `[ref:rust_99793_tait]` (although it might not be so in the general case). [1]: https://github.com/rust-lang/rust/pull/95474 --- doc/toolchain_limitations.md | 52 ------------------- src/r3_core/src/bind.rs | 97 ++++++------------------------------ 2 files changed, 16 insertions(+), 133 deletions(-) diff --git a/doc/toolchain_limitations.md b/doc/toolchain_limitations.md index f2b839e473..99499fdf53 100644 --- a/doc/toolchain_limitations.md +++ b/doc/toolchain_limitations.md @@ -554,25 +554,6 @@ const _: () = tokenlock::with_branded_token(|token| { ``` -### `[tag:rust_99793_tait]` False-positive "cycle detected" in `const fn` with TAIT - -*Upstream issue:* [rust-lang/rust#99793](https://github.com/rust-lang/rust/issues/99793) (possibly related) - -```rust -#![feature(type_alias_impl_trait)] -type Unit = impl Copy; -fn unit(x: T) -> Unit { core::mem::forget(x) } -``` - -```rust,compile_fail,E0391 -#![feature(type_alias_impl_trait)] -type Unit = impl Copy; -// error[E0391]: cycle detected when computing type of -// `main::_doctest_main_lib_rs_647_0::Unit::{opaque#0} -const fn unit(x: T) -> Unit { core::mem::forget(x) } -``` - - ## Unsized types ### `[tag:unsized_maybe_uninit]` `MaybeUninit` requires `T: Sized` @@ -591,39 +572,6 @@ fn foo(_: &core::mem::MaybeUninit<[u8]>) {} ### `[tag:missing_interior_mutability_trait]` Missing trait for representing the lack of interior mutability *Upstream RFC:* [rust-lang/rfcs#2944](https://github.com/rust-lang/rfcs/pull/2944) (closed) -\ - -## Existential types - -### `[tag:opaque_type_extraneous_capture]` An opaque type captures unused generic type parameters - -It may be possible that it's an intended behavior. - -```rust -#![feature(type_alias_impl_trait)] -trait Trait { - type Projection: 'static + Send; - fn get(self) -> Self::Projection; -} -type Projection = impl 'static + Send; -impl Trait for (T, U) { - type Projection = Projection; - fn get(self) -> Self::Projection { self.1 } -} -``` - -```rust,compile_fail,E0310 -#![feature(type_alias_impl_trait)] -trait Trait { - type Projection: 'static + Send; - fn get(self) -> Self::Projection; -} -impl Trait for (T, U) { - // error[E0310]: the parameter type `T` may not live long enough - type Projection = impl 'static + Send; - fn get(self) -> Self::Projection { self.1 } -} -``` ## Macros diff --git a/src/r3_core/src/bind.rs b/src/r3_core/src/bind.rs index 8197c7ceff..9d1c537f55 100644 --- a/src/r3_core/src/bind.rs +++ b/src/r3_core/src/bind.rs @@ -1199,7 +1199,7 @@ macro_rules! impl_fn_bind { { type Output = Output; - type BoundFn = BoundFn; + type BoundFn = impl FnOnce() -> Output + Copy + Send + 'static; fn bind( self, @@ -1209,52 +1209,20 @@ macro_rules! impl_fn_bind { Binder::register_dependency(&binder, ctx); let intermediate = Binder::into_runtime_binder(binder); - BoundFn { - func: self, - runtime_binders: intermediate, + move || { + // Safety: `runtime_binders` was created by the corresponding + // type's `into_runtime_binder` method. + // `CfgBindRegistry::finalize` checks that the borrowing + // rules regarding the materialization output are observed. + // If the check fails, so does the compilation, and this + // runtime code will never be executed. + let ($( $fieldI, )*) = unsafe { + <( $( $RuntimeBinderI, )* ) as RuntimeBinder>::materialize(intermediate) + }; + self($( $fieldI, )*) } } - } - - // This opaque type must be defined outside the above `impl` to - // prevent the unintended capturing of `$BinderI`. - // [ref:opaque_type_extraneous_capture] - // type BoundFn - // where - // $( $RuntimeBinderI: RuntimeBinder, )* - // T: for<'call> FnOnce($( $RuntimeBinderI::Target<'call>, )*) - // -> Output + Copy + Send + 'static, - // = impl FnOnce() -> Output + Copy + Send + 'static; - - // FIXME: This is supposed to be a TAIT like the one above, but - // [ref:rust_99793_tait] prevents that - #[derive(Copy, Clone)] - pub struct BoundFn { - func: T, - runtime_binders: ($( $RuntimeBinderI, )*), - } - - impl FnOnce<()> for BoundFn - where - $( $RuntimeBinderI: RuntimeBinder, )* - T: for<'call> FnOnce($( $RuntimeBinderI::Target<'call>, )*) -> Output, - { - type Output = Output; - - #[inline] - extern "rust-call" fn call_once(self, (): ()) -> Output { - // Safety: `runtime_binders` was created by the corresponding - // type's `into_runtime_binder` method. - // `CfgBindRegistry::finalize` checks that the borrowing - // rules regarding the materialization output are observed. - // If the check fails, so does the compilation, and this - // runtime code will never be executed. - let ($( $fieldI, )*) = unsafe { - <( $( $RuntimeBinderI, )* ) as RuntimeBinder>::materialize(self.runtime_binders) - }; - (self.func)($( $fieldI, )*) - } - } + } // impl }; // const _ }; // end of macro arm @@ -1342,44 +1310,11 @@ where { type Output = NewOutput; - type BoundFn = MappedBoundFn; + type BoundFn = impl FnOnce() -> NewOutput + Copy + Send + 'static; fn bind(self, binder: Binder, ctx: &mut CfgBindCtx<'_>) -> Self::BoundFn { - MappedBoundFn { - inner_bound_fn: self.inner.bind(binder, ctx), - mapper: self.mapper, - } - } -} - -// // This opaque type must be defined outside this trait to -// // prevent the unintended capturing of `Binder`. -// // [ref:opaque_type_extraneous_capture] -// type MappedBoundFn -// where -// InnerBoundFn: FnOnce() -> Output + Copy + Send + 'static, -// Mapper: FnOnce(Output) -> NewOutput + Copy + Send + 'static, -// = impl FnOnce() -> NewOutput + Copy + Send + 'static; - -// FIXME: This is supposed to be a TAIT like the one above, but -// [ref:rust_99793_tait] prevents that -#[doc(hidden)] -#[derive(Copy, Clone)] -pub struct MappedBoundFn { - inner_bound_fn: InnerBoundFn, - mapper: Mapper, -} - -impl FnOnce<()> for MappedBoundFn -where - InnerBoundFn: FnOnce() -> Output + Copy + Send + 'static, - Mapper: FnOnce(Output) -> NewOutput + Copy + Send + 'static, -{ - type Output = NewOutput; - - #[inline] - extern "rust-call" fn call_once(self, (): ()) -> Self::Output { - (self.mapper)((self.inner_bound_fn)()) + let inner_bound_fn = self.inner.bind(binder, ctx); + move || (self.mapper)(inner_bound_fn()) } }