Skip to content

Commit 1584a80

Browse files
Dustyn Loydacopybara-github
Dustyn Loyda
authored andcommitted
Make isSubtypeWithoutStructuralTyping also treat object literal typedefs as structural.
PiperOrigin-RevId: 697810976
1 parent 4713b75 commit 1584a80

File tree

5 files changed

+34
-14
lines changed

5 files changed

+34
-14
lines changed

src/com/google/javascript/rhino/jstype/SubtypeChecker.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,9 @@ private boolean isObjectSubtypeHelper(ObjectType subtype, ObjectType supertype)
305305
*/
306306
return this.isStructuralSubtypeHelper(
307307
subtype, supertype, PropertyOptionality.VOIDABLE_PROPS_ARE_OPTIONAL);
308-
} else if (!subAndSuperAreSameBaseType && supertype.isRecordType()) {
308+
} else if (!subAndSuperAreSameBaseType
309+
&& supertype.isRecordType()
310+
&& this.isUsingStructuralTyping) {
309311
/*
310312
* Anonymous record types are always considered structurally when supertypes.
311313
*

test/com/google/javascript/jscomp/CheckConformanceTest.java

+1
Original file line numberDiff line numberDiff line change
@@ -1000,6 +1000,7 @@ public void testBannedPropertyWhitelist0() {
10001000
String dDecl =
10011001
lines("/** @constructor */ function D() {}", "/** @type {string} */", "D.prototype.p;");
10021002

1003+
testConformance(cDecl, dDecl);
10031004
String typedefDecl =
10041005
lines(
10051006
"/** @typedef {{p: string}} */ let E;",

test/com/google/javascript/jscomp/TypeCheckCovarianceTest.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package com.google.javascript.jscomp;
1818

1919
import static com.google.javascript.jscomp.TypeCheck.STRICT_INEXISTENT_PROPERTY;
20+
import static com.google.javascript.jscomp.TypeCheck.STRICT_INEXISTENT_UNION_PROPERTY;
2021

2122
import org.junit.Test;
2223
import org.junit.runner.RunWith;
@@ -792,7 +793,7 @@ public void testCovarianceForRecordType25() {
792793
" var y;",
793794
" y.abort();",
794795
"}")
795-
.addDiagnostic(STRICT_INEXISTENT_PROPERTY)
796+
.addDiagnostic(STRICT_INEXISTENT_UNION_PROPERTY)
796797
.run();
797798
}
798799

test/com/google/javascript/jscomp/TypeCheckTest.java

+11-6
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import static com.google.javascript.jscomp.TypeCheck.INSTANTIATE_ABSTRACT_CLASS;
2424
import static com.google.javascript.jscomp.TypeCheck.POSSIBLE_INEXISTENT_PROPERTY_EXPLANATION;
2525
import static com.google.javascript.jscomp.TypeCheck.STRICT_INEXISTENT_PROPERTY;
26+
import static com.google.javascript.jscomp.TypeCheck.STRICT_INEXISTENT_UNION_PROPERTY;
2627
import static com.google.javascript.jscomp.parsing.JsDocInfoParser.BAD_TYPE_WIKI_LINK;
2728
import static com.google.javascript.jscomp.testing.ScopeSubject.assertScope;
2829
import static com.google.javascript.rhino.testing.NodeSubject.assertNode;
@@ -2578,7 +2579,8 @@ public void testDontDropPropertiesInUnion1() {
25782579
"function f(x) {",
25792580
" var /** null */ n = x.b;",
25802581
"}")
2581-
.addDiagnostic(STRICT_INEXISTENT_PROPERTY)
2582+
.addDiagnostic(STRICT_INEXISTENT_UNION_PROPERTY)
2583+
.addDiagnostic(TypeValidator.TYPE_MISMATCH_WARNING)
25822584
.run();
25832585
}
25842586

@@ -2590,7 +2592,8 @@ public void testDontDropPropertiesInUnion2() {
25902592
"function f(x) {",
25912593
" var /** null */ n = x.b;",
25922594
"}")
2593-
.addDiagnostic(STRICT_INEXISTENT_PROPERTY)
2595+
.addDiagnostic(STRICT_INEXISTENT_UNION_PROPERTY)
2596+
.addDiagnostic(TypeValidator.TYPE_MISMATCH_WARNING)
25942597
.run();
25952598
}
25962599

@@ -2602,7 +2605,7 @@ public void testDontDropPropertiesInUnion3() {
26022605
"function f(x) {}",
26032606
"/** @param {{a: number}} x */",
26042607
"function g(x) { return x.b; }")
2605-
.addDiagnostic(STRICT_INEXISTENT_PROPERTY)
2608+
.addDiagnostic(TypeCheck.INEXISTENT_PROPERTY)
26062609
.run();
26072610
}
26082611

@@ -2639,21 +2642,23 @@ public void testDontDropPropertiesInUnion6() {
26392642
.addDiagnostic(
26402643
lines(
26412644
"initializing variable", //
2642-
"found : {a: number}",
2645+
"found : ({",
2646+
" a: number,",
2647+
" b: string",
2648+
"}|{a: number})",
26432649
"required: null"))
26442650
.run();
26452651
}
26462652

26472653
@Test
26482654
public void testDontDropPropertiesInUnion7() {
2649-
// Only a strict warning because in the registry we map {a, c} to {b, d}
26502655
newTest()
26512656
.addSource(
26522657
"/** @param {{a: number}|{a:number, b:string}} x */",
26532658
"function f(x) {}",
26542659
"/** @param {{c: number}|{c:number, d:string}} x */",
26552660
"function g(x) { return x.b; }")
2656-
.addDiagnostic(STRICT_INEXISTENT_PROPERTY)
2661+
.addDiagnostic(TypeCheck.INEXISTENT_PROPERTY)
26572662
.run();
26582663
}
26592664

test/com/google/javascript/rhino/jstype/JSTypeTest.java

+17-6
Original file line numberDiff line numberDiff line change
@@ -2780,7 +2780,7 @@ public void testRecordTypeLeastSuperType1() {
27802780
JSType subRecordType = builder.build();
27812781

27822782
JSType leastSupertype = recordType.getLeastSupertype(subRecordType);
2783-
assertTypeEquals(leastSupertype, recordType);
2783+
assertTypeEquals(leastSupertype, registry.createUnionType(recordType, subRecordType));
27842784
}
27852785

27862786
@Test
@@ -5555,11 +5555,22 @@ public void verifySubtypeChain(List<JSType> typeChain, boolean checkSubtyping) t
55555555

55565556
JSType expectedSupremum = i < j ? typeI : typeJ;
55575557
JSType expectedInfimum = i > j ? typeI : typeJ;
5558-
5559-
assertTypeEquals(
5560-
expectedSupremum + " should be the least supertype of " + typeI +
5561-
" and " + typeJ,
5562-
expectedSupremum, typeI.getLeastSupertype(typeJ));
5558+
JSType typeIleastSupertype = typeI.getLeastSupertype(typeJ);
5559+
JSType typeJleastSupertype = typeJ.getLeastSupertype(typeI);
5560+
5561+
// The `isSubtypeWithoutStructuralTyping` function now considers object literal typedefs
5562+
// as structural types. To ensure accuracy, this check must be extended to accommodate
5563+
// scenarios where the least supertype is a union type.
5564+
//
5565+
// For example, the least supertype of `{a: number}` and `{a: string, b: number}` is
5566+
// now the union type `{a: number} | {a: string, b: number}`.
5567+
5568+
if (!typeIleastSupertype.isSubtypeOf(typeJleastSupertype)) {
5569+
assertTypeEquals(
5570+
expectedSupremum + " should be the least supertype of " + typeI + " and " + typeJ,
5571+
expectedSupremum,
5572+
typeI.getLeastSupertype(typeJ));
5573+
}
55635574

55645575
// TODO(nicksantos): Should these tests pass?
55655576
//assertTypeEquals(

0 commit comments

Comments
 (0)