Index: runtime/vm/parser.cc |
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc |
index 6371905dbf3df53434cb69fd6d43d239d9ae4ae9..95f0e1c290ee2c188f7f05025f11b27c79d3ba45 100644 |
--- a/runtime/vm/parser.cc |
+++ b/runtime/vm/parser.cc |
@@ -1557,29 +1557,31 @@ SequenceNode* Parser::ParseImplicitClosure(const Function& func) { |
OpenFunctionBlock(func); |
+ const Function& parent = Function::Handle(func.parent_function()); |
+ intptr_t type_args_len = 0; // Length of type args vector passed to parent. |
+ LocalVariable* type_args_var = NULL; |
if (FLAG_reify_generic_functions) { |
// The parent function of an implicit closure is the original function, i.e. |
// non-closurized. It is not an enclosing function in the usual sense of a |
// parent function. Do not set parent_type_arguments() in parsed_function_. |
- ASSERT(func.IsGeneric() == func.HasGenericParent()); |
+ ASSERT(func.IsGeneric() == parent.IsGeneric()); |
if (func.IsGeneric()) { |
+ type_args_len = func.NumTypeParameters(); |
// Insert function type arguments variable to scope. |
- LocalVariable* function_type_arguments = new (Z) LocalVariable( |
+ type_args_var = new (Z) LocalVariable( |
TokenPosition::kNoSource, TokenPosition::kNoSource, |
Symbols::FunctionTypeArgumentsVar(), Object::dynamic_type()); |
- current_block_->scope->AddVariable(function_type_arguments); |
+ current_block_->scope->AddVariable(type_args_var); |
ASSERT(FunctionLevel() == 0); |
- parsed_function_->set_function_type_arguments(function_type_arguments); |
+ parsed_function_->set_function_type_arguments(type_args_var); |
} |
} |
- // TODO(regis): Pass the function type arguments if func is generic. |
ParamList params; |
params.AddFinalParameter(token_pos, &Symbols::ClosureParameter(), |
&Object::dynamic_type()); |
- const Function& parent = Function::Handle(func.parent_function()); |
if (parent.IsImplicitSetterFunction()) { |
const TokenPosition ident_pos = func.token_pos(); |
ASSERT(IsIdentifier()); |
@@ -1605,7 +1607,8 @@ SequenceNode* Parser::ParseImplicitClosure(const Function& func) { |
LocalScope* scope = current_block_->scope; |
AddFormalParamsToScope(¶ms, scope); |
- ArgumentListNode* func_args = new ArgumentListNode(token_pos); |
+ ArgumentListNode* func_args = |
+ new ArgumentListNode(token_pos, type_args_var, type_args_len); |
if (!func.is_static()) { |
func_args->Add(LoadReceiver(token_pos)); |
} |
@@ -1654,9 +1657,10 @@ SequenceNode* Parser::ParseImplicitClosure(const Function& func) { |
ArgumentListNode* arguments = BuildNoSuchMethodArguments( |
token_pos, func_name, *func_args, NULL, false); |
+ const intptr_t kTypeArgsLen = 0; |
const intptr_t kNumArguments = 2; // Receiver, InvocationMirror. |
- ArgumentsDescriptor args_desc( |
- Array::Handle(Z, ArgumentsDescriptor::New(kNumArguments))); |
+ ArgumentsDescriptor args_desc(Array::Handle( |
+ Z, ArgumentsDescriptor::New(kTypeArgsLen, kNumArguments))); |
Function& no_such_method = |
Function::ZoneHandle(Z, Resolver::ResolveDynamicForReceiverClass( |
owner, Symbols::NoSuchMethod(), args_desc)); |
@@ -1797,9 +1801,10 @@ SequenceNode* Parser::ParseNoSuchMethodDispatcher(const Function& func) { |
const String& func_name = String::ZoneHandle(Z, func.name()); |
ArgumentListNode* arguments = |
BuildNoSuchMethodArguments(token_pos, func_name, *func_args, NULL, false); |
+ const intptr_t kTypeArgsLen = 0; |
const intptr_t kNumArguments = 2; // Receiver, InvocationMirror. |
ArgumentsDescriptor args_desc( |
- Array::Handle(Z, ArgumentsDescriptor::New(kNumArguments))); |
+ Array::Handle(Z, ArgumentsDescriptor::New(kTypeArgsLen, kNumArguments))); |
Function& no_such_method = Function::ZoneHandle( |
Z, |
Resolver::ResolveDynamicForReceiverClass( |
@@ -2378,7 +2383,8 @@ RawFunction* Parser::GetSuperFunction(TokenPosition token_pos, |
Function& super_func = Function::Handle( |
Z, Resolver::ResolveDynamicAnyArgs(Z, super_class, name)); |
if (!super_func.IsNull() && |
- !super_func.AreValidArguments(arguments->length(), arguments->names(), |
+ !super_func.AreValidArguments(arguments->type_args_len(), |
+ arguments->length(), arguments->names(), |
NULL)) { |
super_func = Function::null(); |
} else if (super_func.IsNull() && resolve_getter) { |
@@ -2416,12 +2422,19 @@ StaticCallNode* Parser::BuildInvocationMirrorAllocation( |
arguments->Add(new LiteralNode(args_pos, function_name)); |
// The second argument is the arguments descriptor of the original function. |
const Array& args_descriptor = Array::ZoneHandle( |
- ArgumentsDescriptor::New(function_args.length(), function_args.names())); |
+ ArgumentsDescriptor::New(function_args.type_args_len(), |
+ function_args.length(), function_args.names())); |
arguments->Add(new LiteralNode(args_pos, args_descriptor)); |
// The third argument is an array containing the original function arguments, |
- // including the receiver. |
+ // including the function type arguments and the receiver. |
ArrayNode* args_array = |
new ArrayNode(args_pos, Type::ZoneHandle(Type::ArrayType())); |
+ // The type_args_var is only used in the generated body of an implicit closure |
+ // where noSuchMethod should never be called. |
+ ASSERT(function_args.type_args_var() == NULL); |
+ if (!function_args.type_arguments().IsNull()) { |
+ // TODO(regis): Pass the original type arguments to the invocation mirror. |
+ } |
for (intptr_t i = 0; i < function_args.length(); i++) { |
AstNode* arg = function_args.NodeAt(i); |
if ((temp_for_last_arg != NULL) && (i == function_args.length() - 1)) { |
@@ -2467,16 +2480,18 @@ ArgumentListNode* Parser::BuildNoSuchMethodArguments( |
} |
-AstNode* Parser::ParseSuperCall(const String& function_name) { |
+AstNode* Parser::ParseSuperCall(const String& function_name, |
+ const TypeArguments& func_type_args) { |
TRACE_PARSER("ParseSuperCall"); |
ASSERT(CurrentToken() == Token::kLPAREN); |
const TokenPosition supercall_pos = TokenPos(); |
- // 'this' parameter is the first argument to super call. |
- ArgumentListNode* arguments = new ArgumentListNode(supercall_pos); |
+ // 'this' parameter is the first argument to super call (after the type args). |
+ ArgumentListNode* arguments = |
+ new ArgumentListNode(supercall_pos, func_type_args); |
AstNode* receiver = LoadReceiver(supercall_pos); |
arguments->Add(receiver); |
- ParseActualParameters(arguments, kAllowConst); |
+ ParseActualParameters(arguments, Object::null_type_arguments(), kAllowConst); |
const bool kResolveGetter = true; |
bool is_no_such_method = false; |
@@ -2490,7 +2505,8 @@ AstNode* Parser::ParseSuperCall(const String& function_name) { |
AstNode* closure = new StaticGetterNode( |
supercall_pos, LoadReceiver(supercall_pos), super_class, function_name); |
// 'this' is not passed as parameter to the closure. |
- ArgumentListNode* closure_arguments = new ArgumentListNode(supercall_pos); |
+ ArgumentListNode* closure_arguments = |
+ new ArgumentListNode(supercall_pos, func_type_args); |
for (int i = 1; i < arguments->length(); i++) { |
closure_arguments->Add(arguments->NodeAt(i)); |
} |
@@ -2705,7 +2721,8 @@ StaticCallNode* Parser::GenerateSuperConstructorCall( |
} |
String& error_message = String::Handle(Z); |
- if (!super_ctor.AreValidArguments(arguments->length(), arguments->names(), |
+ if (!super_ctor.AreValidArguments(arguments->type_args_len(), |
+ arguments->length(), arguments->names(), |
&error_message)) { |
ReportError(supercall_pos, |
"invalid arguments passed to super constructor '%s()': %s", |
@@ -2740,7 +2757,7 @@ StaticCallNode* Parser::ParseSuperInitializer(const Class& cls, |
// 'this' parameter must not be accessible to the other super call arguments. |
receiver->set_invisible(true); |
- ParseActualParameters(arguments, kAllowConst); |
+ ParseActualParameters(arguments, Object::null_type_arguments(), kAllowConst); |
receiver->set_invisible(false); |
// Resolve the constructor. |
@@ -2760,7 +2777,8 @@ StaticCallNode* Parser::ParseSuperInitializer(const Class& cls, |
ReportError(supercall_pos, "super constructor must be const"); |
} |
String& error_message = String::Handle(Z); |
- if (!super_ctor.AreValidArguments(arguments->length(), arguments->names(), |
+ if (!super_ctor.AreValidArguments(arguments->type_args_len(), |
+ arguments->length(), arguments->names(), |
&error_message)) { |
ReportError(supercall_pos, |
"invalid arguments passed to super class constructor '%s': %s", |
@@ -3132,7 +3150,7 @@ void Parser::ParseConstructorRedirection(const Class& cls, |
arguments->Add(implicit_argument); |
receiver->set_invisible(true); |
- ParseActualParameters(arguments, kAllowConst); |
+ ParseActualParameters(arguments, Object::null_type_arguments(), kAllowConst); |
receiver->set_invisible(false); |
// Resolve the constructor. |
const Function& redirect_ctor = |
@@ -3151,7 +3169,8 @@ void Parser::ParseConstructorRedirection(const Class& cls, |
String::Handle(Z, redirect_ctor.UserVisibleName()).ToCString()); |
} |
String& error_message = String::Handle(Z); |
- if (!redirect_ctor.AreValidArguments(arguments->length(), arguments->names(), |
+ if (!redirect_ctor.AreValidArguments(arguments->type_args_len(), |
+ arguments->length(), arguments->names(), |
&error_message)) { |
ReportError(call_pos, "invalid arguments passed to constructor '%s': %s", |
String::Handle(Z, redirect_ctor.UserVisibleName()).ToCString(), |
@@ -9618,9 +9637,10 @@ AstNode* Parser::MakeStaticCall(const String& cls_name, |
ArgumentListNode* arguments) { |
const Class& cls = Class::Handle(Z, Library::LookupCoreClass(cls_name)); |
ASSERT(!cls.IsNull()); |
+ const intptr_t kTypeArgsLen = 0; // Not passing type args to generic func. |
const Function& func = Function::ZoneHandle( |
- Z, Resolver::ResolveStatic(cls, func_name, arguments->length(), |
- arguments->names())); |
+ Z, Resolver::ResolveStatic(cls, func_name, kTypeArgsLen, |
+ arguments->length(), arguments->names())); |
ASSERT(!func.IsNull()); |
return new (Z) StaticCallNode(arguments->token_pos(), func, arguments); |
} |
@@ -11626,14 +11646,19 @@ AstNode* Parser::ParseUnaryExpr() { |
ArgumentListNode* Parser::ParseActualParameters( |
ArgumentListNode* implicit_arguments, |
+ const TypeArguments& func_type_args, |
bool require_const) { |
TRACE_PARSER("ParseActualParameters"); |
ASSERT(CurrentToken() == Token::kLPAREN); |
const bool saved_mode = SetAllowFunctionLiterals(true); |
ArgumentListNode* arguments; |
if (implicit_arguments == NULL) { |
- arguments = new (Z) ArgumentListNode(TokenPos()); |
+ // TODO(regis): When require_const is true, do we need to check that |
+ // func_type_args are null or instantiated? |
+ arguments = new (Z) ArgumentListNode(TokenPos(), func_type_args); |
} else { |
+ // If implicit arguments are provided, they include type arguments (if any). |
+ ASSERT(func_type_args.IsNull()); |
arguments = implicit_arguments; |
} |
const GrowableObjectArray& names = |
@@ -11684,15 +11709,17 @@ ArgumentListNode* Parser::ParseActualParameters( |
AstNode* Parser::ParseStaticCall(const Class& cls, |
const String& func_name, |
TokenPosition ident_pos, |
+ const TypeArguments& func_type_args, |
const LibraryPrefix* prefix) { |
TRACE_PARSER("ParseStaticCall"); |
const TokenPosition call_pos = TokenPos(); |
ASSERT(CurrentToken() == Token::kLPAREN); |
- ArgumentListNode* arguments = ParseActualParameters(NULL, kAllowConst); |
+ ArgumentListNode* arguments = |
+ ParseActualParameters(NULL, func_type_args, kAllowConst); |
const int num_arguments = arguments->length(); |
const Function& func = Function::ZoneHandle( |
- Z, Resolver::ResolveStatic(cls, func_name, num_arguments, |
- arguments->names())); |
+ Z, Resolver::ResolveStatic(cls, func_name, func_type_args.Length(), |
+ num_arguments, arguments->names())); |
if (func.IsNull()) { |
// Check if there is a static field of the same name, it could be a closure |
// and so we try and invoke the closure. |
@@ -11704,9 +11731,10 @@ AstNode* Parser::ParseStaticCall(const Class& cls, |
const String& getter_name = |
String::ZoneHandle(Z, Field::LookupGetterSymbol(func_name)); |
if (!getter_name.IsNull()) { |
+ const int kTypeArgsLen = 0; // no type arguments. |
const int kNumArguments = 0; // no arguments. |
- func = Resolver::ResolveStatic(cls, getter_name, kNumArguments, |
- Object::empty_array()); |
+ func = Resolver::ResolveStatic(cls, getter_name, kTypeArgsLen, |
+ kNumArguments, Object::empty_array()); |
if (!func.IsNull()) { |
ASSERT(func.kind() != RawFunction::kImplicitStaticFinalGetter); |
closure = new (Z) StaticGetterNode( |
@@ -11725,7 +11753,8 @@ AstNode* Parser::ParseStaticCall(const Class& cls, |
NULL, // No existing function. |
prefix); |
} else if (cls.IsTopLevel() && (cls.library() == Library::CoreLibrary()) && |
- (func.name() == Symbols::Identical().raw())) { |
+ (func.name() == Symbols::Identical().raw()) && |
+ func_type_args.IsNull()) { |
// This is the predefined toplevel function identical(a,b). |
// Create a comparison node instead of a static call to the function. |
ASSERT(num_arguments == 2); |
@@ -11759,20 +11788,24 @@ AstNode* Parser::ParseStaticCall(const Class& cls, |
AstNode* Parser::ParseInstanceCall(AstNode* receiver, |
const String& func_name, |
TokenPosition ident_pos, |
+ const TypeArguments& func_type_args, |
bool is_conditional) { |
TRACE_PARSER("ParseInstanceCall"); |
CheckToken(Token::kLPAREN); |
- ArgumentListNode* arguments = ParseActualParameters(NULL, kAllowConst); |
+ ArgumentListNode* arguments = |
+ ParseActualParameters(NULL, func_type_args, kAllowConst); |
return new (Z) InstanceCallNode(ident_pos, receiver, func_name, arguments, |
is_conditional); |
} |
-AstNode* Parser::ParseClosureCall(AstNode* closure) { |
+AstNode* Parser::ParseClosureCall(AstNode* closure, |
+ const TypeArguments& func_type_args) { |
TRACE_PARSER("ParseClosureCall"); |
const TokenPosition call_pos = TokenPos(); |
ASSERT(CurrentToken() == Token::kLPAREN); |
- ArgumentListNode* arguments = ParseActualParameters(NULL, kAllowConst); |
+ ArgumentListNode* arguments = |
+ ParseActualParameters(NULL, func_type_args, kAllowConst); |
return BuildClosureCall(call_pos, closure, arguments); |
} |
@@ -11972,29 +12005,31 @@ AstNode* Parser::ParseSelectors(AstNode* primary, bool is_cascade) { |
if (IsArgumentPart()) { |
// Identifier followed by optional type arguments and opening paren: |
// method call. |
+ TypeArguments& func_type_args = TypeArguments::ZoneHandle(Z); |
if (CurrentToken() == Token::kLT) { |
// Type arguments. |
if (!FLAG_generic_method_syntax) { |
ReportError("generic type arguments not supported."); |
} |
- // TODO(regis): Pass type arguments in generic call. |
- // For now, resolve type arguments and ignore. |
- ParseTypeArguments(ClassFinalizer::kCanonicalize); |
+ func_type_args = ParseTypeArguments(ClassFinalizer::kCanonicalize); |
+ if (!FLAG_reify_generic_functions) { |
+ func_type_args = TypeArguments::null(); |
+ } |
} |
PrimaryNode* primary_node = left->AsPrimaryNode(); |
if ((primary_node != NULL) && primary_node->primary().IsClass()) { |
// Static method call prefixed with class name. |
const Class& cls = Class::Cast(primary_node->primary()); |
- selector = |
- ParseStaticCall(cls, *ident, ident_pos, primary_node->prefix()); |
+ selector = ParseStaticCall(cls, *ident, ident_pos, func_type_args, |
+ primary_node->prefix()); |
} else { |
if ((primary_node != NULL) && primary_node->is_deferred_reference()) { |
const Class& cls = Class::Handle(library_.toplevel_class()); |
- selector = |
- ParseStaticCall(cls, *ident, ident_pos, primary_node->prefix()); |
+ selector = ParseStaticCall(cls, *ident, ident_pos, func_type_args, |
+ primary_node->prefix()); |
} else { |
- selector = |
- ParseInstanceCall(left, *ident, ident_pos, is_conditional); |
+ selector = ParseInstanceCall(left, *ident, ident_pos, |
+ func_type_args, is_conditional); |
} |
} |
} else { |
@@ -12063,14 +12098,16 @@ AstNode* Parser::ParseSelectors(AstNode* primary, bool is_cascade) { |
selector = new (Z) |
LoadIndexedNode(bracket_pos, array, index, Class::ZoneHandle(Z)); |
} else if (IsArgumentPart()) { |
+ TypeArguments& func_type_args = TypeArguments::ZoneHandle(Z); |
if (CurrentToken() == Token::kLT) { |
// Type arguments. |
if (!FLAG_generic_method_syntax) { |
ReportError("generic type arguments not supported."); |
} |
- // TODO(regis): Pass type arguments in generic call. |
- // For now, resolve type arguments and ignore. |
- ParseTypeArguments(ClassFinalizer::kCanonicalize); |
+ func_type_args = ParseTypeArguments(ClassFinalizer::kCanonicalize); |
+ if (!FLAG_reify_generic_functions) { |
+ func_type_args = TypeArguments::null(); |
+ } |
} |
if (left->IsPrimaryNode()) { |
PrimaryNode* primary_node = left->AsPrimaryNode(); |
@@ -12081,7 +12118,8 @@ AstNode* Parser::ParseSelectors(AstNode* primary, bool is_cascade) { |
if (func.is_static()) { |
// Parse static function call. |
Class& cls = Class::Handle(Z, func.Owner()); |
- selector = ParseStaticCall(cls, func_name, primary_pos); |
+ selector = |
+ ParseStaticCall(cls, func_name, primary_pos, func_type_args); |
} else { |
// Dynamic function call on implicit "this" parameter. |
if (current_function().is_static()) { |
@@ -12090,9 +12128,9 @@ AstNode* Parser::ParseSelectors(AstNode* primary, bool is_cascade) { |
"from static function", |
func_name.ToCString()); |
} |
- selector = |
- ParseInstanceCall(LoadReceiver(primary_pos), func_name, |
- primary_pos, false /* is_conditional */); |
+ selector = ParseInstanceCall(LoadReceiver(primary_pos), func_name, |
+ primary_pos, func_type_args, |
+ false /* is_conditional */); |
} |
} else if (primary_node->primary().IsString()) { |
// Primary is an unresolved name. |
@@ -12104,20 +12142,23 @@ AstNode* Parser::ParseSelectors(AstNode* primary, bool is_cascade) { |
if (primary_node->is_deferred_reference()) { |
// The static call will be converted to throwing a NSM error. |
const Class& cls = Class::Handle(library_.toplevel_class()); |
- selector = |
- ParseStaticCall(cls, name, primary_pos, primary_node->prefix()); |
+ selector = ParseStaticCall(cls, name, primary_pos, func_type_args, |
+ primary_node->prefix()); |
} else if (current_function().is_static()) { |
// The static call will be converted to throwing a NSM error. |
- selector = ParseStaticCall(current_class(), name, primary_pos); |
+ selector = ParseStaticCall(current_class(), name, primary_pos, |
+ func_type_args); |
} else { |
// Treat as call to unresolved (instance) method. |
selector = |
ParseInstanceCall(LoadReceiver(primary_pos), name, primary_pos, |
- false /* is_conditional */); |
+ func_type_args, false /* is_conditional */); |
} |
} else if (primary_node->primary().IsTypeParameter()) { |
+ // TODO(regis): What about the parsed type arguments? |
selector = LoadTypeParameter(primary_node); |
} else if (primary_node->primary().IsClass()) { |
+ // TODO(regis): What about the parsed type arguments? |
const Class& type_class = Class::Cast(primary_node->primary()); |
AbstractType& type = Type::ZoneHandle( |
Z, Type::New(type_class, Object::null_type_arguments(), |
@@ -12133,7 +12174,7 @@ AstNode* Parser::ParseSelectors(AstNode* primary, bool is_cascade) { |
} else { |
// Left is not a primary node; this must be a closure call. |
AstNode* closure = left; |
- selector = ParseClosureCall(closure); |
+ selector = ParseClosureCall(closure, func_type_args); |
} |
} else { |
// No (more) selectors to parse. |
@@ -12683,10 +12724,11 @@ StaticGetterNode* Parser::RunStaticFieldInitializer( |
NoReloadScope no_reload_scope(isolate(), thread()); |
NoOOBMessageScope no_msg_scope(thread()); |
field.SetStaticValue(Object::transition_sentinel()); |
- const int kNumArguments = 0; // no arguments. |
+ const int kTypeArgsLen = 0; // No type argument vector. |
+ const int kNumArguments = 0; // No arguments. |
const Function& func = Function::Handle( |
- Z, Resolver::ResolveStatic(field_owner, getter_name, kNumArguments, |
- Object::empty_array())); |
+ Z, Resolver::ResolveStatic(field_owner, getter_name, kTypeArgsLen, |
+ kNumArguments, Object::empty_array())); |
ASSERT(!func.IsNull()); |
ASSERT(func.kind() == RawFunction::kImplicitStaticFinalGetter); |
Object& const_value = Object::Handle(Z); |
@@ -12737,8 +12779,10 @@ RawObject* Parser::EvaluateConstConstructorCall( |
ArgumentListNode* arguments) { |
NoReloadScope no_reload_scope(isolate(), thread()); |
NoOOBMessageScope no_msg_scope(thread()); |
+ // Factories and constructors are not generic functions. |
+ const int kTypeArgsLen = 0; |
// Factories have one extra argument: the type arguments. |
- // Constructors have 1 extra arguments: receiver. |
+ // Constructors have one extra arguments: receiver. |
const int kNumExtraArgs = 1; |
const int num_arguments = arguments->length() + kNumExtraArgs; |
const Array& arg_values = |
@@ -12765,8 +12809,9 @@ RawObject* Parser::EvaluateConstConstructorCall( |
ASSERT(arg->IsLiteralNode()); |
arg_values.SetAt((i + kNumExtraArgs), arg->AsLiteralNode()->literal()); |
} |
- const Array& args_descriptor = Array::Handle( |
- Z, ArgumentsDescriptor::New(num_arguments, arguments->names())); |
+ const Array& args_descriptor = |
+ Array::Handle(Z, ArgumentsDescriptor::New(kTypeArgsLen, num_arguments, |
+ arguments->names())); |
const Object& result = Object::Handle( |
Z, DartEntry::InvokeFunction(constructor, arg_values, args_descriptor)); |
if (result.IsError()) { |
@@ -14070,7 +14115,8 @@ AstNode* Parser::ParseNewOperator(Token::Kind op_kind) { |
if (!is_tearoff_expression) { |
CheckToken(Token::kLPAREN); |
call_pos = TokenPos(); |
- arguments = ParseActualParameters(NULL, is_const); |
+ arguments = |
+ ParseActualParameters(NULL, TypeArguments::ZoneHandle(Z), is_const); |
} else { |
// Allocate dummy node with no arguments so we don't have to deal |
// with the NULL corner case below. |
@@ -14249,9 +14295,10 @@ AstNode* Parser::ParseNewOperator(Token::Kind op_kind) { |
} |
ASSERT(!is_tearoff_expression); |
+ const int kTypeArgsLen = 0; |
String& error_message = String::Handle(Z); |
- if (!constructor.AreValidArguments(arguments_length, arguments->names(), |
- &error_message)) { |
+ if (!constructor.AreValidArguments(kTypeArgsLen, arguments_length, |
+ arguments->names(), &error_message)) { |
const String& external_constructor_name = |
(named_constructor ? constructor_name : type_class_name); |
if (is_const) { |
@@ -14657,8 +14704,19 @@ AstNode* Parser::ParsePrimary() { |
ConsumeToken(); |
const TokenPosition ident_pos = TokenPos(); |
const String& ident = *ExpectIdentifier("identifier expected"); |
- if (CurrentToken() == Token::kLPAREN) { |
- primary = ParseSuperCall(ident); |
+ if (IsArgumentPart()) { |
+ TypeArguments& func_type_args = TypeArguments::ZoneHandle(Z); |
+ if (CurrentToken() == Token::kLT) { |
+ // Type arguments. |
+ if (!FLAG_generic_method_syntax) { |
+ ReportError("generic type arguments not supported."); |
+ } |
+ func_type_args = ParseTypeArguments(ClassFinalizer::kCanonicalize); |
+ if (!FLAG_reify_generic_functions) { |
+ func_type_args = TypeArguments::null(); |
+ } |
+ } |
+ primary = ParseSuperCall(ident, func_type_args); |
} else { |
primary = ParseSuperFieldAccess(ident, ident_pos); |
} |