[Kernel] Signal an error for invalid native invocations

Calls to the factory constructor 'new List' can turn into static
invocations of a backend-specific factory function.  Signal an error
instead of crashing.

Change-Id: Id0a8a7f0f847c03225b7fa9da2351032d15522e0
Reviewed-on: https://dart-review.googlesource.com/c/90006
Reviewed-by: Aske Simon Christensen <askesc@google.com>
Commit-Queue: Kevin Millikin <kmillikin@google.com>
This commit is contained in:
Kevin Millikin 2019-01-17 15:12:04 +00:00 committed by commit-bot@chromium.org
parent d51a847891
commit b00193fa5f
4 changed files with 24 additions and 44 deletions

View file

@ -17,6 +17,7 @@ import 'package:kernel/ast.dart'
MapConstant,
Member,
NullConstant,
Procedure,
StaticInvocation,
StringConstant,
TreeNode;
@ -49,7 +50,7 @@ import '../fasta_codes.dart'
import '../loader.dart' show Loader;
import '../problems.dart' show unexpected, unimplemented;
import '../problems.dart' show unexpected;
class KernelConstantErrorReporter extends ErrorReporter {
final Loader<Library> loader;
@ -110,10 +111,22 @@ class KernelConstantErrorReporter extends ErrorReporter {
@override
String invalidStaticInvocation(
List<TreeNode> context, TreeNode node, Member target) {
// TODO(kmillikin) For an invalid factory invocation we should adopt a
// better message. This will show something like:
//
// "The invocation of 'List' is not allowed within a const context."
//
// Which is not quite right when the code was "new List()".
String name = target.name.toString();
if (target is Procedure && target.isFactory) {
if (name.isEmpty) {
name = target.enclosingClass.name;
} else {
name = '${target.enclosingClass.name}.${name}';
}
}
return addProblem(
node,
templateConstEvalInvalidStaticInvocation
.withArguments(target.name.toString()));
node, templateConstEvalInvalidStaticInvocation.withArguments(name));
}
@override
@ -200,7 +213,7 @@ class KernelConstantsBackend extends ConstantsBackend {
List<TreeNode> context,
StaticInvocation node,
ErrorReporter errorReporter,
void abortEvaluation(String message)) {
Constant abortEvaluation(String message)) {
// VM-specific names of the fromEnvironment factory constructors.
if (nativeName == 'Bool_fromEnvironment' ||
nativeName == 'Integer_fromEnvironment' ||
@ -224,7 +237,7 @@ class KernelConstantsBackend extends ConstantsBackend {
return unexpected('valid constructor invocation', node.toString(),
node.fileOffset, node.location.file);
}
return unimplemented('constant evaluation of ${nativeName}',
node.fileOffset, node.location.file);
return abortEvaluation(
errorReporter.invalidStaticInvocation(context, node, node.target));
}
}

View file

@ -1226,32 +1226,7 @@ class ConstantEvaluator extends RecursiveVisitor {
// Helper methods:
void ensureIsSubtype(Constant constant, DartType type, TreeNode node) {
DartType constantType;
if (constant is NullConstant) {
constantType = new InterfaceType(coreTypes.nullClass);
} else if (constant is BoolConstant) {
constantType = new InterfaceType(coreTypes.boolClass);
} else if (constant is IntConstant) {
constantType = new InterfaceType(coreTypes.intClass);
} else if (constant is DoubleConstant) {
constantType = new InterfaceType(coreTypes.doubleClass);
} else if (constant is StringConstant) {
constantType = new InterfaceType(coreTypes.stringClass);
} else if (constant is MapConstant) {
constantType = new InterfaceType(
coreTypes.mapClass, <DartType>[constant.keyType, constant.valueType]);
} else if (constant is ListConstant) {
constantType = new InterfaceType(
coreTypes.stringClass, <DartType>[constant.typeArgument]);
} else if (constant is InstanceConstant) {
constantType = new InterfaceType(constant.klass, constant.typeArguments);
} else if (constant is TearOffConstant) {
constantType = constant.procedure.function.functionType;
} else if (constant is TypeLiteralConstant) {
constantType = new InterfaceType(coreTypes.typeClass);
} else {
throw new Exception('No support for ${constant.runtimeType}.runtimeType');
}
DartType constantType = constant.getType(typeEnvironment);
if (!typeEnvironment.isSubtypeOf(constantType, type)) {
throw new _AbortCurrentEvaluation(
@ -1463,7 +1438,7 @@ abstract class ConstantsBackend {
List<TreeNode> context,
StaticInvocation node,
ErrorReporter errorReporter,
void abortEvaluation(String message));
Constant abortEvaluation(String message));
Constant lowerListConstant(ListConstant constant);
Constant lowerMapConstant(MapConstant constant);
}

View file

@ -51,7 +51,7 @@ class VmConstantsBackend implements ConstantsBackend {
List<TreeNode> context,
StaticInvocation node,
ErrorReporter errorReporter,
void abortEvaluation(String message)) {
Constant abortEvaluation(String message)) {
if ([
'Bool_fromEnvironment',
'Integer_fromEnvironment',
@ -118,7 +118,7 @@ class VmConstantsBackend implements ConstantsBackend {
makeConstant: (v) => new StringConstant(v));
}
} else {
abortEvaluation(errorReporter.invalidDartType(
return abortEvaluation(errorReporter.invalidDartType(
context,
node.arguments.positional.first,
argument,

View file

@ -56,7 +56,6 @@ LibTest/isolate/ReceivePort/lastWhere_A01_t01: RuntimeError
[ $compiler == fasta ]
Language/Statements/For/syntax_t13: Crash # Assertion error: kernel_shadow_ast.dart: 'receiver == null': is not true.
Language/Statements/For/syntax_t20: Crash # Assertion error: kernel_shadow_ast.dart: 'receiver == null': is not true.
LanguageFeatures/Constant_update2018/CastOperator_A04_t02: Crash
LanguageFeatures/Constant_update2018/NewOperators_A01_t01: Crash
LanguageFeatures/Constant_update2018/NewOperators_A01_t02: Crash
LanguageFeatures/Constant_update2018/NewOperators_A02_t01: CompileTimeError
@ -66,11 +65,8 @@ LanguageFeatures/Constant_update2018/NewOperators_A02_t05: CompileTimeError
LanguageFeatures/Constant_update2018/NewOperators_A02_t07: CompileTimeError
LanguageFeatures/Constant_update2018/NewOperators_A02_t08: CompileTimeError
LanguageFeatures/Constant_update2018/ShortCircuitOperators_A01_t02: Crash
LanguageFeatures/Constant_update2018/ShortCircuitOperators_A01_t05: Crash
LanguageFeatures/Constant_update2018/ShortCircuitOperators_A02_t05: Crash
LanguageFeatures/Constant_update2018/ShortCircuitOperators_A03_t03: Crash
LanguageFeatures/Constant_update2018/ShortCircuitOperators_A03_t04: Crash
LanguageFeatures/Constant_update2018/ShortCircuitOperators_A03_t06: Crash
LanguageFeatures/Constant_update2018/TypeTestOperator_A01_t01: Crash
LanguageFeatures/Constant_update2018/TypeTestOperator_A01_t02: Crash
LanguageFeatures/Constant_update2018/TypeTestOperator_A02_t01: Crash
@ -839,7 +835,6 @@ LibTest/isolate/ReceivePort/transform_A01_t01: RuntimeError
LanguageFeatures/Constant_update2018/CastOperator_A01_t01: DartkCrash
LanguageFeatures/Constant_update2018/CastOperator_A02_t01: DartkCrash
LanguageFeatures/Constant_update2018/CastOperator_A02_t02: DartkCrash
LanguageFeatures/Constant_update2018/CastOperator_A04_t02: DartkCrash
LanguageFeatures/Constant_update2018/NewOperators_A01_t01: DartkCrash
LanguageFeatures/Constant_update2018/NewOperators_A01_t02: DartkCrash
LanguageFeatures/Constant_update2018/NewOperators_A02_t01: Fail
@ -849,10 +844,7 @@ LanguageFeatures/Constant_update2018/NewOperators_A02_t05: CompileTimeError
LanguageFeatures/Constant_update2018/NewOperators_A02_t07: Fail
LanguageFeatures/Constant_update2018/NewOperators_A02_t08: CompileTimeError
LanguageFeatures/Constant_update2018/ShortCircuitOperators_A01_t02: DartkCrash
LanguageFeatures/Constant_update2018/ShortCircuitOperators_A01_t05: DartkCrash
LanguageFeatures/Constant_update2018/ShortCircuitOperators_A02_t05: DartkCrash
LanguageFeatures/Constant_update2018/ShortCircuitOperators_A03_t05: DartkCrash
LanguageFeatures/Constant_update2018/ShortCircuitOperators_A03_t06: DartkCrash
LanguageFeatures/Constant_update2018/TypeTestOperator_A01_t01: DartkCrash
LanguageFeatures/Constant_update2018/TypeTestOperator_A01_t02: DartkCrash
LanguageFeatures/Constant_update2018/TypeTestOperator_A02_t01: DartkCrash