Skip to content

Commit

Permalink
[dart2js] Clean up nullability adjustments in interface sufficiency test
Browse files Browse the repository at this point in the history
Now that #60076 has been
addressed, we no longer need to widen the nullability ourselves.

Change-Id: I4bc5a1767d9e2d98bcf0ca4c24171482e0f600ac
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/409162
Commit-Queue: Mayank Patke <fishythefish@google.com>
Reviewed-by: Stephen Adams <sra@google.com>
  • Loading branch information
fishythefish authored and Commit Queue committed Feb 13, 2025
1 parent 23cac7c commit 66fa0e2
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 11 deletions.
14 changes: 3 additions & 11 deletions pkg/compiler/lib/src/ssa/builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7740,26 +7740,18 @@ class KernelSsaGraphBuilder extends ir.VisitorDefault<void>
final sufficiency = closedWorld.elementMap.typeEnvironment
.computeTypeShapeCheckSufficiency(
expressionStaticType: operandType,
// Add `?` in case operand is nullable:
checkTargetType: checkedType.withDeclaredNullability(
ir.Nullability.nullable,
),
checkTargetType: checkedType,
subtypeCheckMode: ir.SubtypeCheckMode.withNullabilities,
);

// If `true` the caller only needs to check nullabillity and the actual
// concrete class, no need to check [testedAgainstType] arguments.
if (sufficiency == ir.TypeShapeCheckSufficiency.interfaceShape) {
return ir.InterfaceType(
return closedWorld.elementMap.coreTypes.rawType(
checkedType.classNode,
(operandType is ir.InterfaceType &&
operandType.nullability == ir.Nullability.nonNullable)
operandType.nullability == ir.Nullability.nonNullable
? ir.Nullability.nonNullable
: checkedType.nullability,
[
for (final parameter in checkedType.classNode.typeParameters)
parameter.defaultType,
],
);
}
}
Expand Down
103 changes: 103 additions & 0 deletions pkg/compiler/test/codegen/data/is_test_weakening_with_bounds.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// Copyright (c) 2025, 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.

// `is` tests against some parameterized interface types are equivalent to a
// weaker test for just the interace. The weaker test is usually more efficient,
// sometimes being compiled to `instanceof`.

class Base<T extends num> {
/*member: Base.test1:function(other) {
if (other instanceof A.D1)
return other.foo$0();
return "other";
}*/
@pragma('dart2js:parameter:trust')
String test1(Base<T> other) {
if (other is D1<T>) return other.foo();
return 'other';
}

/*member: Base.test1qn:function(other) {
if (other instanceof A.D1)
return other.foo$0();
return "other";
}*/
@pragma('dart2js:parameter:trust')
String test1qn(Base<T>? other) {
if (other is D1<T>) return other.foo();
return 'other';
}

/*member: Base.test1nq:function(other) {
if (other instanceof A.D1)
return other.method$0();
return "other";
}*/
@pragma('dart2js:parameter:trust')
String? test1nq(Base<T> other) {
if (other is D1<T>?) return other.method(); // No promotion, so can't foo().
return 'other';
}

/*member: Base.test1qq:function(other) {
var t1;
if (type$.nullable_D1_dynamic._is(other)) {
t1 = other.foo$0();
return t1;
}
return "other";
}*/
@pragma('dart2js:parameter:trust')
String? test1qq(Base<T>? other) {
if (other is D1<T>?) return other?.foo();
return 'other';
}

/*member: Base.test2:function(other) {
if (other instanceof A.D2)
return other.bar$0();
return "other";
}*/
@pragma('dart2js:parameter:trust')
String test2(Base<T> other) {
if (other is D2<T>) return other.bar();
return 'other';
}

@pragma('dart2js:never-inline')
/*member: Base.method:ignore*/
String method() => 'Base.method';
}

class D1<T extends num> extends Base<T> {
@pragma('dart2js:never-inline')
/*member: D1.foo:ignore*/
String foo() => 'D1<$T>.foo';
}

class D2<T extends num> extends D1<T> {
@pragma('dart2js:never-inline')
/*member: D2.bar:ignore*/
String bar() => 'D2.bar';
}

/*member: main:ignore*/
main() {
final items = [Base<int>(), D1<int>(), D2<int>()];

for (final item in items) {
print(item.test1(items.first));
print(item.test1(item));

print(item.test1qn(items.first));
print(item.test1qn(item));
print(item.test1nq(items.first));
print(item.test1nq(item));
print(item.test1qq(items.first));
print(item.test1qq(item));

print(item.test2(items.first));
print(item.test2(item));
}
}

0 comments on commit 66fa0e2

Please sign in to comment.