Description
This is related to #912.
The following code doesn't work:
fn main() {
for iter::eachi(some({a: 0})) |i, a| {
#debug["%u %d", i, a.a];
}
}
It fails with
nubs/closure-trait-infer.rs:3:27: 3:30 error: the type of this value must be known in this context
nubs/closure-trait-infer.rs:3 #debug["%u %d", i, a.a];
which is really unfortunate.
eachi
is declared with the prototype fn eachi<A,IA:base_iter<A>>(vec: IA, blk: fn(uint, A) -> bool)
. When called in the above code, IA is instantiated with the type option<{a: int}>
, and a note is made that option<{a: int}>
must implement the trait base_iter<A>
. However, without knowing the details of the implementation, there is no way to know that the only A
such that option<{a: int}>
implements base_iter<A>
is {a: int}
.
I can think of a couple of possible solutions, varying wildly in feasibility:
-
Do some sort of opportunistic impl search during typechecking, probably in some super ad-hoc place such as during function argument typechecking, after checking the non-closure arguments but before checking closure arguments. This is not particularly principled but might be pretty feasible.
-
Introduce proper higher kinded type variables and traits over them. Then traits wouldn't be parameterized over type variables but would instead be implemented for higher kinds. The signature of
eachi
would befn eachi<A,IA:base_iter>(vec: IA<A>, blk: fn(uint, A) -> bool)
andIA<A>
would be unified withoption<{a: int}>
right off the bat. -
Fix issue Block type-inference sometimes fails #912 so that the type isn't needed while typechecking the closure.