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

Error extending Fn trait then using it as a trait object: the value of the associated type `Output must be specified #24010

Closed
carllerche opened this issue Apr 3, 2015 · 17 comments · Fixed by #55687
Labels
A-associated-items Area: Associated items such as associated types and consts. A-traits Area: Trait system C-bug Category: This is a bug.

Comments

@carllerche
Copy link
Member

trait Foo: Fn(i32) + Send { }
impl<T:?Sized + Fn(i32) + Send> Foo for T { }

fn wants_foo(t: Box<Foo>) {
}

fn main() {
  let f = Box::new(|x| println!("{}", x));
  wants_foo(f);
}

Output:

<anon>:9:13: 9:14 error: the value of the associated type `Output` (from the trait `core::ops::FnOnce`) must be specified [E0191]
<anon>:9   wants_foo(f);
                     ^

cc @nikomatsakis

@nikomatsakis
Copy link
Contributor

The problem is that the associated type is defined in a supertrait, and we don't consider that case when we check that the object type is well-formed.

@steveklabnik steveklabnik added A-traits Area: Trait system A-associated-items Area: Associated items such as associated types and consts. labels Apr 4, 2015
@Diggsey
Copy link
Contributor

Diggsey commented May 7, 2015

It can be quite painful to work around this problem, as it's the only way to create aliases for traits.

When you have bounds such as the following scattered all over the code: Fn(&(Any + Send), &'static str, u32) + 'static, it's much nicer to be able to give it a short name.

@jonhoo
Copy link
Contributor

jonhoo commented Jun 1, 2015

@Diggsey: what workaround would you propose? I've been hitting my head against this wall for a while now, and am getting nowhere..

@Diggsey
Copy link
Contributor

Diggsey commented Jun 1, 2015

@jonhoo I don't know about your particular use-case, but for me I was using this to create a short alias for a trait - the workaround was just to use the long name everywhere, ie. Fn(&(Any + Send), &'static str, u32) + 'static

@jonhoo
Copy link
Contributor

jonhoo commented Jun 1, 2015

My use-case is exactly the same. I was hoping I might be able to use a macro that expanded to the type, but that doesn't seem to work either. I suppose I'll just have to use the full signature for now..

@Kimundi
Copy link
Member

Kimundi commented Sep 5, 2015

@nikomatsakis Why is that case not considered?

@nikomatsakis
Copy link
Contributor

@Kimundi it's a bug, really.

@Kimundi
Copy link
Member

Kimundi commented Sep 12, 2015

Ah, okay it sounded like that was intentional :)

@DGolubets
Copy link

Is it going to be fixed in any upcoming version?

@nikomatsakis
Copy link
Contributor

Note that @durka points out in #29328 this does technically allow one to violate some stability restrictions, but probably not in a way that matters:

trait FnAlias: Fn() {}

fn main() {
    let _: FnAlias;            // error
    let _: FnAlias<Output=()>; // no error, but I shouldn't be able to do this!
}

@jimmycuadra
Copy link
Contributor

This bug is very annoying. I have the same use case as @Diggsey and @jonhoo: creating an alias of a trait with cumbersome bounds that I don't want to have to repeat everywhere.

In case it's not obvious from the title, this doesn't have to do with the Fn trait specifically. It's just about supertrait associated types being ignored when using the subtrait. Here's a simpler illustration:

trait A {
    type Assoc;
    // Pretend there are several more associated types here to make uses of `Box<A>` inconvenient.
}

trait B: A<Assoc=()> {}

fn takes_b(b: Box<B>) {}

which results in:

error[E0191]: the value of the associated type `Assoc` (from the trait `A`) must be specified
 --> src/lib.rs:8:19
  |
8 | fn takes_b(b: Box<B>) {}
  |                   ^ missing associated type `Assoc` value

The compiler should be able to infer that type Assoc = () here.

@maurer
Copy link
Contributor

maurer commented May 23, 2017

use std::iter::Iterator;

pub trait LeapfrogIterator<T, V> : Iterator<Item=(T,V)> {
    fn next_above(&mut self, &T) -> Option<(T, V)>;
}

fn main () {
    let v: Box<LeapfrogIterator<i64, i64>> = unimplemented!();
}

https://is.gd/VcQmki

is another concrete use case - if I want to extend Iterator in this way, I need to write LeapfrogIterator<K, V, Item=(K, V)> every time I want to talk about the trait, even though this is the only legal value for Item to take on. (This doesn't express the bug in a new way, but is an example I ran into organically and eventually found this bug due to.)

@glyn
Copy link

glyn commented Jun 15, 2017

I hit this when trying to create an alias of a FnMut trait. Using a macro still doesn't work as @jonhoo found two years ago, e.g. https://is.gd/h9CZ8H, because trait bounds don't seem to accept macro invocations.

glyn added a commit to cloudfoundry/jvmkill that referenced this issue Jun 15, 2017
Also:
* Avoid unhelpful compiler warnings
* Capture common code in a macro

Note: it would have been nice to alias the closure type, but
rust-lang/rfcs#1733 is not yet implemented and macros
can't cope (rust-lang/rust#24010).
glyn added a commit to cloudfoundry/jvmkill that referenced this issue Jun 16, 2017
Also:
* Avoid unhelpful compiler warnings
* Capture common code in a macro

Note: it would have been nice to alias the closure type, but
rust-lang/rfcs#1733 is not yet implemented and macros
can't cope (rust-lang/rust#24010).
glyn added a commit to cloudfoundry/jvmkill that referenced this issue Jun 16, 2017
Also:
* Avoid unhelpful compiler warnings
* Capture common code in a macro

Note: it would have been nice to alias the closure type, but
rust-lang/rfcs#1733 is not yet implemented and macros
can't cope (rust-lang/rust#24010).
glyn added a commit to cloudfoundry/jvmkill that referenced this issue Jun 16, 2017
Also:
* Avoid unhelpful compiler warnings
* Capture common code in a macro

Note: it would have been nice to alias the closure type, but
rust-lang/rfcs#1733 is not yet implemented and macros
can't cope (rust-lang/rust#24010).
glyn added a commit to cloudfoundry/jvmkill that referenced this issue Jun 16, 2017
Also:
* Avoid unhelpful compiler warnings
* Capture common code in a macro

Note: it would have been nice to alias the closure type, but
rust-lang/rfcs#1733 is not yet implemented and macros
can't cope (rust-lang/rust#24010).
glyn added a commit to cloudfoundry/jvmkill that referenced this issue Jun 16, 2017
Also:
* Avoid unhelpful compiler warnings
* Capture common code in a macro

Note: it would have been nice to alias the closure type, but
rust-lang/rfcs#1733 is not yet implemented and macros
can't cope (rust-lang/rust#24010).
glyn added a commit to cloudfoundry/jvmkill that referenced this issue Jun 16, 2017
Also:
* Avoid unhelpful compiler warnings
* Capture common code in a macro

Note: it would have been nice to alias the closure type, but
rust-lang/rfcs#1733 is not yet implemented and macros
can't cope (rust-lang/rust#24010).
glyn added a commit to cloudfoundry/jvmkill that referenced this issue Jun 26, 2017
Also:
* Avoid unhelpful compiler warnings
* Capture common code in a macro

Note: it would have been nice to alias the closure type, but
rust-lang/rfcs#1733 is not yet implemented and macros
can't cope (rust-lang/rust#24010).
glyn added a commit to cloudfoundry/jvmkill that referenced this issue Jun 29, 2017
Also:
* Avoid unhelpful compiler warnings
* Capture common code in a macro

Note: it would have been nice to alias the closure type, but
rust-lang/rfcs#1733 is not yet implemented and macros
can't cope (rust-lang/rust#24010).
@durka
Copy link
Contributor

durka commented Jul 4, 2017

@nikomatsakis

The problem is that the associated type is defined in a supertrait, and we don't consider that case when we check that the object type is well-formed.

@Kimundi it's a bug, really.

Is it possible to give some mentoring hints for fixing this?

glyn added a commit to cloudfoundry/jvmkill that referenced this issue Jul 5, 2017
Also:
* Avoid unhelpful compiler warnings
* Capture common code in a macro

Note: it would have been nice to alias the closure type, but
rust-lang/rfcs#1733 is not yet implemented and macros
can't cope (rust-lang/rust#24010).
@Mark-Simulacrum Mark-Simulacrum added the C-bug Category: This is a bug. label Jul 22, 2017
@durka durka mentioned this issue Oct 5, 2017
10 tasks
bors added a commit that referenced this issue Dec 14, 2017
trait alias infrastructure

This will be an implementation of trait aliases (RFC 1733, #41517).

Progress so far:

- [x] Feature gate
- [x] Add to parser
  - [x] `where` clauses
    - [x] prohibit LHS type parameter bounds via AST validation #45047 (comment)
- [x] Add to AST and HIR
  - [x] make a separate PathSource for trait alias contexts #45047 (comment)
- [x] Stub out enough of typeck and resolve to just barely not ICE

Postponed:

- [ ] Actually implement the alias part
- [ ] #21903
- [ ] #24010

I need some pointers on where to start with that last one. The test currently does this:

```
error[E0283]: type annotations required: cannot resolve `_: CD`
  --> src/test/run-pass/trait-alias.rs:34:16
   |
34 |     let both = foo();
   |                ^^^
   |
   = note: required by `foo`
```
@mbrubeck
Copy link
Contributor

I think this is the same as #23856.

@alexreg
Copy link
Contributor

alexreg commented Oct 10, 2018

@mbrubeck I think so too. Have we confirmed it yet? If so, worth closing this as duplicate.

@alexreg
Copy link
Contributor

alexreg commented Nov 5, 2018

Okay, we have a fix! Waiting for review and merge on #55687.

pietroalbini added a commit to pietroalbini/rust that referenced this issue Nov 10, 2018
Take supertraits into account when calculating associated types

Fixes rust-lang#24010 and rust-lang#23856. Applies to trait aliases too.

As a by-product, this PR also makes repeated bindings of the same associated item in the same definition a hard error. This was previously a warning with a note about it becoming a hard error in the future. See rust-lang#50589 for more info.

I talked about this with @nikomatsakis recently, but only very superficially, so this shouldn't stop anyone from assigning it to themself to review and r+.

N.B. The "WIP" commits represent imperfect attempts to solve the problem just for trait objects, but I've left them in for reference for the sake of whomever is reviewing this.

CC @carllerche @theemathas @durka @mbrubeck
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 such as associated types and consts. A-traits Area: Trait system C-bug Category: This is a bug.
Projects
None yet
Development

Successfully merging a pull request may close this issue.