Skip to content

Commit 396e154

Browse files
Temp commit
1 parent 8e9602e commit 396e154

File tree

3 files changed

+112
-34
lines changed

3 files changed

+112
-34
lines changed

src/Fable.Core/Fable.Core.Util.fs

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,44 @@ module Testing =
3939

4040

4141
module Reflection =
42-
let isUnion (x: obj): bool = nativeOnly
43-
let isRecord (x: obj): bool = nativeOnly
44-
45-
let getCaseTag (x: obj): int = nativeOnly
46-
let getCaseName (x: obj): string = nativeOnly
47-
let getCaseFields (x: obj): obj[] = nativeOnly
42+
open FSharp.Reflection
43+
44+
let isUnion (x: obj): bool =
45+
#if FABLE_COMPILER
46+
nativeOnly
47+
#else
48+
FSharpType.IsUnion(x.GetType())
49+
#endif
50+
51+
let isRecord (x: obj): bool =
52+
#if FABLE_COMPILER
53+
nativeOnly
54+
#else
55+
FSharpType.IsRecord(x.GetType())
56+
#endif
57+
58+
let getCaseTag (x: obj): int =
59+
#if FABLE_COMPILER
60+
nativeOnly
61+
#else
62+
let uci, _ = FSharpValue.GetUnionFields(x, x.GetType())
63+
uci.Tag
64+
#endif
65+
66+
let getCaseName (x: obj): string =
67+
#if FABLE_COMPILER
68+
nativeOnly
69+
#else
70+
let uci, _ = FSharpValue.GetUnionFields(x, x.GetType())
71+
uci.Name
72+
#endif
73+
74+
let getCaseFields (x: obj): obj[] =
75+
#if FABLE_COMPILER
76+
nativeOnly
77+
#else
78+
FSharpValue.GetUnionFields(x, x.GetType()) |> snd
79+
#endif
4880

4981
module Compiler =
5082
/// Compiler full version as string

src/fable-library/Reflection.ts

Lines changed: 58 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ export class CaseInfo {
1818
}
1919
}
2020

21+
export const enum ErasedUnion {
22+
Default,
23+
WithTag
24+
}
25+
2126
export type EnumCase = [string, number];
2227

2328
export class MethodInfo {
@@ -32,13 +37,21 @@ export class MethodInfo {
3237
export class TypeInfo implements IEquatable<TypeInfo> {
3338
constructor(
3439
public fullname: string,
35-
public generics?: TypeInfo[],
36-
public construct?: Constructor,
37-
public parent?: TypeInfo,
38-
public fields?: () => FieldInfo[],
39-
public cases?: () => CaseInfo[],
40-
public enumCases?: EnumCase[]) {
41-
}
40+
private info?: {
41+
generics?: TypeInfo[],
42+
construct?: Constructor,
43+
parent?: TypeInfo,
44+
fields?: () => FieldInfo[],
45+
cases?: () => CaseInfo[],
46+
enumCases?: EnumCase[],
47+
}
48+
) { }
49+
public get generics() { return this.info?.generics; }
50+
public get construct() { return this.info?.construct; }
51+
public get parent() { return this.info?.parent; }
52+
public get fields() { return this.info?.fields; }
53+
public get cases() { return this.info?.cases; }
54+
public get enumCases() { return this.info?.enumCases; }
4255
public toString() {
4356
return fullName(this);
4457
}
@@ -83,59 +96,74 @@ export function class_type(
8396
generics?: TypeInfo[],
8497
construct?: Constructor,
8598
parent?: TypeInfo): TypeInfo {
86-
return new TypeInfo(fullname, generics, construct, parent);
99+
return new TypeInfo(fullname, { generics, construct, parent });
87100
}
88101

89102
export function record_type(
90103
fullname: string,
91104
generics: TypeInfo[],
92105
construct: Constructor,
93106
fields: () => FieldInfo[]): TypeInfo {
94-
return new TypeInfo(fullname, generics, construct, undefined, fields);
107+
return new TypeInfo(fullname, { generics, construct, fields });
95108
}
96109

97110
export function anonRecord_type(...fields: FieldInfo[]): TypeInfo {
98-
return new TypeInfo("", undefined, undefined, undefined, () => fields);
111+
return new TypeInfo("", { fields: () => fields });
99112
}
100113

101114
export function union_type(
102115
fullname: string,
103116
generics: TypeInfo[],
104117
construct: Constructor,
105118
cases: () => FieldInfo[][]): TypeInfo {
106-
const t: TypeInfo = new TypeInfo(fullname, generics, construct, undefined, undefined, () => {
107-
const caseNames = construct.prototype.cases() as string[];
108-
return cases().map((fields, i) => new CaseInfo(t, i, caseNames[i], fields))
119+
const t: TypeInfo = new TypeInfo(fullname, {
120+
generics,
121+
construct,
122+
cases() {
123+
const caseNames = construct.prototype.cases() as string[];
124+
return cases().map((fields, i) => new CaseInfo(t, i, caseNames[i], fields))
125+
}
109126
});
110127
return t;
111128
}
112129

113130
export function tuple_type(...generics: TypeInfo[]): TypeInfo {
114-
return new TypeInfo("System.Tuple`" + generics.length, generics);
131+
return new TypeInfo("System.Tuple`" + generics.length, { generics });
115132
}
116133

117134
export function delegate_type(...generics: TypeInfo[]): TypeInfo {
118-
return new TypeInfo("System.Func`" + generics.length, generics);
135+
return new TypeInfo("System.Func`" + generics.length, { generics });
119136
}
120137

121138
export function lambda_type(argType: TypeInfo, returnType: TypeInfo): TypeInfo {
122-
return new TypeInfo("Microsoft.FSharp.Core.FSharpFunc`2", [argType, returnType]);
139+
return new TypeInfo("Microsoft.FSharp.Core.FSharpFunc`2", {
140+
generics: [argType, returnType]
141+
});
123142
}
124143

125144
export function option_type(generic: TypeInfo): TypeInfo {
126-
return new TypeInfo("Microsoft.FSharp.Core.FSharpOption`1", [generic]);
145+
return new TypeInfo("Microsoft.FSharp.Core.FSharpOption`1", {
146+
generics: [generic]
147+
});
127148
}
128149

129150
export function list_type(generic: TypeInfo): TypeInfo {
130-
return new TypeInfo("Microsoft.FSharp.Collections.FSharpList`1", [generic]);
151+
return new TypeInfo("Microsoft.FSharp.Collections.FSharpList`1", {
152+
generics: [generic]
153+
});
131154
}
132155

133156
export function array_type(generic: TypeInfo): TypeInfo {
134-
return new TypeInfo("[]", [generic]);
157+
return new TypeInfo("[]", {
158+
generics: [generic]
159+
});
135160
}
136161

137162
export function enum_type(fullname: string, underlyingType: TypeInfo, enumCases: EnumCase[]): TypeInfo {
138-
return new TypeInfo(fullname, [underlyingType], undefined, undefined, undefined, undefined, enumCases);
163+
return new TypeInfo(fullname, {
164+
generics: [underlyingType],
165+
enumCases
166+
});
139167
}
140168

141169
export function measure_type(fullname: string): TypeInfo {
@@ -262,7 +290,9 @@ export function isInstanceOfType(t: TypeInfo, o: any) {
262290
* but it should be enough for type comparison purposes
263291
*/
264292
export function getGenericTypeDefinition(t: TypeInfo) {
265-
return t.generics == null ? t : new TypeInfo(t.fullname, t.generics.map(() => obj_type));
293+
return t.generics == null ? t : new TypeInfo(t.fullname, {
294+
generics: t.generics.map(() => obj_type)
295+
});
266296
}
267297

268298
export function getEnumUnderlyingType(t: TypeInfo) {
@@ -452,12 +482,13 @@ export function makeTuple(values: any[], _t: TypeInfo): any {
452482

453483
export function makeGenericType(t: TypeInfo, generics: TypeInfo[]): TypeInfo {
454484
return new TypeInfo(
455-
t.fullname,
456-
generics,
457-
t.construct,
458-
t.parent,
459-
t.fields,
460-
t.cases);
485+
t.fullname, {
486+
generics,
487+
construct: t.construct,
488+
parent: t.parent,
489+
fields: t.fields,
490+
cases: t.cases
491+
});
461492
}
462493

463494
export function createInstance(t: TypeInfo, consArgs?: any[]): any {

src/quicktest/QuickTest.fs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,13 @@ let measureTime (f: unit -> unit): unit = emitJsStatement () """
7979
// testCase "Addition works" <| fun () ->
8080
// 2 + 2 |> equal 4
8181

82-
[<Erase>]
82+
// [<Erase>]
8383
type MyRecord =
8484
{ Foo: int }
8585

86+
type MyRecord2 =
87+
{ Bar: MyRecord }
88+
8689
let testMyRecord (r: MyRecord) =
8790
r.Foo
8891

@@ -100,6 +103,18 @@ let test = function
100103
Zas 5.67890 |> test |> printfn "%s"
101104
Foo("oh", 3) |> test |> printfn "%s"
102105

106+
[<Erase>]
107+
type WrappedNum = Num of int with
108+
static member ( + ) (Num x, Num y) = 2 * (x + y) |> Num
109+
110+
let add1 (x: WrappedNum) y = x + y
111+
112+
let add2 (x: WrappedNum) y = x + Num y
113+
114+
testCase "Can resolve custom operators on erased types" <| fun () -> // See #2915
115+
add1 (Num 4) (Num 5) |> equal (Num 18)
116+
add2 (Num 4) 5 |> equal (Num 18)
117+
103118
(*
104119
module TaggedUnion =
105120
type Base<'Kind> =

0 commit comments

Comments
 (0)