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

<Box<T> as Deref>::Target is not equivalent to T in this case. #76956

Closed
someguynamedjosh opened this issue Sep 20, 2020 · 6 comments · Fixed by #90017
Closed

<Box<T> as Deref>::Target is not equivalent to T in this case. #76956

someguynamedjosh opened this issue Sep 20, 2020 · 6 comments · Fixed by #90017
Labels
A-associated-items Area: Associated items (types, constants & functions) C-bug Category: This is a bug. E-needs-test Call for participation: An issue has been fixed and does not reproduce, but no test has been added.

Comments

@someguynamedjosh
Copy link

This code compiles correctly:

struct Data {
    boxed: Box<&'static i32>
}

impl Data {
    fn use_data(&self, user: impl for <'a> FnOnce(&'a i32)) {
        user(*self.boxed)
    }
}

However, this code does not:

use std::ops::Deref;

struct Data {
    boxed: Box<&'static i32>
}

impl Data {
    fn use_data(&self, user: impl for <'a> FnOnce(<Box<&'a i32> as Deref>::Target)) {
        user(*self.boxed)
    }
}

The only change was effectively replacing T with <Box<T> as Deref>::Target. My understanding is that these are supposed to be equivalent as it is defined that way in the standard library. The exact compile error is as follows:

error[E0308]: mismatched types
 --> src/main.rs:9:14
  |
9 |         user(*self.boxed)
  |              ^^^^^^^^^^^ expected associated type, found `&i32`
  |
  = note: expected associated type `<std::boxed::Box<&i32> as std::ops::Deref>::Target`
                   found reference `&'static i32`
  = help: consider constraining the associated type `<std::boxed::Box<&i32> as std::ops::Deref>::Target` to `&'static i32` or calling a method that returns `<std::boxed::Box<&i32> as std::ops::Deref>::Target`
  = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html

error[E0277]: expected a `std::ops::FnOnce<(&i32,)>` closure, found `impl for<'a> FnOnce(<Box<&'a i32> as Deref>::Target)`
 --> src/main.rs:9:9
  |
9 |         user(*self.boxed)
  |         ^^^^^^^^^^^^^^^^^ expected an `FnOnce<(&i32,)>` closure, found `impl for<'a> FnOnce(<Box<&'a i32> as Deref>::Target)`
  |
  = help: the trait `std::ops::FnOnce<(&i32,)>` is not implemented for `impl for<'a> FnOnce(<Box<&'a i32> as Deref>::Target)`
help: consider further restricting this bound
  |
8 |     fn use_data(&self, user: impl for <'a> FnOnce(<Box<&'a i32> as Deref>::Target) + std::ops::FnOnce<(&i32,)>) {
  |                                                                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 2 previous errors

Some errors have detailed explanations: E0277, E0308.
For more information about an error, try `rustc --explain E0277`.
error: could not compile `playground`.

To learn more, run the command again with --verbose.

Meta

The error also occurs on the Nightly compiler.

@someguynamedjosh someguynamedjosh added the C-bug Category: This is a bug. label Sep 20, 2020
@lcnr lcnr added the A-associated-items Area: Associated items (types, constants & functions) label Sep 21, 2020
@lcnr
Copy link
Contributor

lcnr commented Sep 21, 2020

We currently do not normalize projections <Ty as Trait>::AssociatedType if they contain unbound variables (stuff which is introduced using a for qualifier, 'a in your example). This means that we never actually see that <Box<&'a i32> as Deref>::Target is equal to &'a i32.

cc @eddyb @nikomatsakis but I don't think we can do much about cases like this for now.

@smmalis37
Copy link
Contributor

Is this the same underlying issue as #74736 and possibly #72582?

@lcnr
Copy link
Contributor

lcnr commented Sep 28, 2020

I think #74736 has a similar cause. #72582 is caused by something different, probably related to #41756

@lcnr
Copy link
Contributor

lcnr commented Oct 28, 2020

Using trait objects instead of impl Trait has the same issue

use std::ops::Deref;

fn use_data(v: &'static i32, user: &dyn for<'a> Fn(<Box<&'a i32> as Deref>::Target)) {
    user(v)
}

@smmalis37
Copy link
Contributor

Came up with another interesting version. This will fail to typecheck:

struct Container<'a>(std::marker::PhantomData<&'a ()>);

struct Empty;

trait Trait {
    type Assoc;
}

impl<'a> Trait for Container<'a> {
    type Assoc = Empty;
}

fn foo(x: impl for <'a> FnOnce(<Container<'a> as Trait>::Assoc)) {
    x(Empty);
}

Replacing the header of foo with this will successfully typecheck:

fn foo<'a>(x: impl FnOnce(<Container<'a> as Trait>::Assoc)) {

Might be useful for diffing.

bors added a commit to rust-lang-ci/rust that referenced this issue Aug 25, 2021
…komatsakis

Normalize projections under binders

Fixes rust-lang#70243
Fixes rust-lang#70120
Fixes rust-lang#62529
Fixes rust-lang#87219

Issues to followup on after (probably fixed, but no test added here):
rust-lang#76956
rust-lang#56556
rust-lang#79207
rust-lang#85636

r? `@nikomatsakis`
@jackh726
Copy link
Member

Fixed by #85499. Not going to close this because this is a simple example that didn't ICE, but still failed to compile.

@jackh726 jackh726 added the E-needs-test Call for participation: An issue has been fixed and does not reproduce, but no test has been added. label Aug 26, 2021
GuillaumeGomez added a commit to GuillaumeGomez/rust that referenced this issue Oct 25, 2021
Add a couple tests for normalize under binder issues

Closes rust-lang#56556
Closes rust-lang#76956

r? `@nikomatsakis`
@bors bors closed this as completed in 2d85c7e Oct 25, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-associated-items Area: Associated items (types, constants & functions) C-bug Category: This is a bug. E-needs-test Call for participation: An issue has been fixed and does not reproduce, but no test has been added.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants