-
Notifications
You must be signed in to change notification settings - Fork 833
Closed
Labels
Milestone
Description
The following functions demonstrate the affect:
let f (a:obj) (b:obj) =
match a, b with
| :? char, :? char -> 0
| :? int, :? int -> 1
| _ -> -1
let g (a:obj) (b:obj) =
match a, b with
| :? char, :? char -> 0
| :? int, :? int -> 1
| :? byte, :? byte -> 2
| _ -> -1
let h (a:obj) (b:obj) =
match a, b with
| :? char, :? char -> 0
| :? int, :? int -> 1
| :? byte, :? byte -> 2
| :? float, :? float -> 3
| _ -> -1
So type size of the Il generated from those functions is 60, 143, 337 bytes respectively.
The array checking code in prim_types.fs in the funciton GenericEqualityObj which has 8 type-checks creates IL which is around 8K.
Expected behavior
This should be a linear increase.
Actual behavior
The exponential behaviour is due to the AST duplicating the remaining code in both the first and second failing check.
Known workarounds
You can work around this by putting a catch all, and then matching again.
In the prim_types code this would look like this:
match arr1,yobj with
| (:? (obj[]) as arr1), (:? (obj[]) as arr2) -> GenericEqualityObjArray er iec arr1 arr2
| _ ->
match arr1,yobj with
| (:? (byte[]) as arr1), (:? (byte[]) as arr2) -> GenericEqualityByteArray arr1 arr2
| _ ->
match arr1,yobj with
| (:? (int32[]) as arr1), (:? (int32[]) as arr2) -> GenericEqualityInt32Array arr1 arr2
| _ ->
match arr1,yobj with
| (:? (int64[]) as arr1), (:? (int64[]) as arr2) -> GenericEqualityInt64Array arr1 arr2
| _ ->
match arr1,yobj with
| (:? (char[]) as arr1), (:? (char[]) as arr2) -> GenericEqualityCharArray arr1 arr2
| _ ->
match arr1,yobj with
| (:? (float32[]) as arr1), (:? (float32[]) as arr2) -> GenericEqualitySingleArray er arr1 arr2
| _ ->
match arr1,yobj with
| (:? (float[]) as arr1), (:? (float[]) as arr2) -> GenericEqualityDoubleArray er arr1 arr2
| _ ->
match arr1,yobj with
| _ , (:? System.Array as arr2) -> GenericEqualityArbArray er iec arr1 arr2
| _ -> xobj.Equals(yobj)