dart-lang / sdk

The Dart SDK, including the VM, JS and Wasm compilers, analysis, core libraries, and more.
https://dart.dev
BSD 3-Clause "New" or "Revised" License
10.25k stars 1.58k forks source link

Method with required parameter can be overriden by the method with non-required parameter. #39713

Closed iarkh closed 4 years ago

iarkh commented 4 years ago

Dart VM version: 2.7.0-dev.2.1 (Mon Dec 2 20:10:59 2019 +0100) on "windows_x64"

In the following source code method with required parameter is overriden by the method with the parameter which is not required:

class B { void test({required int? i}) {} }
class A extends B { void test({int? i}) {} }

main() {
  A a = A();
  a.test();
}

Sample output is:

$> dartanalyzer --enable-experiment=non-nullable test.dart Analyzing test.dart... No issues found!

$> dart --enable-experiment=non-nullable test.dart $>

I was unable to find exact Specification assertion which claims that it should not be so, however it looks like such a behavior is incorrect.

For example, the following source code is similar with the one above and produces a compile error with analyzer. It passes without errors with dart, and it seems like analyzer behaves correctly:

class B { void test({required int? i}) {} }
class A extends B { void test({int? i}) {} }

main() {
  A a = A();
  a.test();

  B b = a;
  b.test();
}

Sample output is:

$> dartanalyzer --enable-experiment=non-nullable test.dart Analyzing test.dart... error - The named parameter 'i' is required but was not provided. - test.dart:9:5 - missing_required_argument 1 error found.

$> dart --enable-experiment=non-nullable test.dart $>

eernstg commented 4 years ago

This is working as intended: It is OK to override a method taking a required named parameter p by a method where p is not required. (This is equally benign as overriding foo(int i) in C by foo([int i]) in D implements C: Invocations of foo on a receiver of type D are safe also when the static receiver type is C.)

For the invocations, a.test() is correct (because it is statically known that the argument can be omitted), but b.test() is an error (because the static type says that the argument is required).