From ff29264050bba9ae823b7fc41eccf88dae28a28b Mon Sep 17 00:00:00 2001 From: Sathya Gunasekaran Date: Wed, 21 Dec 2022 21:13:57 +0000 Subject: [PATCH] [typer] Remove type inference of fields Given that our type inference needs to be very conservative, there's not a lot of benefit to having such fine grained type inference. In the future, we can use type information from flow/ts for inference. --- compiler/forget/src/HIR/HIR.ts | 32 +--- compiler/forget/src/HIR/InferTypes.ts | 180 +++--------------- .../fixtures/hir/component.expect.md | 36 ++-- ...reeze-possibly-mutable-arguments.expect.md | 22 +-- .../fixtures/hir/reverse-postorder.expect.md | 40 ++-- .../fixtures/hir/type-field-load.expect.md | 4 +- .../type-test-field-load-binary-op.expect.md | 22 +-- .../hir/type-test-field-store.expect.md | 4 +- .../hir/type-test-polymorphic.expect.md | 8 +- 9 files changed, 93 insertions(+), 255 deletions(-) diff --git a/compiler/forget/src/HIR/HIR.ts b/compiler/forget/src/HIR/HIR.ts index 36c5990da0..4f0db335aa 100644 --- a/compiler/forget/src/HIR/HIR.ts +++ b/compiler/forget/src/HIR/HIR.ts @@ -451,15 +451,13 @@ export type Type = | PrimitiveType | FunctionType | ObjectType - | PropType | PolyType | TypeVar; export type PrimitiveType = { kind: "Primitive" }; export type FunctionType = { kind: "Function"; }; -export type ObjectType = { kind: "Object"; properties: Map }; -export type PropType = { kind: "Prop"; objectType: Type; name: string }; +export type ObjectType = { kind: "Object" }; export type TypeVar = { kind: "Type"; id: TypeId; @@ -497,7 +495,6 @@ export function typeEquals(tA: Type, tB: Type): boolean { typeVarEquals(tA, tB) || funcTypeEquals(tA, tB) || objectTypeEquals(tA, tB) || - propTypeEquals(tA, tB) || primitiveTypeEquals(tA, tB) || polyTypeEquals(tA, tB) ); @@ -519,32 +516,7 @@ function polyTypeEquals(tA: Type, tB: Type): boolean { } function objectTypeEquals(tA: Type, tB: Type): boolean { - if (tA.kind === "Object" && tB.kind === "Object") { - if (tA.properties.size !== tB.properties.size) { - return false; - } - - for (const key of tA.properties.keys()) { - if (!typeEquals(tA.properties.get(key)!, tB.properties.get(key)!)) { - return false; - } - } - - return true; - } - - return false; -} - -function propTypeEquals(tA: Type, tB: Type): boolean { - if (tA.kind === "Prop" && tB.kind === "Prop") { - if (tA.name !== tB.name) { - return false; - } - return objectTypeEquals(tA.objectType, tB.objectType); - } - - return false; + return tA.kind === "Object" && tB.kind === "Object"; } function funcTypeEquals(tA: Type, tB: Type): boolean { diff --git a/compiler/forget/src/HIR/InferTypes.ts b/compiler/forget/src/HIR/InferTypes.ts index 13fbc48aca..63fc5f04a9 100644 --- a/compiler/forget/src/HIR/InferTypes.ts +++ b/compiler/forget/src/HIR/InferTypes.ts @@ -3,10 +3,7 @@ import invariant from "invariant"; import { HIRFunction, Instruction, - LValue, - makeType, Place, - PropType, Type, typeEquals, TypeId, @@ -85,130 +82,60 @@ function generateTypeEquation( unifier: Unifier ): Array { const equations: Array = []; + + function add(left: Type | null, right: Type | null) { + if (left === null || right === null) return; + equations.push({ + left, + right, + }); + } + const { lvalue, value } = instr; - const left: Type | null = assignTypeForLvalue(lvalue, equations, unifier); + const left = assignType(lvalue?.place); switch (value.kind) { case "Primitive": { - if (left !== null) { - equations.push({ - left, - right: { kind: "Primitive" }, - }); - } + add(left, { kind: "Primitive" }); break; } case "Identifier": { - if (left !== null) { - let right: Type = assignTypeForPlace(value, equations); - equations.push({ - left, - right, - }); - } - + add(left, assignType(value)); break; } case "BinaryExpression": { if (isPrimitiveBinaryOp(value.operator)) { - equations.push({ - left: value.left.identifier.type, - right: { kind: "Primitive" }, - }); - equations.push({ - left: value.right.identifier.type, - right: { kind: "Primitive" }, - }); + add(assignType(value.left), { kind: "Primitive" }); + add(assignType(value.right), { kind: "Primitive" }); } - - if (left !== null) { - equations.push({ - left, - right: { kind: "Primitive" }, - }); - } - + add(left, { kind: "Primitive" }); break; } case "CallExpression": { - const argTypes = value.args.map((a) => a.identifier.type); - - // TODO(gsn): Handle method calls separately - if (value.callee.memberPath !== null) { - break; - } - - equations.push({ - left: value.callee.identifier.type, - right: { kind: "Function" }, - }); - + add(assignType(value.callee), { kind: "Function" }); break; } case "ObjectExpression": { invariant(left !== null, "invald object expression"); - const properties = new Map( - [...(value.properties?.entries() ?? [])].map(([prop, place]) => [ - prop, - place.identifier.type, - ]) - ); - - equations.push({ - left, - right: { - kind: "Object", - properties, - }, - }); + add(left, { kind: "Object" }); break; } } return equations; } -function assignTypeForPlace( - value: Place, - equations: Array -): Type { - if (value.memberPath === null) { - return value.identifier.type; +function assignType(place: Place | undefined): Type | null { + // We type only top level identifiers. Typing objects is not very useful + // when we have to be so conservative. + if (place?.memberPath !== null) { + return null; } - if (value.memberPath.length > 1) { - // TODO(gsn): Lower nested memberPaths in HIR - return makeType(); - } - - const propName = value.memberPath[0]; - const propType = makeType(); - equations.push({ - left: propType, - right: { - kind: "Prop", - objectType: value.identifier.type, - name: propName, - }, - }); - - return propType; -} - -function assignTypeForLvalue( - lvalue: LValue | null, - equations: Array, - unifier: Unifier -): Type | null { - if (lvalue === null) return null; - - return ( - unifier.generalize(lvalue.place.identifier.type, lvalue.place.memberPath) ?? - assignTypeForPlace(lvalue.place, equations) - ); + return place.identifier.type; } type Substitution = Map; @@ -242,11 +169,6 @@ class Unifier { return; } - if (type.kind === "Prop") { - this.bindToProp(v, type); - return; - } - if (this.occursCheck(v, type)) { throw new Error("cycle detected"); } @@ -254,26 +176,6 @@ class Unifier { this.substitutions.set(v.id, type); } - bindToProp(type: TypeVar, prop: PropType) { - let object = prop.objectType; - - if (object.kind === "Type" && this.substitutions.has(object.id)) { - object = this.substitutions.get(object.id)!; - } - - if (object.kind === "Object") { - if (!object.properties.has(prop.name)) { - object.properties.set(prop.name, type); - return; - } - - this.unify(object.properties.get(prop.name)!, type); - return; - } - - this.substitutions.set(type.id, prop); - } - occursCheck(v: TypeVar, type: Type): boolean { if (typeEquals(v, type)) return true; @@ -281,22 +183,10 @@ class Unifier { return this.occursCheck(v, this.substitutions.get(type.id)!); } - if (type.kind === "Object") { - return [...type.properties.values()].some((p) => this.occursCheck(v, p)); - } - - if (type.kind === "Prop") { - return this.occursCheck(v, type.objectType); - } - return false; } get(type: Type): Type { - if (type.kind === "Primitive") { - return type; - } - if (type.kind === "Type") { if (this.substitutions.has(type.id)) { return this.get(this.substitutions.get(type.id)!); @@ -307,28 +197,4 @@ class Unifier { return type; } - - generalize(objectType: Type, name: Array | null): Type | null { - if (objectType.kind === "Type" && this.substitutions.has(objectType.id)) { - objectType = this.substitutions.get(objectType.id)!; - } - - if ( - name !== null && - objectType.kind === "Object" && - objectType.properties.has(name[0]) - ) { - let type = objectType.properties.get(name[0])!; - if (type.kind === "Poly") { - return type; - } - - type = { kind: "Poly" }; - - objectType.properties.set(name[0], type); - return type; - } - - return null; - } } diff --git a/compiler/forget/src/__tests__/fixtures/hir/component.expect.md b/compiler/forget/src/__tests__/fixtures/hir/component.expect.md index e529c173dc..ea335f62cc 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/component.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/component.expect.md @@ -35,12 +35,12 @@ function Component(props) { ``` bb0: - [1] Const mutate items$30:TProp = read props$29.items - [2] Const mutate maxItems$31:TProp = read props$29.maxItems - [3] Const mutate renderedItems$32_@0:TPrimitive[3:33] = Array [] + [1] Const mutate items$30 = read props$29.items + [2] Const mutate maxItems$31 = read props$29.maxItems + [3] Const mutate renderedItems$32_@0[3:33] = Array [] [4] Const mutate seen$33_@0[3:33] = New mutate Set$5() [5] Const mutate $34:TPrimitive = 0 - [6] Const mutate max$35_@2:TPrimitive = Call mutate Math$7.max(read $34:TPrimitive, read maxItems$31:TProp) + [6] Const mutate max$35_@2:TPrimitive = Call mutate Math$7.max(read $34:TPrimitive, read maxItems$31) [7] For init=bb3 test=bb1 loop=bb5 update=bb4 fallthrough=bb2 bb3: predecessor blocks: bb0 @@ -92,15 +92,15 @@ bb4: [32] Goto bb1 bb2: predecessor blocks: bb6 bb1 - [33] Const mutate count$66:TProp = read renderedItems$32_@0.length + [33] Const mutate count$66 = read renderedItems$32_@0.length [34] Const mutate $67:TPrimitive = "div" [35] Const mutate $68 = "\n " [36] Const mutate $69:TPrimitive = "h1" [37] Const mutate $70 = " Items" - [38] Const mutate t7$71_@5 = JSX {freeze count$66:TProp}{read $70} + [38] Const mutate t7$71_@5 = JSX {freeze count$66}{read $70} [39] Const mutate $72 = "\n " [40] Const mutate $73 = "\n " - [41] Const mutate t10$74_@6 = JSX {read $68}{read t7$71_@5}{read $72}{freeze renderedItems$32_@0:TPrimitive}{read $73} + [41] Const mutate t10$74_@6 = JSX {read $68}{read t7$71_@5}{read $72}{freeze renderedItems$32_@0}{read $73} [42] Return read t10$74_@6 ``` @@ -110,14 +110,14 @@ bb2: function Component( props, ) { - [1] Const mutate items$30:TProp = read props$29.items - [2] Const mutate maxItems$31:TProp = read props$29.maxItems - scope @0 [3:33] deps=[read maxItems$31:TProp, read items$30.length, read items$30] out=[renderedItems$32_@0] { - [3] Const mutate renderedItems$32_@0:TPrimitive[3:33] = Array [] + [1] Const mutate items$30 = read props$29.items + [2] Const mutate maxItems$31 = read props$29.maxItems + scope @0 [3:33] deps=[read maxItems$31, read items$30.length, read items$30] out=[renderedItems$32_@0] { + [3] Const mutate renderedItems$32_@0[3:33] = Array [] [4] Const mutate seen$33_@0[3:33] = New mutate Set$5() [5] Const mutate $34:TPrimitive = 0 - scope @2 [6:7] deps=[read maxItems$31:TProp] out=[max$35_@2] { - [6] Const mutate max$35_@2:TPrimitive = Call mutate Math$7.max(read $34:TPrimitive, read maxItems$31:TProp) + scope @2 [6:7] deps=[read maxItems$31] out=[max$35_@2] { + [6] Const mutate max$35_@2:TPrimitive = Call mutate Math$7.max(read $34:TPrimitive, read maxItems$31) } for ( [8] Let mutate i$36_@0:TPrimitive[3:33] = 0 @@ -153,18 +153,18 @@ function Component( } } } - [33] Const mutate count$66:TProp = read renderedItems$32_@0.length + [33] Const mutate count$66 = read renderedItems$32_@0.length [34] Const mutate $67:TPrimitive = "div" [35] Const mutate $68 = "\n " [36] Const mutate $69:TPrimitive = "h1" [37] Const mutate $70 = " Items" - scope @5 [38:39] deps=[freeze count$66:TProp] out=[$71_@5] { - [38] Const mutate $71_@5 = JSX {freeze count$66:TProp}{read $70} + scope @5 [38:39] deps=[freeze count$66] out=[$71_@5] { + [38] Const mutate $71_@5 = JSX {freeze count$66}{read $70} } [39] Const mutate $72 = "\n " [40] Const mutate $73 = "\n " - scope @6 [41:42] deps=[read $71_@5, freeze renderedItems$32_@0:TPrimitive] out=[$74_@6] { - [41] Const mutate $74_@6 = JSX {read $68}{read $71_@5}{read $72}{freeze renderedItems$32_@0:TPrimitive}{read $73} + scope @6 [41:42] deps=[read $71_@5, freeze renderedItems$32_@0] out=[$74_@6] { + [41] Const mutate $74_@6 = JSX {read $68}{read $71_@5}{read $72}{freeze renderedItems$32_@0}{read $73} } return read $74_@6 } diff --git a/compiler/forget/src/__tests__/fixtures/hir/hooks-freeze-possibly-mutable-arguments.expect.md b/compiler/forget/src/__tests__/fixtures/hir/hooks-freeze-possibly-mutable-arguments.expect.md index 36091d96cf..b0093d2ba7 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/hooks-freeze-possibly-mutable-arguments.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/hooks-freeze-possibly-mutable-arguments.expect.md @@ -26,15 +26,15 @@ function call(x) {} ``` bb0: - [1] Const mutate cond$8:TProp = read props$7.cond - [2] Const mutate x$9:TProp = read props$7.x + [1] Const mutate cond$8 = read props$7.cond + [2] Const mutate x$9 = read props$7.x [3] Const mutate a$10:TPrimitive = undefined [4] Let mutate a$14_@0[4:9] = undefined - [4] If (read cond$8:TProp) then:bb2 else:bb3 fallthrough=bb1 + [4] If (read cond$8) then:bb2 else:bb3 fallthrough=bb1 bb2: predecessor blocks: bb0 - [5] Const mutate a$11:TProp = read x$9:TProp - [6] Reassign mutate a$14_@0[4:9] = read a$11:TProp + [5] Const mutate a$11 = read x$9 + [6] Reassign mutate a$14_@0[4:9] = read a$11 [6] Goto bb1 bb3: predecessor blocks: bb0 @@ -55,14 +55,14 @@ bb1: function Component( props, ) { - [1] Const mutate cond$8:TProp = read props$7.cond - [2] Const mutate x$9:TProp = read props$7.x + [1] Const mutate cond$8 = read props$7.cond + [2] Const mutate x$9 = read props$7.x [3] Const mutate a$10:TPrimitive = undefined - scope @0 [4:9] deps=[read cond$8:TProp, read x$9:TProp] out=[a$14_@0] { + scope @0 [4:9] deps=[read cond$8, read x$9] out=[a$14_@0] { [4] Let mutate a$14_@0[4:9] = undefined - if (read cond$8:TProp) { - [5] Const mutate a$11:TProp = read x$9:TProp - [6] Reassign mutate a$14_@0[4:9] = read a$11:TProp + if (read cond$8) { + [5] Const mutate a$11 = read x$9 + [6] Reassign mutate a$14_@0[4:9] = read a$11 } else { scope @1 [7:8] deps=[] out=[a$12_@1] { [7] Const mutate a$12_@1 = Array [] diff --git a/compiler/forget/src/__tests__/fixtures/hir/reverse-postorder.expect.md b/compiler/forget/src/__tests__/fixtures/hir/reverse-postorder.expect.md index 6d963eb143..183ad86d07 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/reverse-postorder.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/reverse-postorder.expect.md @@ -52,31 +52,31 @@ bb2: Fallthrough: bb1 bb8: predecessor blocks: bb2 - [7] Const mutate x$11:TProp = read props$6.v0 - [8] Reassign mutate x$16_@0[2:18] = read x$11:TProp + [7] Const mutate x$11 = read props$6.v0 + [8] Reassign mutate x$16_@0[2:18] = read x$11 [8] Goto bb1 bb6: predecessor blocks: bb2 - [9] Const mutate x$12:TProp = read props$6.v1 - [10] Reassign mutate x$16_@0[2:18] = read x$12:TProp + [9] Const mutate x$12 = read props$6.v1 + [10] Reassign mutate x$16_@0[2:18] = read x$12 [10] Goto bb1 bb4: predecessor blocks: bb2 - [11] Const mutate x$13:TProp = read props$6.v2 - [12] Reassign mutate x$16_@0[2:18] = read x$13:TProp + [11] Const mutate x$13 = read props$6.v2 + [12] Reassign mutate x$16_@0[2:18] = read x$13 [12] Goto bb1 bb10: predecessor blocks: bb0 [13] If (read props$6.cond2) then:bb12 else:bb13 fallthrough=bb1 bb12: predecessor blocks: bb10 - [14] Const mutate x$14:TProp = read props$6.b - [15] Reassign mutate x$16_@0[2:18] = read x$14:TProp + [14] Const mutate x$14 = read props$6.b + [15] Reassign mutate x$16_@0[2:18] = read x$14 [15] Goto bb1 bb13: predecessor blocks: bb10 - [16] Const mutate x$15:TProp = read props$6.c - [17] Reassign mutate x$16_@0[2:18] = read x$15:TProp + [16] Const mutate x$15 = read props$6.c + [17] Reassign mutate x$16_@0[2:18] = read x$15 [17] Goto bb1 bb1: predecessor blocks: bb8 bb6 bb4 bb12 bb13 @@ -99,29 +99,29 @@ function Component( [5] Const mutate $10:TPrimitive = 0 switch (read props$6.test) { case read $10:TPrimitive: { - [7] Const mutate x$11:TProp = read props$6.v0 - [8] Reassign mutate x$16_@0[2:18] = read x$11:TProp + [7] Const mutate x$11 = read props$6.v0 + [8] Reassign mutate x$16_@0[2:18] = read x$11 break bb1 } case read $9:TPrimitive: { - [9] Const mutate x$12:TProp = read props$6.v1 - [10] Reassign mutate x$16_@0[2:18] = read x$12:TProp + [9] Const mutate x$12 = read props$6.v1 + [10] Reassign mutate x$16_@0[2:18] = read x$12 break bb1 } case read $8:TPrimitive: { } default: { - [11] Const mutate x$13:TProp = read props$6.v2 - [12] Reassign mutate x$16_@0[2:18] = read x$13:TProp + [11] Const mutate x$13 = read props$6.v2 + [12] Reassign mutate x$16_@0[2:18] = read x$13 } } } else { if (read props$6.cond2) { - [14] Const mutate x$14:TProp = read props$6.b - [15] Reassign mutate x$16_@0[2:18] = read x$14:TProp + [14] Const mutate x$14 = read props$6.b + [15] Reassign mutate x$16_@0[2:18] = read x$14 } else { - [16] Const mutate x$15:TProp = read props$6.c - [17] Reassign mutate x$16_@0[2:18] = read x$15:TProp + [16] Const mutate x$15 = read props$6.c + [17] Reassign mutate x$16_@0[2:18] = read x$15 } } } diff --git a/compiler/forget/src/__tests__/fixtures/hir/type-field-load.expect.md b/compiler/forget/src/__tests__/fixtures/hir/type-field-load.expect.md index 0f06c4868f..0ca6d71b05 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/type-field-load.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/type-field-load.expect.md @@ -15,7 +15,7 @@ function component() { bb0: [1] Const mutate $4:TPrimitive = 1 [2] Const mutate x$5_@0:TObject = Object { t: read $4:TPrimitive } - [3] Const mutate p$6:TPrimitive = read x$5_@0.t + [3] Const mutate p$6 = read x$5_@0.t [4] Return ``` @@ -28,7 +28,7 @@ function component( scope @0 [2:3] deps=[] out=[x$5_@0] { [2] Const mutate x$5_@0:TObject = Object { t: read $4:TPrimitive } } - [3] Const mutate p$6:TPrimitive = read x$5_@0.t + [3] Const mutate p$6 = read x$5_@0.t return } diff --git a/compiler/forget/src/__tests__/fixtures/hir/type-test-field-load-binary-op.expect.md b/compiler/forget/src/__tests__/fixtures/hir/type-test-field-load-binary-op.expect.md index d70c0be5b0..46c1032f52 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/type-test-field-load-binary-op.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/type-test-field-load-binary-op.expect.md @@ -19,17 +19,17 @@ function component() { ``` bb0: - [1] Const mutate t0$10_@0:TPrimitive = Call mutate makeSomePrimitive$1:TFunction() - [2] Const mutate t1$11_@1:TPrimitive = Call mutate makeSomePrimitive$1:TFunction() - [3] Const mutate x$12_@2:TObject = Object { u: read t0$10_@0:TPrimitive, v: read t1$11_@1:TPrimitive } + [1] Const mutate t0$10_@0 = Call mutate makeSomePrimitive$1:TFunction() + [2] Const mutate t1$11_@1 = Call mutate makeSomePrimitive$1:TFunction() + [3] Const mutate x$12_@2:TObject = Object { u: read t0$10_@0, v: read t1$11_@1 } [4] Const mutate u$13:TPrimitive = read x$12_@2.u [5] Const mutate v$14:TPrimitive = read x$12_@2.v [6] Const mutate $15:TPrimitive = Binary read u$13:TPrimitive > read v$14:TPrimitive [7] If (read $15:TPrimitive) then:bb1 else:bb1 fallthrough=bb1 bb1: predecessor blocks: bb0 - [8] Const mutate y$16:TPrimitive = read x$12_@2.u - [9] Const mutate z$17:TPrimitive = read x$12_@2.v + [8] Const mutate y$16 = read x$12_@2.u + [9] Const mutate z$17 = read x$12_@2.v [10] Return ``` @@ -39,21 +39,21 @@ bb1: function component( ) { scope @0 [1:2] deps=[] out=[$10_@0] { - [1] Const mutate $10_@0:TPrimitive = Call mutate makeSomePrimitive$1:TFunction() + [1] Const mutate $10_@0 = Call mutate makeSomePrimitive$1:TFunction() } scope @1 [2:3] deps=[] out=[$11_@1] { - [2] Const mutate $11_@1:TPrimitive = Call mutate makeSomePrimitive$1:TFunction() + [2] Const mutate $11_@1 = Call mutate makeSomePrimitive$1:TFunction() } - scope @2 [3:4] deps=[read $10_@0:TPrimitive, read $11_@1:TPrimitive] out=[x$12_@2] { - [3] Const mutate x$12_@2:TObject = Object { u: read $10_@0:TPrimitive, v: read $11_@1:TPrimitive } + scope @2 [3:4] deps=[read $10_@0, read $11_@1] out=[x$12_@2] { + [3] Const mutate x$12_@2:TObject = Object { u: read $10_@0, v: read $11_@1 } } [4] Const mutate u$13:TPrimitive = read x$12_@2.u [5] Const mutate v$14:TPrimitive = read x$12_@2.v [6] Const mutate $15:TPrimitive = Binary read u$13:TPrimitive > read v$14:TPrimitive if (read $15:TPrimitive) { } - [8] Const mutate y$16:TPrimitive = read x$12_@2.u - [9] Const mutate z$17:TPrimitive = read x$12_@2.v + [8] Const mutate y$16 = read x$12_@2.u + [9] Const mutate z$17 = read x$12_@2.v return } diff --git a/compiler/forget/src/__tests__/fixtures/hir/type-test-field-store.expect.md b/compiler/forget/src/__tests__/fixtures/hir/type-test-field-store.expect.md index 405abdaa1d..6166f1f1d5 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/type-test-field-store.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/type-test-field-store.expect.md @@ -18,7 +18,7 @@ bb0: [1] Const mutate x$4_@0:TObject[1:4] = Object { } [2] Const mutate q$5_@1:TObject = Object { } [3] Reassign store x$4_@0.t[1:4] = read q$5_@1:TObject - [4] Const mutate z$6:TObject = read x$4_@0.t + [4] Const mutate z$6 = read x$4_@0.t [5] Return ``` @@ -34,7 +34,7 @@ function component( } [3] Reassign store x$4_@0.t[1:4] = read q$5_@1:TObject } - [4] Const mutate z$6:TObject = read x$4_@0.t + [4] Const mutate z$6 = read x$4_@0.t return } diff --git a/compiler/forget/src/__tests__/fixtures/hir/type-test-polymorphic.expect.md b/compiler/forget/src/__tests__/fixtures/hir/type-test-polymorphic.expect.md index 06ead4275c..e9f636e992 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/type-test-polymorphic.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/type-test-polymorphic.expect.md @@ -27,9 +27,9 @@ bb0: [3] Const mutate o$8_@1:TObject = Object { } [4] Const mutate x$9_@2:TObject[4:8] = Object { } [5] Reassign store x$9_@2.t[4:8] = read p$7_@0:TPrimitive - [6] Const mutate z$10_@2:TPrimitive[4:8] = read x$9_@2.t + [6] Const mutate z$10_@2[4:8] = read x$9_@2.t [7] Reassign store x$9_@2.t[4:8] = read o$8_@1:TObject - [8] Const mutate y$11:TPoly = read x$9_@2.t + [8] Const mutate y$11 = read x$9_@2.t [9] Return ``` @@ -48,10 +48,10 @@ function component( scope @2 [4:8] deps=[read p$7_@0:TPrimitive, read o$8_@1:TObject] out=[x$9_@2] { [4] Const mutate x$9_@2:TObject[4:8] = Object { } [5] Reassign store x$9_@2.t[4:8] = read p$7_@0:TPrimitive - [6] Const mutate z$10_@2:TPrimitive[4:8] = read x$9_@2.t + [6] Const mutate z$10_@2[4:8] = read x$9_@2.t [7] Reassign store x$9_@2.t[4:8] = read o$8_@1:TObject } - [8] Const mutate y$11:TPoly = read x$9_@2.t + [8] Const mutate y$11 = read x$9_@2.t return }