Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Erroneous E0367 on struct containing a closure returning an array #58311

Closed
carado opened this issue Feb 8, 2019 · 1 comment · Fixed by #67059
Closed

Erroneous E0367 on struct containing a closure returning an array #58311

carado opened this issue Feb 8, 2019 · 1 comment · Fixed by #67059
Labels
A-typesystem Area: The type system C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@carado
Copy link

carado commented Feb 8, 2019

The following code fails in the playground, on the latest stable (1.32.0), latest beta (1.33.0-beta.6) and latest nightly (2019-02-07):

struct S<F: Fn() -> [u8; 1]>(F);

impl<F: Fn() -> [u8; 1]> Drop for S<F> {
    fn drop(&mut self) {}
}

fn main() {}

The error is the following:

error[E0367]: The requirement `<F as std::ops::FnOnce<()>>::Output == [u8; _]` is added only by the Drop impl.
 --> src/main.rs:3:1
  |
3 | / impl<F: Fn() -> [u8; 1]> Drop for S<F> {
4 | |     fn drop(&mut self) {}
5 | | }
  | |_^
  |
note: The same requirement must be part of the struct/enum definition
 --> src/main.rs:1:1
  |
1 | struct S<F: Fn() -> [u8; 1]>(F);
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

The error seems to be the same regardless of rust version, and regardless of whether the function is an Fn, an FnMut, or an FnOnce (in particular, the error mentions std::ops::FnOnce<()>>::Output even when F isn't an FnOnce, if that's relevant).

The error does not occur when the return type [u8; 1] is replaced with, for example, u8 or (u8, u8), but still occurs with a more complex type still containing an array such as (u8, [u8; 1], u8);

Have a nice day.

@carado
Copy link
Author

carado commented Feb 9, 2019

As a workaround (and in case that helps), I've found that using a type alias works.

type Array = [u8; 1];

struct S<F: Fn() -> Array>(F);

impl<F: Fn() -> Array> Drop for S<F> {
    fn drop(&mut self) {}
}

fn main() {}

Compiles as expected.

@jonas-schievink jonas-schievink added A-typesystem Area: The type system T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. C-bug Category: This is a bug. labels Feb 9, 2019
TommasoBianchi added a commit to TommasoBianchi/rust that referenced this issue Dec 5, 2019
Centril added a commit to Centril/rust that referenced this issue Dec 21, 2019
…felix

Fix too restrictive checks on Drop impls

Fixes rust-lang#34426. Fixes rust-lang#58311.

This PR completes and extends rust-lang#59497 (which has been inactive for a while now).
The problem generating both issues was that when checking that the `Predicate`s of the `Drop` impl are exactly the same as the ones of the struct definition, the check was essentially performed by a simple `==` operator, which was not handling correctly HRTBs and involved `Fn` types.

The implemented solution relies on the `relate` machinery to more correctly equate `Predicate`s, and on `anonymize_late_bound_regions` to handle HRTB in a more general way. As the `Relate` trait currently is implemented only for `TraitPredicate` and `ProjectionPredicate` (and as they were the ones generating problems), `relate` is used only for them while for other `Predicate`s the equality check is kept. I'm currently considering whether it would make sense to implement the `Relate` trait also for all other `Predicate`s to render the proposed solution more general.
@bors bors closed this as completed in 1113eb5 Dec 21, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-typesystem Area: The type system C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants