Skip to content

Commit

Permalink
refactor(core): remove the work-around for `[ref:opaque_type_extraneo…
Browse files Browse the repository at this point in the history
…us_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]: rust-lang/rust#95474
  • Loading branch information
yvt committed Nov 10, 2022
1 parent 67972c7 commit 04348c6
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 133 deletions.
52 changes: 0 additions & 52 deletions doc/toolchain_limitations.md
Original file line number Diff line number Diff line change
Expand Up @@ -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<T> = impl Copy;
fn unit<T>(x: T) -> Unit<T> { core::mem::forget(x) }
```

```rust,compile_fail,E0391
#![feature(type_alias_impl_trait)]
type Unit<T> = impl Copy;
// error[E0391]: cycle detected when computing type of
// `main::_doctest_main_lib_rs_647_0::Unit::{opaque#0}
const fn unit<T>(x: T) -> Unit<T> { core::mem::forget(x) }
```


## Unsized types

### `[tag:unsized_maybe_uninit]` `MaybeUninit<T>` requires `T: Sized`
Expand All @@ -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<U: 'static + Send> = impl 'static + Send;
impl<T, U: 'static + Send> Trait for (T, U) {
type Projection = Projection<U>;
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<T, U: 'static + Send> 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
Expand Down
97 changes: 16 additions & 81 deletions src/r3_core/src/bind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1199,7 +1199,7 @@ macro_rules! impl_fn_bind {
{
type Output = Output;

type BoundFn = BoundFn<T, $( $RuntimeBinderI, )*>;
type BoundFn = impl FnOnce() -> Output + Copy + Send + 'static;

fn bind(
self,
Expand All @@ -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<T, Output, $( $RuntimeBinderI, )*>
// 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<T, $( $RuntimeBinderI, )*> {
func: T,
runtime_binders: ($( $RuntimeBinderI, )*),
}

impl<T, Output, $( $RuntimeBinderI, )*> FnOnce<()> for BoundFn<T, $( $RuntimeBinderI, )*>
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

Expand Down Expand Up @@ -1342,44 +1310,11 @@ where
{
type Output = NewOutput;

type BoundFn = MappedBoundFn<InnerBoundFn, Mapper>;
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<InnerBoundFn, Output, Mapper, NewOutput>
// 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<InnerBoundFn, Mapper> {
inner_bound_fn: InnerBoundFn,
mapper: Mapper,
}

impl<InnerBoundFn, Output, Mapper, NewOutput> FnOnce<()> for MappedBoundFn<InnerBoundFn, Mapper>
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())
}
}

Expand Down

0 comments on commit 04348c6

Please sign in to comment.