It is OK to declare a const constructor in a class with a mixin, if it has no fields.
R=brianwilkerson@google.com Change-Id: I76c427fe24b8f06711c3adcac8bacd45900240b1 Reviewed-on: https://dart-review.googlesource.com/62482 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
committed by
commit-bot@chromium.org
parent
88a88b03dc
commit
46167dfd88
@@ -81,7 +81,7 @@ const List<ErrorCode> errorCodeValues = const [
|
||||
CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER,
|
||||
CompileTimeErrorCode.CONST_CONSTRUCTOR_THROWS_EXCEPTION,
|
||||
CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_FIELD_INITIALIZED_BY_NON_CONST,
|
||||
CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN,
|
||||
CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD,
|
||||
CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER,
|
||||
CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD,
|
||||
CompileTimeErrorCode.CONST_DEFERRED_CLASS,
|
||||
|
||||
@@ -95,7 +95,7 @@ class AnalysisDriver implements AnalysisDriverGeneric {
|
||||
/**
|
||||
* The version of data format, should be incremented on every format change.
|
||||
*/
|
||||
static const int DATA_VERSION = 61;
|
||||
static const int DATA_VERSION = 62;
|
||||
|
||||
/**
|
||||
* The number of exception contexts allowed to write. Once this field is
|
||||
|
||||
@@ -484,14 +484,19 @@ class CompileTimeErrorCode extends ErrorCode {
|
||||
* specify a constant constructor of the superclass of the immediately
|
||||
* enclosing class or a compile-time error occurs.
|
||||
*
|
||||
* 9 Mixins: For each generative constructor named ... an implicitly declared
|
||||
* constructor named ... is declared.
|
||||
* 12.1 Mixin Application: For each generative constructor named ... an
|
||||
* implicitly declared constructor named ... is declared. If Sq is a
|
||||
* generative const constructor, and M does not declare any fields, Cq is
|
||||
* also a const constructor.
|
||||
*/
|
||||
static const CompileTimeErrorCode CONST_CONSTRUCTOR_WITH_MIXIN =
|
||||
const CompileTimeErrorCode('CONST_CONSTRUCTOR_WITH_MIXIN',
|
||||
"Const constructor can't be declared for a class with a mixin.",
|
||||
correction: "Try removing the 'const' keyword, or "
|
||||
"removing the 'with' clause from the class declaration.");
|
||||
static const CompileTimeErrorCode CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD =
|
||||
const CompileTimeErrorCode(
|
||||
'CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD',
|
||||
"Const constructor can't be declared for a class with a mixin "
|
||||
"that declares a field.",
|
||||
correction: "Try removing the 'const' keyword or "
|
||||
"removing the 'with' clause from the class declaration, "
|
||||
"or removing fields from the mixin class.");
|
||||
|
||||
/**
|
||||
* 7.6.3 Constant Constructors: The superinitializer that appears, explicitly
|
||||
|
||||
@@ -3242,11 +3242,13 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
|
||||
return;
|
||||
}
|
||||
// check for mixins
|
||||
if (_enclosingClass.mixins.length != 0) {
|
||||
_errorReporter.reportErrorForNode(
|
||||
CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN,
|
||||
constructor.returnType);
|
||||
return;
|
||||
for (var mixin in _enclosingClass.mixins) {
|
||||
if (mixin.element.fields.isNotEmpty) {
|
||||
_errorReporter.reportErrorForNode(
|
||||
CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD,
|
||||
constructor.returnType);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// try to find and check super constructor invocation
|
||||
for (ConstructorInitializer initializer in constructor.initializers) {
|
||||
|
||||
@@ -240,9 +240,16 @@ class CompileTimeErrorCodeTest_Kernel extends CompileTimeErrorCodeTest_Driver {
|
||||
|
||||
@override
|
||||
@failingTest
|
||||
test_constConstructorWithMixin() async {
|
||||
// Expected 1 errors of type CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN, found 0
|
||||
await super.test_constConstructorWithMixin();
|
||||
@FastaProblem('https://github.com/dart-lang/sdk/issues/33645')
|
||||
test_constConstructorWithMixinWithField() async {
|
||||
return super.test_constConstructorWithMixinWithField();
|
||||
}
|
||||
|
||||
@override
|
||||
@failingTest
|
||||
@FastaProblem('https://github.com/dart-lang/sdk/issues/33645')
|
||||
test_constConstructorWithMixinWithField_final() async {
|
||||
return super.test_constConstructorWithMixinWithField_final();
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -1026,15 +1026,33 @@ int f() {
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
test_constConstructorWithMixin() async {
|
||||
test_constConstructorWithMixinWithField() async {
|
||||
Source source = addSource(r'''
|
||||
class M {
|
||||
class A {
|
||||
var a;
|
||||
}
|
||||
class A extends Object with M {
|
||||
const A();
|
||||
class B extends Object with A {
|
||||
const B();
|
||||
}''');
|
||||
await computeAnalysisResult(source);
|
||||
assertErrors(source, [CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN]);
|
||||
assertErrors(source, [
|
||||
CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD,
|
||||
CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD
|
||||
]);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
test_constConstructorWithMixinWithField_final() async {
|
||||
Source source = addSource(r'''
|
||||
class A {
|
||||
final int a = 0;
|
||||
}
|
||||
class B extends Object with A {
|
||||
const B();
|
||||
}''');
|
||||
await computeAnalysisResult(source);
|
||||
assertErrors(
|
||||
source, [CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD]);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
@@ -1076,7 +1094,7 @@ class B extends Object with A {
|
||||
}''');
|
||||
await computeAnalysisResult(source);
|
||||
assertErrors(source, [
|
||||
CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN,
|
||||
CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD,
|
||||
CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD
|
||||
]);
|
||||
verify([source]);
|
||||
@@ -1617,6 +1635,27 @@ f() { return const T(0, 1, c: 2, d: 3); }''');
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
test_constWithNonConst_in_const_context() async {
|
||||
Source source = addSource(r'''
|
||||
class A {
|
||||
const A(x);
|
||||
}
|
||||
class B {
|
||||
}
|
||||
main() {
|
||||
const A(B());
|
||||
}
|
||||
''');
|
||||
await computeAnalysisResult(source);
|
||||
// TODO(a14n): the error CONST_WITH_NON_CONSTANT_ARGUMENT is redundant and
|
||||
// ought to be suppressed.
|
||||
assertErrors(source, [
|
||||
CompileTimeErrorCode.CONST_WITH_NON_CONST,
|
||||
CompileTimeErrorCode.CONST_WITH_NON_CONSTANT_ARGUMENT
|
||||
]);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
test_constWithNonConst_with() async {
|
||||
Source source = addSource(r'''
|
||||
class B {
|
||||
@@ -1639,27 +1678,6 @@ main() {
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
test_constWithNonConst_in_const_context() async {
|
||||
Source source = addSource(r'''
|
||||
class A {
|
||||
const A(x);
|
||||
}
|
||||
class B {
|
||||
}
|
||||
main() {
|
||||
const A(B());
|
||||
}
|
||||
''');
|
||||
await computeAnalysisResult(source);
|
||||
// TODO(a14n): the error CONST_WITH_NON_CONSTANT_ARGUMENT is redundant and
|
||||
// ought to be suppressed.
|
||||
assertErrors(source, [
|
||||
CompileTimeErrorCode.CONST_WITH_NON_CONST,
|
||||
CompileTimeErrorCode.CONST_WITH_NON_CONSTANT_ARGUMENT
|
||||
]);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
test_constWithNonConstantArgument_annotation() async {
|
||||
Source source = addSource(r'''
|
||||
class A {
|
||||
@@ -2749,6 +2767,98 @@ var b2 = const bool.fromEnvironment('x', defaultValue: 1);''');
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
test_genericFunctionTypeArgument_class() async {
|
||||
Source source = addSource(r'''
|
||||
class C<T> {}
|
||||
C<T Function<T>(T)> c;''');
|
||||
await computeAnalysisResult(source);
|
||||
assertErrors(source,
|
||||
[CompileTimeErrorCode.GENERIC_FUNCTION_CANNOT_BE_TYPE_ARGUMENT]);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
test_genericFunctionTypeArgument_function() async {
|
||||
Source source = addSource(r'''
|
||||
T f<T>(T) => null;
|
||||
main() { f<S Function<S>(S)>(null); }''');
|
||||
await computeAnalysisResult(source);
|
||||
assertErrors(source,
|
||||
[CompileTimeErrorCode.GENERIC_FUNCTION_CANNOT_BE_TYPE_ARGUMENT]);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
test_genericFunctionTypeArgument_functionType() async {
|
||||
Source source = addSource(r'''
|
||||
T Function<T>(T) f;
|
||||
main() { f<S Function<S>(S)>(null); }''');
|
||||
await computeAnalysisResult(source);
|
||||
assertErrors(source,
|
||||
[CompileTimeErrorCode.GENERIC_FUNCTION_CANNOT_BE_TYPE_ARGUMENT]);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
@failingTest
|
||||
test_genericFunctionTypeArgument_inference_function() async {
|
||||
// TODO(mfairhurst) how should these inference errors be reported?
|
||||
Source source = addSource(r'''
|
||||
T f<T>(T) => null;
|
||||
main() { f(<S>(S s) => s); }''');
|
||||
await computeAnalysisResult(source);
|
||||
assertErrors(source,
|
||||
[CompileTimeErrorCode.GENERIC_FUNCTION_CANNOT_BE_TYPE_ARGUMENT]);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
@failingTest
|
||||
test_genericFunctionTypeArgument_inference_functionType() async {
|
||||
// TODO(mfairhurst) how should these inference errors be reported?
|
||||
Source source = addSource(r'''
|
||||
T Function<T>(T) f;
|
||||
main() { f(<S>(S s) => s); }''');
|
||||
await computeAnalysisResult(source);
|
||||
assertErrors(source,
|
||||
[CompileTimeErrorCode.GENERIC_FUNCTION_CANNOT_BE_TYPE_ARGUMENT]);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
@failingTest
|
||||
test_genericFunctionTypeArgument_inference_method() async {
|
||||
// TODO(mfairhurst) how should these inference errors be reported?
|
||||
Source source = addSource(r'''
|
||||
class C {
|
||||
T f<T>(T) => null;
|
||||
}
|
||||
main() { new C().f(<S>(S s) => s); }''');
|
||||
await computeAnalysisResult(source);
|
||||
assertErrors(source,
|
||||
[CompileTimeErrorCode.GENERIC_FUNCTION_CANNOT_BE_TYPE_ARGUMENT]);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
test_genericFunctionTypeArgument_method() async {
|
||||
Source source = addSource(r'''
|
||||
class C {
|
||||
T f<T>(T) => null;
|
||||
}
|
||||
main() { new C().f<S Function<S>(S)>(null); }''');
|
||||
await computeAnalysisResult(source);
|
||||
assertErrors(source,
|
||||
[CompileTimeErrorCode.GENERIC_FUNCTION_CANNOT_BE_TYPE_ARGUMENT]);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
@failingTest
|
||||
test_genericFunctionTypeArgument_typedef() async {
|
||||
// TODO(mfairhurst) diagnose these parse errors to give the correct error
|
||||
Source source = addSource(r'''
|
||||
typedef T f<T>(T t);
|
||||
final T<Function<S>(int)> x = null;''');
|
||||
await computeAnalysisResult(source);
|
||||
assertErrors(source,
|
||||
[CompileTimeErrorCode.GENERIC_FUNCTION_CANNOT_BE_TYPE_ARGUMENT]);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
test_genericFunctionTypeAsBound_class() async {
|
||||
Source source = addSource(r'''
|
||||
class C<T extends S Function<S>(S)> {
|
||||
@@ -7063,98 +7173,6 @@ f() { return const G<B>(); }''');
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
test_genericFunctionTypeArgument_class() async {
|
||||
Source source = addSource(r'''
|
||||
class C<T> {}
|
||||
C<T Function<T>(T)> c;''');
|
||||
await computeAnalysisResult(source);
|
||||
assertErrors(source,
|
||||
[CompileTimeErrorCode.GENERIC_FUNCTION_CANNOT_BE_TYPE_ARGUMENT]);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
test_genericFunctionTypeArgument_functionType() async {
|
||||
Source source = addSource(r'''
|
||||
T Function<T>(T) f;
|
||||
main() { f<S Function<S>(S)>(null); }''');
|
||||
await computeAnalysisResult(source);
|
||||
assertErrors(source,
|
||||
[CompileTimeErrorCode.GENERIC_FUNCTION_CANNOT_BE_TYPE_ARGUMENT]);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
test_genericFunctionTypeArgument_function() async {
|
||||
Source source = addSource(r'''
|
||||
T f<T>(T) => null;
|
||||
main() { f<S Function<S>(S)>(null); }''');
|
||||
await computeAnalysisResult(source);
|
||||
assertErrors(source,
|
||||
[CompileTimeErrorCode.GENERIC_FUNCTION_CANNOT_BE_TYPE_ARGUMENT]);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
test_genericFunctionTypeArgument_method() async {
|
||||
Source source = addSource(r'''
|
||||
class C {
|
||||
T f<T>(T) => null;
|
||||
}
|
||||
main() { new C().f<S Function<S>(S)>(null); }''');
|
||||
await computeAnalysisResult(source);
|
||||
assertErrors(source,
|
||||
[CompileTimeErrorCode.GENERIC_FUNCTION_CANNOT_BE_TYPE_ARGUMENT]);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
@failingTest
|
||||
test_genericFunctionTypeArgument_inference_functionType() async {
|
||||
// TODO(mfairhurst) how should these inference errors be reported?
|
||||
Source source = addSource(r'''
|
||||
T Function<T>(T) f;
|
||||
main() { f(<S>(S s) => s); }''');
|
||||
await computeAnalysisResult(source);
|
||||
assertErrors(source,
|
||||
[CompileTimeErrorCode.GENERIC_FUNCTION_CANNOT_BE_TYPE_ARGUMENT]);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
@failingTest
|
||||
test_genericFunctionTypeArgument_inference_function() async {
|
||||
// TODO(mfairhurst) how should these inference errors be reported?
|
||||
Source source = addSource(r'''
|
||||
T f<T>(T) => null;
|
||||
main() { f(<S>(S s) => s); }''');
|
||||
await computeAnalysisResult(source);
|
||||
assertErrors(source,
|
||||
[CompileTimeErrorCode.GENERIC_FUNCTION_CANNOT_BE_TYPE_ARGUMENT]);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
@failingTest
|
||||
test_genericFunctionTypeArgument_inference_method() async {
|
||||
// TODO(mfairhurst) how should these inference errors be reported?
|
||||
Source source = addSource(r'''
|
||||
class C {
|
||||
T f<T>(T) => null;
|
||||
}
|
||||
main() { new C().f(<S>(S s) => s); }''');
|
||||
await computeAnalysisResult(source);
|
||||
assertErrors(source,
|
||||
[CompileTimeErrorCode.GENERIC_FUNCTION_CANNOT_BE_TYPE_ARGUMENT]);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
@failingTest
|
||||
test_genericFunctionTypeArgument_typedef() async {
|
||||
// TODO(mfairhurst) diagnose these parse errors to give the correct error
|
||||
Source source = addSource(r'''
|
||||
typedef T f<T>(T t);
|
||||
final T<Function<S>(int)> x = null;''');
|
||||
await computeAnalysisResult(source);
|
||||
assertErrors(source,
|
||||
[CompileTimeErrorCode.GENERIC_FUNCTION_CANNOT_BE_TYPE_ARGUMENT]);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
test_undefinedAnnotation_unresolved_identifier() async {
|
||||
Source source = addSource(r'''
|
||||
@unresolved
|
||||
|
||||
@@ -123,13 +123,6 @@ class NonErrorResolverTest_Kernel extends NonErrorResolverTest_Driver {
|
||||
return super.test_constConstructorWithNonConstSuper_unresolved();
|
||||
}
|
||||
|
||||
@override
|
||||
@failingTest
|
||||
@potentialAnalyzerProblem
|
||||
test_constConstructorWithNonFinalField_mixin() async {
|
||||
return super.test_constConstructorWithNonFinalField_mixin();
|
||||
}
|
||||
|
||||
@override
|
||||
@failingTest
|
||||
@potentialAnalyzerProblem
|
||||
|
||||
@@ -1314,6 +1314,18 @@ const int value = 12345;
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
test_constConstructorWithMixinWithField() async {
|
||||
Source source = addSource(r'''
|
||||
class M {
|
||||
}
|
||||
class A extends Object with M {
|
||||
const A();
|
||||
}''');
|
||||
await computeAnalysisResult(source);
|
||||
assertNoErrors(source);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
test_constConstructorWithNonConstSuper_explicit() async {
|
||||
Source source = addSource(r'''
|
||||
class A {
|
||||
@@ -1368,19 +1380,6 @@ class A {
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
test_constConstructorWithNonFinalField_mixin() async {
|
||||
Source source = addSource(r'''
|
||||
class A {
|
||||
a() {}
|
||||
}
|
||||
class B extends Object with A {
|
||||
const B();
|
||||
}''');
|
||||
await computeAnalysisResult(source);
|
||||
assertErrors(source, [CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN]);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
test_constConstructorWithNonFinalField_static() async {
|
||||
Source source = addSource(r'''
|
||||
class A {
|
||||
|
||||
@@ -14,6 +14,8 @@ config_import_corelib_test: StaticWarning, OK
|
||||
conflicting_type_variable_and_setter_test: CompileTimeError # Issue 25525
|
||||
const_cast2_test/01: CompileTimeError
|
||||
const_cast2_test/none: CompileTimeError
|
||||
const_constructor_mixin3_test/01: MissingCompileTimeError # Issue 33644
|
||||
const_constructor_mixin_test/01: MissingCompileTimeError # Issue 33644
|
||||
const_for_in_variable_test/01: MissingCompileTimeError # Issue 25161
|
||||
constructor_call_wrong_argument_count_negative_test: Fail # Issue 11585
|
||||
constructor_type_parameter_test/00: MissingCompileTimeError # Issue 33110
|
||||
|
||||
@@ -33,6 +33,8 @@ conflicting_generic_interfaces_simple_test: MissingCompileTimeError
|
||||
conflicting_type_variable_and_setter_test: CompileTimeError
|
||||
const_cast2_test/01: CompileTimeError
|
||||
const_cast2_test/none: CompileTimeError
|
||||
const_constructor_mixin3_test/01: MissingCompileTimeError # Issue 33644
|
||||
const_constructor_mixin_test/01: MissingCompileTimeError # Issue 33644
|
||||
const_for_in_variable_test/01: MissingCompileTimeError
|
||||
const_types_test/07: MissingCompileTimeError
|
||||
const_types_test/08: MissingCompileTimeError
|
||||
|
||||
Reference in New Issue
Block a user