mirror of
https://github.com/dart-lang/sdk
synced 2024-09-20 05:51:37 +00:00
Fix receiver refining optimization in the presence of null: any Object method can be called on the null object.
R=karlklose@google.com Review URL: https://codereview.chromium.org//23353002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@26418 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
parent
87530aa003
commit
4e107aa0c0
|
@ -21,8 +21,6 @@ class FlatTypeMask implements TypeMask {
|
|||
FlatTypeMask(DartType base, int kind, bool isNullable)
|
||||
: this.internal(base, (kind << 1) | (isNullable ? 1 : 0));
|
||||
|
||||
FlatTypeMask.empty()
|
||||
: this.internal(null, (EMPTY << 1) | 1);
|
||||
FlatTypeMask.exact(DartType base)
|
||||
: this.internal(base, (EXACT << 1) | 1);
|
||||
FlatTypeMask.subclass(DartType base)
|
||||
|
@ -31,6 +29,7 @@ class FlatTypeMask implements TypeMask {
|
|||
: this.internal(base, (SUBTYPE << 1) | 1);
|
||||
|
||||
const FlatTypeMask.nonNullEmpty(): base = null, flags = 0;
|
||||
const FlatTypeMask.empty() : base = null, flags = 1;
|
||||
|
||||
FlatTypeMask.nonNullExact(DartType base)
|
||||
: this.internal(base, EXACT << 1);
|
||||
|
|
|
@ -13,7 +13,7 @@ abstract class TypeMask {
|
|||
factory TypeMask(DartType base, int kind, bool isNullable)
|
||||
=> new FlatTypeMask(base, kind, isNullable);
|
||||
|
||||
factory TypeMask.empty() => new FlatTypeMask.empty();
|
||||
const factory TypeMask.empty() = FlatTypeMask.empty;
|
||||
|
||||
factory TypeMask.exact(DartType base) => new FlatTypeMask.exact(base);
|
||||
factory TypeMask.subclass(DartType base) => new FlatTypeMask.subclass(base);
|
||||
|
|
|
@ -220,6 +220,9 @@ class FullFunctionSetQuery extends FunctionSetQuery {
|
|||
: [cls];
|
||||
})
|
||||
.map((cls) {
|
||||
if (compiler.backend.isNullImplementation(cls)) {
|
||||
return const TypeMask.empty();
|
||||
}
|
||||
return compiler.world.hasSubclasses(cls)
|
||||
? new TypeMask.nonNullSubclass(cls.rawType)
|
||||
: new TypeMask.nonNullExact(cls.rawType);
|
||||
|
|
|
@ -365,7 +365,7 @@ class JSBool extends Interceptor implements bool {
|
|||
/**
|
||||
* The interceptor class for [Null].
|
||||
*
|
||||
* This class defines implementations for *all* methods on [Object] since the
|
||||
* This class defines implementations for *all* methods on [Object] since
|
||||
* the methods on Object assume the receiver is non-null. This means that
|
||||
* JSNull will always be in the interceptor set for methods defined on Object.
|
||||
*/
|
||||
|
|
|
@ -154,6 +154,8 @@ const String DEFAULT_INTERCEPTORSLIB = r'''
|
|||
class JSNull extends Interceptor {
|
||||
bool operator==(other) => identical(null, other);
|
||||
get hashCode => throw "JSNull.hashCode not implemented.";
|
||||
String toString() => 'Null';
|
||||
Type get runtimeType => null;
|
||||
}
|
||||
class JSBool extends Interceptor implements bool {
|
||||
}
|
||||
|
|
|
@ -441,6 +441,14 @@ testSpecialization2() {
|
|||
return a;
|
||||
}
|
||||
|
||||
testSpecialization3() {
|
||||
var a = returnDynamic() ? null : 42;
|
||||
a.toString();
|
||||
// Test that calling an [Object] method on [a] will not lead to
|
||||
// infer that [a] is not null;
|
||||
return a;
|
||||
}
|
||||
|
||||
testReturnInvokeDynamicGetter() => new A().myFactory();
|
||||
|
||||
var topLevelConstList = const [42];
|
||||
|
@ -582,6 +590,7 @@ main() {
|
|||
testCascade2();
|
||||
testSpecialization1();
|
||||
testSpecialization2();
|
||||
testSpecialization3();
|
||||
}
|
||||
""";
|
||||
|
||||
|
@ -706,4 +715,5 @@ void main() {
|
|||
typesTask.rawTypeOf(findElement(compiler, 'CascadeHelper'))));
|
||||
checkReturn('testSpecialization1', typesTask.numType);
|
||||
checkReturn('testSpecialization2', typesTask.dynamicType);
|
||||
checkReturn('testSpecialization3', typesTask.intType.nullable());
|
||||
}
|
||||
|
|
22
tests/language/refine_receiver_null_test.dart
Normal file
22
tests/language/refine_receiver_null_test.dart
Normal file
|
@ -0,0 +1,22 @@
|
|||
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
// Regression test for dart2js that used to infer that code following
|
||||
// a dynamic call could assume the receiver is not null. This does not
|
||||
// work for Object methods.
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
import "compiler_annotations.dart";
|
||||
|
||||
main() {
|
||||
var a = true ? null : 42;
|
||||
a.toString();
|
||||
foo(a);
|
||||
}
|
||||
|
||||
@DontInline()
|
||||
foo(a) {
|
||||
var f = () => 42;
|
||||
Expect.throws(() => a + 42, (e) => e is NoSuchMethodError);
|
||||
}
|
Loading…
Reference in a new issue