Skip to content

Optional Generics? #1387

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

Open
esDotDev opened this issue Dec 27, 2020 · 7 comments
Open

Optional Generics? #1387

esDotDev opened this issue Dec 27, 2020 · 7 comments

Comments

@esDotDev
Copy link

A problem with the current Generic implementation, is anytime you want to specify one type, you need to declare them all. This can lead to excessive typing and obfuscation of intent.

Sometimes I find I need to add specificity to just one of the types, it would be nice if this could be expressed as:

useProp<_, _, float>();

Instead of the current:

useProp<KnownType1, KnownType2, float>();

I've had to do this when there is some ambiguity to the inferred types, and you need to add a little bit of an extra hint to the compiler.

An example of such a case is like this:

class Thing<T> {}
void useThing<T>(Thing<T> t, T value) {}

void fn() {
  //Thing t is declared to be of type bool
  Thing<bool> t = Thing<bool>();
  // But somehow, this is not an error...
  useThing(Thing<bool>(), 1); // No error here :(
  // We need to give it another hint; 
  useThing<bool>(Thing<bool>(), 1); //Now we have an error :) 
}

If Thing was instead Thing<T1,T2,T3> this gets pretty annoying. The fact it falls to dynamic here is also annoying, but I guess that is a separate issue, or maybe a linter rule I'm missing.

@srawlins srawlins transferred this issue from dart-lang/sdk Dec 28, 2020
@leafpetersen
Copy link
Member

// But somehow, this is not an error...
useThing(Thing(), 1); // No error here :(

I know this isn't your primary question, but concretely, this is because when designing Dart 2 inference, we chose to use subtype constraints instead of equality constraints. In other words, for your example we produce the constraints that bool must be a subtype of T, and int must be a subtype of T, and Object is a valid solution for those constraints. This allows a lot more types to be inferred, which can be good (among other things, it greatly improved our ability to compile existing Dart 1 code unchanged) but also can be bad, since as you observe it allows types to be inferred that may be less than useful.

@leafpetersen
Copy link
Member

To your primary question, this is a reasonable thing to think about doing - I don't think there'd be anything hard about it integrating it into inference. @munificent if we make _ a non-binding pattern with pattern matching, this might be something to consider.

@eernstg
Copy link
Member

eernstg commented Jan 6, 2021

An obvious line of thinking would be that when, say, o.f is a method with type parameters X1 extends B1, X2 extends B2, X3 extends B3 and o.f(arg1, arg2) is subject to type inference, and the resulting invocation is o1.f<T1, T2, T3>(arg11, arg21) then o.f<_, _, float>(arg1, arg2) is subject to type inference where the constraint set is the same, except that we add float <: X3 <: float.

However, that immediately calls for some syntax that allows us to specify other constraints, e.g., float <: X3 or X3 <: List<X2>.

The approach where we can only specify an equality constraint may be a pragmatic sweet spot, but it might also be worth considering a feature where we can specify a broader set of constraints.

@munificent
Copy link
Member

@munificent if we make _ a non-binding pattern with pattern matching, this might be something to consider.

+1. Note that my current proposal does not make _ non-binding in any existing uses (since that would be a breaking change), just inside the pattern matching syntax. Making _ non-binding in a type argument position is technically potentially a breaking change, but honestly who has a type named _?

@listepo
Copy link

listepo commented May 10, 2023

what about default types?

class Test<T = int, V = String> { ...
class TestBase<T extends BaseType = BaseType> { ...

@munificent
Copy link
Member

what about default types?

That's a different feature: #283.

@rrousselGit
Copy link

Nit: The title feels like it is suggesting a different feature than what it actually asks.
I read it as "Support class Foo<A, [B> then Foo<int>/Foo<int, double>".

I do want to be able to write final MyClass<A, _>, but the missing generic is technically still required.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants