-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
no analyzer syntax error when using the old function type syntax inside a function type using the new syntax #30596
Comments
I believe there is just one issue with current tools: The behaviors you report for the VM are correct. The syntax error in I just tried to run |
Here is a series of samples, that demonstrate the problem:
import "dart:async";
typedef F1 = Stream<T> Function<T>(Iterable<T> values);
void test1(F1 f) {}
main() {
test1(null);
print("ok");
}
Output:
D:\dev\dart\co19.idea17\Utils>d:\dev\dart\dart-sdk\bin\dartanalyzer.bat
--strong test1.dart
Analyzing test1.dart...
No issues found!
D:\dev\dart\co19.idea17\Utils>d:\dev\dart\dart-sdk\bin\dart.exe --checked
test1.dart
ok
import "dart:async";
typedef F2 = Stream<T> Function<T>(Iterable<T> values, {bool Function(T element) isError});
void test2(F2 f) {}
main() {
test2(null);
print("ok");
}
Output:
D:\dev\dart\co19.idea17\Utils>d:\dev\dart\dart-sdk\bin\dartanalyzer.bat
--strong test2.dart
Analyzing test2.dart...
Unhandled exception:
NoSuchMethodError: The getter 'element' was called on null.
Receiver: null
Tried calling: element
...
D:\dev\dart\co19.idea17\Utils>d:\dev\dart\dart-sdk\bin\dart.exe --checked
test2.dart
ok
import "dart:async";
typedef F3 = Stream<T> Function<T>(Iterable<T> values, {bool isError(T element)});
void test3(F3 f) {}
main() {
test3(null);
print("ok");
}
Output:
D:\dev\dart\co19.idea17\Utils>d:\dev\dart\dart-sdk\bin\dartanalyzer.bat
--strong test3.dart
Analyzing test3.dart...
No issues found!
D:\dev\dart\co19.idea17\Utils>d:\dev\dart\dart-sdk\bin\dart.exe --checked
test3.dart
'file:///D:/dev/dart/co19.idea17/Utils/test3.dart': error: line 3 pos 69:
',' or '}' expected
typedef F3 = Stream Function(Iterable values, {bool isError(T element)});
import "dart:async";
typedef Stream<T> F4<T>(Iterable<T> values);
I haven't checked the other cases, but this one stands out.
This does not define a generic function type. It defines a parameterized typedef.
To define a generic type, you need to write;
typedef F4 = Stream<T> F4<T>(Iterable<T> values);
void test4(F4 f) {
This declares test4 to expect an F4<dynamic> (I think, but *some* instantiation
of F4 since F4 itself isn't generic).
f<int>([1,2,3]);
}
main() {
test4(<T>(Iterable<T> data) => new Stream<T>.fromIterable(data));
This passes a generic function as argument where a non generic function is expected ...
print("ok");
}
Output
D:\dev\dart\co19.idea17\Utils>d:\dev\dart\dart-sdk\bin\dartanalyzer.bat
--strong test4.dart
Analyzing test4.dart...
error - The method '(Iterable) → Stream' is declared with 0 type
parameters, but 1 type arguments were given at test4.dart:6:3 -
wrong_number_of_type_arguments_method
... so this error is correct. The `f` variable has type (Iterable<dunamic>)->Stream<dynamic>, and you try to pass a type argument to it.
error - The argument type '(Iterable) → Stream' can't be assigned to the
parameter type 'F4(Iterable) → Stream' at test4.dart:10:9 -
argument_type_not_assignable
2 errors found.
D:\dev\dart\co19.idea17\Utils>d:\dev\dart\dart-sdk\bin\dart.exe --checked
test4.dart
ok
import "dart:async";
typedef Stream<T> F5<T>(Iterable<T> values, {bool isError(T element)});
Same problem here, typedef is itself generic, not the function types it
defines.
|
PS: I took 'valid typedef declarations' literally and only checked the typedef declarations, so that's the reason why I didn't see any of the issues with the usages of those typedef'd names in the example programs further down. The The only remaining issue is still that the analyzer does not declare a syntax error on |
Here is an update for Dart VM version: 1.25.0-dev.16.3 (Mon Sep 11 04:15:09 2017) on "windows_x64"
The Dart analyzer crash for |
A parameterized typedef is a type level function (that is, a compile-time function which maps types to types). So With the type of a generic function like The informal spec of the new |
To elaborate on Erik's distinction, we needed two kinds of type parameters - one for the typedef and one for the defined method. The old syntax couldn't support that, and we didn't want to break the existing parameterized typedefs, so to declare a generic function type, you need the new syntax. typedef F<T> = Pair<T,S> Function<S>(T, S); This declares a typedef named The old-style typedefs cannot define generic function types, so: typedef T Id<T>(T x); is a parameterzied typedef, and typedef Id<T> = T Function(T); That is a parameterized typedef which defines a family of non-generic function types. |
This is quite complex for understanding. typedef Stream<T> F4<T>(Iterable<T> values);
void testList<T>(List<T> list, T x) {
list.add(x);
}
void testF4<T>(F4<T> f, Iterable<T> data) {
f<T>(data);
}
testList<int>([1,2,3], 4);
testF4<int>((Iterable<int> data)=>new Stream<int>.fromIterable(data), [1,2,3]);
|
Yes, a parameterized typedef can (and indeed must) be given a type argument before it can be used. You can omit writing the type argument, it then defaults to So, Below that, you call |
It's also necessary to remember that the VM doesn't actually have generic functions yet. It's still running Dart 1 semantics with erasure of all function generics. It doesn't check whether a function type was intended to be generic or not, it just erases the type arguments, which explains why it accepts things that Dart 2/strong-mode implementations recognize as an error. So, all in all, I think the two actual errors here are the analyzer crashing and the analyzer not catching the syntax error. |
Sounds like the analyzer crash is fixed, and that the remaining issue is the missing syntax error. I'll update the title of this issue to match. |
Could you specify the version in which the crash is fixed? |
I'm not sure when the fix was introduced, but I ran the F2 repro ( In terms of released SDKs, it's likely that 1.24.x versions of the SDK will have issues, and 2.0.0-dev versions will not. |
Dart analyzer now features the syntax error for f3: typedef f3 = Stream<T> Function<T>(Iterable<T> values, {bool isError(T element)}); results in:
It also still has errors for test4 and test5: typedef Stream<T> F4<T>(Iterable<T> values);
typedef Stream<T> F5<T>(Iterable<T> values, {bool isError(T element)});
void test4(F4 f) {
f<int>([1,2,3]);
}
void test5(F5 f) {
f<int>([1,2,3]);
}
void main() {
test4(<T>(Iterable<T> data) => new Stream<T>.fromIterable(data));
test5(<T>(Iterable<T> values, {bool isError(T element)}) => null);
} produces:
Looks like this is all fixed. |
Dart Vm and Analyzer produce different results for valid
typedef
declarations.Here is a short summary:
typedef F1 = Stream<T> Function<T>(Iterable<T> values);
typedef F2 = Stream<T> Function<T>(Iterable<T> values, {bool Function(T element) isError});
typedef F3 = Stream<T> Function<T>(Iterable<T> values, {bool isError(T element)});
typedef Stream<T> F4<T>(Iterable<T> values);
typedef Stream<T> F5<T>(Iterable<T> values, {bool isError(T element)});
Here is a series of samples, that demonstrate the problem:
Output:
Output:
Output:
Output
Output:
Dart VM version: 1.24.2 (Thu Jun 22 08:55:56 2017) on "windows_x64"
The text was updated successfully, but these errors were encountered: