diff --git a/src/fsharp/TcGlobals.fs b/src/fsharp/TcGlobals.fs index a676671aaa..c1f0655523 100755 --- a/src/fsharp/TcGlobals.fs +++ b/src/fsharp/TcGlobals.fs @@ -673,54 +673,52 @@ type public TcGlobals(compilingFslib: bool, ilg:ILGlobals, fslibCcu: CcuThunk, d let addFieldNeverAttrs (fdef:ILFieldDef) = {fdef with CustomAttrs = addNeverAttrs fdef.CustomAttrs} let mkDebuggerTypeProxyAttribute (ty : ILType) = mkILCustomAttribute ilg (findSysILTypeRef tname_DebuggerTypeProxyAttribute, [ilg.typ_Type], [ILAttribElem.TypeRef (Some ty.TypeRef)], []) + let entries1 = + [| "Int32" , v_int_tcr + "IntPtr" , v_nativeint_tcr + "UIntPtr" , v_unativeint_tcr + "Int16" , v_int16_tcr + "Int64" , v_int64_tcr + "UInt16" , v_uint16_tcr + "UInt32" , v_uint32_tcr + "UInt64" , v_uint64_tcr + "SByte" , v_sbyte_tcr + "Decimal" , v_decimal_tcr + "Byte" , v_byte_tcr + "Boolean" , v_bool_tcr + "String" , v_string_tcr + "Object" , v_obj_tcr + "Exception", v_exn_tcr + "Char" , v_char_tcr + "Double" , v_float_tcr + "Single" , v_float32_tcr |] + |> Array.map (fun (nm, tcr) -> + let ty = mkNonGenericTy tcr + nm, findSysTyconRef sys nm, (fun _ -> ty)) + + let entries2 = + [| + "FSharpFunc`2" , v_fastFunc_tcr , (fun tinst -> mkFunTy (List.item 0 tinst) (List.item 1 tinst)) + "Tuple`2" , v_ref_tuple2_tcr , decodeTupleTy tupInfoRef + "Tuple`3" , v_ref_tuple3_tcr , decodeTupleTy tupInfoRef + "Tuple`4" , v_ref_tuple4_tcr , decodeTupleTy tupInfoRef + "Tuple`5" , v_ref_tuple5_tcr , decodeTupleTy tupInfoRef + "Tuple`6" , v_ref_tuple6_tcr , decodeTupleTy tupInfoRef + "Tuple`7" , v_ref_tuple7_tcr , decodeTupleTy tupInfoRef + "Tuple`8" , v_ref_tuple8_tcr , decodeTupleTy tupInfoRef + "ValueTuple`2" , v_struct_tuple2_tcr , decodeTupleTy tupInfoStruct + "ValueTuple`3" , v_struct_tuple3_tcr , decodeTupleTy tupInfoStruct + "ValueTuple`4" , v_struct_tuple4_tcr , decodeTupleTy tupInfoStruct + "ValueTuple`5" , v_struct_tuple5_tcr , decodeTupleTy tupInfoStruct + "ValueTuple`6" , v_struct_tuple6_tcr , decodeTupleTy tupInfoStruct + "ValueTuple`7" , v_struct_tuple7_tcr , decodeTupleTy tupInfoStruct + "ValueTuple`8" , v_struct_tuple8_tcr , decodeTupleTy tupInfoStruct |] + // Build a map that uses the "canonical" F# type names and TyconRef's for these // in preference to the .NET type names. Doing this normalization is a fairly performance critical // piece of code as it is frequently invoked in the process of converting .NET metadata to F# internal // compiler data structures (see import.fs). - let betterTyconRefMap = - begin - let entries1 = - [| "Int32" , v_int_tcr - "IntPtr" , v_nativeint_tcr - "UIntPtr" , v_unativeint_tcr - "Int16" , v_int16_tcr - "Int64" , v_int64_tcr - "UInt16" , v_uint16_tcr - "UInt32" , v_uint32_tcr - "UInt64" , v_uint64_tcr - "SByte" , v_sbyte_tcr - "Decimal" , v_decimal_tcr - "Byte" , v_byte_tcr - "Boolean" , v_bool_tcr - "String" , v_string_tcr - "Object" , v_obj_tcr - "Exception", v_exn_tcr - "Char" , v_char_tcr - "Double" , v_float_tcr - "Single" , v_float32_tcr |] - |> Array.map (fun (nm, tcr) -> - let ty = mkNonGenericTy tcr - nm, findSysTyconRef sys nm, (fun _ -> ty)) - - let entries2 = - [| - "FSharpFunc`2" , v_fastFunc_tcr , (fun tinst -> mkFunTy (List.item 0 tinst) (List.item 1 tinst)) - "Tuple`2" , v_ref_tuple2_tcr , decodeTupleTy tupInfoRef - "Tuple`3" , v_ref_tuple3_tcr , decodeTupleTy tupInfoRef - "Tuple`4" , v_ref_tuple4_tcr , decodeTupleTy tupInfoRef - "Tuple`5" , v_ref_tuple5_tcr , decodeTupleTy tupInfoRef - "Tuple`6" , v_ref_tuple6_tcr , decodeTupleTy tupInfoRef - "Tuple`7" , v_ref_tuple7_tcr , decodeTupleTy tupInfoRef - "Tuple`8" , v_ref_tuple8_tcr , decodeTupleTy tupInfoRef - "ValueTuple`2" , v_struct_tuple2_tcr , decodeTupleTy tupInfoStruct - "ValueTuple`3" , v_struct_tuple3_tcr , decodeTupleTy tupInfoStruct - "ValueTuple`4" , v_struct_tuple4_tcr , decodeTupleTy tupInfoStruct - "ValueTuple`5" , v_struct_tuple5_tcr , decodeTupleTy tupInfoStruct - "ValueTuple`6" , v_struct_tuple6_tcr , decodeTupleTy tupInfoStruct - "ValueTuple`7" , v_struct_tuple7_tcr , decodeTupleTy tupInfoStruct - "ValueTuple`8" , v_struct_tuple8_tcr , decodeTupleTy tupInfoStruct |] - - let entries = Array.append entries1 entries2 + let buildTyconMapper (entries: (string * TyconRef * _)[]) = if compilingFslib then // This map is for use when building FSharp.Core.dll. The backing Tycon's may not yet exist for // the TyconRef's we have in our hands, hence we can't dereference them to find their stamps. @@ -759,8 +757,10 @@ type public TcGlobals(compilingFslib: bool, ilg:ILGlobals, fslibCcu: CcuThunk, d let key = tcref2.Stamp if dict.ContainsKey key then Some(dict.[key] tinst) else None) - end - + + let betterTyconRefMapper = buildTyconMapper (Array.append entries1 entries2) + + let decodeTyconRefMapper = buildTyconMapper entries2 override x.ToString() = "" member __.ilg=ilg @@ -1052,7 +1052,8 @@ type public TcGlobals(compilingFslib: bool, ilg:ILGlobals, fslibCcu: CcuThunk, d member val attrib_SecuritySafeCriticalAttribute = findSysAttrib "System.Security.SecuritySafeCriticalAttribute" member val attrib_ComponentModelEditorBrowsableAttribute = findSysAttrib "System.ComponentModel.EditorBrowsableAttribute" - member __.better_tcref_map = betterTyconRefMap + member __.betterTyconRefMap = betterTyconRefMapper + member __.decodeTyconRefMap = decodeTyconRefMapper member __.new_decimal_info = v_new_decimal_info member __.seq_info = v_seq_info member val seq_vref = (ValRefForIntrinsic v_seq_info) diff --git a/src/fsharp/TypeChecker.fs b/src/fsharp/TypeChecker.fs index ef41ac4aaa..889a20db10 100755 --- a/src/fsharp/TypeChecker.fs +++ b/src/fsharp/TypeChecker.fs @@ -4858,31 +4858,44 @@ and TcProvidedTypeApp cenv env tpenv tcref args m = /// Note that the generic type may be a nested generic type List.ListEnumerator. /// In this case, 'args' is only the instantiation of the suffix type arguments, and pathTypeArgs gives /// the prefix of type arguments. -and TcTypeApp cenv newOk checkCxs occ env tpenv m tcref pathTypeArgs (args: SynType list) = +and TcTypeApp cenv newOk checkCxs occ env tpenv m tcref pathTypeArgs (synArgTys: SynType list) = CheckTyconAccessible cenv.amap m env.eAccessRights tcref |> ignore CheckEntityAttributes cenv.g tcref m |> CommitOperationResult #if EXTENSIONTYPING // Provided types are (currently) always non-generic. Their names may include mangled // static parameters, which are passed by the provider. - if tcref.Deref.IsProvided then TcProvidedTypeApp cenv env tpenv tcref args m else + if tcref.Deref.IsProvided then TcProvidedTypeApp cenv env tpenv tcref synArgTys m else #endif let tps,_,tinst,_ = infoOfTyconRef m tcref + // If we're not checking constraints, i.e. when we first assert the super/interfaces of a type definition, then just // clear the constraint lists of the freshly generated type variables. A little ugly but fairly localized. if checkCxs = NoCheckCxs then tps |> List.iter (fun tp -> tp.typar_constraints <- []) - if tinst.Length <> pathTypeArgs.Length + args.Length then - error (TyconBadArgs(env.DisplayEnv,tcref,pathTypeArgs.Length + args.Length,m)) - let args',tpenv = + if tinst.Length <> pathTypeArgs.Length + synArgTys.Length then + error (TyconBadArgs(env.DisplayEnv,tcref,pathTypeArgs.Length + synArgTys.Length,m)) + + let argTys,tpenv = // Get the suffix of typars - let tpsForArgs = List.drop (tps.Length - args.Length) tps + let tpsForArgs = List.drop (tps.Length - synArgTys.Length) tps let kindsForArgs = tpsForArgs |> List.map (fun tp -> tp.Kind) - TcTypesOrMeasures (Some kindsForArgs) cenv newOk checkCxs occ env tpenv args m - let args' = pathTypeArgs @ args' + TcTypesOrMeasures (Some kindsForArgs) cenv newOk checkCxs occ env tpenv synArgTys m + + // Add the types of the enclosing class for a nested type + let actualArgTys = pathTypeArgs @ argTys + if checkCxs = CheckCxs then - List.iter2 (UnifyTypes cenv env m) tinst args' - mkAppTy tcref args', tpenv + List.iter2 (UnifyTypes cenv env m) tinst actualArgTys + + // Try to decode System.Tuple --> F~ tuple types etc. + let ty = + let decode = if cenv.g.compilingFslib then None else cenv.g.decodeTyconRefMap tcref actualArgTys + match decode with + | Some res -> res + | None -> mkAppTy tcref actualArgTys + + ty, tpenv and TcTypeOrMeasureAndRecover optKind cenv newOk checkCxs occ env tpenv ty = try TcTypeOrMeasure optKind cenv newOk checkCxs occ env tpenv ty diff --git a/src/fsharp/import.fs b/src/fsharp/import.fs index 8b0a8534a8..06458f3276 100644 --- a/src/fsharp/import.fs +++ b/src/fsharp/import.fs @@ -151,7 +151,7 @@ let CanImportILTypeRef (env:ImportMap) m (tref:ILTypeRef) = /// Prefer the F# abbreviation for some built-in types, e.g. 'string' rather than /// 'System.String', since we prefer the F# abbreviation to the .NET equivalents. let ImportTyconRefApp (env:ImportMap) tcref tyargs = - match env.g.better_tcref_map tcref tyargs with + match env.g.betterTyconRefMap tcref tyargs with | Some res -> res | None -> TType_app (tcref,tyargs) diff --git a/tests/fsharp/tests.fs b/tests/fsharp/tests.fs index 585c5620b0..e0ec951165 100644 --- a/tests/fsharp/tests.fs +++ b/tests/fsharp/tests.fs @@ -1671,6 +1671,14 @@ module TypecheckTests = #endif #if !FSHARP_SUITE_DRIVES_CORECLR_TESTS + [] + let ``sigs pos27`` () = + let cfg = testConfig "typecheck/sigs" + fsc cfg "%s --target:exe -o:pos27.exe" cfg.fsc_flags ["pos27.fs"] + copy_y cfg (cfg.FSCBinPath ++ "System.ValueTuple.dll") ("." ++ "System.ValueTuple.dll") + + peverify cfg "pos27.exe" + [] let ``sigs pos26`` () = let cfg = testConfig "typecheck/sigs" diff --git a/tests/fsharp/typecheck/sigs/neg23.bsl b/tests/fsharp/typecheck/sigs/neg23.bsl index 6e818ff820..9b473fd24a 100644 --- a/tests/fsharp/typecheck/sigs/neg23.bsl +++ b/tests/fsharp/typecheck/sigs/neg23.bsl @@ -1,15 +1,15 @@ -neg23.fs(9,21,9,24): typecheck error FS0438: Duplicate method. The method 'Foo' has the same name and signature as another method in type 'DuplicateOverloadUpToErasure1.SomeClass' once tuples, functions, units of measure and/or provided types are erased. +neg23.fs(9,21,9,24): typecheck error FS0438: Duplicate method. The method 'Foo' has the same name and signature as another method in type 'DuplicateOverloadUpToErasure1.SomeClass'. -neg23.fs(7,21,7,24): typecheck error FS0438: Duplicate method. The method 'Foo' has the same name and signature as another method in type 'DuplicateOverloadUpToErasure1.SomeClass' once tuples, functions, units of measure and/or provided types are erased. +neg23.fs(7,21,7,24): typecheck error FS0438: Duplicate method. The method 'Foo' has the same name and signature as another method in type 'DuplicateOverloadUpToErasure1.SomeClass'. -neg23.fs(19,21,19,24): typecheck error FS0438: Duplicate method. The method 'Foo' has the same name and signature as another method in type 'DuplicateOverloadUpToErasure2.SomeClass' once tuples, functions, units of measure and/or provided types are erased. +neg23.fs(19,21,19,24): typecheck error FS0438: Duplicate method. The method 'Foo' has the same name and signature as another method in type 'DuplicateOverloadUpToErasure2.SomeClass'. -neg23.fs(17,21,17,24): typecheck error FS0438: Duplicate method. The method 'Foo' has the same name and signature as another method in type 'DuplicateOverloadUpToErasure2.SomeClass' once tuples, functions, units of measure and/or provided types are erased. +neg23.fs(17,21,17,24): typecheck error FS0438: Duplicate method. The method 'Foo' has the same name and signature as another method in type 'DuplicateOverloadUpToErasure2.SomeClass'. -neg23.fs(28,21,28,24): typecheck error FS0438: Duplicate method. The method 'Foo' has the same name and signature as another method in type 'DuplicateOverloadUpToErasure3.SomeClass' once tuples, functions, units of measure and/or provided types are erased. +neg23.fs(28,21,28,24): typecheck error FS0438: Duplicate method. The method 'Foo' has the same name and signature as another method in type 'DuplicateOverloadUpToErasure3.SomeClass'. -neg23.fs(26,21,26,24): typecheck error FS0438: Duplicate method. The method 'Foo' has the same name and signature as another method in type 'DuplicateOverloadUpToErasure3.SomeClass' once tuples, functions, units of measure and/or provided types are erased. +neg23.fs(26,21,26,24): typecheck error FS0438: Duplicate method. The method 'Foo' has the same name and signature as another method in type 'DuplicateOverloadUpToErasure3.SomeClass'. neg23.fs(55,21,55,24): typecheck error FS0438: Duplicate method. The method 'Foo' has the same name and signature as another method in type 'DuplicateOverloadUpToErasure6.SomeClass' once tuples, functions, units of measure and/or provided types are erased. diff --git a/tests/fsharp/typecheck/sigs/pos27.fs b/tests/fsharp/typecheck/sigs/pos27.fs new file mode 100644 index 0000000000..554e8d8a95 --- /dev/null +++ b/tests/fsharp/typecheck/sigs/pos27.fs @@ -0,0 +1,25 @@ +module Pos27 + +module TUple = + let x1: System.Tuple = System.Tuple.Create(1) + let x2: System.Tuple = System.Tuple.Create(1,2) + let x3: System.Tuple = System.Tuple.Create(1,2,3) + let x4: System.Tuple = System.Tuple.Create(1,2,3,4) + let x5: System.Tuple = System.Tuple.Create(1,2,3,4,5) + let x6: System.Tuple = System.Tuple.Create(1,2,3,4,5,6) + let x7: System.Tuple = System.Tuple.Create(1,2,3,4,5,6,7) + let x9: System.Tuple> = System.Tuple.Create(1,2,3,4,5,6,7,8) + +module ValueTuple = + let x1: System.ValueTuple = System.ValueTuple.Create(1) + let x2: System.ValueTuple = System.ValueTuple.Create(1,2) + let x3: System.ValueTuple = System.ValueTuple.Create(1,2,3) + let x4: System.ValueTuple = System.ValueTuple.Create(1,2,3,4) + let x5: System.ValueTuple = System.ValueTuple.Create(1,2,3,4,5) + let x6: System.ValueTuple = System.ValueTuple.Create(1,2,3,4,5,6) + let x7: System.ValueTuple = System.ValueTuple.Create(1,2,3,4,5,6,7) + let x9: System.ValueTuple> = System.ValueTuple.Create(1,2,3,4,5,6,7,8) + +module FSharpFunc = + let x1: FSharpFunc = (fun x -> x + 1) + let x2: FSharpFunc> = (fun x y -> x + 1 + y) diff --git a/tests/fsharpqa/Source/Conformance/DeclarationElements/MemberDefinitions/OverloadingMembers/E_InferredTypeNotUnique01.fs b/tests/fsharpqa/Source/Conformance/DeclarationElements/MemberDefinitions/OverloadingMembers/E_InferredTypeNotUnique01.fs index ade29cda4c..5485583a4a 100644 --- a/tests/fsharpqa/Source/Conformance/DeclarationElements/MemberDefinitions/OverloadingMembers/E_InferredTypeNotUnique01.fs +++ b/tests/fsharpqa/Source/Conformance/DeclarationElements/MemberDefinitions/OverloadingMembers/E_InferredTypeNotUnique01.fs @@ -1,6 +1,6 @@ // #Regression #Conformance #DeclarationElements #MemberDefinitions #Overloading // Regression test for FSharp1.0:3762 - Using FastFunc explicitly is not differentiate from function types, thus causing compiler to create bad method tables, maybe other problems -//Duplicate method\. The method 'Foo' has the same name and signature as another method in type 'SomeClass' once tuples, functions, units of measure and/or provided types are erased\. +//Duplicate method\. The method 'Foo' has the same name and signature as another method in type 'SomeClass'\. // Note: as of Beta2, FastFunc became FSharpFunc type SomeClass() =