Use type variables on Typedef correctly.

R=johnniwinther@google.com, paulberry@google.com

Review-Url: https://codereview.chromium.org/2967923002 .
This commit is contained in:
Peter von der Ahé 2017-07-05 13:12:26 +02:00
parent a3406c38e2
commit 6bb89e4fbf
25 changed files with 134 additions and 142 deletions

View file

@ -6,7 +6,6 @@ library fasta.function_type_alias_builder;
import 'builder.dart'
show
FormalParameterBuilder,
LibraryBuilder,
MetadataBuilder,
TypeBuilder,
@ -15,20 +14,12 @@ import 'builder.dart'
abstract class FunctionTypeAliasBuilder<T extends TypeBuilder, R>
extends TypeDeclarationBuilder<T, R> {
final T returnType;
final T type;
final List<TypeVariableBuilder> typeVariables;
final List<FormalParameterBuilder> formals;
FunctionTypeAliasBuilder(
List<MetadataBuilder> metadata,
this.returnType,
String name,
this.typeVariables,
this.formals,
LibraryBuilder parent,
int charOffset)
FunctionTypeAliasBuilder(List<MetadataBuilder> metadata, String name,
this.typeVariables, this.type, LibraryBuilder parent, int charOffset)
: super(metadata, null, name, parent, charOffset);
String get debugName => "FunctionTypeAliasBuilder";

View file

@ -4,43 +4,39 @@
library fasta.dill_typedef_builder;
import 'package:front_end/src/fasta/builder/library_builder.dart';
import 'package:front_end/src/fasta/errors.dart';
import 'package:kernel/ast.dart' show DartType, Typedef;
import 'package:front_end/src/fasta/errors.dart' show internalError;
import '../kernel/kernel_builder.dart'
show
FormalParameterBuilder,
KernelFunctionTypeAliasBuilder,
KernelTypeBuilder,
KernelFunctionTypeBuilder,
LibraryBuilder,
MetadataBuilder,
TypeVariableBuilder;
import 'dill_library_builder.dart' show DillLibraryBuilder;
class DillFunctionTypeAliasBuilder extends KernelFunctionTypeAliasBuilder {
DillFunctionTypeAliasBuilder(Typedef typedef, DillLibraryBuilder parent)
: super(null, null, typedef.name, null, null, parent, typedef.fileOffset,
: super(null, typedef.name, null, null, parent, typedef.fileOffset,
typedef);
@override
List<FormalParameterBuilder> get formals {
return internalError('Not implemented.');
}
List<MetadataBuilder> get metadata {
return internalError('Not implemented.');
}
@override
KernelTypeBuilder get returnType {
return internalError('Not implemented.');
}
@override
List<TypeVariableBuilder> get typeVariables {
return internalError('Not implemented.');
}
@override
KernelFunctionTypeBuilder get type {
return internalError('Not implemented.');
}
@override
DartType buildThisType(LibraryBuilder library) => thisType ??= target.type;
}

View file

@ -17,70 +17,72 @@ import 'package:kernel/type_algebra.dart' show substitute;
import 'kernel_builder.dart'
show
FormalParameterBuilder,
FunctionTypeAliasBuilder,
KernelFunctionTypeBuilder,
KernelTypeBuilder,
KernelTypeVariableBuilder,
LibraryBuilder,
MetadataBuilder,
TypeVariableBuilder,
computeDefaultTypeArguments;
import 'kernel_function_type_builder.dart' show buildFunctionType;
class KernelFunctionTypeAliasBuilder
extends FunctionTypeAliasBuilder<KernelTypeBuilder, DartType> {
extends FunctionTypeAliasBuilder<KernelFunctionTypeBuilder, DartType> {
final Typedef target;
DartType thisType;
KernelFunctionTypeAliasBuilder(
List<MetadataBuilder> metadata,
KernelTypeBuilder returnType,
String name,
List<TypeVariableBuilder> typeVariables,
List<FormalParameterBuilder> formals,
KernelFunctionTypeBuilder type,
LibraryBuilder parent,
int charOffset,
[Typedef target])
: target = target ??
(new Typedef(name, null, fileUri: parent.target.fileUri)
..fileOffset = charOffset),
super(metadata, returnType, name, typeVariables, formals, parent,
charOffset);
super(metadata, name, typeVariables, type, parent, charOffset);
Typedef build(LibraryBuilder libraryBuilder) {
// TODO(ahe): We need to move type parameters from [thisType] to [target].
return target..type ??= buildThisType(libraryBuilder);
}
DartType buildThisType(LibraryBuilder library) {
if (thisType != null) {
if (thisType == const InvalidType()) {
thisType = const DynamicType();
if (const InvalidType() == thisType) {
library.addCompileTimeError(
charOffset, "The typedef '$name' has a reference to itself.");
return const DynamicType();
}
return thisType;
}
thisType = const InvalidType();
return thisType =
buildFunctionType(library, returnType, typeVariables, formals);
DartType builtType = type?.build(library) ?? const DynamicType();
if (typeVariables != null) {
for (KernelTypeVariableBuilder tv in typeVariables) {
tv.parameter.bound = tv?.bound?.build(library);
target.typeParameters.add(tv.parameter..parent = target);
}
}
return thisType = builtType;
}
/// [arguments] have already been built.
DartType buildTypesWithBuiltArguments(
LibraryBuilder library, List<DartType> arguments) {
var thisType = buildThisType(library);
if (thisType is DynamicType) return thisType;
if (const DynamicType() == thisType) return thisType;
FunctionType result = thisType;
if (result.typeParameters.isEmpty && arguments == null) return result;
if (target.typeParameters.isEmpty && arguments == null) return result;
arguments =
computeDefaultTypeArguments(library, result.typeParameters, arguments);
computeDefaultTypeArguments(library, target.typeParameters, arguments);
Map<TypeParameter, DartType> substitution = <TypeParameter, DartType>{};
for (int i = 0; i < result.typeParameters.length; i++) {
substitution[result.typeParameters[i]] = arguments[i];
for (int i = 0; i < target.typeParameters.length; i++) {
substitution[target.typeParameters[i]] = arguments[i];
}
return substitute(result.withoutTypeParameters, substitution);
return substitute(result, substitution);
}
@override
@ -89,7 +91,7 @@ class KernelFunctionTypeAliasBuilder
var thisType = buildThisType(library);
if (thisType is DynamicType) return thisType;
FunctionType result = thisType;
if (result.typeParameters.isEmpty && arguments == null) return result;
if (target.typeParameters.isEmpty && arguments == null) return result;
// Otherwise, substitute.
List<DartType> builtArguments = <DartType>[];
if (arguments != null) {

View file

@ -34,7 +34,37 @@ class KernelFunctionTypeBuilder extends FunctionTypeBuilder
: super(charOffset, fileUri, returnType, typeVariables, formals);
DartType build(LibraryBuilder library) {
return buildFunctionType(library, returnType, typeVariables, formals);
DartType builtReturnType =
returnType?.build(library) ?? const DynamicType();
List<DartType> positionalParameters = <DartType>[];
List<NamedType> namedParameters;
int requiredParameterCount = 0;
if (formals != null) {
for (KernelFormalParameterBuilder formal in formals) {
DartType type = formal.type?.build(library) ?? const DynamicType();
if (formal.isPositional) {
positionalParameters.add(type);
if (formal.isRequired) requiredParameterCount++;
} else if (formal.isNamed) {
namedParameters ??= <NamedType>[];
namedParameters.add(new NamedType(formal.name, type));
}
}
if (namedParameters != null) {
namedParameters.sort();
}
}
List<TypeParameter> typeParameters;
if (typeVariables != null) {
typeParameters = <TypeParameter>[];
for (KernelTypeVariableBuilder t in typeVariables) {
typeParameters.add(t.parameter);
}
}
return new FunctionType(positionalParameters, builtReturnType,
namedParameters: namedParameters ?? const <NamedType>[],
typeParameters: typeParameters ?? const <TypeParameter>[],
requiredParameterCount: requiredParameterCount);
}
Supertype buildSupertype(LibraryBuilder library) {
@ -44,40 +74,3 @@ class KernelFunctionTypeBuilder extends FunctionTypeBuilder
return null;
}
}
FunctionType buildFunctionType(
LibraryBuilder library,
KernelTypeBuilder returnType,
List<TypeVariableBuilder> typeVariables,
List<FormalParameterBuilder> formals) {
DartType builtReturnType = returnType?.build(library) ?? const DynamicType();
List<DartType> positionalParameters = <DartType>[];
List<NamedType> namedParameters;
int requiredParameterCount = 0;
if (formals != null) {
for (KernelFormalParameterBuilder formal in formals) {
DartType type = formal.type?.build(library) ?? const DynamicType();
if (formal.isPositional) {
positionalParameters.add(type);
if (formal.isRequired) requiredParameterCount++;
} else if (formal.isNamed) {
namedParameters ??= <NamedType>[];
namedParameters.add(new NamedType(formal.name, type));
}
}
if (namedParameters != null) {
namedParameters.sort();
}
}
List<TypeParameter> typeParameters;
if (typeVariables != null) {
typeParameters = <TypeParameter>[];
for (KernelTypeVariableBuilder t in typeVariables) {
typeParameters.add(t.parameter);
}
}
return new FunctionType(positionalParameters, builtReturnType,
namedParameters: namedParameters ?? const <NamedType>[],
typeParameters: typeParameters ?? const <TypeParameter>[],
requiredParameterCount: requiredParameterCount);
}

View file

@ -32,7 +32,6 @@ import 'kernel_builder.dart'
ClassBuilder,
ConstructorReferenceBuilder,
FormalParameterBuilder,
FunctionTypeAliasBuilder,
InvalidTypeBuilder,
KernelConstructorBuilder,
KernelEnumBuilder,
@ -613,13 +612,12 @@ class KernelLibraryBuilder
void addFunctionTypeAlias(
List<MetadataBuilder> metadata,
KernelTypeBuilder returnType,
String name,
List<TypeVariableBuilder> typeVariables,
List<FormalParameterBuilder> formals,
covariant KernelFunctionTypeBuilder type,
int charOffset) {
FunctionTypeAliasBuilder typedef = new KernelFunctionTypeAliasBuilder(
metadata, returnType, name, typeVariables, formals, this, charOffset);
KernelFunctionTypeAliasBuilder typedef = new KernelFunctionTypeAliasBuilder(
metadata, name, typeVariables, type, this, charOffset);
checkTypeVariables(typeVariables, typedef);
// Nested declaration began in `OutlineBuilder.beginFunctionTypeAlias`.
endNestedDeclaration("#typedef").resolveTypes(typeVariables, this);
@ -634,6 +632,9 @@ class KernelLibraryBuilder
var builder = new KernelFunctionTypeBuilder(
charOffset, fileUri, returnType, typeVariables, formals);
checkTypeVariables(typeVariables, builder);
// Nested declaration began in `OutlineBuilder.beginFunctionType` or
// `OutlineBuilder.beginFunctionTypedFormalParameter`.
endNestedDeclaration("#function_type").resolveTypes(typeVariables, this);
return addType(builder);
}

View file

@ -33,11 +33,11 @@ class KernelTypeVariableBuilder
DartType buildType(
LibraryBuilder library, List<KernelTypeBuilder> arguments) {
if (arguments != null) {
return inputError(null, null,
"Can't use type arguments with type parameter $parameter");
} else {
return new TypeParameterType(parameter);
library.addWarning(arguments.first.charOffset,
"Can't use type arguments with type parameter $parameter",
fileUri: fileUri);
}
return new TypeParameterType(parameter);
}
DartType buildTypesWithBuiltArguments(
@ -55,6 +55,7 @@ class KernelTypeVariableBuilder
}
void finish(LibraryBuilder library, KernelClassBuilder object) {
parameter.bound = bound?.build(library) ?? object.buildType(library, null);
parameter.bound ??=
bound?.build(library) ?? object.buildType(library, null);
}
}

View file

@ -497,22 +497,6 @@ class OutlineBuilder extends UnhandledListener {
// Ignored for now.
}
@override
void endFunctionTypedFormalParameter(
Token thisKeyword, FormalParameterType kind) {
debugEvent("FunctionTypedFormalParameter");
List<FormalParameterBuilder> formals = pop();
int formalsOffset = pop();
List<TypeVariableBuilder> typeVariables = pop();
int charOffset = pop();
String name = pop();
TypeBuilder returnType = pop();
push(library.addFunctionType(
returnType, typeVariables, formals, formalsOffset));
push(name);
push(charOffset);
}
@override
void endOptionalFormalParameters(
int count, Token beginToken, Token endToken) {
@ -611,6 +595,18 @@ class OutlineBuilder extends UnhandledListener {
silenceParserErrors = false;
}
@override
void beginFunctionType(Token beginToken) {
debugEvent("beginFunctionType");
library.beginNestedDeclaration("#function_type", hasMembers: false);
}
@override
void beginFunctionTypedFormalParameter(Token token) {
debugEvent("beginFunctionTypedFormalParameter");
library.beginNestedDeclaration("#function_type", hasMembers: false);
}
@override
void endFunctionType(Token functionToken, Token endToken) {
debugEvent("FunctionType");
@ -622,22 +618,42 @@ class OutlineBuilder extends UnhandledListener {
returnType, typeVariables, formals, functionToken.charOffset));
}
@override
void endFunctionTypedFormalParameter(
Token thisKeyword, FormalParameterType kind) {
debugEvent("FunctionTypedFormalParameter");
List<FormalParameterBuilder> formals = pop();
int formalsOffset = pop();
List<TypeVariableBuilder> typeVariables = pop();
int charOffset = pop();
String name = pop();
TypeBuilder returnType = pop();
push(library.addFunctionType(
returnType, typeVariables, formals, formalsOffset));
push(name);
push(charOffset);
}
@override
void endFunctionTypeAlias(
Token typedefKeyword, Token equals, Token endToken) {
debugEvent("endFunctionTypeAlias");
List<FormalParameterBuilder> formals;
List<TypeVariableBuilder> typeVariables;
String name;
TypeBuilder returnType;
int charOffset;
FunctionTypeBuilder functionType;
if (equals == null) {
formals = pop();
List<FormalParameterBuilder> formals = pop();
pop(); // formals offset
typeVariables = pop();
charOffset = pop();
name = pop();
returnType = pop();
TypeBuilder returnType = pop();
// Create a nested declaration that is ended below by
// `library.addFunctionType`.
library.beginNestedDeclaration("#function_type", hasMembers: false);
functionType =
library.addFunctionType(returnType, null, formals, charOffset);
} else {
var type = pop();
typeVariables = pop();
@ -649,8 +665,7 @@ class OutlineBuilder extends UnhandledListener {
// `type.typeVariables`. A typedef can have type variables, and a new
// function type can also have type variables (representing the type of
// a generic function).
formals = type.formals;
returnType = type.returnType;
functionType = type;
} else {
// TODO(ahe): Improve this error message.
library.addCompileTimeError(
@ -659,7 +674,7 @@ class OutlineBuilder extends UnhandledListener {
}
List<MetadataBuilder> metadata = pop();
library.addFunctionTypeAlias(
metadata, returnType, name, typeVariables, formals, charOffset);
metadata, name, typeVariables, functionType, charOffset);
checkEmpty(typedefKeyword.charOffset);
silenceParserErrors = true;
}

View file

@ -243,10 +243,9 @@ abstract class SourceLibraryBuilder<T extends TypeBuilder, R>
void addFunctionTypeAlias(
List<MetadataBuilder> metadata,
T returnType,
String name,
List<TypeVariableBuilder> typeVariables,
List<FormalParameterBuilder> formals,
FunctionTypeBuilder type,
int charOffset);
FunctionTypeBuilder addFunctionType(

View file

@ -81,7 +81,6 @@ final subpackageRules = {
]),
'lib/src/fasta/dill': new SubpackageRules(allowedDependencies: [
'lib/src/fasta',
'lib/src/fasta/builder',
'lib/src/fasta/kernel',
]),
'lib/src/fasta/kernel': new SubpackageRules(allowedDependencies: [

View file

@ -2,7 +2,7 @@ library;
import self as self;
import "dart:core" as core;
typedef Callback = <T extends core::Object>(T) → void;
typedef Callback<T extends core::Object> = (T) → void;
class Foo<T extends core::Object> extends core::Object {
final field self::Foo::T finalField;
final field (self::Foo::T) → void callbackField;

View file

@ -2,7 +2,7 @@ library;
import self as self;
import "dart:core" as core;
typedef Callback = <T extends core::Object>(T) → void;
typedef Callback<T extends core::Object> = (T) → void;
class Foo<T extends core::Object> extends core::Object {
final field self::Foo::T finalField;
final field (self::Foo::T) → void callbackField;

View file

@ -2,7 +2,7 @@ library test;
import self as self;
import "dart:core" as core;
typedef F = <T extends core::Object>() → T;
typedef F<T extends core::Object> = () → T;
class A extends core::Object {
constructor •() → void
: super core::Object::•()

View file

@ -2,7 +2,7 @@ library test;
import self as self;
import "dart:core" as core;
typedef Function2 = <S extends core::Object, T extends core::Object>(S) → T;
typedef Function2<S extends core::Object, T extends core::Object> = (S) → T;
class A<T extends core::Object> extends core::Object {
field (self::A::T) → self::A::T x;
constructor •((self::A::T) → self::A::T x) → void

View file

@ -2,7 +2,7 @@ library test;
import self as self;
import "dart:core" as core;
typedef F = <T extends core::Object>() → void;
typedef F<T extends core::Object> = () → void;
class Foo extends core::Object {
const constructor •(core::List<core::String> l) → void
: super core::Object::•()

View file

@ -2,7 +2,7 @@ library test;
import self as self;
import "dart:core" as core;
typedef F = <T extends core::Object>() → void;
typedef F<T extends core::Object> = () → void;
class Foo extends core::Object {
const constructor •(core::List<core::String> l) → void
;

View file

@ -2,7 +2,7 @@ library test;
import self as self;
import "dart:core" as core;
typedef Function2 = <S extends core::Object, T extends core::Object>([S]) → T;
typedef Function2<S extends core::Object, T extends core::Object> = ([S]) → T;
class Foo extends core::Object {
field core::List<core::int> x;
constructor •([core::List<core::int> x = const <core::int>[1]]) → void

View file

@ -2,7 +2,7 @@ library test;
import self as self;
import "dart:core" as core;
typedef Function2 = <S extends core::Object, T extends core::Object>(S) → T;
typedef Function2<S extends core::Object, T extends core::Object> = (S) → T;
static method main() → void {
{
(core::int) → core::String l0 = (core::int x) → core::String => null;

View file

@ -2,8 +2,8 @@ library test;
import self as self;
import "dart:core" as core;
typedef Asserter = <T extends core::Object>(T) → void;
typedef AsserterBuilder = <S extends core::Object, T extends core::Object>(S) → (T) → void;
typedef Asserter<T extends core::Object> = (T) → void;
typedef AsserterBuilder<S extends core::Object, T extends core::Object> = (S) → (T) → void;
class DartType extends core::Object {
constructor •() → void
: super core::Object::•()

View file

@ -2,7 +2,7 @@ library test;
import self as self;
import "dart:core" as core;
typedef F = <V extends core::Object>(V) → void;
typedef F<V extends core::Object> = (V) → void;
class C<T extends core::Object> extends self::D<self::C::T> {
constructor •() → void
: super self::D::•()

View file

@ -2,7 +2,7 @@ library test;
import self as self;
import "dart:core" as core;
typedef G = <V extends core::Object>() → core::List<V>;
typedef G<V extends core::Object> = () → core::List<V>;
class C<T extends core::Object> extends self::D<self::C::T> {
constructor •() → void
: super self::D::•()

View file

@ -2,7 +2,7 @@ library test;
import self as self;
import "dart:core" as core;
typedef F = <V extends core::Object>() → V;
typedef F<V extends core::Object> = () → V;
class C<T extends core::Object> extends self::D<self::C::T> {
constructor •() → void
: super self::D::•()

View file

@ -2,6 +2,6 @@ library test;
import self as self;
import "dart:core" as core;
typedef F = <T extends core::Object>() → T;
typedef F<T extends core::Object> = () → T;
static final field core::Map<core::String, () → core::int> x = <core::String, () → core::int>{};
static method main() → dynamic {}

View file

@ -348,8 +348,10 @@ class BinaryPrinter extends Visitor {
writeOffset(node.fileOffset);
writeStringReference(node.name);
writeUriReference(node.fileUri ?? '');
_typeParameterIndexer.enter(node.typeParameters);
writeNodeList(node.typeParameters);
writeNode(node.type);
_typeParameterIndexer.exit(node.typeParameters);
}
void writeAnnotation(Expression annotation) {

View file

@ -168,8 +168,6 @@ Language/Statements/Yield_and_Yield_Each/Yield_Each/location_t01: MissingCompile
Language/Statements/Yield_and_Yield_Each/Yield_Each/location_t03: MissingCompileTimeError # Issue 25495
Language/Statements/Yield_and_Yield_Each/Yield_Each/location_t05: MissingCompileTimeError # Issue 25495
Language/Types/Static_Types/deferred_type_t01: RuntimeError # Kernel Issue 28335 (deferred libraries)
Language/Types/Type_Declarations/Typedef/self_reference_t08: MissingCompileTimeError
Language/Types/Type_Declarations/Typedef/self_reference_t09: MissingCompileTimeError
Language/Types/Type_Void/syntax_t02: MissingCompileTimeError
Language/Variables/final_or_static_initialization_t02: MissingCompileTimeError
Language/Variables/final_or_static_initialization_t03: MissingCompileTimeError

View file

@ -144,9 +144,6 @@ const_instance_field_test/01: MissingCompileTimeError # Fasta bug: Const instanc
cyclic_constructor_test/01: MissingCompileTimeError # Fasta bug: Cyclic constructor redirection.
cyclic_typedef_test/10: MissingCompileTimeError # Fasta bug: Cyclic typedef via type variable.
cyclic_typedef_test/11: MissingCompileTimeError # Fasta bug: Cyclic typedef via type variable.
const_optional_args_negative_test: Fail # Fasta bug: Default parameter values must be const.
named_parameters_default_eq_test/02: MissingCompileTimeError # Fasta bug: Default values are not allowed on redirecting factory constructors.
@ -173,8 +170,6 @@ regress_29349_test: CompileTimeError # Fasta bug: Parser bug.
const_native_factory_test/01: MissingCompileTimeError # Fasta bug: Issue 29763
generic_function_typedef_test: RuntimeError # Fasta bug: resolution of type variables in typedef.
constants_test/05: Crash # Fasta bug: getter call in compile-time constant.
assignable_expression_test/50: MissingCompileTimeError # Test bug: Test doesn't execute erroneous code.