mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 19:40:29 +00:00
[ddc] Avoid weak mode warning in FutureOr casts
This is not intended to change the result of the cast in any mode. An optimization for casting null in weak mode accidentally added warnings when casting to a FutureOr (non-nullable) of a legacy type. Also moves the `is` and `as` methods for FutureOr types from being hard-coded in the compiler to the runtime method that builds the type. Tested on golem and found no attributable performance regressions: https://golem.corp.goog/Comparison?team=dartdevc#targetA%3Ddartdevc-null%3BmachineTypeA%3Dlinux-x64%3BrevisionA%3D88970%3BpatchA%3Dnshahan-FutureOr-Fix%3BtargetB%3Ddartdevc-null%3BmachineTypeB%3Dlinux-x64%3BrevisionB%3D88964%3BpatchB%3DNone Change-Id: I44a23c7e2e1d15bc6c383fc95b19f99b584a3f7a Fixes: https://github.com/dart-lang/sdk/issues/43990 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/170001 Reviewed-by: Mark Zhou <markzipan@google.com> Commit-Queue: Nicholas Shahan <nshahan@google.com>
This commit is contained in:
parent
53c82cbc4b
commit
ab7dc265d7
|
@ -1082,29 +1082,8 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
|
|||
}
|
||||
|
||||
if (c == _coreTypes.deprecatedFutureOrClass) {
|
||||
// These methods are difficult to place in the runtime or patch files.
|
||||
// * They need to be callable from the class but they can't be static
|
||||
// methods on the FutureOr class in Dart because they reference the
|
||||
// generic type parameter.
|
||||
// * There isn't an obvious place in dart:_runtime were we could place a
|
||||
// method that adds these type tests (similar to addTypeTests()) because
|
||||
// in the bootstrap ordering the Future class hasn't been defined yet.
|
||||
var typeParam =
|
||||
TypeParameterType(c.typeParameters[0], Nullability.undetermined);
|
||||
var typeT = visitTypeParameterType(typeParam);
|
||||
var futureOfT = visitInterfaceType(InterfaceType(
|
||||
_coreTypes.futureClass, currentLibrary.nonNullable, [typeParam]));
|
||||
body.add(js.statement('''
|
||||
#.is = function is_FutureOr(o) {
|
||||
return #.is(o) || #.is(o);
|
||||
}
|
||||
''', [className, typeT, futureOfT]));
|
||||
body.add(js.statement('''
|
||||
#.as = function as_FutureOr(o) {
|
||||
if (#.is(o) || #.is(o)) return o;
|
||||
return #.as(o, this);
|
||||
}
|
||||
''', [className, typeT, futureOfT, runtimeModule]));
|
||||
// Custom type tests for FutureOr types are attached when the type is
|
||||
// constructed in the runtime normalizeFutureOr method.
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -164,6 +164,29 @@ normalizeFutureOr(typeConstructor, setBaseClass) {
|
|||
// as a FutureOr because it is equal to 'async.FutureOr` (in the JS).
|
||||
JS('!', '#[#] = #', genericType, _originalDeclaration, normalize);
|
||||
JS('!', '#(#)', addTypeCaches, genericType);
|
||||
// Add FutureOr specific is and as methods.
|
||||
is_FutureOr(obj) =>
|
||||
JS<bool>('!', '#.is(#)', typeArg, obj) ||
|
||||
JS<bool>('!', '#(#).is(#)', getGenericClass(Future), typeArg, obj);
|
||||
JS('!', '#.is = #', genericType, is_FutureOr);
|
||||
|
||||
as_FutureOr(obj) {
|
||||
// Special test to handle case for mixed mode non-nullable FutureOr of a
|
||||
// legacy type. This allows casts like `null as FutureOr<int*>` to work
|
||||
// in weak and sound mode.
|
||||
if (obj == null && _jsInstanceOf(typeArg, LegacyType)) {
|
||||
return obj;
|
||||
}
|
||||
|
||||
if (JS<bool>('!', '#.is(#)', typeArg, obj) ||
|
||||
JS<bool>('!', '#(#).is(#)', getGenericClass(Future), typeArg, obj)) {
|
||||
return obj;
|
||||
}
|
||||
return cast(obj, JS('!', '#(#)', getGenericClass(FutureOr), typeArg));
|
||||
}
|
||||
|
||||
JS('!', '#.as = #', genericType, as_FutureOr);
|
||||
|
||||
return genericType;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue