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

Allow "void" as a type argument #27504

Closed
5 tasks done
munificent opened this issue Oct 5, 2016 · 14 comments
Closed
5 tasks done

Allow "void" as a type argument #27504

munificent opened this issue Oct 5, 2016 · 14 comments
Assignees
Labels
area-language Dart language related items (some items might be better tracked at github.com/dart-lang/language). closed-duplicate Closed in favor of an existing report customer-flutter language-strong-mode-polish

Comments

@munificent
Copy link
Member

munificent commented Oct 5, 2016

The language will change to allow void as a type argument in generics (and as a type annotation in general).

This comes up in cases like:

  • A function that returns nothing asynchronously could return Future<void>. Today, code either uses Future, which doesn't give you great static checking of the result, or Future<Null>, which is kind of unfamiliar to most users.
  • Generic visitor classes that are parametric on their visit methods' return types. If you want to create a visitor that returns nothing, it would be nice to be able to explicitly extend AstVisitor<void>.

We also allow void to be the type annotation for locals, parameters, fields, ...

In Dart 1, void should simply be treated like Object, except as a return type for function types (where the old behavior should be kept).

In strong mode, an additional "voidness" rule will disallow assignments from void to Object when the assignment is statically visible. We will update the bug when we have a document ready.

@munificent munificent added the area-language Dart language related items (some items might be better tracked at github.com/dart-lang/language). label Oct 5, 2016
@munificent munificent added this to the 1.50 milestone Oct 5, 2016
@lrhn
Copy link
Member

lrhn commented Oct 6, 2016

A void function can actually return anything (or more precisely: a function assignable to a function type with void return type, can return anything because of the way "more specific" is defined on functions).

That has led to errors where someone does

void foo() => delegate.foo();

but the delegate type's foo overrides the expected type with a function returning non-void and returns a non-null value. In checked mode that's an error.

The fix for that will likely be to allow anything to be returned by a void function. That makes void act like Object (and at runtime, it will likely be Object) except that you can't use a value with static type void for anything.

@floitschG
Copy link
Contributor

Status update: we need to do #27727 for 1.50, but can implement this issue at a later point.

Hixie added a commit to Hixie/flutter that referenced this issue Nov 15, 2016
See flutter#6861

This silences all but two of the warnings from https://travis-ci.org/flutter/flutter/builds/176055550

One of the silenced warnings was a genuine code error.

Some of the others were correct but there was no way for the analyzer to know, and I worked around them.

The remainder are problems with the analyzer, specifically dart-lang/sdk#27827 and dart-lang/sdk#27504.
Hixie added a commit to flutter/flutter that referenced this issue Nov 15, 2016
See #6861

This silences all but two of the warnings from https://travis-ci.org/flutter/flutter/builds/176055550

One of the silenced warnings was a genuine code error.

Some of the others were correct but there was no way for the analyzer to know, and I worked around them.

The remainder are problems with the analyzer, specifically dart-lang/sdk#27827 and dart-lang/sdk#27504.
@dskloetg
Copy link

Another use case could be that raw generic types could implicitly have void as their generic type parameter if the user has disabled implicit dynamic.

@zoechi
Copy link
Contributor

zoechi commented Jan 17, 2017

@dskloetg this is tackled already. See #27727 mentioned by floitschG above and #17518, #26275

@dskloetg
Copy link

dskloetg commented Jan 17, 2017

@zoechi I'm not sure how that is related.
I mean the following. Today when I write Future (without type parameter), it's interpreted as Future<dynamic>. With --no-implicit-dynamic it could be interpreted as Future<void> instead.

@zoechi
Copy link
Contributor

zoechi commented Jan 17, 2017

@dskloetg Currently you can use Future<Null> to get what you expect from Future<void>. AFAIK the work done in the linked issues, is to allow void where currently Null is required.

@dskloetg
Copy link

dskloetg commented Jan 17, 2017

<Null> is a hack (e.g. it has .toString()). I wouldn't argue to enable a hack with --no-implicit-dynamic.
I'm talking about implicitly having <void> when you don't specify it.

@kasperl
Copy link

kasperl commented Jan 31, 2017

The STRONG_MODE_INVALID_CAST_FUNCTION_EXPR is ignored in ~24 places in the Flutter code base. This seems important to address.

@kasperl kasperl added this to the 1.23 milestone Feb 1, 2017
@nex3
Copy link
Member

nex3 commented Feb 15, 2017

I've run into two issues relating to this with code like the following:

import 'dart:async';

void foo(x) {}

void main() {
  Future.wait([
    new Future.value().then(foo),
    new Future<bool>.value(false)
  ]);
}

On 1.22, this produces the error The element type 'Future<bool>' can't be assigned to the list type 'Future<void>'. After talking to @leafpetersen, it seems like there are two issues here:

  1. Future<bool> should be assignable to Future<void>.
  2. The LUB for these two futures should be something they're both assignable to.

@lrhn
Copy link
Member

lrhn commented Feb 16, 2017

The LUB is a continuing problem. It's not very good at handling generic classes, so the LUB of Future<void> and Future<bool> is ... Object.
The LUB in the specification is based on super-interfaces, not super-types, and the only super-interface of Future<bool> is Object. Even if Future<void> is a super-type of Future<bool>, LUB(Future<void>, Future<bool>) is still Object.

We need a better LUB, even more so now that it's used in inference too.

@floitschG
Copy link
Contributor

I updated the issue description to reflect the current status.

@mit-mit mit-mit modified the milestones: 1.24, 1.23 Mar 15, 2017
@eernstg eernstg modified the milestones: 1.25, 1.24 May 10, 2017
@crelier
Copy link
Contributor

crelier commented May 30, 2017

Do we have tests for this feature?

@eernstg
Copy link
Member

eernstg commented May 31, 2017

Not yet. I'll be writing an informal spec, and I expect that we can obtain tests from multiple contributors including the language team, as we've done before.

@anders-sandholm
Copy link
Contributor

This is a subset of the functionality described in Generalized void meta issue #30176

@anders-sandholm anders-sandholm added the closed-duplicate Closed in favor of an existing report label Nov 29, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-language Dart language related items (some items might be better tracked at github.com/dart-lang/language). closed-duplicate Closed in favor of an existing report customer-flutter language-strong-mode-polish
Projects
None yet
Development

No branches or pull requests