Page 1 of 1

Type extensions and parameterization

PostPosted: Fri Oct 25, 2013 2:46 pm
by sephthir
In my working with Cobra, I ran into an interesting problem (feature?) regarding extensions of parameterized types with parameterized methods. Take, for example, the following code:

Code: Select all
use System.Linq

extend IEnumerable<of T>
    def cast<of R> as IEnumerable<of R>
        return Enumerable.cast<of R>(this) to !

class Example
    def main
        list = [[0, 1], [1, 2], [2, 3]]
        enumerable = list.cast<of IEnumerable<of int>>


This generates an exception from the underlying compiler after the C# code generation phase:

Code: Select all
paramtest.cobra(10): error: The type arguments for method "Extend_IEnumerable__T__paramtest.Cast<T,R>(System.Collections.Generic.IEnumerable<T>)" cannot be inferred from the usage. Try specifying the type arguments explicitly


This appears to be because the resulting call to the generated extension method relies entirely upon implicit parameterization, based on looking at the intermediary C#:

Code: Select all
enumerable=(Extend_IEnumerable__T__paramtest.Cast(list));


Since the type parameter being passed in is not indicated by the type of an argument to the extension method, it's not being implicitly specified and the C# compiler can't know what it is.

My question then is, is this an unimplemented piece, or an intentional limitation on what extension methods are capable of? I will certainly give you that it is a corner case to some degree (since usually, you don't have type parameters without arguments), but it certainly could come up.

The larger ramifications of not being able to specify type arguments could impact other things as well, I would think, such as a possible multiple-inheritance-esque situation with extended interfaces, like such:

Code: Select all
interface IHasValue<of T>
    def concat(v0 as T, v1 as T) as T

class StringIntClass implements IHasValue<of String>, IHasValue<of int>
    def concat(v0 as String, v1 as String) as String
        return v0 + v1
    def concat(v0 as int, v1 as int) as int
        return v0 + v1

extend IHasValue<of T>
    def extendedMethod(v0 as T, v1 as T) as T
        return .concat(v0, v1)

class Example
    def main
        print StringIntClass().extendedMethod(0, 1) # Example line 1
        print StringIntClass().extendedMethod("one", "two") # Example line 2


In this example, if you try to call the first example line above, you get a compile-time error saying that the method takes string arguments, but if you try to call the second example line above, you get an error that the type arguments can't be inferred.

What this all boils down to is more-or-less that I'm wondering what the future of extensions and parameterized types is, partially out of my own curiosity (because I don't necessarily need to use any of the examples here), and partially because I did some digging and put some thought into how it works now, and how it might work. Thanks!

Re: Type extensions and parameterization

PostPosted: Sat Oct 26, 2013 2:29 am
by Charles
This is a gap/bug. I'm not sure of the timeline for fixing it. I took a stab at it and got part way there, but have to think some more about the rest of it. And it's time for bed. (Hmm no sleepy smiley...)

Re: Type extensions and parameterization

PostPosted: Sat Oct 26, 2013 9:12 am
by sephthir
That's kind of what I thought, but just wanted to make sure. Mostly just one of those "wait, what?" moments while trying to program. I had a few thoughts on implementation, but the more I thought about it, the more nebulous and complex the problem became. Kind of an odd corner case, and not the most straightforward to fix! Thanks for the quick reply! :)

Re: Type extensions and parameterization

PostPosted: Wed Oct 30, 2013 8:36 pm
by Charles
I forgot to mention that for your first code example, you can use a for-expression like so:
enumerable = for x in list get x to IEnumerable<of int>