Fix overly strict invalid return checking.

In changing the proposed spec to address comments in a way that was intended to be
non-breaking, I accidentally introduced some new (unintended) restrictions.  This
fixes the spec, rolls back the change in analyzer, and adjusts the language tests
appropriately.

Change-Id: I487b0eaacbfa1447d4ee909c0a56e435c2088990
Reviewed-on: https://dart-review.googlesource.com/70462
Reviewed-by: Mike Fairhurst <mfairhurst@google.com>
This commit is contained in:
Leaf Petersen 2018-08-17 01:25:18 +00:00
parent 61fe321224
commit 891b7164ac
15 changed files with 61 additions and 220 deletions

View file

@ -67,7 +67,7 @@ The rules for an asynchronous non-generator function with declared return type
* and `flatten(S)` is `void`, `dynamic` or `Null`
* `return exp;` where `exp` has static type `S` is a valid return if:
* `flatten(T)` is not `void`
* `T` is not `void`
* and `flatten(S)` is not `void`
* and `Future<flatten(S)>` is assignable to `T`
@ -114,7 +114,7 @@ The rules for an asynchronous non-generator function with declared return type
* `return;` is an error if `flatten(T)` is not `void`, `dynamic`, or `Null`
* `return exp;` where `exp` has static type `S` is an error if `flatten(T)` is
* `return exp;` where `exp` has static type `S` is an error if `T` is
`void` and `flatten(S)` is not `void`, `dynamic`, or `Null`
* `return exp;` where `exp` has static type `S` is an error if `flatten(S)` is

View file

@ -5269,7 +5269,8 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
if (toType.isDynamic || toType.isDartCoreNull || toType.isBottom) {
return;
}
} else {
}
if (!expectedType.isVoid && !fromType.isVoid) {
var checkWithType = (!_inAsync)
? fromType
: _typeProvider.futureType.instantiate(<DartType>[fromType]);

View file

@ -1,18 +0,0 @@
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
/*
* `return exp;` where `exp` has static type `S` is an error if `flatten(T)` is
`void` and `flatten(S)` is not `void`, `dynamic`, or `Null`
*/
int v = null;
Future<void> test() async {
return /*@compile-error=unspecified*/ v;
}
void main() {
test();
}

View file

@ -1,18 +0,0 @@
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
/*
* `return exp;` where `exp` has static type `S` is an error if `flatten(T)` is
`void` and `flatten(S)` is not `void`, `dynamic`, or `Null`
*/
int v = null;
FutureOr<void> test() async {
return /*@compile-error=unspecified*/ v;
}
void main() {
test();
}

View file

@ -1,18 +0,0 @@
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
/*
* `return exp;` where `exp` has static type `S` is an error if `flatten(T)` is
`void` and `flatten(S)` is not `void`, `dynamic`, or `Null`
*/
Object v = null;
Future<void> test() async {
return /*@compile-error=unspecified*/ v;
}
void main() {
test();
}

View file

@ -1,18 +0,0 @@
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
/*
* `return exp;` where `exp` has static type `S` is an error if `flatten(T)` is
`void` and `flatten(S)` is not `void`, `dynamic`, or `Null`
*/
Object v = null;
FutureOr<void> test() async {
return /*@compile-error=unspecified*/ v;
}
void main() {
test();
}

View file

@ -1,18 +0,0 @@
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
/*
* `return exp;` where `exp` has static type `S` is an error if `flatten(T)` is
`void` and `flatten(S)` is not `void`, `dynamic`, or `Null`
*/
Future<int> v = null;
Future<void> test() async {
return /*@compile-error=unspecified*/ v;
}
void main() {
test();
}

View file

@ -1,18 +0,0 @@
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
/*
* `return exp;` where `exp` has static type `S` is an error if `flatten(T)` is
`void` and `flatten(S)` is not `void`, `dynamic`, or `Null`
*/
Future<int> v = null;
FutureOr<void> test() async {
return /*@compile-error=unspecified*/ v;
}
void main() {
test();
}

View file

@ -1,18 +0,0 @@
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
/*
* `return exp;` where `exp` has static type `S` is an error if `flatten(T)` is
`void` and `flatten(S)` is not `void`, `dynamic`, or `Null`
*/
FutureOr<int> v = null;
Future<void> test() async {
return /*@compile-error=unspecified*/ v;
}
void main() {
test();
}

View file

@ -1,18 +0,0 @@
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
/*
* `return exp;` where `exp` has static type `S` is an error if `flatten(T)` is
`void` and `flatten(S)` is not `void`, `dynamic`, or `Null`
*/
FutureOr<int> v = null;
FutureOr<void> test() async {
return /*@compile-error=unspecified*/ v;
}
void main() {
test();
}

View file

@ -1,18 +0,0 @@
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
/*
* `return exp;` where `exp` has static type `S` is an error if `flatten(T)` is
`void` and `flatten(S)` is not `void`, `dynamic`, or `Null`
*/
Future<Object> v = null;
Future<void> test() async {
return /*@compile-error=unspecified*/ v;
}
void main() {
test();
}

View file

@ -1,18 +0,0 @@
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
/*
* `return exp;` where `exp` has static type `S` is an error if `flatten(T)` is
`void` and `flatten(S)` is not `void`, `dynamic`, or `Null`
*/
Future<Object> v = null;
FutureOr<void> test() async {
return /*@compile-error=unspecified*/ v;
}
void main() {
test();
}

View file

@ -1,18 +0,0 @@
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
/*
* `return exp;` where `exp` has static type `S` is an error if `flatten(T)` is
`void` and `flatten(S)` is not `void`, `dynamic`, or `Null`
*/
FutureOr<Object> v = null;
Future<void> test() async {
return /*@compile-error=unspecified*/ v;
}
void main() {
test();
}

View file

@ -1,18 +0,0 @@
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
/*
* `return exp;` where `exp` has static type `S` is an error if `flatten(T)` is
`void` and `flatten(S)` is not `void`, `dynamic`, or `Null`
*/
FutureOr<Object> v = null;
FutureOr<void> test() async {
return /*@compile-error=unspecified*/ v;
}
void main() {
test();
}

View file

@ -319,7 +319,7 @@ FutureOr<void> async_Null_to_FutureOr_void_() async {
/*
* `return exp;` where `exp` has static type `S` is a valid return if:
* `flatten(T)` is not `void`
* `T` is not `void`
* and `flatten(S)` is not `void`
* and `Future<flatten(S)>` is assignable to `T`
*/
@ -343,6 +343,46 @@ Future<int> async_Future_int__to_Future_int_() async {
return fvi;
}
Future<void> async_int_to_Future_void__e() async => vi;
Future<void> async_int_to_Future_void_() async {
return vi;
}
Future<void> async_Object_to_Future_void__e() async => vo;
Future<void> async_Object_to_Future_void_() async {
return vo;
}
Future<void> async_FutureOr_int__to_Future_void__e() async => fovi;
Future<void> async_FutureOr_int__to_Future_void_() async {
return fovi;
}
Future<void> async_Future_int__to_Future_void__e() async => fvi;
Future<void> async_Future_int__to_Future_void_() async {
return fvi;
}
FutureOr<void> async_int_to_FutureOr_void__e() async => vi;
FutureOr<void> async_int_to_FutureOr_void_() async {
return vi;
}
FutureOr<void> async_Object_to_FutureOr_void__e() async => vo;
FutureOr<void> async_Object_to_FutureOr_void_() async {
return vo;
}
FutureOr<void> async_FutureOr_int__to_FutureOr_void__e() async => fovi;
FutureOr<void> async_FutureOr_int__to_FutureOr_void_() async {
return fovi;
}
FutureOr<void> async_Future_int__to_FutureOr_void__e() async => fvi;
FutureOr<void> async_Future_int__to_FutureOr_void_() async {
return fvi;
}
void main() {
async_int_to_void_e();
async_int_to_Future_void__e();
@ -462,4 +502,20 @@ void main() {
async_FutureOr_int__to_Future_int_();
async_Future_int__to_Future_int__e();
async_Future_int__to_Future_int_();
async_int_to_Future_void__e();
async_int_to_Future_void_();
async_Object_to_Future_void__e();
async_Object_to_Future_void_();
async_FutureOr_int__to_Future_void__e();
async_FutureOr_int__to_Future_void_();
async_Future_int__to_Future_void__e();
async_Future_int__to_Future_void_();
async_int_to_FutureOr_void__e();
async_int_to_FutureOr_void_();
async_Object_to_FutureOr_void__e();
async_Object_to_FutureOr_void_();
async_FutureOr_int__to_FutureOr_void__e();
async_FutureOr_int__to_FutureOr_void_();
async_Future_int__to_FutureOr_void__e();
async_Future_int__to_FutureOr_void_();
}