@@ -628,27 +628,6 @@ module internal Impl =
628628
629629 //-----------------------------------------------------------------
630630 // TUPLE DECOMPILATION
631- let tupleNames =
632- [|
633- " System.Tuple`1"
634- " System.Tuple`2"
635- " System.Tuple`3"
636- " System.Tuple`4"
637- " System.Tuple`5"
638- " System.Tuple`6"
639- " System.Tuple`7"
640- " System.Tuple`8"
641- " System.Tuple"
642- " System.ValueTuple`1"
643- " System.ValueTuple`2"
644- " System.ValueTuple`3"
645- " System.ValueTuple`4"
646- " System.ValueTuple`5"
647- " System.ValueTuple`6"
648- " System.ValueTuple`7"
649- " System.ValueTuple`8"
650- " System.ValueTuple"
651- |]
652631
653632 let simpleTupleNames =
654633 [|
@@ -679,69 +658,137 @@ module internal Impl =
679658 // used in F# type providers.
680659 typ.IsGenericType
681660 && typ.Namespace = " System"
682- && simpleTupleNames |> Seq .exists typ.Name.StartsWith
661+ && simpleTupleNames |> Array .exists typ.Name.StartsWith
683662
684663 let maxTuple = 8
685664 // Which field holds the nested tuple?
686665 let tupleEncField = maxTuple - 1
687666
688- let dictionaryLock = obj ()
689- let refTupleTypes = Dictionary< Assembly, Type[]>()
690- let valueTupleTypes = Dictionary< Assembly, Type[]>()
691-
692- let rec mkTupleType isStruct ( asm : Assembly ) ( tys : Type []) =
693- let table =
694- let makeIt n =
695- let tupleFullName n =
696- let structOffset = if isStruct then 9 else 0
697- let index = n - 1 + structOffset
698- tupleNames.[ index]
699-
700- match n with
701- | 1 -> asm.GetType( tupleFullName 1 )
702- | 2 -> asm.GetType( tupleFullName 2 )
703- | 3 -> asm.GetType( tupleFullName 3 )
704- | 4 -> asm.GetType( tupleFullName 4 )
705- | 5 -> asm.GetType( tupleFullName 5 )
706- | 6 -> asm.GetType( tupleFullName 6 )
707- | 7 -> asm.GetType( tupleFullName 7 )
708- | 8 -> asm.GetType( tupleFullName 8 )
709- | _ -> invalidArg " tys" ( SR.GetString( SR.invalidTupleTypes))
710-
711- let tables =
712- if isStruct then
713- valueTupleTypes
714- else
715- refTupleTypes
716-
717- match lock dictionaryLock ( fun () -> tables.TryGetValue asm) with
718- | false , _ ->
719- // the Dictionary<>s here could be ConcurrentDictionary<>'s, but then
720- // that would lock while initializing the Type array (maybe not an issue)
721- let mutable a = Array.init< Type> 8 ( fun i -> makeIt ( i + 1 ))
722-
723- lock dictionaryLock ( fun () ->
724- match tables.TryGetValue asm with
725- | true , t -> a <- t
726- | false , _ -> tables.Add( asm, a))
727-
728- a
729- | true , t -> t
730-
731- match tys.Length with
732- | 1 -> table.[ 0 ]. MakeGenericType tys
733- | 2 -> table.[ 1 ]. MakeGenericType tys
734- | 3 -> table.[ 2 ]. MakeGenericType tys
735- | 4 -> table.[ 3 ]. MakeGenericType tys
736- | 5 -> table.[ 4 ]. MakeGenericType tys
737- | 6 -> table.[ 5 ]. MakeGenericType tys
738- | 7 -> table.[ 6 ]. MakeGenericType tys
739- | n when n >= maxTuple ->
740- let tysA = tys.[ 0 .. tupleEncField - 1 ]
741- let tysB = tys.[ maxTuple - 1 ..]
742- let tyB = mkTupleType isStruct asm tysB
743- table.[ 7 ]. MakeGenericType( Array.append tysA [| tyB |])
744- | _ -> invalidArg " tys" ( SR.GetString( SR.invalidTupleTypes))
667+ module internal TupleFromSpecifiedAssembly =
668+ let private tupleNames =
669+ [|
670+ " System.Tuple`1"
671+ " System.Tuple`2"
672+ " System.Tuple`3"
673+ " System.Tuple`4"
674+ " System.Tuple`5"
675+ " System.Tuple`6"
676+ " System.Tuple`7"
677+ " System.Tuple`8"
678+ " System.Tuple"
679+ " System.ValueTuple`1"
680+ " System.ValueTuple`2"
681+ " System.ValueTuple`3"
682+ " System.ValueTuple`4"
683+ " System.ValueTuple`5"
684+ " System.ValueTuple`6"
685+ " System.ValueTuple`7"
686+ " System.ValueTuple`8"
687+ " System.ValueTuple"
688+ |]
689+
690+ let private dictionaryLock = obj ()
691+ let private refTupleTypes = Dictionary< Assembly, Type[]>()
692+ let private valueTupleTypes = Dictionary< Assembly, Type[]>()
693+
694+ let rec mkTupleType isStruct ( asm : Assembly ) ( tys : Type []) =
695+ let table =
696+ let makeIt n =
697+ let tupleFullName n =
698+ let structOffset = if isStruct then 9 else 0
699+ let index = n - 1 + structOffset
700+ tupleNames.[ index]
701+
702+ match n with
703+ | 1 -> asm.GetType( tupleFullName 1 )
704+ | 2 -> asm.GetType( tupleFullName 2 )
705+ | 3 -> asm.GetType( tupleFullName 3 )
706+ | 4 -> asm.GetType( tupleFullName 4 )
707+ | 5 -> asm.GetType( tupleFullName 5 )
708+ | 6 -> asm.GetType( tupleFullName 6 )
709+ | 7 -> asm.GetType( tupleFullName 7 )
710+ | 8 -> asm.GetType( tupleFullName 8 )
711+ | _ -> invalidArg " tys" ( SR.GetString( SR.invalidTupleTypes))
712+
713+ let tables =
714+ if isStruct then
715+ valueTupleTypes
716+ else
717+ refTupleTypes
718+
719+ match lock dictionaryLock ( fun () -> tables.TryGetValue asm) with
720+ | false , _ ->
721+ // the Dictionary<>s here could be ConcurrentDictionary<>'s, but then
722+ // that would lock while initializing the Type array (maybe not an issue)
723+ let mutable a = Array.init< Type> 8 ( fun i -> makeIt ( i + 1 ))
724+
725+ lock dictionaryLock ( fun () ->
726+ match tables.TryGetValue asm with
727+ | true , t -> a <- t
728+ | false , _ -> tables.Add( asm, a))
729+
730+ a
731+ | true , t -> t
732+
733+ match tys.Length with
734+ | 1 -> table.[ 0 ]. MakeGenericType tys
735+ | 2 -> table.[ 1 ]. MakeGenericType tys
736+ | 3 -> table.[ 2 ]. MakeGenericType tys
737+ | 4 -> table.[ 3 ]. MakeGenericType tys
738+ | 5 -> table.[ 4 ]. MakeGenericType tys
739+ | 6 -> table.[ 5 ]. MakeGenericType tys
740+ | 7 -> table.[ 6 ]. MakeGenericType tys
741+ | n when n >= maxTuple ->
742+ let tysA = tys.[ 0 .. tupleEncField - 1 ]
743+ let tysB = tys.[ maxTuple - 1 ..]
744+ let tyB = mkTupleType isStruct asm tysB
745+ table.[ 7 ]. MakeGenericType( Array.append tysA [| tyB |])
746+ | _ -> invalidArg " tys" ( SR.GetString( SR.invalidTupleTypes))
747+
748+ let refTupleTypesNetStandard =
749+ [|
750+ typedefof< System.Tuple<_>>
751+ typedefof< System.Tuple<_, _>>
752+ typedefof< System.Tuple<_, _, _>>
753+ typedefof< System.Tuple<_, _, _, _>>
754+ typedefof< System.Tuple<_, _, _, _, _>>
755+ typedefof< System.Tuple<_, _, _, _, _, _>>
756+ typedefof< System.Tuple<_, _, _, _, _, _, _>>
757+ typedefof< System.Tuple<_, _, _, _, _, _, _, _>>
758+ |]
759+
760+ let structTupleTypesNetStandard =
761+ [|
762+ typedefof< System.ValueTuple<_>>
763+ typedefof< System.ValueTuple<_, _>>
764+ typedefof< System.ValueTuple<_, _, _>>
765+ typedefof< System.ValueTuple<_, _, _, _>>
766+ typedefof< System.ValueTuple<_, _, _, _, _>>
767+ typedefof< System.ValueTuple<_, _, _, _, _, _>>
768+ typedefof< System.ValueTuple<_, _, _, _, _, _, _>>
769+ typedefof< System.ValueTuple<_, _, _, _, _, _, _, _>>
770+ |]
771+
772+ /// Index of the recursively-nested Tuple type within the table of types
773+ [<Literal>]
774+ let nestedTupIndex = 7
775+
776+ /// Index of the last regular (non-nested) tuple type within the table of types
777+ [<Literal>]
778+ let lastRegularTupIndex = 6 //nestedTupIndex - 1 (wait for arithmetic in constants)
779+
780+ let rec mkTupleTypeNetStandard ( tupTyTbl : Type []) ( tys : Type []) =
781+ let tblIdx = tys.Length - 1
782+ assert ( tblIdx >= 0 )
783+ assert ( nestedTupIndex = tupTyTbl.Length - 1 )
784+
785+ match tblIdx with
786+ | idx when idx < nestedTupIndex -> tupTyTbl[ idx ]. MakeGenericType tys
787+ | _ ->
788+ let tysA = tys.[ 0 .. lastRegularTupIndex]
789+ let tysB = tys.[ nestedTupIndex..]
790+ let tyB = mkTupleTypeNetStandard tupTyTbl tysB
791+ tupTyTbl.[ nestedTupIndex]. MakeGenericType([| yield ! tysA; yield tyB |])
745792
746793 let rec getTupleTypeInfo ( typ : Type ) =
747794 if not ( isTupleType typ) then
@@ -1111,18 +1158,13 @@ type FSharpType =
11111158 static member MakeTupleType ( types : Type []) =
11121159 checkNonNull " types" types
11131160
1114- // No assembly passed therefore just get framework local version of Tuple
1115- let asm = typeof < System.Tuple >. Assembly
1161+ if types.Length = 0 then
1162+ invalidArg " types " ( SR.GetString ( SR.invalidTupleTypes ))
11161163
1117- if
1118- types
1119- |> Array.exists ( function
1120- | null -> true
1121- | _ -> false )
1122- then
1164+ if types |> Array.exists isNull then
11231165 invalidArg " types" ( SR.GetString( SR.nullsNotAllowedInArray))
11241166
1125- mkTupleType false asm types
1167+ mkTupleTypeNetStandard refTupleTypesNetStandard types
11261168
11271169 static member MakeTupleType ( asm : Assembly , types : Type []) =
11281170 checkNonNull " types" types
@@ -1135,7 +1177,7 @@ type FSharpType =
11351177 then
11361178 invalidArg " types" ( SR.GetString( SR.nullsNotAllowedInArray))
11371179
1138- mkTupleType false asm types
1180+ TupleFromSpecifiedAssembly. mkTupleType false asm types
11391181
11401182 static member MakeStructTupleType ( asm : Assembly , types : Type []) =
11411183 checkNonNull " types" types
@@ -1148,7 +1190,18 @@ type FSharpType =
11481190 then
11491191 invalidArg " types" ( SR.GetString( SR.nullsNotAllowedInArray))
11501192
1151- mkTupleType true asm types
1193+ TupleFromSpecifiedAssembly.mkTupleType true asm types
1194+
1195+ static member MakeStructTupleType ( types : Type []) =
1196+ checkNonNull " types" types
1197+
1198+ if types.Length = 0 then
1199+ invalidArg " types" ( SR.GetString( SR.invalidTupleTypes))
1200+
1201+ if types |> Array.exists isNull then
1202+ invalidArg " types" ( SR.GetString( SR.nullsNotAllowedInArray))
1203+
1204+ mkTupleTypeNetStandard structTupleTypesNetStandard types
11521205
11531206 static member GetTupleElements ( tupleType : Type ) =
11541207 checkTupleType ( " tupleType" , tupleType)
0 commit comments