Skip to content

Commit 149b799

Browse files
liamappelbecommit-bot@chromium.org
authored andcommitted
[vm] Check required flag during function resolution.
Bug: #39660 Bug: #38843 Change-Id: I2eb5f5ac38d7b1896db5c57399c42cdb41b16094 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/137737 Commit-Queue: Liam Appelbe <[email protected]> Reviewed-by: Alexander Markov <[email protected]> Reviewed-by: Régis Crelier <[email protected]>
1 parent 75de086 commit 149b799

File tree

2 files changed

+64
-51
lines changed

2 files changed

+64
-51
lines changed

runtime/vm/object.cc

Lines changed: 40 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -7426,45 +7426,10 @@ bool Function::AreValidArguments(NNBDMode mode,
74267426
intptr_t num_arguments,
74277427
const Array& argument_names,
74287428
String* error_message) const {
7429-
const intptr_t num_named_arguments =
7430-
argument_names.IsNull() ? 0 : argument_names.Length();
7431-
if (!AreValidArgumentCounts(num_type_arguments, num_arguments,
7432-
num_named_arguments, error_message)) {
7433-
return false;
7434-
}
7435-
// Verify that all argument names are valid parameter names.
7436-
Zone* zone = Thread::Current()->zone();
7437-
String& argument_name = String::Handle(zone);
7438-
String& parameter_name = String::Handle(zone);
7439-
for (intptr_t i = 0; i < num_named_arguments; i++) {
7440-
argument_name ^= argument_names.At(i);
7441-
ASSERT(argument_name.IsSymbol());
7442-
bool found = false;
7443-
const intptr_t num_positional_args = num_arguments - num_named_arguments;
7444-
const intptr_t num_parameters = NumParameters();
7445-
for (intptr_t j = num_positional_args; !found && (j < num_parameters);
7446-
j++) {
7447-
parameter_name = ParameterNameAt(j);
7448-
ASSERT(argument_name.IsSymbol());
7449-
if (argument_name.Equals(parameter_name)) {
7450-
found = true;
7451-
}
7452-
}
7453-
if (!found) {
7454-
if (error_message != NULL) {
7455-
const intptr_t kMessageBufferSize = 64;
7456-
char message_buffer[kMessageBufferSize];
7457-
Utils::SNPrint(message_buffer, kMessageBufferSize,
7458-
"no optional formal parameter named '%s'",
7459-
argument_name.ToCString());
7460-
// Allocate in old space because it can be invoked in background
7461-
// optimizing compilation.
7462-
*error_message = String::New(message_buffer, Heap::kOld);
7463-
}
7464-
return false;
7465-
}
7466-
}
7467-
return true;
7429+
const Array& args_desc_array = Array::Handle(ArgumentsDescriptor::New(
7430+
num_type_arguments, num_arguments, argument_names, Heap::kNew));
7431+
ArgumentsDescriptor args_desc(args_desc_array);
7432+
return AreValidArguments(mode, args_desc, error_message);
74687433
}
74697434

74707435
bool Function::AreValidArguments(NNBDMode mode,
@@ -7478,41 +7443,65 @@ bool Function::AreValidArguments(NNBDMode mode,
74787443
num_named_arguments, error_message)) {
74797444
return false;
74807445
}
7481-
if (FLAG_null_safety) {
7482-
// TODO(regis): Check required named arguments.
7483-
}
74847446
// Verify that all argument names are valid parameter names.
74857447
Zone* zone = Thread::Current()->zone();
74867448
String& argument_name = String::Handle(zone);
74877449
String& parameter_name = String::Handle(zone);
7450+
const intptr_t num_positional_args = num_arguments - num_named_arguments;
7451+
const intptr_t num_parameters = NumParameters();
74887452
for (intptr_t i = 0; i < num_named_arguments; i++) {
74897453
argument_name = args_desc.NameAt(i);
74907454
ASSERT(argument_name.IsSymbol());
74917455
bool found = false;
7492-
const intptr_t num_positional_args = num_arguments - num_named_arguments;
7493-
const int num_parameters = NumParameters();
7494-
for (intptr_t j = num_positional_args; !found && (j < num_parameters);
7495-
j++) {
7456+
for (intptr_t j = num_positional_args; j < num_parameters; j++) {
74967457
parameter_name = ParameterNameAt(j);
7497-
ASSERT(argument_name.IsSymbol());
7458+
ASSERT(parameter_name.IsSymbol());
74987459
if (argument_name.Equals(parameter_name)) {
74997460
found = true;
7461+
break;
75007462
}
75017463
}
75027464
if (!found) {
7503-
if (error_message != NULL) {
7465+
if (error_message != nullptr) {
75047466
const intptr_t kMessageBufferSize = 64;
75057467
char message_buffer[kMessageBufferSize];
75067468
Utils::SNPrint(message_buffer, kMessageBufferSize,
75077469
"no optional formal parameter named '%s'",
75087470
argument_name.ToCString());
7509-
// Allocate in old space because it can be invoked in background
7510-
// optimizing compilation.
7511-
*error_message = String::New(message_buffer, Heap::kOld);
7471+
*error_message = String::New(message_buffer);
75127472
}
75137473
return false;
75147474
}
75157475
}
7476+
if (FLAG_null_safety) {
7477+
// Verify that all required named parameters are filled.
7478+
for (intptr_t j = num_positional_args; j < num_parameters; j++) {
7479+
if (IsRequiredAt(j)) {
7480+
parameter_name = ParameterNameAt(j);
7481+
ASSERT(parameter_name.IsSymbol());
7482+
bool found = false;
7483+
for (intptr_t i = 0; i < num_named_arguments; i++) {
7484+
argument_name = args_desc.NameAt(i);
7485+
ASSERT(argument_name.IsSymbol());
7486+
if (argument_name.Equals(parameter_name)) {
7487+
found = true;
7488+
break;
7489+
}
7490+
}
7491+
if (!found) {
7492+
if (error_message != nullptr) {
7493+
const intptr_t kMessageBufferSize = 64;
7494+
char message_buffer[kMessageBufferSize];
7495+
Utils::SNPrint(message_buffer, kMessageBufferSize,
7496+
"missing required named parameter '%s'",
7497+
parameter_name.ToCString());
7498+
*error_message = String::New(message_buffer);
7499+
}
7500+
return false;
7501+
}
7502+
}
7503+
}
7504+
}
75167505
return true;
75177506
}
75187507

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
// Requirements=nnbd-strong
6+
import 'package:expect/expect.dart';
7+
8+
class Foo {
9+
int foo(
10+
{required String a,
11+
required String b,
12+
required String c,
13+
required String d}) {
14+
return a.length + b.length + c.length + d.length;
15+
}
16+
}
17+
18+
main() {
19+
Expect.equals(8, Foo().foo(a: "aa", b: "bb", c: "cc", d: "dd"));
20+
21+
// Test that we throw a NoSuchMethodError, not a TypeError due to c.length.
22+
dynamic f = Foo();
23+
Expect.throwsNoSuchMethodError(() => f.foo(a: "aa", b: "bb", d: "dd"));
24+
}

0 commit comments

Comments
 (0)