Copy subtype tests

The tests are copied from pkg/kernel/test/type_subtype_test.dart

Change-Id: I1120aa7ae1928fc20982f24fab14925b9ee851c8
Reviewed-on: https://dart-review.googlesource.com/c/90229
Reviewed-by: Dmitry Stefantsov <dmitryas@google.com>
This commit is contained in:
Peter von der Ahé 2019-01-29 13:29:32 +00:00 committed by commit-bot@chromium.org
parent 219a2fcf66
commit d025ff5367
5 changed files with 236 additions and 8 deletions

View file

@ -32,10 +32,11 @@ import "type_parser.dart"
ParsedVoidType,
Visitor;
Library parseLibrary(Uri uri, String text, {Uri fileUri}) {
Library parseLibrary(Uri uri, String text,
{Uri fileUri, KernelEnvironment environment}) {
fileUri ??= uri;
environment ??= new KernelEnvironment(uri, fileUri);
Library library = new Library(uri, fileUri: fileUri);
KernelEnvironment environment = new KernelEnvironment(uri, fileUri);
for (ParsedType type in type_parser.parse(text)) {
Node node = environment.kernelFromParsedType(type);
if (node is Class) {
@ -144,7 +145,14 @@ class KernelFromParsedType implements Visitor<Node, KernelEnvironment> {
FunctionType visitFunctionType(
ParsedFunctionType node, KernelEnvironment environment) {
throw "not implemented: $node";
DartType returnType =
node.returnType?.accept<Node, KernelEnvironment>(this, environment);
List<DartType> arguments = <DartType>[];
for (ParsedType argument in node.arguments.required) {
arguments
.add(argument.accept<Node, KernelEnvironment>(this, environment));
}
return new FunctionType(arguments, returnType);
}
VoidType visitVoidType(ParsedVoidType node, KernelEnvironment environment) {

View file

@ -4,13 +4,21 @@
import "package:expect/expect.dart" show Expect;
import "package:kernel/ast.dart" show Component, Library;
import "package:kernel/ast.dart" show Component, DartType, Library;
import "package:kernel/class_hierarchy.dart" show ClassHierarchy;
import "package:kernel/core_types.dart" show CoreTypes;
import "package:kernel/text/ast_to_text.dart" show Printer;
import "kernel_type_parser.dart" show parseLibrary;
import "package:kernel/type_environment.dart" show TypeEnvironment;
import "kernel_type_parser.dart" show KernelEnvironment, parseLibrary;
import "shared_type_tests.dart" show SubtypeTest;
import "type_parser.dart" as type_parser show parse;
const String testSdk = """
class Object;
@ -23,6 +31,7 @@ const String testSdk = """
class Future<T>;
class FutureOr<T>;
class Null;
class Function;
""";
const String expectedSdk = """
@ -49,14 +58,39 @@ class FutureOr<T extends self::Object = dynamic> extends self::Object {
}
class Null extends self::Object {
}
class Function extends self::Object {
}
""";
main() {
Library library = parseLibrary(Uri.parse("dart:core"), testSdk);
Uri uri = Uri.parse("dart:core");
KernelEnvironment environment = new KernelEnvironment(uri, uri);
Library library = parseLibrary(uri, testSdk, environment: environment);
StringBuffer sb = new StringBuffer();
Printer printer = new Printer(sb);
printer.writeLibraryFile(library);
Expect.stringEquals(expectedSdk, "$sb");
Component component = new Component(libraries: <Library>[library]);
new ClassHierarchy(component);
ClassHierarchy hierarchy = new ClassHierarchy(component);
CoreTypes coreTypes = new CoreTypes(component);
new KernelSubtypeTest(coreTypes, hierarchy, environment).run();
}
class KernelSubtypeTest extends SubtypeTest<DartType> {
final CoreTypes coreTypes;
final ClassHierarchy hierarchy;
final KernelEnvironment environment;
KernelSubtypeTest(this.coreTypes, this.hierarchy, this.environment);
DartType toType(String text) {
return environment.kernelFromParsedType(type_parser.parse(text).single);
}
bool isSubtypeImpl(DartType subtype, DartType supertype, bool legacyMode) {
return new TypeEnvironment(coreTypes, hierarchy, legacyMode: legacyMode)
.isSubtypeOf(subtype, supertype);
}
}

View file

@ -0,0 +1,170 @@
// Copyright (c) 2019, 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 "package:expect/expect.dart" show Expect;
abstract class SubtypeTest<T> {
void isSubtype(String subtypeString, String supertypeString,
{bool legacyMode: false, String typeParameters}) {
T subtype = toType(subtypeString);
T supertype = toType(supertypeString);
String mode = legacyMode ? " (legacy)" : "";
Expect.isTrue(isSubtypeImpl(subtype, supertype, legacyMode),
"$subtype should be a subtype of $supertype$mode.");
}
void isNotSubtype(String subtypeString, String supertypeString,
{bool legacyMode: false, String typeParameters}) {
T subtype = toType(subtypeString);
T supertype = toType(supertypeString);
String mode = legacyMode ? " (legacy)" : "";
Expect.isFalse(isSubtypeImpl(subtype, supertype, legacyMode),
"$subtype shouldn't be a subtype of $supertype$mode.");
}
T toType(String text);
bool isSubtypeImpl(T subtype, T supertype, bool legacyMode);
void run() {
isSubtype('int', 'num', legacyMode: true);
isSubtype('int', 'Comparable<num>', legacyMode: true);
isSubtype('int', 'Comparable<Object>', legacyMode: true);
isSubtype('int', 'Object', legacyMode: true);
isSubtype('double', 'num', legacyMode: true);
isNotSubtype('int', 'double', legacyMode: true);
isNotSubtype('int', 'Comparable<int>', legacyMode: true);
isNotSubtype('int', 'Iterable<int>', legacyMode: true);
isNotSubtype('Comparable<int>', 'Iterable<int>', legacyMode: true);
isSubtype('List<int>', 'List<int>', legacyMode: true);
isSubtype('List<int>', 'Iterable<int>', legacyMode: true);
isSubtype('List<int>', 'List<num>', legacyMode: true);
isSubtype('List<int>', 'Iterable<num>', legacyMode: true);
isSubtype('List<int>', 'List<Object>', legacyMode: true);
isSubtype('List<int>', 'Iterable<Object>', legacyMode: true);
isSubtype('List<int>', 'Object', legacyMode: true);
isSubtype('List<int>', 'List<Comparable<Object>>', legacyMode: true);
isSubtype('List<int>', 'List<Comparable<num>>', legacyMode: true);
isSubtype('List<int>', 'List<Comparable<Comparable<num>>>',
legacyMode: true);
isNotSubtype('List<int>', 'List<double>', legacyMode: true);
isNotSubtype('List<int>', 'Iterable<double>', legacyMode: true);
isNotSubtype('List<int>', 'Comparable<int>', legacyMode: true);
isNotSubtype('List<int>', 'List<Comparable<int>>', legacyMode: true);
isNotSubtype('List<int>', 'List<Comparable<Comparable<int>>>',
legacyMode: true);
isSubtype('(num) -> num', '(int) -> num', legacyMode: true);
isSubtype('(num) -> int', '(num) -> num', legacyMode: true);
isSubtype('(num) -> int', '(int) -> num', legacyMode: true);
isNotSubtype('(int) -> int', '(num) -> num', legacyMode: true);
isSubtype('(num) -> (num) -> num', '(num) -> (int) -> num',
legacyMode: true);
isNotSubtype('(num) -> (int) -> int', '(num) -> (num) -> num',
legacyMode: true);
// TODO(ahe): Remove this as the implementation improves.
return;
// ignore: dead_code
isSubtype('(x:num) -> num', '(x:int) -> num',
legacyMode: true); // named parameters
isSubtype('(num,x:num) -> num', '(int,x:int) -> num', legacyMode: true);
isSubtype('(x:num) -> int', '(x:num) -> num', legacyMode: true);
isNotSubtype('(x:int) -> int', '(x:num) -> num', legacyMode: true);
isSubtype('<E>(E) -> int', '<E>(E) -> num',
legacyMode: true); // type parameters
isSubtype('<E>(num) -> E', '<E>(int) -> E', legacyMode: true);
isSubtype('<E>(E,num) -> E', '<E>(E,int) -> E', legacyMode: true);
isNotSubtype('<E>(E,num) -> E', '<E>(E,E) -> E', legacyMode: true);
isSubtype('<E>(E) -> (E) -> E', '<F>(F) -> (F) -> F', legacyMode: true);
isSubtype('<E>(E, (int,E) -> E) -> E', '<E>(E, (int,E) -> E) -> E',
legacyMode: true);
isSubtype('<E>(E, (int,E) -> E) -> E', '<E>(E, (num,E) -> E) -> E',
legacyMode: true);
isNotSubtype('<E,F>(E) -> (F) -> E', '<E>(E) -> <F>(F) -> E',
legacyMode: true);
isNotSubtype('<E,F>(E) -> (F) -> E', '<F,E>(E) -> (F) -> E',
legacyMode: true);
isNotSubtype('<E>(E,num) -> E', '<E:num>(E,E) -> E', legacyMode: true);
isNotSubtype('<E:num>(E) -> int', '<E:int>(E) -> int', legacyMode: true);
isNotSubtype('<E:num>(E) -> E', '<E:int>(E) -> E', legacyMode: true);
isNotSubtype('<E:num>(int) -> E', '<E:int>(int) -> E', legacyMode: true);
isSubtype('<E:num>(E) -> E', '<F:num>(F) -> num', legacyMode: true);
isSubtype('<E:int>(E) -> E', '<F:int>(F) -> num', legacyMode: true);
isSubtype('<E:int>(E) -> E', '<F:int>(F) -> int', legacyMode: true);
isNotSubtype('<E>(int) -> int', '(int) -> int', legacyMode: true);
isNotSubtype('<E,F>(int) -> int', '<E>(int) -> int', legacyMode: true);
isSubtype('<E:List<E>>(E) -> E', '<F:List<F>>(F) -> F', legacyMode: true);
isNotSubtype('<E:Iterable<E>>(E) -> E', '<F:List<F>>(F) -> F',
legacyMode: true);
isNotSubtype('<E>(E,List<Object>) -> E', '<F:List<F>>(F,F) -> F',
legacyMode: true);
isNotSubtype('<E>(E,List<Object>) -> List<E>', '<F:List<F>>(F,F) -> F',
legacyMode: true);
isNotSubtype('<E>(E,List<Object>) -> int', '<F:List<F>>(F,F) -> F',
legacyMode: true);
isNotSubtype('<E>(E,List<Object>) -> E', '<F:List<F>>(F,F) -> void',
legacyMode: true);
isSubtype('int', 'FutureOr<int>');
isSubtype('int', 'FutureOr<num>');
isSubtype('Future<int>', 'FutureOr<int>');
isSubtype('Future<int>', 'FutureOr<num>');
isSubtype('Future<int>', 'FutureOr<Object>');
isSubtype('FutureOr<int>', 'FutureOr<int>');
isSubtype('FutureOr<int>', 'FutureOr<num>');
isSubtype('FutureOr<int>', 'Object');
isNotSubtype('int', 'FutureOr<double>');
isNotSubtype('FutureOr<double>', 'int');
isNotSubtype('FutureOr<int>', 'Future<num>');
isNotSubtype('FutureOr<int>', 'num');
// T & B <: T & A if B <: A
isSubtype('T & int', 'T & int', legacyMode: true);
isSubtype('T & int', 'T & num', legacyMode: true);
isSubtype('T & num', 'T & num', legacyMode: true);
isNotSubtype('T & num', 'T & int', legacyMode: true);
// T & B <: T extends A if B <: A
// (Trivially satisfied since promoted bounds are always a isSubtype of the
// original bound)
isSubtype('T & int', 'T', legacyMode: true, typeParameters: 'T: int');
isSubtype('T & int', 'T', legacyMode: true, typeParameters: 'T: num');
isSubtype('T & num', 'T', legacyMode: true, typeParameters: 'T: num');
// T extends B <: T & A if B <: A
isSubtype('T', 'T & int', legacyMode: true, typeParameters: 'T: int');
isSubtype('T', 'T & num', legacyMode: true, typeParameters: 'T: int');
isSubtype('T', 'T & num', legacyMode: true, typeParameters: 'T: num');
isNotSubtype('T', 'T & int', legacyMode: true, typeParameters: 'T: num');
// T extends A <: T extends A
isSubtype('T', 'T', legacyMode: true, typeParameters: 'T: num');
// S & B <: A if B <: A, A is not S (or a promotion thereof)
isSubtype('S & int', 'int', legacyMode: true);
isSubtype('S & int', 'num', legacyMode: true);
isSubtype('S & num', 'num', legacyMode: true);
isNotSubtype('S & num', 'int', legacyMode: true);
isNotSubtype('S & num', 'T', legacyMode: true);
isNotSubtype('S & num', 'T & num', legacyMode: true);
// S extends B <: A if B <: A, A is not S (or a promotion thereof)
isSubtype('S', 'int', legacyMode: true, typeParameters: 'S: int');
isSubtype('S', 'num', legacyMode: true, typeParameters: 'S: int');
isSubtype('S', 'num', legacyMode: true, typeParameters: 'S: num');
isNotSubtype('S', 'int', legacyMode: true, typeParameters: 'S: num');
isNotSubtype('S', 'T', legacyMode: true, typeParameters: 'S: num');
isNotSubtype('S', 'T & num', legacyMode: true, typeParameters: 'S: num');
}
}

View file

@ -4,6 +4,9 @@
import "package:front_end/src/fasta/scanner.dart" show scanString, Token;
import "package:front_end/src/fasta/parser/type_info_impl.dart"
show splitCloser;
abstract class ParsedType {
R accept<R, A>(Visitor<R, A> visitor, [A a]);
}
@ -136,7 +139,14 @@ class ParsedTypeVariable extends ParsedType {
ParsedTypeVariable(this.name, this.bound);
String toString() => name;
String toString() {
if (bound == null) return name;
StringBuffer sb = new StringBuffer();
sb.write(name);
sb.write(" extends ");
sb.write(bound);
return "$sb";
}
R accept<R, A>(Visitor<R, A> visitor, [A a]) {
return visitor.visitTypeVariable(this, a);
@ -228,6 +238,7 @@ class Parser {
advance();
arguments.add(parseType());
}
peek = splitCloser(peek);
expect(">");
}
return new ParsedInterfaceType(name, arguments);
@ -291,6 +302,7 @@ class Parser {
do {
typeVariables.add(parseTypeVariable());
} while (optionalAdvance(","));
peek = splitCloser(peek);
expect(">");
}
return typeVariables;

View file

@ -33,5 +33,9 @@ typedef MyList<T> List<T>;
typedef StringList List<String>;
typedef VoidFunction () -> void;
typedef GenericFunction<T> () -> T;
List<List<Object>>
List<List<List<Object>>>
class A<T extends List<Object>>;
class B<T extends List<List<Object>>>;
""");
}