From e88de601f3fead9d7185781a9c7b05d53086cbf4 Mon Sep 17 00:00:00 2001 From: Lincoln Atkinson Date: Thu, 7 Apr 2016 00:31:47 -0700 Subject: [PATCH 001/129] Implement CallerLineInfo for F#-style optional args --- src/fsharp/ConstraintSolver.fs | 4 ++-- src/fsharp/NicePrint.fs | 2 +- src/fsharp/PostInferenceChecks.fs | 14 ++++++++++++-- src/fsharp/TcGlobals.fs | 5 ++++- src/fsharp/TypeChecker.fs | 16 ++++++++++------ src/fsharp/TypeRelations.fs | 7 +++++-- src/fsharp/infos.fs | 29 ++++++++++++++++++++--------- 7 files changed, 54 insertions(+), 23 deletions(-) diff --git a/src/fsharp/ConstraintSolver.fs b/src/fsharp/ConstraintSolver.fs index eeb87a4b7b1..04e5a825e26 100644 --- a/src/fsharp/ConstraintSolver.fs +++ b/src/fsharp/ConstraintSolver.fs @@ -1849,7 +1849,7 @@ and CanMemberSigsMatchUpToCheck if isArray1DTy g calledArg.CalledArgumentType then let paramArrayElemTy = destArrayTy g calledArg.CalledArgumentType let reflArgInfo = calledArg.ReflArgInfo // propgate the reflected-arg info to each param array argument - calledMeth.ParamArrayCallerArgs |> OptionD (IterateD (fun callerArg -> subsumeArg (CalledArg((0,0),false,NotOptional,false,None,reflArgInfo,paramArrayElemTy)) callerArg)) + calledMeth.ParamArrayCallerArgs |> OptionD (IterateD (fun callerArg -> subsumeArg (CalledArg((0,0),false,NotOptional,NoCallerInfo,false,None,reflArgInfo,paramArrayElemTy)) callerArg)) else CompleteD) @@ -1872,7 +1872,7 @@ and CanMemberSigsMatchUpToCheck let calledArgTy = rfinfo.FieldType rfinfo.Name, calledArgTy - subsumeArg (CalledArg((-1, 0), false, NotOptional, false, Some (mkSynId m name), ReflectedArgInfo.None, calledArgTy)) caller) )) ++ (fun () -> + subsumeArg (CalledArg((-1, 0), false, NotOptional, NoCallerInfo, false, Some (mkSynId m name), ReflectedArgInfo.None, calledArgTy)) caller) )) ++ (fun () -> // - Always take the return type into account for // -- op_Explicit, op_Implicit diff --git a/src/fsharp/NicePrint.fs b/src/fsharp/NicePrint.fs index 0705d0eeae2..a9b829834c6 100755 --- a/src/fsharp/NicePrint.fs +++ b/src/fsharp/NicePrint.fs @@ -1194,7 +1194,7 @@ module InfoMemberPrinting = /// Format the arguments of a method to a buffer. /// /// This uses somewhat "old fashioned" printf-style buffer printing. - let formatParamDataToBuffer denv os (ParamData(isParamArray, _isOutArg, optArgInfo, nmOpt, _reflArgInfo, pty)) = + let formatParamDataToBuffer denv os (ParamData(isParamArray, _isOutArg, optArgInfo, _callerInfoInfo, nmOpt, _reflArgInfo, pty)) = let isOptArg = optArgInfo.IsOptional match isParamArray, nmOpt, isOptArg, tryDestOptionTy denv.g pty with // Layout an optional argument diff --git a/src/fsharp/PostInferenceChecks.fs b/src/fsharp/PostInferenceChecks.fs index 8ab4f90b485..1de489a19ba 100644 --- a/src/fsharp/PostInferenceChecks.fs +++ b/src/fsharp/PostInferenceChecks.fs @@ -1315,10 +1315,20 @@ let CheckEntityDefn cenv env (tycon:Entity) = if minfo.NumArgs.Length > 1 && (minfo.GetParamDatas(cenv.amap, m, minfo.FormalMethodInst) - |> List.existsSquared (fun (ParamData(isParamArrayArg, isOutArg, optArgInfo, _, reflArgInfo, ty)) -> - isParamArrayArg || isOutArg || reflArgInfo.AutoQuote || optArgInfo.IsOptional || isByrefTy cenv.g ty)) then + |> List.existsSquared (fun (ParamData(isParamArrayArg, isOutArg, optArgInfo, callerInfoInfo, _, reflArgInfo, ty)) -> + isParamArrayArg || isOutArg || reflArgInfo.AutoQuote || optArgInfo.IsOptional || callerInfoInfo <> NoCallerInfo || isByrefTy cenv.g ty)) then errorR(Error(FSComp.SR.chkCurriedMethodsCantHaveOutParams(), m)) + if minfo.NumArgs.Length = 1 then + minfo.GetParamDatas(cenv.amap, m, minfo.FormalMethodInst) + |> List.iterSquared (fun (ParamData(_, _, optArgInfo, callerInfoInfo, _, _, ty)) -> + match (optArgInfo, callerInfoInfo) with + | _, NoCallerInfo + | CallerSide(_), CallerLineNumber when (typeEquiv cenv.g cenv.g.int32_ty ty) -> () + | CalleeSide, CallerLineNumber when (isOptionTy cenv.g ty) && (typeEquiv cenv.g cenv.g.int32_ty (destOptionTy cenv.g ty)) -> () + | _ -> errorR(Error((1234, "Bogus caller info definition"), m)) + ) + for pinfo in immediateProps do let nm = pinfo.PropertyName let m = (match pinfo.ArbitraryValRef with None -> m | Some vref -> vref.DefinitionRange) diff --git a/src/fsharp/TcGlobals.fs b/src/fsharp/TcGlobals.fs index b9174acb89b..c99f8c27f12 100755 --- a/src/fsharp/TcGlobals.fs +++ b/src/fsharp/TcGlobals.fs @@ -300,6 +300,8 @@ type public TcGlobals = attrib_PreserveSigAttribute : BuiltinAttribInfo option attrib_MethodImplAttribute : BuiltinAttribInfo attrib_ExtensionAttribute : BuiltinAttribInfo + attrib_CallerLineNumberAttribute : BuiltinAttribInfo + tcref_System_Collections_Generic_IList : TyconRef tcref_System_Collections_Generic_IReadOnlyList : TyconRef tcref_System_Collections_Generic_ICollection : TyconRef @@ -1202,7 +1204,8 @@ let mkTcGlobals (compilingFslib,sysCcu,ilg,fslibCcu,directoryToResolveRelativePa attrib_PreserveSigAttribute = mkSystemRuntimeInteropServicesAttribute "System.Runtime.InteropServices.PreserveSigAttribute" attrib_MethodImplAttribute = mkSystemRuntimeAttrib "System.Runtime.CompilerServices.MethodImplAttribute" attrib_ExtensionAttribute = mkSystemRuntimeAttrib "System.Runtime.CompilerServices.ExtensionAttribute" - + attrib_CallerLineNumberAttribute = mkSystemRuntimeAttrib "System.Runtime.CompilerServices.CallerLineNumberAttribute" + attrib_ProjectionParameterAttribute = mk_MFCore_attrib "ProjectionParameterAttribute" attrib_CustomOperationAttribute = mk_MFCore_attrib "CustomOperationAttribute" attrib_NonSerializedAttribute = if ilg.traits.NonSerializedAttributeScopeRef.IsSome then Some(mkSystemRuntimeAttrib "System.NonSerializedAttribute") else None diff --git a/src/fsharp/TypeChecker.fs b/src/fsharp/TypeChecker.fs index 96022bb7da0..574094ac821 100755 --- a/src/fsharp/TypeChecker.fs +++ b/src/fsharp/TypeChecker.fs @@ -8680,7 +8680,7 @@ and TcMethodApplication let denv = env.DisplayEnv - let isSimpleFormalArg (isParamArrayArg, isOutArg, optArgInfo: OptionalArgInfo, _reflArgInfo: ReflectedArgInfo) = + let isSimpleFormalArg (isParamArrayArg, isOutArg, optArgInfo: OptionalArgInfo, _callerInfoInfo: CallerInfoInfo, _reflArgInfo: ReflectedArgInfo) = not isParamArrayArg && not isOutArg && not optArgInfo.IsOptional let callerObjArgTys = objArgs |> List.map (tyOfExpr cenv.g) @@ -9040,7 +9040,7 @@ and TcMethodApplication if HasHeadType cenv.g cenv.g.tcref_System_Collections_Generic_Dictionary finalCalledMethInfo.EnclosingType && finalCalledMethInfo.IsConstructor && not (finalCalledMethInfo.GetParamDatas(cenv.amap, mItem, finalCalledMeth.CallerTyArgs) - |> List.existsSquared (fun (ParamData(_,_,_,_,_,ty)) -> + |> List.existsSquared (fun (ParamData(_,_,_,_,_,_,ty)) -> HasHeadType cenv.g cenv.g.tcref_System_Collections_Generic_IEqualityComparer ty)) then match argsOfAppTy cenv.g finalCalledMethInfo.EnclosingType with @@ -9191,13 +9191,18 @@ and TcMethodApplication let wrapper2,rhs = build currCalledArgTy dfltVal2 (wrapper2 >> mkCompGenLet mMethExpr v rhs), mkValAddr mMethExpr (mkLocalValRef v) build calledArgTy dfltVal - | CalleeSide -> + | CalleeSide -> let calledNonOptTy = if isOptionTy cenv.g calledArgTy then destOptionTy cenv.g calledArgTy else calledArgTy // should be unreachable - emptyPreBinder,mkUnionCaseExpr(mkNoneCase cenv.g,[calledNonOptTy],[],mMethExpr) + + match calledArg.CallerInfoInfo with + | CallerLineNumber when typeEquiv cenv.g calledNonOptTy cenv.g.int_ty -> + let lineExpr = Expr.Const(Const.Int32(mMethExpr.StartLine), mMethExpr, calledNonOptTy) + emptyPreBinder,mkUnionCaseExpr(mkSomeCase cenv.g,[calledNonOptTy],[lineExpr],mMethExpr) + | _ -> emptyPreBinder,mkUnionCaseExpr(mkNoneCase cenv.g,[calledNonOptTy],[],mMethExpr) // Combine the variable allocators (if any) let wrapper = (wrapper >> wrapper2) @@ -9207,12 +9212,11 @@ and TcMethodApplication // Handle optional arguments let wrapOptionalArg (assignedArg: AssignedCalledArg<_>) = - let (CallerArg(callerArgTy,m,isOptCallerArg,expr)) = assignedArg.CallerArg + let (CallerArg(callerArgTy,m,isOptCallerArg,expr)) = assignedArg.CallerArg match assignedArg.CalledArg.OptArgInfo with | NotOptional -> if isOptCallerArg then errorR(Error(FSComp.SR.tcFormalArgumentIsNotOptional(),m)) assignedArg - | _ -> let expr = match assignedArg.CalledArg.OptArgInfo with diff --git a/src/fsharp/TypeRelations.fs b/src/fsharp/TypeRelations.fs index 443ae5812c6..46a7090f15b 100755 --- a/src/fsharp/TypeRelations.fs +++ b/src/fsharp/TypeRelations.fs @@ -1517,15 +1517,17 @@ type CalledArg = { Position: (int * int) IsParamArray : bool OptArgInfo : OptionalArgInfo + CallerInfoInfo : CallerInfoInfo IsOutArg: bool ReflArgInfo: ReflectedArgInfo NameOpt: Ident option CalledArgumentType : TType } -let CalledArg(pos,isParamArray,optArgInfo,isOutArg,nameOpt,reflArgInfo,calledArgTy) = +let CalledArg(pos,isParamArray,optArgInfo,callerInfoInfo,isOutArg,nameOpt,reflArgInfo,calledArgTy) = { Position=pos IsParamArray=isParamArray OptArgInfo =optArgInfo + CallerInfoInfo = callerInfoInfo IsOutArg=isOutArg ReflArgInfo=reflArgInfo NameOpt=nameOpt @@ -1653,10 +1655,11 @@ type CalledMethArgSet<'T> = let MakeCalledArgs amap m (minfo:MethInfo) minst = // Mark up the arguments with their position, so we can sort them back into order later let paramDatas = minfo.GetParamDatas(amap, m, minst) - paramDatas |> List.mapiSquared (fun i j (ParamData(isParamArrayArg,isOutArg,optArgInfo,nmOpt,reflArgInfo,typeOfCalledArg)) -> + paramDatas |> List.mapiSquared (fun i j (ParamData(isParamArrayArg,isOutArg,optArgInfo,callerInfoFlags,nmOpt,reflArgInfo,typeOfCalledArg)) -> { Position=(i,j) IsParamArray=isParamArrayArg OptArgInfo=optArgInfo + CallerInfoInfo=callerInfoFlags IsOutArg=isOutArg ReflArgInfo=reflArgInfo NameOpt=nmOpt diff --git a/src/fsharp/infos.fs b/src/fsharp/infos.fs index 3d685ecab50..f8b9ba411ea 100755 --- a/src/fsharp/infos.fs +++ b/src/fsharp/infos.fs @@ -513,6 +513,12 @@ type OptionalArgInfo = else NotOptional +type CallerInfoInfo = + | NoCallerInfo + | CallerLineNumber + | CallerMemberName + | CallerFilePath + [] type ReflectedArgInfo = | None @@ -535,8 +541,8 @@ type ParamNameAndType = [] /// Full information about a parameter returned for use by the type checker and language service. type ParamData = - /// ParamData(isParamArray, isOut, optArgInfo, nameOpt, reflArgInfo, ttype) - ParamData of bool * bool * OptionalArgInfo * Ident option * ReflectedArgInfo * TType + /// ParamData(isParamArray, isOut, optArgInfo, callerInfoInfo, nameOpt, reflArgInfo, ttype) + ParamData of bool * bool * OptionalArgInfo * CallerInfoInfo * Ident option * ReflectedArgInfo * TType //------------------------------------------------------------------------- @@ -1271,8 +1277,11 @@ type MethInfo = | _ -> ReflectedArgInfo.None let isOutArg = (p.IsOut && not p.IsIn) // Note: we get default argument values from VB and other .NET language metadata - let optArgInfo = OptionalArgInfo.FromILParameter g amap m ilMethInfo.MetadataScope ilMethInfo.DeclaringTypeInst p - yield (isParamArrayArg, isOutArg, optArgInfo, reflArgInfo) ] ] + let optArgInfo = OptionalArgInfo.FromILParameter g amap m ilMethInfo.MetadataScope ilMethInfo.DeclaringTypeInst p + let isCallerLineNumberArg = TryFindILAttribute g.attrib_CallerLineNumberAttribute p.CustomAttrs + let callerInfoInfo = if isCallerLineNumberArg then CallerLineNumber else NoCallerInfo + + yield (isParamArrayArg, isOutArg, optArgInfo, callerInfoInfo, reflArgInfo) ] ] | FSMeth(g,_,vref,_) -> GetArgInfosOfMember x.IsCSharpStyleExtensionMember g vref @@ -1286,7 +1295,9 @@ type MethInfo = let isOptArg = HasFSharpAttribute g g.attrib_OptionalArgumentAttribute argInfo.Attribs // Note: can't specify caller-side default arguments in F#, by design (default is specified on the callee-side) let optArgInfo = if isOptArg then CalleeSide else NotOptional - (isParamArrayArg, isOutArg, optArgInfo, reflArgInfo)) + let isCallerLineNumberArg = HasFSharpAttribute g g.attrib_CallerLineNumberAttribute argInfo.Attribs + let callerInfoInfo = if isCallerLineNumberArg then CallerLineNumber else NoCallerInfo + (isParamArrayArg, isOutArg, optArgInfo, callerInfoInfo, reflArgInfo)) | DefaultStructCtor _ -> [[]] @@ -1302,7 +1313,7 @@ type MethInfo = | Some ([ Some (:? bool as b) ], _) -> ReflectedArgInfo.Quote b | Some _ -> ReflectedArgInfo.Quote false | None -> ReflectedArgInfo.None - yield (isParamArrayArg, p.PUntaint((fun p -> p.IsOut), m), optArgInfo, reflArgInfo)] ] + yield (isParamArrayArg, p.PUntaint((fun p -> p.IsOut), m), optArgInfo, NoCallerInfo, reflArgInfo)] ] #endif @@ -1401,8 +1412,8 @@ type MethInfo = #endif let paramAttribs = x.GetParamAttribs(amap, m) - (paramAttribs,paramNamesAndTypes) ||> List.map2 (List.map2 (fun (isParamArrayArg,isOutArg,optArgInfo,reflArgInfo) (ParamNameAndType(nmOpt,pty)) -> - ParamData(isParamArrayArg,isOutArg,optArgInfo,nmOpt,reflArgInfo,pty))) + (paramAttribs,paramNamesAndTypes) ||> List.map2 (List.map2 (fun (isParamArrayArg,isOutArg,optArgInfo,callerInfoInfo,reflArgInfo) (ParamNameAndType(nmOpt,pty)) -> + ParamData(isParamArrayArg,isOutArg,optArgInfo,callerInfoInfo,nmOpt,reflArgInfo,pty))) /// Select all the type parameters of the declaring type of a method. @@ -1927,7 +1938,7 @@ type PropInfo = /// Get the details of the indexer parameters associated with the property member x.GetParamDatas(amap,m) = x.GetParamNamesAndTypes(amap,m) - |> List.map (fun (ParamNameAndType(nmOpt,pty)) -> ParamData(false, false, NotOptional, nmOpt, ReflectedArgInfo.None, pty)) + |> List.map (fun (ParamNameAndType(nmOpt,pty)) -> ParamData(false, false, NotOptional, NoCallerInfo, nmOpt, ReflectedArgInfo.None, pty)) /// Get the types of the indexer parameters associated with the property member x.GetParamTypes(amap,m) = From f4f6bf926a5260ed730167c5381270e49494abd0 Mon Sep 17 00:00:00 2001 From: Lincoln Atkinson Date: Thu, 7 Apr 2016 10:06:52 -0700 Subject: [PATCH 002/129] Fix incorrect when guard in bogus args check --- src/fsharp/PostInferenceChecks.fs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/fsharp/PostInferenceChecks.fs b/src/fsharp/PostInferenceChecks.fs index 1de489a19ba..6cc8298b27e 100644 --- a/src/fsharp/PostInferenceChecks.fs +++ b/src/fsharp/PostInferenceChecks.fs @@ -1310,24 +1310,25 @@ let CheckEntityDefn cenv env (tycon:Entity) = else errorR(Error(FSComp.SR.chkDuplicateMethodWithSuffix(nm),m)) - if minfo.NumArgs.Length > 1 && others |> List.exists (fun minfo2 -> not (IsAbstractDefaultPair2 minfo minfo2)) then + let numCurriedArgSets = minfo.NumArgs.Length + + if numCurriedArgSets > 1 && others |> List.exists (fun minfo2 -> not (IsAbstractDefaultPair2 minfo minfo2)) then errorR(Error(FSComp.SR.chkDuplicateMethodCurried nm,m)) - if minfo.NumArgs.Length > 1 && + if numCurriedArgSets > 1 && (minfo.GetParamDatas(cenv.amap, m, minfo.FormalMethodInst) |> List.existsSquared (fun (ParamData(isParamArrayArg, isOutArg, optArgInfo, callerInfoInfo, _, reflArgInfo, ty)) -> isParamArrayArg || isOutArg || reflArgInfo.AutoQuote || optArgInfo.IsOptional || callerInfoInfo <> NoCallerInfo || isByrefTy cenv.g ty)) then errorR(Error(FSComp.SR.chkCurriedMethodsCantHaveOutParams(), m)) - if minfo.NumArgs.Length = 1 then + if numCurriedArgSets = 1 then minfo.GetParamDatas(cenv.amap, m, minfo.FormalMethodInst) |> List.iterSquared (fun (ParamData(_, _, optArgInfo, callerInfoInfo, _, _, ty)) -> match (optArgInfo, callerInfoInfo) with - | _, NoCallerInfo + | _, NoCallerInfo -> () | CallerSide(_), CallerLineNumber when (typeEquiv cenv.g cenv.g.int32_ty ty) -> () | CalleeSide, CallerLineNumber when (isOptionTy cenv.g ty) && (typeEquiv cenv.g cenv.g.int32_ty (destOptionTy cenv.g ty)) -> () - | _ -> errorR(Error((1234, "Bogus caller info definition"), m)) - ) + | _ -> errorR(Error((1234, "Bogus caller info definition"), m))) for pinfo in immediateProps do let nm = pinfo.PropertyName From 445887af8dd89897af315554d0d654f732a633d5 Mon Sep 17 00:00:00 2001 From: Lincoln Atkinson Date: Thu, 7 Apr 2016 14:03:34 -0700 Subject: [PATCH 003/129] Support CallerLineInfo for C#-style caller-side optional args --- src/fsharp/TypeChecker.fs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/fsharp/TypeChecker.fs b/src/fsharp/TypeChecker.fs index 574094ac821..db22e4cbf24 100755 --- a/src/fsharp/TypeChecker.fs +++ b/src/fsharp/TypeChecker.fs @@ -9169,7 +9169,12 @@ and TcMethodApplication | ByrefTy cenv.g inst -> build inst (PassByRef(inst, currDfltVal)) | _ -> - emptyPreBinder,Expr.Const(TcFieldInit mMethExpr fieldInit,mMethExpr,currCalledArgTy) + match calledArg.CallerInfoInfo with + | CallerLineNumber when typeEquiv cenv.g currCalledArgTy cenv.g.int_ty -> + emptyPreBinder,Expr.Const(Const.Int32(mMethExpr.StartLine), mMethExpr, currCalledArgTy) + | _ -> + emptyPreBinder,Expr.Const(TcFieldInit mMethExpr fieldInit,mMethExpr,currCalledArgTy) + | WrapperForIDispatch -> match cenv.g.ilg.traits.SystemRuntimeInteropServicesScopeRef.Value with | None -> error(Error(FSComp.SR.fscSystemRuntimeInteropServicesIsRequired(), mMethExpr)) From fb16599c302187e332a859c98d5729a7e994ce78 Mon Sep 17 00:00:00 2001 From: "Avi.Avni" Date: Fri, 8 Apr 2016 01:23:59 +0300 Subject: [PATCH 004/129] implement CallerFilePath --- src/fsharp/PostInferenceChecks.fs | 2 ++ src/fsharp/TcGlobals.fs | 2 ++ src/fsharp/TypeChecker.fs | 5 +++++ src/fsharp/infos.fs | 3 ++- 4 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/fsharp/PostInferenceChecks.fs b/src/fsharp/PostInferenceChecks.fs index 6cc8298b27e..1e9bc81204e 100644 --- a/src/fsharp/PostInferenceChecks.fs +++ b/src/fsharp/PostInferenceChecks.fs @@ -1328,6 +1328,8 @@ let CheckEntityDefn cenv env (tycon:Entity) = | _, NoCallerInfo -> () | CallerSide(_), CallerLineNumber when (typeEquiv cenv.g cenv.g.int32_ty ty) -> () | CalleeSide, CallerLineNumber when (isOptionTy cenv.g ty) && (typeEquiv cenv.g cenv.g.int32_ty (destOptionTy cenv.g ty)) -> () + | CallerSide(_), CallerFilePath when (typeEquiv cenv.g cenv.g.string_ty ty) -> () + | CalleeSide, CallerFilePath when (isOptionTy cenv.g ty) && (typeEquiv cenv.g cenv.g.string_ty (destOptionTy cenv.g ty)) -> () | _ -> errorR(Error((1234, "Bogus caller info definition"), m))) for pinfo in immediateProps do diff --git a/src/fsharp/TcGlobals.fs b/src/fsharp/TcGlobals.fs index c99f8c27f12..2a9b7a496f0 100755 --- a/src/fsharp/TcGlobals.fs +++ b/src/fsharp/TcGlobals.fs @@ -301,6 +301,7 @@ type public TcGlobals = attrib_MethodImplAttribute : BuiltinAttribInfo attrib_ExtensionAttribute : BuiltinAttribInfo attrib_CallerLineNumberAttribute : BuiltinAttribInfo + attrib_CallerFilePathAttribute : BuiltinAttribInfo tcref_System_Collections_Generic_IList : TyconRef tcref_System_Collections_Generic_IReadOnlyList : TyconRef @@ -1205,6 +1206,7 @@ let mkTcGlobals (compilingFslib,sysCcu,ilg,fslibCcu,directoryToResolveRelativePa attrib_MethodImplAttribute = mkSystemRuntimeAttrib "System.Runtime.CompilerServices.MethodImplAttribute" attrib_ExtensionAttribute = mkSystemRuntimeAttrib "System.Runtime.CompilerServices.ExtensionAttribute" attrib_CallerLineNumberAttribute = mkSystemRuntimeAttrib "System.Runtime.CompilerServices.CallerLineNumberAttribute" + attrib_CallerFilePathAttribute = mkSystemRuntimeAttrib "System.Runtime.CompilerServices.CallerFilePathAttribute" attrib_ProjectionParameterAttribute = mk_MFCore_attrib "ProjectionParameterAttribute" attrib_CustomOperationAttribute = mk_MFCore_attrib "CustomOperationAttribute" diff --git a/src/fsharp/TypeChecker.fs b/src/fsharp/TypeChecker.fs index db22e4cbf24..835dd2fdb8d 100755 --- a/src/fsharp/TypeChecker.fs +++ b/src/fsharp/TypeChecker.fs @@ -9172,6 +9172,8 @@ and TcMethodApplication match calledArg.CallerInfoInfo with | CallerLineNumber when typeEquiv cenv.g currCalledArgTy cenv.g.int_ty -> emptyPreBinder,Expr.Const(Const.Int32(mMethExpr.StartLine), mMethExpr, currCalledArgTy) + | CallerFilePath when typeEquiv cenv.g currCalledArgTy cenv.g.string_ty -> + emptyPreBinder,Expr.Const(Const.String(mMethExpr.FileName), mMethExpr, currCalledArgTy) | _ -> emptyPreBinder,Expr.Const(TcFieldInit mMethExpr fieldInit,mMethExpr,currCalledArgTy) @@ -9207,6 +9209,9 @@ and TcMethodApplication | CallerLineNumber when typeEquiv cenv.g calledNonOptTy cenv.g.int_ty -> let lineExpr = Expr.Const(Const.Int32(mMethExpr.StartLine), mMethExpr, calledNonOptTy) emptyPreBinder,mkUnionCaseExpr(mkSomeCase cenv.g,[calledNonOptTy],[lineExpr],mMethExpr) + | CallerFilePath when typeEquiv cenv.g calledNonOptTy cenv.g.string_ty -> + let filePathExpr = Expr.Const(Const.String(mMethExpr.FileName), mMethExpr, calledNonOptTy) + emptyPreBinder,mkUnionCaseExpr(mkSomeCase cenv.g,[calledNonOptTy],[filePathExpr],mMethExpr) | _ -> emptyPreBinder,mkUnionCaseExpr(mkNoneCase cenv.g,[calledNonOptTy],[],mMethExpr) // Combine the variable allocators (if any) diff --git a/src/fsharp/infos.fs b/src/fsharp/infos.fs index f8b9ba411ea..9a0fc58f855 100755 --- a/src/fsharp/infos.fs +++ b/src/fsharp/infos.fs @@ -1296,7 +1296,8 @@ type MethInfo = // Note: can't specify caller-side default arguments in F#, by design (default is specified on the callee-side) let optArgInfo = if isOptArg then CalleeSide else NotOptional let isCallerLineNumberArg = HasFSharpAttribute g g.attrib_CallerLineNumberAttribute argInfo.Attribs - let callerInfoInfo = if isCallerLineNumberArg then CallerLineNumber else NoCallerInfo + let isCallerFilePathArg = HasFSharpAttribute g g.attrib_CallerFilePathAttribute argInfo.Attribs + let callerInfoInfo = if isCallerLineNumberArg then CallerLineNumber elif isCallerFilePathArg then CallerFilePath else NoCallerInfo (isParamArrayArg, isOutArg, optArgInfo, callerInfoInfo, reflArgInfo)) | DefaultStructCtor _ -> From 4999c7e9f81d1825bb66d44b0bf7d17ad32a3ac2 Mon Sep 17 00:00:00 2001 From: Lincoln Atkinson Date: Thu, 14 Apr 2016 09:53:35 -0700 Subject: [PATCH 005/129] Add simple test for CallerLineNumber --- .../Imported/CallerInfo/CallerLineNumber.fs | 14 ++++++++++++++ .../Imported/CallerInfo/env.lst | 2 ++ tests/fsharpqa/Source/test.lst | 1 + 3 files changed, 17 insertions(+) create mode 100644 tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerLineNumber.fs create mode 100644 tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/env.lst diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerLineNumber.fs b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerLineNumber.fs new file mode 100644 index 00000000000..259f8d12bb6 --- /dev/null +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerLineNumber.fs @@ -0,0 +1,14 @@ +namespace Test + +open System.Runtime.CompilerServices + +type MyTy() = + static member GetCallerLineNumber([] ?line : int) = + line + +module Program = + [] + let main (_:string[]) = + match MyTy.GetCallerLineNumber() with + | Some(12) -> 0 + | _ -> 1 diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/env.lst b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/env.lst new file mode 100644 index 00000000000..241d1ee66a5 --- /dev/null +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/env.lst @@ -0,0 +1,2 @@ + SOURCE=CallerLineNumber.fs SCFLAGS="--test:ErrorRanges" # CallerLineNumber.fs + diff --git a/tests/fsharpqa/Source/test.lst b/tests/fsharpqa/Source/test.lst index 624a477c9d2..d8afce454b2 100644 --- a/tests/fsharpqa/Source/test.lst +++ b/tests/fsharpqa/Source/test.lst @@ -224,6 +224,7 @@ Conformance08 Conformance\PatternMatching\Wildcard Conformance08 Conformance\Signatures\SignatureConformance Conformance08 Conformance\Signatures\SignatureTypes Conformance08 Conformance\SpecialAttributesAndTypes\Imported\System.ThreadStatic +Conformance08 Conformance\SpecialAttributesAndTypes\Imported\CallerInfo Conformance08 Conformance\TypesAndTypeConstraints\CheckingSyntacticTypes Conformance08 Conformance\TypesAndTypeConstraints\LogicalPropertiesOfTypes Conformance08 Conformance\TypesAndTypeConstraints\TypeConstraints From c9c54a13d3159827eef57f95ca58542a1f61e385 Mon Sep 17 00:00:00 2001 From: "Avi.Avni" Date: Fri, 15 Apr 2016 01:14:27 +0300 Subject: [PATCH 006/129] Add simple test for CallerFilePath --- .../Imported/CallerInfo/CallerFilePath.fs | 14 ++++++++++++++ .../Imported/CallerInfo/env.lst | 1 + 2 files changed, 15 insertions(+) create mode 100644 tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerFilePath.fs diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerFilePath.fs b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerFilePath.fs new file mode 100644 index 00000000000..80b093039e7 --- /dev/null +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerFilePath.fs @@ -0,0 +1,14 @@ +namespace Test + +open System.Runtime.CompilerServices + +type MyTy() = + static member GetCallerFilePath([] ?path : string) = + path + +module Program = + [] + let main (_:string[]) = + match MyTy.GetCallerFilePath() with + | Some(path) when path.EndsWith("Conformance\SpecialAttributesAndTypes\Imported\CallerInfo\CallerFilePath.fs") -> 0 + | _ -> 1 diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/env.lst b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/env.lst index 241d1ee66a5..8ef55b903c9 100644 --- a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/env.lst +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/env.lst @@ -1,2 +1,3 @@ SOURCE=CallerLineNumber.fs SCFLAGS="--test:ErrorRanges" # CallerLineNumber.fs + SOURCE=CallerFilePath.fs SCFLAGS="--test:ErrorRanges" # CallerFilePath.fs From 08224bcd6db32e46c4655564e2d9c82cc8b5282b Mon Sep 17 00:00:00 2001 From: "Avi.Avni" Date: Sat, 16 Apr 2016 23:07:12 +0300 Subject: [PATCH 007/129] add test for ignore the compiler value and add negativ tests --- .../Imported/CallerInfo/CallerFilePath.fs | 4 ++-- .../Imported/CallerInfo/CallerLineNumber.fs | 4 ++-- .../Imported/CallerInfo/E_CallerFilePath.fs | 12 ++++++++++++ .../Imported/CallerInfo/E_CallerLineNumber.fs | 12 ++++++++++++ .../Imported/CallerInfo/env.lst | 2 ++ 5 files changed, 30 insertions(+), 4 deletions(-) create mode 100644 tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/E_CallerFilePath.fs create mode 100644 tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/E_CallerLineNumber.fs diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerFilePath.fs b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerFilePath.fs index 80b093039e7..f28edf8a674 100644 --- a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerFilePath.fs +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerFilePath.fs @@ -9,6 +9,6 @@ type MyTy() = module Program = [] let main (_:string[]) = - match MyTy.GetCallerFilePath() with - | Some(path) when path.EndsWith("Conformance\SpecialAttributesAndTypes\Imported\CallerInfo\CallerFilePath.fs") -> 0 + match MyTy.GetCallerFilePath(), MyTy.GetCallerFilePath("42") with + | Some(path), Some("42") when path.EndsWith("Conformance\SpecialAttributesAndTypes\Imported\CallerInfo\CallerFilePath.fs") -> 0 | _ -> 1 diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerLineNumber.fs b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerLineNumber.fs index 259f8d12bb6..24a3ca209a0 100644 --- a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerLineNumber.fs +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerLineNumber.fs @@ -9,6 +9,6 @@ type MyTy() = module Program = [] let main (_:string[]) = - match MyTy.GetCallerLineNumber() with - | Some(12) -> 0 + match MyTy.GetCallerLineNumber(), MyTy.GetCallerLineNumber(42) with + | Some(12), Some(42) -> 0 | _ -> 1 diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/E_CallerFilePath.fs b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/E_CallerFilePath.fs new file mode 100644 index 00000000000..cdb317997b3 --- /dev/null +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/E_CallerFilePath.fs @@ -0,0 +1,12 @@ +//Bogus caller info definition +//Bogus caller info definition +namespace Test + +open System.Runtime.CompilerServices + +type MyTy() = + static member GetCallerFilePathNotString([] ?path : int) = + path + + static member GetCallerFilePathNotOptional([] path : string) = + path \ No newline at end of file diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/E_CallerLineNumber.fs b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/E_CallerLineNumber.fs new file mode 100644 index 00000000000..13ac4118ea8 --- /dev/null +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/E_CallerLineNumber.fs @@ -0,0 +1,12 @@ +//Bogus caller info definition +//Bogus caller info definition +namespace Test + +open System.Runtime.CompilerServices + +type MyTy() = + static member GetCallerLineNumberNotInt([] ?line : string) = + line + + static member GetCallerLineNumberNotOptional([] line : string) = + line \ No newline at end of file diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/env.lst b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/env.lst index 8ef55b903c9..5815e90e52e 100644 --- a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/env.lst +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/env.lst @@ -1,3 +1,5 @@ SOURCE=CallerLineNumber.fs SCFLAGS="--test:ErrorRanges" # CallerLineNumber.fs SOURCE=CallerFilePath.fs SCFLAGS="--test:ErrorRanges" # CallerFilePath.fs + SOURCE=E_CallerLineNumber.fs SCFLAGS="--test:ErrorRanges" # E_CallerLineNumber.fs + SOURCE=E_CallerFilePath.fs SCFLAGS="--test:ErrorRanges" # E_CallerFilePath.fs From d8662a3d93c5bf52d2bd8fc8d7330e8491922b5b Mon Sep 17 00:00:00 2001 From: Lincoln Atkinson Date: Mon, 18 Apr 2016 15:37:36 -0700 Subject: [PATCH 008/129] Escape backslashes --- .../Imported/CallerInfo/CallerFilePath.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerFilePath.fs b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerFilePath.fs index f28edf8a674..d7d5732ffc5 100644 --- a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerFilePath.fs +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerFilePath.fs @@ -10,5 +10,5 @@ module Program = [] let main (_:string[]) = match MyTy.GetCallerFilePath(), MyTy.GetCallerFilePath("42") with - | Some(path), Some("42") when path.EndsWith("Conformance\SpecialAttributesAndTypes\Imported\CallerInfo\CallerFilePath.fs") -> 0 + | Some(path), Some("42") when path.EndsWith("Conformance\\SpecialAttributesAndTypes\\Imported\\CallerInfo\\CallerFilePath.fs") -> 0 | _ -> 1 From 1ec094ffd6fd2697865c0935ba87a2750283da96 Mon Sep 17 00:00:00 2001 From: Lincoln Atkinson Date: Mon, 18 Apr 2016 16:17:00 -0700 Subject: [PATCH 009/129] Add tests covering C#-style optional parameters --- .../Imported/CallerInfo/CSharpLib.cs | 23 +++++++++++++ .../Imported/CallerInfo/CallerFilePath.fs | 33 +++++++++++++++++-- .../Imported/CallerInfo/CallerLineNumber.fs | 21 ++++++++++-- .../Imported/CallerInfo/env.lst | 4 +-- 4 files changed, 73 insertions(+), 8 deletions(-) create mode 100644 tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CSharpLib.cs diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CSharpLib.cs b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CSharpLib.cs new file mode 100644 index 00000000000..ee1c7d4f834 --- /dev/null +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CSharpLib.cs @@ -0,0 +1,23 @@ +using System; +using System.Runtime.CompilerServices; + +namespace CSharpLib +{ + public class CallerInfoTest + { + public static int LineNumber([CallerLineNumber] int line = 777) + { + return line; + } + + public static string FilePath([CallerFilePath] string filePath = "dummy1") + { + return filePath; + } + + public static Tuple AllInfo(int normalArg, [CallerFilePath] string filePath = "dummy2", [CallerLineNumber] int line = 778) + { + return new Tuple(filePath, line); + } + } +} \ No newline at end of file diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerFilePath.fs b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerFilePath.fs index d7d5732ffc5..f305304fff0 100644 --- a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerFilePath.fs +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerFilePath.fs @@ -1,14 +1,41 @@ namespace Test open System.Runtime.CompilerServices +open CSharpLib type MyTy() = static member GetCallerFilePath([] ?path : string) = path module Program = + let matchesPath path (s : string) = + s.EndsWith(path) + && not (s.Contains("\\\\")) + && not (path.Contains("\\.\\")) + && not (path.Contains("\\..\\")) + + [] let main (_:string[]) = - match MyTy.GetCallerFilePath(), MyTy.GetCallerFilePath("42") with - | Some(path), Some("42") when path.EndsWith("Conformance\\SpecialAttributesAndTypes\\Imported\\CallerInfo\\CallerFilePath.fs") -> 0 - | _ -> 1 + + match MyTy.GetCallerFilePath() with + | Some(path) when matchesPath "Conformance\\SpecialAttributesAndTypes\\Imported\\CallerInfo\\CallerFilePath.fs" path -> () + | x -> failwithf "Unexpected: %A" x + + match MyTy.GetCallerFilePath("42") with + | Some("42") -> () + | x -> failwithf "Unexpected: %A" x + + match CallerInfoTest.FilePath() with + | path when matchesPath "Conformance\\SpecialAttributesAndTypes\\Imported\\CallerInfo\\CallerFilePath.fs" path -> () + | x -> failwithf "Unexpected: %A" x + + match CallerInfoTest.FilePath("xyz") with + | "xyz" -> () + | x -> failwithf "Unexpected: %A" x + + match CallerInfoTest.AllInfo(21) with + | (path, _) when matchesPath "Conformance\\SpecialAttributesAndTypes\\Imported\\CallerInfo\\CallerFilePath.fs" path -> () + | x -> failwithf "Unexpected C# result with multiple parameter types: %A" x + + 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerLineNumber.fs b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerLineNumber.fs index 24a3ca209a0..f30d42dfba1 100644 --- a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerLineNumber.fs +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerLineNumber.fs @@ -1,6 +1,7 @@ namespace Test open System.Runtime.CompilerServices +open CSharpLib type MyTy() = static member GetCallerLineNumber([] ?line : int) = @@ -9,6 +10,20 @@ type MyTy() = module Program = [] let main (_:string[]) = - match MyTy.GetCallerLineNumber(), MyTy.GetCallerLineNumber(42) with - | Some(12), Some(42) -> 0 - | _ -> 1 + if MyTy.GetCallerLineNumber() <> Some(13) then + failwith "Unexpected F# CallerLineNumber" + + if MyTy.GetCallerLineNumber(42) <> Some(42) then + failwith "Unexpected F# CallerLineNumber" + + if CallerInfoTest.LineNumber() <> 19 then + failwith "Unexpected C# CallerLineNumber" + + if CallerInfoTest.LineNumber(88) <> 88 then + failwith "Unexpected C# CallerLineNumber" + + match CallerInfoTest.AllInfo(21) with + | (_, 25) -> () + | x -> failwithf "Unexpected C# result with multiple parameter types: %A" x + + 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/env.lst b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/env.lst index 5815e90e52e..bb430c0b586 100644 --- a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/env.lst +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/env.lst @@ -1,5 +1,5 @@ - SOURCE=CallerLineNumber.fs SCFLAGS="--test:ErrorRanges" # CallerLineNumber.fs - SOURCE=CallerFilePath.fs SCFLAGS="--test:ErrorRanges" # CallerFilePath.fs + SOURCE=CallerLineNumber.fs SCFLAGS="-r CSharpLib.dll --test:ErrorRanges" PRECMD="\$CSC_PIPE /t:library CSharpLib.cs" # CallerLineNumber.fs + SOURCE=CallerFilePath.fs SCFLAGS="-r CSharpLib.dll --test:ErrorRanges" PRECMD="\$CSC_PIPE /t:library CSharpLib.cs" # CallerFilePath.fs SOURCE=E_CallerLineNumber.fs SCFLAGS="--test:ErrorRanges" # E_CallerLineNumber.fs SOURCE=E_CallerFilePath.fs SCFLAGS="--test:ErrorRanges" # E_CallerFilePath.fs From e5ddc394f82ee3036207a916215a70d7a17ea586 Mon Sep 17 00:00:00 2001 From: Lincoln Atkinson Date: Mon, 18 Apr 2016 17:25:31 -0700 Subject: [PATCH 010/129] Update error reporting for caller info attributes --- src/fsharp/FSComp.txt | 4 +++- src/fsharp/PostInferenceChecks.fs | 19 ++++++++++++++----- src/fsharp/infos.fs | 7 +++++++ 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/fsharp/FSComp.txt b/src/fsharp/FSComp.txt index ab16418c8b9..e65b744a439 100644 --- a/src/fsharp/FSComp.txt +++ b/src/fsharp/FSComp.txt @@ -256,7 +256,7 @@ chkUnionCaseDefaultAugmentation,"default augmentation of the union case" 438,chkDuplicateMethod,"Duplicate method. The method '%s' has the same name and signature as another method in this type." 438,chkDuplicateMethodWithSuffix,"Duplicate method. The method '%s' has the same name and signature as another method in this type once tuples, functions, units of measure and/or provided types are erased." 439,chkDuplicateMethodCurried,"The method '%s' has curried arguments but has the same name as another method in this type. Methods with curried arguments cannot be overloaded. Consider using a method taking tupled arguments." -440,chkCurriedMethodsCantHaveOutParams,"Methods with curried arguments cannot declare 'out', 'ParamArray', 'optional', 'ReflectedDefinition' or 'byref' arguments" +440,chkCurriedMethodsCantHaveOutParams,"Methods with curried arguments cannot declare 'out', 'ParamArray', 'optional', 'ReflectedDefinition', 'byref', 'CallerLineNumber', or 'CallerFilePath' arguments" 441,chkDuplicateProperty,"Duplicate property. The property '%s' has the same name and signature as another property in this type." 441,chkDuplicatePropertyWithSuffix,"Duplicate property. The property '%s' has the same name and signature as another property in this type once tuples, functions, units of measure and/or provided types are erased." 442,chkDuplicateMethodInheritedType,"Duplicate method. The abstract method '%s' has the same name and signature as an abstract method in an inherited type." @@ -1063,6 +1063,8 @@ lexIndentOffForML,"Consider using a file with extension '.ml' or '.mli' instead" 1243,parsUnexpectedQuotationOperatorInTypeAliasDidYouMeanVerbatimString,"Unexpected quotation operator '<@' in type definition. If you intend to pass a verbatim string as a static argument to a type provider, put a space between the '<' and '@' characters." 1244,parsErrorParsingAsOperatorName,"Attempted to parse this as an operator name, but failed" 1245,lexInvalidUnicodeLiteral,"\U%s is not a valid Unicode character escape sequence" +1246,tcCallerInfoWrongType,"'%s' must be applied to an argument of type '%s', but has been applied to an argument of type '%s'" +1247,tcCallerInfoNotOptional,"'%s' can only be applied to optional arguments" # Fsc.exe resource strings fscTooManyErrors,"Exiting - too many errors" 2001,docfileNoXmlSuffix,"The documentation file has no .xml suffix" diff --git a/src/fsharp/PostInferenceChecks.fs b/src/fsharp/PostInferenceChecks.fs index 1e9bc81204e..872749a9dd0 100644 --- a/src/fsharp/PostInferenceChecks.fs +++ b/src/fsharp/PostInferenceChecks.fs @@ -1326,11 +1326,20 @@ let CheckEntityDefn cenv env (tycon:Entity) = |> List.iterSquared (fun (ParamData(_, _, optArgInfo, callerInfoInfo, _, _, ty)) -> match (optArgInfo, callerInfoInfo) with | _, NoCallerInfo -> () - | CallerSide(_), CallerLineNumber when (typeEquiv cenv.g cenv.g.int32_ty ty) -> () - | CalleeSide, CallerLineNumber when (isOptionTy cenv.g ty) && (typeEquiv cenv.g cenv.g.int32_ty (destOptionTy cenv.g ty)) -> () - | CallerSide(_), CallerFilePath when (typeEquiv cenv.g cenv.g.string_ty ty) -> () - | CalleeSide, CallerFilePath when (isOptionTy cenv.g ty) && (typeEquiv cenv.g cenv.g.string_ty (destOptionTy cenv.g ty)) -> () - | _ -> errorR(Error((1234, "Bogus caller info definition"), m))) + | NotOptional, _ -> errorR(Error(FSComp.SR.tcCallerInfoNotOptional(callerInfoInfo.ToString()),m)) + | CallerSide(_), CallerLineNumber -> + if not (typeEquiv cenv.g cenv.g.int32_ty ty) then + errorR(Error(FSComp.SR.tcCallerInfoWrongType(callerInfoInfo.ToString(), "int", NicePrint.minimalStringOfType cenv.denv ty),m)) + | CalleeSide, CallerLineNumber -> + if not ((isOptionTy cenv.g ty) && (typeEquiv cenv.g cenv.g.int32_ty (destOptionTy cenv.g ty))) then + errorR(Error(FSComp.SR.tcCallerInfoWrongType(callerInfoInfo.ToString(), "int", NicePrint.minimalStringOfType cenv.denv (destOptionTy cenv.g ty)),m)) + | CallerSide(_), CallerFilePath -> + if not (typeEquiv cenv.g cenv.g.string_ty ty) then + errorR(Error(FSComp.SR.tcCallerInfoWrongType(callerInfoInfo.ToString(), "string", NicePrint.minimalStringOfType cenv.denv ty),m)) + | CalleeSide, CallerFilePath -> + if not ((isOptionTy cenv.g ty) && (typeEquiv cenv.g cenv.g.string_ty (destOptionTy cenv.g ty))) then + errorR(Error(FSComp.SR.tcCallerInfoWrongType(callerInfoInfo.ToString(), "string", NicePrint.minimalStringOfType cenv.denv (destOptionTy cenv.g ty)),m)) + | _ -> failwith "impossible") for pinfo in immediateProps do let nm = pinfo.PropertyName diff --git a/src/fsharp/infos.fs b/src/fsharp/infos.fs index 9a0fc58f855..d36edbdba5f 100755 --- a/src/fsharp/infos.fs +++ b/src/fsharp/infos.fs @@ -519,6 +519,13 @@ type CallerInfoInfo = | CallerMemberName | CallerFilePath + override x.ToString() = + match x with + | NoCallerInfo -> "NoCallerInfo" + | CallerLineNumber -> "CallerLineNumber" + | CallerMemberName -> "CallerMemberName" + | CallerFilePath -> "CallerFilePath" + [] type ReflectedArgInfo = | None From 5b607d4d323e3d58b367c1c3f4501380adfcaa24 Mon Sep 17 00:00:00 2001 From: "Avi.Avni" Date: Tue, 19 Apr 2016 07:45:58 +0300 Subject: [PATCH 011/129] fix ILMeth read CallerFilePathAttribute --- src/fsharp/infos.fs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/fsharp/infos.fs b/src/fsharp/infos.fs index d36edbdba5f..10854c75fcd 100755 --- a/src/fsharp/infos.fs +++ b/src/fsharp/infos.fs @@ -1286,7 +1286,8 @@ type MethInfo = // Note: we get default argument values from VB and other .NET language metadata let optArgInfo = OptionalArgInfo.FromILParameter g amap m ilMethInfo.MetadataScope ilMethInfo.DeclaringTypeInst p let isCallerLineNumberArg = TryFindILAttribute g.attrib_CallerLineNumberAttribute p.CustomAttrs - let callerInfoInfo = if isCallerLineNumberArg then CallerLineNumber else NoCallerInfo + let isCallerFilePathArg = TryFindILAttribute g.attrib_CallerFilePathAttribute p.CustomAttrs + let callerInfoInfo = if isCallerLineNumberArg then CallerLineNumber elif isCallerFilePathArg then CallerFilePath else NoCallerInfo yield (isParamArrayArg, isOutArg, optArgInfo, callerInfoInfo, reflArgInfo) ] ] From 29a8271c762bf1cbb2a18a19c24ca4e45e363b03 Mon Sep 17 00:00:00 2001 From: "Avi.Avni" Date: Tue, 19 Apr 2016 07:52:07 +0300 Subject: [PATCH 012/129] fix expected test error message --- .../Imported/CallerInfo/E_CallerFilePath.fs | 4 ++-- .../Imported/CallerInfo/E_CallerLineNumber.fs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/E_CallerFilePath.fs b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/E_CallerFilePath.fs index cdb317997b3..8eccc449b8d 100644 --- a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/E_CallerFilePath.fs +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/E_CallerFilePath.fs @@ -1,5 +1,5 @@ -//Bogus caller info definition -//Bogus caller info definition +//'CallerFilePath' must be applied to an argument of type 'string', but has been applied to an argument of type 'int' +//'CallerFilePath' can only be applied to optional arguments namespace Test open System.Runtime.CompilerServices diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/E_CallerLineNumber.fs b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/E_CallerLineNumber.fs index 13ac4118ea8..b89004e0214 100644 --- a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/E_CallerLineNumber.fs +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/E_CallerLineNumber.fs @@ -1,5 +1,5 @@ -//Bogus caller info definition -//Bogus caller info definition +//'CallerLineNumber' must be applied to an argument of type 'int', but has been applied to an argument of type 'string' +//'CallerLineNumber' can only be applied to optional arguments namespace Test open System.Runtime.CompilerServices From b7235bbb64d631bcd5fb6989ec7f25c07b9eeb11 Mon Sep 17 00:00:00 2001 From: "Avi.Avni" Date: Tue, 19 Apr 2016 08:15:34 +0300 Subject: [PATCH 013/129] fix error message --- .../MemberDeclarations/E_byref_two_arguments_curried.fsx | 2 +- .../MemberDeclarations/E_optional_two_arguments_curried.fsx | 2 +- .../MemberDeclarations/E_out_two_arguments_curried.fsx | 2 +- .../MemberDeclarations/E_paramarray_two_arguments_curried.fsx | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/ClassTypes/MemberDeclarations/E_byref_two_arguments_curried.fsx b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/ClassTypes/MemberDeclarations/E_byref_two_arguments_curried.fsx index 2f99a7564d3..68bd6ad5b0b 100644 --- a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/ClassTypes/MemberDeclarations/E_byref_two_arguments_curried.fsx +++ b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/ClassTypes/MemberDeclarations/E_byref_two_arguments_curried.fsx @@ -2,6 +2,6 @@ // Regression test for FSHARP1.0:5580 // disallow curried byref parameters // Out arguments - curried -//Methods with curried arguments cannot declare 'out', 'ParamArray', 'optional', 'ReflectedDefinition' or 'byref' arguments$ +//Methods with curried arguments cannot declare 'out', 'ParamArray', 'optional', 'ReflectedDefinition', 'byref', 'CallerLineNumber', or 'CallerFilePath' arguments type Misc2() = static member M (foo : int byref) (bar : int byref) = foo <- 10 diff --git a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/ClassTypes/MemberDeclarations/E_optional_two_arguments_curried.fsx b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/ClassTypes/MemberDeclarations/E_optional_two_arguments_curried.fsx index 20786eb74ec..f788556262b 100644 --- a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/ClassTypes/MemberDeclarations/E_optional_two_arguments_curried.fsx +++ b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/ClassTypes/MemberDeclarations/E_optional_two_arguments_curried.fsx @@ -2,6 +2,6 @@ // Regression test for FSHARP1.0:5580 // disallow curried byref parameters // optional arguments - curried -//Methods with curried arguments cannot declare 'out', 'ParamArray', 'optional', 'ReflectedDefinition' or 'byref' arguments$ +//Methods with curried arguments cannot declare 'out', 'ParamArray', 'optional', 'ReflectedDefinition', 'byref', 'CallerLineNumber', or 'CallerFilePath' arguments type Misc0() = static member M (?foo : int) (?bar : int) = 10 diff --git a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/ClassTypes/MemberDeclarations/E_out_two_arguments_curried.fsx b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/ClassTypes/MemberDeclarations/E_out_two_arguments_curried.fsx index 4f167735666..b7754e95dde 100644 --- a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/ClassTypes/MemberDeclarations/E_out_two_arguments_curried.fsx +++ b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/ClassTypes/MemberDeclarations/E_out_two_arguments_curried.fsx @@ -2,6 +2,6 @@ // Regression test for FSHARP1.0:5580 // disallow curried byref parameters // Out arguments - curried -//Methods with curried arguments cannot declare 'out', 'ParamArray', 'optional', 'ReflectedDefinition' or 'byref' arguments$ +//Methods with curried arguments cannot declare 'out', 'ParamArray', 'optional', 'ReflectedDefinition', 'byref', 'CallerLineNumber', or 'CallerFilePath' arguments type Misc2() = static member M ([] foo : int byref) ([] bar : int byref) = foo <- 10 diff --git a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/ClassTypes/MemberDeclarations/E_paramarray_two_arguments_curried.fsx b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/ClassTypes/MemberDeclarations/E_paramarray_two_arguments_curried.fsx index fea11eebf66..5840eee3a07 100644 --- a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/ClassTypes/MemberDeclarations/E_paramarray_two_arguments_curried.fsx +++ b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/ClassTypes/MemberDeclarations/E_paramarray_two_arguments_curried.fsx @@ -2,6 +2,6 @@ // Regression test for FSHARP1.0:5580 // disallow curried byref parameters // ParamArray arguments - non curried -//Methods with curried arguments cannot declare 'out', 'ParamArray', 'optional', 'ReflectedDefinition' or 'byref' arguments$ +//Methods with curried arguments cannot declare 'out', 'ParamArray', 'optional', 'ReflectedDefinition', 'byref', 'CallerLineNumber', or 'CallerFilePath' arguments type Misc0() = static member M ([] args : string[]) ([] argc : int) = args.Length + argc From 6bf9dc5dd19d7ad5de9745852e47742f780da1d0 Mon Sep 17 00:00:00 2001 From: "Avi.Avni" Date: Tue, 19 Apr 2016 08:39:50 +0300 Subject: [PATCH 014/129] add caller file path tests for contructor --- .../Imported/CallerInfo/CallerFilePath.fs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerFilePath.fs b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerFilePath.fs index f305304fff0..2806aadf5b0 100644 --- a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerFilePath.fs +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerFilePath.fs @@ -3,7 +3,11 @@ namespace Test open System.Runtime.CompilerServices open CSharpLib -type MyTy() = +type MyTy([] ?p0 : string) = + let mutable p = p0 + + member x.Path with get() = p + static member GetCallerFilePath([] ?path : string) = path @@ -17,7 +21,17 @@ module Program = [] let main (_:string[]) = - + let o = MyTy() + let o1 = MyTy("42") + + match o.Path with + | Some(path) when matchesPath "Conformance\\SpecialAttributesAndTypes\\Imported\\CallerInfo\\CallerFilePath.fs" path -> () + | x -> failwithf "Unexpected: %A" x + + match o1.Path with + | Some(path) when matchesPath "42" path -> () + | x -> failwithf "Unexpected: %A" x + match MyTy.GetCallerFilePath() with | Some(path) when matchesPath "Conformance\\SpecialAttributesAndTypes\\Imported\\CallerInfo\\CallerFilePath.fs" path -> () | x -> failwithf "Unexpected: %A" x From 19a5762f7d51fc05e3524827139027d1711dfa6d Mon Sep 17 00:00:00 2001 From: "Avi.Avni" Date: Tue, 19 Apr 2016 19:48:17 +0300 Subject: [PATCH 015/129] fix test error message --- tests/fsharp/typecheck/sigs/neg23.bsl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/fsharp/typecheck/sigs/neg23.bsl b/tests/fsharp/typecheck/sigs/neg23.bsl index 1d21a9a9a41..f817caa2ef0 100644 --- a/tests/fsharp/typecheck/sigs/neg23.bsl +++ b/tests/fsharp/typecheck/sigs/neg23.bsl @@ -27,9 +27,9 @@ neg23.fs(82,18,82,20): typecheck error FS0439: The method 'X0' has curried argum neg23.fs(85,18,85,21): typecheck error FS0439: The method 'X01' has curried arguments but has the same name as another method in this type. Methods with curried arguments cannot be overloaded. Consider using a method taking tupled arguments. -neg23.fs(88,18,88,21): typecheck error FS0440: Methods with curried arguments cannot declare 'out', 'ParamArray', 'optional', 'ReflectedDefinition' or 'byref' arguments +neg23.fs(88,18,88,21): typecheck error FS0440: Methods with curried arguments cannot declare 'out', 'ParamArray', 'optional', 'ReflectedDefinition', 'byref', 'CallerLineNumber', or 'CallerFilePath' arguments -neg23.fs(90,18,90,21): typecheck error FS0440: Methods with curried arguments cannot declare 'out', 'ParamArray', 'optional', 'ReflectedDefinition' or 'byref' arguments +neg23.fs(90,18,90,21): typecheck error FS0440: Methods with curried arguments cannot declare 'out', 'ParamArray', 'optional', 'ReflectedDefinition', 'byref', 'CallerLineNumber', or 'CallerFilePath' arguments neg23.fs(93,18,93,21): typecheck error FS0439: The method 'X04' has curried arguments but has the same name as another method in this type. Methods with curried arguments cannot be overloaded. Consider using a method taking tupled arguments. From d2869bebfcb6a6e6f33325a77dc0934adbcd6b8f Mon Sep 17 00:00:00 2001 From: "Avi.Avni" Date: Tue, 19 Apr 2016 19:54:44 +0300 Subject: [PATCH 016/129] change caller file path to return full path --- src/fsharp/TypeChecker.fs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/fsharp/TypeChecker.fs b/src/fsharp/TypeChecker.fs index 835dd2fdb8d..58bae7943a5 100755 --- a/src/fsharp/TypeChecker.fs +++ b/src/fsharp/TypeChecker.fs @@ -9173,7 +9173,7 @@ and TcMethodApplication | CallerLineNumber when typeEquiv cenv.g currCalledArgTy cenv.g.int_ty -> emptyPreBinder,Expr.Const(Const.Int32(mMethExpr.StartLine), mMethExpr, currCalledArgTy) | CallerFilePath when typeEquiv cenv.g currCalledArgTy cenv.g.string_ty -> - emptyPreBinder,Expr.Const(Const.String(mMethExpr.FileName), mMethExpr, currCalledArgTy) + emptyPreBinder,Expr.Const(Const.String(System.IO.Path.GetFullPath(mMethExpr.FileName)), mMethExpr, currCalledArgTy) | _ -> emptyPreBinder,Expr.Const(TcFieldInit mMethExpr fieldInit,mMethExpr,currCalledArgTy) @@ -9210,7 +9210,7 @@ and TcMethodApplication let lineExpr = Expr.Const(Const.Int32(mMethExpr.StartLine), mMethExpr, calledNonOptTy) emptyPreBinder,mkUnionCaseExpr(mkSomeCase cenv.g,[calledNonOptTy],[lineExpr],mMethExpr) | CallerFilePath when typeEquiv cenv.g calledNonOptTy cenv.g.string_ty -> - let filePathExpr = Expr.Const(Const.String(mMethExpr.FileName), mMethExpr, calledNonOptTy) + let filePathExpr = Expr.Const(Const.String(System.IO.Path.GetFullPath(mMethExpr.FileName)), mMethExpr, calledNonOptTy) emptyPreBinder,mkUnionCaseExpr(mkSomeCase cenv.g,[calledNonOptTy],[filePathExpr],mMethExpr) | _ -> emptyPreBinder,mkUnionCaseExpr(mkNoneCase cenv.g,[calledNonOptTy],[],mMethExpr) From e82768033689fde47796358bbb9336e162c67034 Mon Sep 17 00:00:00 2001 From: "Avi.Avni" Date: Fri, 22 Apr 2016 12:05:30 +0300 Subject: [PATCH 017/129] add attribute usage test --- .../Imported/CallerInfo/CSharpLib.cs | 11 +++++++++++ .../Imported/CallerInfo/CallerLineNumber.fs | 7 +++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CSharpLib.cs b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CSharpLib.cs index ee1c7d4f834..44750e38379 100644 --- a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CSharpLib.cs +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CSharpLib.cs @@ -1,4 +1,5 @@ using System; +using System.Reflection; using System.Runtime.CompilerServices; namespace CSharpLib @@ -20,4 +21,14 @@ public static Tuple AllInfo(int normalArg, [CallerFilePath] string return new Tuple(filePath, line); } } + + public class MyCallerInfoAttribute : Attribute + { + public int LineNumber { get; set; } + + public MyCallerInfoAttribute([CallerLineNumber] int lineNumber = -1) + { + LineNumber = lineNumber; + } + } } \ No newline at end of file diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerLineNumber.fs b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerLineNumber.fs index f30d42dfba1..5fb1cb3a211 100644 --- a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerLineNumber.fs +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerLineNumber.fs @@ -3,7 +3,7 @@ namespace Test open System.Runtime.CompilerServices open CSharpLib -type MyTy() = +[]type MyTy() = static member GetCallerLineNumber([] ?line : int) = line @@ -25,5 +25,8 @@ module Program = match CallerInfoTest.AllInfo(21) with | (_, 25) -> () | x -> failwithf "Unexpected C# result with multiple parameter types: %A" x - + + if (typeof.GetCustomAttributes(typeof, false).[0] :?> MyCallerInfoAttribute).LineNumber <> 6 then + failwith "Unexpected C# MyCallerInfoAttribute" + 0 \ No newline at end of file From 12db616bcaca1f9722698f61c0d043278b78ab1e Mon Sep 17 00:00:00 2001 From: Lincoln Atkinson Date: Sun, 24 Apr 2016 17:35:44 -0700 Subject: [PATCH 018/129] Make sure to issue error in the case of multiple caller info attributes --- src/fsharp/infos.fs | 28 +++++++++++++++++-- .../Imported/CallerInfo/E_MultipleAttrs.fs | 21 ++++++++++++++ 2 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/E_MultipleAttrs.fs diff --git a/src/fsharp/infos.fs b/src/fsharp/infos.fs index 10854c75fcd..7308224de33 100755 --- a/src/fsharp/infos.fs +++ b/src/fsharp/infos.fs @@ -1285,9 +1285,20 @@ type MethInfo = let isOutArg = (p.IsOut && not p.IsIn) // Note: we get default argument values from VB and other .NET language metadata let optArgInfo = OptionalArgInfo.FromILParameter g amap m ilMethInfo.MetadataScope ilMethInfo.DeclaringTypeInst p + let isCallerLineNumberArg = TryFindILAttribute g.attrib_CallerLineNumberAttribute p.CustomAttrs let isCallerFilePathArg = TryFindILAttribute g.attrib_CallerFilePathAttribute p.CustomAttrs - let callerInfoInfo = if isCallerLineNumberArg then CallerLineNumber elif isCallerFilePathArg then CallerFilePath else NoCallerInfo + + let callerInfoInfo = + match isCallerLineNumberArg, isCallerFilePathArg with + | false, false -> NoCallerInfo + | true, false -> CallerLineNumber + | false, true -> CallerFilePath + | true, true -> + // if multiple caller info attributes are specified, pick the "wrong" one here + // so that we get an error later + if p.Type.TypeRef.FullName = "System.Int32" then CallerFilePath + else CallerLineNumber yield (isParamArrayArg, isOutArg, optArgInfo, callerInfoInfo, reflArgInfo) ] ] @@ -1303,9 +1314,22 @@ type MethInfo = let isOptArg = HasFSharpAttribute g g.attrib_OptionalArgumentAttribute argInfo.Attribs // Note: can't specify caller-side default arguments in F#, by design (default is specified on the callee-side) let optArgInfo = if isOptArg then CalleeSide else NotOptional + let isCallerLineNumberArg = HasFSharpAttribute g g.attrib_CallerLineNumberAttribute argInfo.Attribs let isCallerFilePathArg = HasFSharpAttribute g g.attrib_CallerFilePathAttribute argInfo.Attribs - let callerInfoInfo = if isCallerLineNumberArg then CallerLineNumber elif isCallerFilePathArg then CallerFilePath else NoCallerInfo + + let callerInfoInfo = + match isCallerLineNumberArg, isCallerFilePathArg with + | false, false -> NoCallerInfo + | true, false -> CallerLineNumber + | false, true -> CallerFilePath + | true, true -> + // if multiple caller info attributes are specified, pick the "wrong" one here + // so that we get an error later + match tryDestOptionTy g ty with + | Some optTy when typeEquiv g g.int32_ty optTy -> CallerFilePath + | _ -> CallerLineNumber + (isParamArrayArg, isOutArg, optArgInfo, callerInfoInfo, reflArgInfo)) | DefaultStructCtor _ -> diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/E_MultipleAttrs.fs b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/E_MultipleAttrs.fs new file mode 100644 index 00000000000..5385abf532b --- /dev/null +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/E_MultipleAttrs.fs @@ -0,0 +1,21 @@ +//'CallerFilePath' must be applied to an argument of type 'string', but has been applied to an argument of type 'int' +//'CallerFilePath' must be applied to an argument of type 'string', but has been applied to an argument of type 'int' +//'CallerLineNumber' must be applied to an argument of type 'int', but has been applied to an argument of type 'int' +//'CallerLineNumber' must be applied to an argument of type 'int', but has been applied to an argument of type 'int' + +namespace Test + +open System.Runtime.CompilerServices + +type MyTy() = + static member A([] [] ?x : int) = + x + + static member B([] [] ?x : int) = + x + + static member C([] [] ?x : string) = + x + + static member D([] [] ?x : string) = + x From 7185fad30afa082c6443937891d543d2869fd1c6 Mon Sep 17 00:00:00 2001 From: Lincoln Atkinson Date: Sun, 24 Apr 2016 17:40:56 -0700 Subject: [PATCH 019/129] Add additional negative tests for non-optional args with option types --- .../Imported/CallerInfo/E_CallerFilePath.fs | 8 ++++++-- .../Imported/CallerInfo/E_CallerLineNumber.fs | 10 +++++++--- .../Imported/CallerInfo/env.lst | 1 + 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/E_CallerFilePath.fs b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/E_CallerFilePath.fs index 8eccc449b8d..d6e160d39af 100644 --- a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/E_CallerFilePath.fs +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/E_CallerFilePath.fs @@ -1,5 +1,6 @@ -//'CallerFilePath' must be applied to an argument of type 'string', but has been applied to an argument of type 'int' -//'CallerFilePath' can only be applied to optional arguments +//'CallerFilePath' must be applied to an argument of type 'string', but has been applied to an argument of type 'int' +//'CallerFilePath' can only be applied to optional arguments +//'CallerFilePath' can only be applied to optional arguments namespace Test open System.Runtime.CompilerServices @@ -9,4 +10,7 @@ type MyTy() = path static member GetCallerFilePathNotOptional([] path : string) = + path + + static member GetCallerFilePathNotOptional([] path : string option) = path \ No newline at end of file diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/E_CallerLineNumber.fs b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/E_CallerLineNumber.fs index b89004e0214..1d66da69961 100644 --- a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/E_CallerLineNumber.fs +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/E_CallerLineNumber.fs @@ -1,5 +1,6 @@ -//'CallerLineNumber' must be applied to an argument of type 'int', but has been applied to an argument of type 'string' -//'CallerLineNumber' can only be applied to optional arguments +//'CallerLineNumber' must be applied to an argument of type 'int', but has been applied to an argument of type 'string' +//'CallerLineNumber' can only be applied to optional arguments +//'CallerLineNumber' can only be applied to optional arguments namespace Test open System.Runtime.CompilerServices @@ -8,5 +9,8 @@ type MyTy() = static member GetCallerLineNumberNotInt([] ?line : string) = line - static member GetCallerLineNumberNotOptional([] line : string) = + static member GetCallerLineNumberNotOptional([] line : int) = + line + + static member GetCallerLineNumberNotOptional([] line : int option) = line \ No newline at end of file diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/env.lst b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/env.lst index bb430c0b586..ea7b5653a7a 100644 --- a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/env.lst +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/env.lst @@ -2,4 +2,5 @@ SOURCE=CallerFilePath.fs SCFLAGS="-r CSharpLib.dll --test:ErrorRanges" PRECMD="\$CSC_PIPE /t:library CSharpLib.cs" # CallerFilePath.fs SOURCE=E_CallerLineNumber.fs SCFLAGS="--test:ErrorRanges" # E_CallerLineNumber.fs SOURCE=E_CallerFilePath.fs SCFLAGS="--test:ErrorRanges" # E_CallerFilePath.fs + SOURCE=E_MutltipleAttrs.fs SCFLAGS="--test:ErrorRanges" # E_MutltipleAttrs.fs From 58bab3f3d387e4e8bcbc479356cca476a51aa5c3 Mon Sep 17 00:00:00 2001 From: Lincoln Atkinson Date: Sun, 24 Apr 2016 17:53:07 -0700 Subject: [PATCH 020/129] Add tests covering directive-defined line number and file name --- .../Imported/CallerInfo/CallerFilePath.fs | 12 +++++++++++- .../Imported/CallerInfo/CallerLineNumber.fs | 17 +++++++++++++---- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerFilePath.fs b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerFilePath.fs index 2806aadf5b0..1353ac55783 100644 --- a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerFilePath.fs +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerFilePath.fs @@ -51,5 +51,15 @@ module Program = match CallerInfoTest.AllInfo(21) with | (path, _) when matchesPath "Conformance\\SpecialAttributesAndTypes\\Imported\\CallerInfo\\CallerFilePath.fs" path -> () | x -> failwithf "Unexpected C# result with multiple parameter types: %A" x - + +# 345 "qwerty1" + match CallerInfoTest.AllInfo(123) with + | (path, _) when matchesPath "Conformance\\SpecialAttributesAndTypes\\Imported\\CallerInfo\\qwerty1" path -> () + | x -> failwithf "Unexpected C# result with multiple parameter types: %A" x + +# 456 "qwerty2" + match CallerInfoTest.AllInfo(123) with + | (path, _) when matchesPath "Conformance\\SpecialAttributesAndTypes\\Imported\\CallerInfo\\qwerty2" path -> () + | x -> failwithf "Unexpected C# result with multiple parameter types: %A" x + 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerLineNumber.fs b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerLineNumber.fs index 5fb1cb3a211..d975ddc02d6 100644 --- a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerLineNumber.fs +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerLineNumber.fs @@ -2,8 +2,8 @@ namespace Test open System.Runtime.CompilerServices open CSharpLib - -[]type MyTy() = +[] +type MyTy() = static member GetCallerLineNumber([] ?line : int) = line @@ -26,7 +26,16 @@ module Program = | (_, 25) -> () | x -> failwithf "Unexpected C# result with multiple parameter types: %A" x - if (typeof.GetCustomAttributes(typeof, false).[0] :?> MyCallerInfoAttribute).LineNumber <> 6 then + if (typeof.GetCustomAttributes(typeof, false).[0] :?> MyCallerInfoAttribute).LineNumber <> 5 then failwith "Unexpected C# MyCallerInfoAttribute" - + +# 345 "qwerty" + match CallerInfoTest.AllInfo(123) with + | (_, 345) -> () + | x -> failwithf "Unexpected C# result with multiple parameter types: %A" x +# 456 "qwerty" + match CallerInfoTest.AllInfo(123) with + | (_, 456) -> () + | x -> failwithf "Unexpected C# result with multiple parameter types: %A" x + 0 \ No newline at end of file From 718204e8bfb647f3fad67c68e6e22bc7127fd4a9 Mon Sep 17 00:00:00 2001 From: Lincoln Atkinson Date: Sun, 24 Apr 2016 18:11:29 -0700 Subject: [PATCH 021/129] Add tests covering FSI --- .../Imported/CallerInfo/ViaInteractive.fsx | 29 +++++++++++++++++++ .../Imported/CallerInfo/env.lst | 3 +- 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/ViaInteractive.fsx diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/ViaInteractive.fsx b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/ViaInteractive.fsx new file mode 100644 index 00000000000..747997b55d6 --- /dev/null +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/ViaInteractive.fsx @@ -0,0 +1,29 @@ +open System.Runtime.CompilerServices +open CSharpLib +;; +type MyTy() = + static member GetCallerFilePath([] ?path : string) = + path + static member GetCallerLineNumber([] ?line : int) = + line +;; +let matchesPath path (s : string) = + s.EndsWith(path) + && not (s.Contains("\\\\")) + && not (path.Contains("\\.\\")) + && not (path.Contains("\\..\\")) + +let scriptName = if Array.contains "--exec" (System.Environment.GetCommandLineArgs()) then "ViaInteractive.fsx" else "stdin" +let checkPath = sprintf "Conformance\\SpecialAttributesAndTypes\\Imported\\CallerInfo\\%s" scriptName +;; +match MyTy.GetCallerFilePath() with +| Some(path) when matchesPath checkPath path -> () +| x -> failwithf "Unexpected: %A" x +;; +if MyTy.GetCallerLineNumber() <> Some(23) then + failwith "Unexpected F# CallerLineNumber" +;; +match CallerInfoTest.AllInfo(21) with +| (path, 26) when matchesPath checkPath path -> () +| x -> failwithf "Unexpected C# result with multiple parameter types: %A" x +;; \ No newline at end of file diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/env.lst b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/env.lst index ea7b5653a7a..98a9b3019e8 100644 --- a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/env.lst +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/env.lst @@ -3,4 +3,5 @@ SOURCE=E_CallerLineNumber.fs SCFLAGS="--test:ErrorRanges" # E_CallerLineNumber.fs SOURCE=E_CallerFilePath.fs SCFLAGS="--test:ErrorRanges" # E_CallerFilePath.fs SOURCE=E_MutltipleAttrs.fs SCFLAGS="--test:ErrorRanges" # E_MutltipleAttrs.fs - + SOURCE=ViaInteractive.fsx SCFLAGS="--test:ErrorRanges" PRECMD="\$CSC_PIPE /t:library CSharpLib.cs" FSIMODE=EXEC COMPILE_ONLY=1 # ViaInteractive.fsx - exec + SOURCE=ViaInteractive.fsx SCFLAGS="--test:ErrorRanges" PRECMD="\$CSC_PIPE /t:library CSharpLib.cs" FSIMODE=PIPE COMPILE_ONLY=1 # ViaInteractive.fsx - pipe From a4d55abe728cee8b463adebce5950d415d572de1 Mon Sep 17 00:00:00 2001 From: Lincoln Atkinson Date: Sun, 24 Apr 2016 18:26:54 -0700 Subject: [PATCH 022/129] Fix tests --- .../Imported/CallerInfo/E_MultipleAttrs.fs | 4 ++-- .../Imported/CallerInfo/ViaInteractive.fsx | 3 ++- .../SpecialAttributesAndTypes/Imported/CallerInfo/env.lst | 6 +++--- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/E_MultipleAttrs.fs b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/E_MultipleAttrs.fs index 5385abf532b..fda49ca239f 100644 --- a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/E_MultipleAttrs.fs +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/E_MultipleAttrs.fs @@ -1,7 +1,7 @@ //'CallerFilePath' must be applied to an argument of type 'string', but has been applied to an argument of type 'int' //'CallerFilePath' must be applied to an argument of type 'string', but has been applied to an argument of type 'int' -//'CallerLineNumber' must be applied to an argument of type 'int', but has been applied to an argument of type 'int' -//'CallerLineNumber' must be applied to an argument of type 'int', but has been applied to an argument of type 'int' +//'CallerLineNumber' must be applied to an argument of type 'int', but has been applied to an argument of type 'string' +//'CallerLineNumber' must be applied to an argument of type 'int', but has been applied to an argument of type 'string' namespace Test diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/ViaInteractive.fsx b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/ViaInteractive.fsx index 747997b55d6..e3668ea3b6a 100644 --- a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/ViaInteractive.fsx +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/ViaInteractive.fsx @@ -26,4 +26,5 @@ if MyTy.GetCallerLineNumber() <> Some(23) then match CallerInfoTest.AllInfo(21) with | (path, 26) when matchesPath checkPath path -> () | x -> failwithf "Unexpected C# result with multiple parameter types: %A" x -;; \ No newline at end of file +;; +#q;; \ No newline at end of file diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/env.lst b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/env.lst index 98a9b3019e8..6f4189af891 100644 --- a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/env.lst +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/env.lst @@ -2,6 +2,6 @@ SOURCE=CallerFilePath.fs SCFLAGS="-r CSharpLib.dll --test:ErrorRanges" PRECMD="\$CSC_PIPE /t:library CSharpLib.cs" # CallerFilePath.fs SOURCE=E_CallerLineNumber.fs SCFLAGS="--test:ErrorRanges" # E_CallerLineNumber.fs SOURCE=E_CallerFilePath.fs SCFLAGS="--test:ErrorRanges" # E_CallerFilePath.fs - SOURCE=E_MutltipleAttrs.fs SCFLAGS="--test:ErrorRanges" # E_MutltipleAttrs.fs - SOURCE=ViaInteractive.fsx SCFLAGS="--test:ErrorRanges" PRECMD="\$CSC_PIPE /t:library CSharpLib.cs" FSIMODE=EXEC COMPILE_ONLY=1 # ViaInteractive.fsx - exec - SOURCE=ViaInteractive.fsx SCFLAGS="--test:ErrorRanges" PRECMD="\$CSC_PIPE /t:library CSharpLib.cs" FSIMODE=PIPE COMPILE_ONLY=1 # ViaInteractive.fsx - pipe + SOURCE=E_MultipleAttrs.fs SCFLAGS="--test:ErrorRanges" # E_MultipleAttrs.fs + SOURCE=ViaInteractive.fsx SCFLAGS="--test:ErrorRanges -r CSharpLib.dll" PRECMD="\$CSC_PIPE /t:library CSharpLib.cs" FSIMODE=EXEC COMPILE_ONLY=1 # ViaInteractive.fsx - exec + SOURCE=ViaInteractive.fsx SCFLAGS="--test:ErrorRanges -r CSharpLib.dll" PRECMD="\$CSC_PIPE /t:library CSharpLib.cs" FSIMODE=PIPE COMPILE_ONLY=1 # ViaInteractive.fsx - pipe From 7c87e1e1ca752a91056c777061663a8a666e1b75 Mon Sep 17 00:00:00 2001 From: "Avi.Avni" Date: Tue, 26 Apr 2016 20:10:05 +0300 Subject: [PATCH 023/129] simplify CallerInfoInfo ToString --- src/fsharp/infos.fs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/fsharp/infos.fs b/src/fsharp/infos.fs index bc2a433ff94..bd00e86680b 100755 --- a/src/fsharp/infos.fs +++ b/src/fsharp/infos.fs @@ -524,12 +524,7 @@ type CallerInfoInfo = | CallerMemberName | CallerFilePath - override x.ToString() = - match x with - | NoCallerInfo -> "NoCallerInfo" - | CallerLineNumber -> "CallerLineNumber" - | CallerMemberName -> "CallerMemberName" - | CallerFilePath -> "CallerFilePath" + override x.ToString() = sprintf "%+A" x [] type ReflectedArgInfo = From 9614626aebdc74b2794b372533998efa4937a619 Mon Sep 17 00:00:00 2001 From: "Avi.Avni" Date: Tue, 26 Apr 2016 20:11:27 +0300 Subject: [PATCH 024/129] add NoCallerInfo as condition to isSimpleFormalArg --- src/fsharp/TypeChecker.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fsharp/TypeChecker.fs b/src/fsharp/TypeChecker.fs index ce56b889cb5..a3dddda371e 100755 --- a/src/fsharp/TypeChecker.fs +++ b/src/fsharp/TypeChecker.fs @@ -8714,7 +8714,7 @@ and TcMethodApplication let denv = env.DisplayEnv let isSimpleFormalArg (isParamArrayArg, isOutArg, optArgInfo: OptionalArgInfo, _callerInfoInfo: CallerInfoInfo, _reflArgInfo: ReflectedArgInfo) = - not isParamArrayArg && not isOutArg && not optArgInfo.IsOptional + not isParamArrayArg && not isOutArg && not optArgInfo.IsOptional && _callerInfoInfo = NoCallerInfo let callerObjArgTys = objArgs |> List.map (tyOfExpr cenv.g) From c2e10362951be5880aaf38cad8ae9e1f8c01968c Mon Sep 17 00:00:00 2001 From: "Avi.Avni" Date: Tue, 26 Apr 2016 20:11:47 +0300 Subject: [PATCH 025/129] removed ;; not needed --- .../Imported/CallerInfo/ViaInteractive.fsx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/ViaInteractive.fsx b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/ViaInteractive.fsx index e3668ea3b6a..4e8821372b9 100644 --- a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/ViaInteractive.fsx +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/ViaInteractive.fsx @@ -1,12 +1,12 @@ open System.Runtime.CompilerServices open CSharpLib -;; + type MyTy() = static member GetCallerFilePath([] ?path : string) = path static member GetCallerLineNumber([] ?line : int) = line -;; + let matchesPath path (s : string) = s.EndsWith(path) && not (s.Contains("\\\\")) @@ -15,16 +15,16 @@ let matchesPath path (s : string) = let scriptName = if Array.contains "--exec" (System.Environment.GetCommandLineArgs()) then "ViaInteractive.fsx" else "stdin" let checkPath = sprintf "Conformance\\SpecialAttributesAndTypes\\Imported\\CallerInfo\\%s" scriptName -;; + match MyTy.GetCallerFilePath() with | Some(path) when matchesPath checkPath path -> () | x -> failwithf "Unexpected: %A" x -;; + if MyTy.GetCallerLineNumber() <> Some(23) then failwith "Unexpected F# CallerLineNumber" -;; + match CallerInfoTest.AllInfo(21) with | (path, 26) when matchesPath checkPath path -> () | x -> failwithf "Unexpected C# result with multiple parameter types: %A" x -;; -#q;; \ No newline at end of file + +#q \ No newline at end of file From ba7c02f553b85a7a806968c624d50bdfa94b3488 Mon Sep 17 00:00:00 2001 From: "Avi.Avni" Date: Tue, 26 Apr 2016 20:12:05 +0300 Subject: [PATCH 026/129] add first class tests --- .../Imported/CallerInfo/CallerLineNumber.fs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerLineNumber.fs b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerLineNumber.fs index d975ddc02d6..665af31c99e 100644 --- a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerLineNumber.fs +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerLineNumber.fs @@ -29,6 +29,14 @@ module Program = if (typeof.GetCustomAttributes(typeof, false).[0] :?> MyCallerInfoAttribute).LineNumber <> 5 then failwith "Unexpected C# MyCallerInfoAttribute" + let getCallerLineNumber = CallerInfoTest.LineNumber + + if () |> CallerInfoTest.LineNumber <> 34 then + failwith "Unexpected C# CallerLineNumber" + + if getCallerLineNumber () <> 32 then + failwith "Unexpected C# CallerLineNumber" + # 345 "qwerty" match CallerInfoTest.AllInfo(123) with | (_, 345) -> () From 081689fb5b04b18fd683a87d5b285c2da9426807 Mon Sep 17 00:00:00 2001 From: "Avi.Avni" Date: Tue, 26 Apr 2016 21:23:41 +0300 Subject: [PATCH 027/129] remove _ --- src/fsharp/TypeChecker.fs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/fsharp/TypeChecker.fs b/src/fsharp/TypeChecker.fs index a3dddda371e..b9223661279 100755 --- a/src/fsharp/TypeChecker.fs +++ b/src/fsharp/TypeChecker.fs @@ -8713,8 +8713,8 @@ and TcMethodApplication let denv = env.DisplayEnv - let isSimpleFormalArg (isParamArrayArg, isOutArg, optArgInfo: OptionalArgInfo, _callerInfoInfo: CallerInfoInfo, _reflArgInfo: ReflectedArgInfo) = - not isParamArrayArg && not isOutArg && not optArgInfo.IsOptional && _callerInfoInfo = NoCallerInfo + let isSimpleFormalArg (isParamArrayArg, isOutArg, optArgInfo: OptionalArgInfo, callerInfoInfo: CallerInfoInfo, _reflArgInfo: ReflectedArgInfo) = + not isParamArrayArg && not isOutArg && not optArgInfo.IsOptional && callerInfoInfo = NoCallerInfo let callerObjArgTys = objArgs |> List.map (tyOfExpr cenv.g) From dba815d981b51f5f722fda70076a590958b5f3d5 Mon Sep 17 00:00:00 2001 From: "Avi.Avni" Date: Thu, 28 Apr 2016 14:23:37 +0300 Subject: [PATCH 028/129] implement CallerMemberName --- src/fsharp/PostInferenceChecks.fs | 9 +++++++-- src/fsharp/TcGlobals.fs | 2 ++ src/fsharp/TypeChecker.fs | 16 ++++++++++++++-- src/fsharp/infos.fs | 24 ++++++++++++++---------- 4 files changed, 37 insertions(+), 14 deletions(-) diff --git a/src/fsharp/PostInferenceChecks.fs b/src/fsharp/PostInferenceChecks.fs index 872749a9dd0..4d0f15a4ab9 100644 --- a/src/fsharp/PostInferenceChecks.fs +++ b/src/fsharp/PostInferenceChecks.fs @@ -1339,8 +1339,13 @@ let CheckEntityDefn cenv env (tycon:Entity) = | CalleeSide, CallerFilePath -> if not ((isOptionTy cenv.g ty) && (typeEquiv cenv.g cenv.g.string_ty (destOptionTy cenv.g ty))) then errorR(Error(FSComp.SR.tcCallerInfoWrongType(callerInfoInfo.ToString(), "string", NicePrint.minimalStringOfType cenv.denv (destOptionTy cenv.g ty)),m)) - | _ -> failwith "impossible") - + | CallerSide(_), CallerMemberName -> + if not (typeEquiv cenv.g cenv.g.string_ty ty) then + errorR(Error(FSComp.SR.tcCallerInfoWrongType(callerInfoInfo.ToString(), "string", NicePrint.minimalStringOfType cenv.denv ty),m)) + | CalleeSide, CallerMemberName -> + if not ((isOptionTy cenv.g ty) && (typeEquiv cenv.g cenv.g.string_ty (destOptionTy cenv.g ty))) then + errorR(Error(FSComp.SR.tcCallerInfoWrongType(callerInfoInfo.ToString(), "string", NicePrint.minimalStringOfType cenv.denv (destOptionTy cenv.g ty)),m))) + for pinfo in immediateProps do let nm = pinfo.PropertyName let m = (match pinfo.ArbitraryValRef with None -> m | Some vref -> vref.DefinitionRange) diff --git a/src/fsharp/TcGlobals.fs b/src/fsharp/TcGlobals.fs index 2a9b7a496f0..d0295bc03aa 100755 --- a/src/fsharp/TcGlobals.fs +++ b/src/fsharp/TcGlobals.fs @@ -302,6 +302,7 @@ type public TcGlobals = attrib_ExtensionAttribute : BuiltinAttribInfo attrib_CallerLineNumberAttribute : BuiltinAttribInfo attrib_CallerFilePathAttribute : BuiltinAttribInfo + attrib_CallerMemberNameAttribute : BuiltinAttribInfo tcref_System_Collections_Generic_IList : TyconRef tcref_System_Collections_Generic_IReadOnlyList : TyconRef @@ -1207,6 +1208,7 @@ let mkTcGlobals (compilingFslib,sysCcu,ilg,fslibCcu,directoryToResolveRelativePa attrib_ExtensionAttribute = mkSystemRuntimeAttrib "System.Runtime.CompilerServices.ExtensionAttribute" attrib_CallerLineNumberAttribute = mkSystemRuntimeAttrib "System.Runtime.CompilerServices.CallerLineNumberAttribute" attrib_CallerFilePathAttribute = mkSystemRuntimeAttrib "System.Runtime.CompilerServices.CallerFilePathAttribute" + attrib_CallerMemberNameAttribute = mkSystemRuntimeAttrib "System.Runtime.CompilerServices.CallerMemberNameAttribute" attrib_ProjectionParameterAttribute = mk_MFCore_attrib "ProjectionParameterAttribute" attrib_CustomOperationAttribute = mk_MFCore_attrib "CustomOperationAttribute" diff --git a/src/fsharp/TypeChecker.fs b/src/fsharp/TypeChecker.fs index b9223661279..b20e3b909d6 100755 --- a/src/fsharp/TypeChecker.fs +++ b/src/fsharp/TypeChecker.fs @@ -269,6 +269,8 @@ type TcEnv = // Information to enforce special restrictions on valid expressions // for .NET constructors. eCtorInfo : CtorInfo option + + eCallerMemberName : string option } member tenv.DisplayEnv = tenv.eNameResEnv.DisplayEnv member tenv.NameEnv = tenv.eNameResEnv @@ -289,7 +291,8 @@ let emptyTcEnv g = eInternalsVisibleCompPaths=[] eModuleOrNamespaceTypeAccumulator= ref (NewEmptyModuleOrNamespaceType Namespace) eFamilyType=None - eCtorInfo=None } + eCtorInfo=None + eCallerMemberName=None} //------------------------------------------------------------------------- // Helpers related to determining if we're in a constructor and/or a class @@ -9207,6 +9210,8 @@ and TcMethodApplication emptyPreBinder,Expr.Const(Const.Int32(mMethExpr.StartLine), mMethExpr, currCalledArgTy) | CallerFilePath when typeEquiv cenv.g currCalledArgTy cenv.g.string_ty -> emptyPreBinder,Expr.Const(Const.String(System.IO.Path.GetFullPath(mMethExpr.FileName)), mMethExpr, currCalledArgTy) + | CallerMemberName when typeEquiv cenv.g currCalledArgTy cenv.g.string_ty && env.eCallerMemberName.IsSome -> + emptyPreBinder,Expr.Const(Const.String(env.eCallerMemberName.Value), mMethExpr, currCalledArgTy) | _ -> emptyPreBinder,Expr.Const(TcFieldInit mMethExpr fieldInit,mMethExpr,currCalledArgTy) @@ -9245,6 +9250,9 @@ and TcMethodApplication | CallerFilePath when typeEquiv cenv.g calledNonOptTy cenv.g.string_ty -> let filePathExpr = Expr.Const(Const.String(System.IO.Path.GetFullPath(mMethExpr.FileName)), mMethExpr, calledNonOptTy) emptyPreBinder,mkUnionCaseExpr(mkSomeCase cenv.g,[calledNonOptTy],[filePathExpr],mMethExpr) + | CallerMemberName when typeEquiv cenv.g calledNonOptTy cenv.g.string_ty && env.eCallerMemberName.IsSome -> + let memberNameExpr = Expr.Const(Const.String(env.eCallerMemberName.Value), mMethExpr, calledNonOptTy) + emptyPreBinder,mkUnionCaseExpr(mkSomeCase cenv.g,[calledNonOptTy],[memberNameExpr],mMethExpr) | _ -> emptyPreBinder,mkUnionCaseExpr(mkNoneCase cenv.g,[calledNonOptTy],[],mMethExpr) // Combine the variable allocators (if any) @@ -9606,7 +9614,11 @@ and TcNormalizedBinding declKind (cenv:cenv) env tpenv overallTy safeThisValOpt match bind with | NormalizedBinding(vis,bkind,isInline,isMutable,attrs,doc,_,valSynData,pat,NormalizedBindingRhs(spatsL,rtyOpt,rhsExpr),mBinding,spBind) -> - + let name = match pat with + | SynPat.Named(_,name,_,_,_) -> Some(name.idText) + | _ -> None + let envinner = {envinner with eCallerMemberName = name } + let (SynValData(memberFlagsOpt,valSynInfo,_)) = valSynData let attrTgt = DeclKind.AllowedAttribTargets memberFlagsOpt declKind diff --git a/src/fsharp/infos.fs b/src/fsharp/infos.fs index bd00e86680b..7d37ad064cb 100755 --- a/src/fsharp/infos.fs +++ b/src/fsharp/infos.fs @@ -1288,13 +1288,15 @@ type MethInfo = let isCallerLineNumberArg = TryFindILAttribute g.attrib_CallerLineNumberAttribute p.CustomAttrs let isCallerFilePathArg = TryFindILAttribute g.attrib_CallerFilePathAttribute p.CustomAttrs + let isCallerMemberNameArg = TryFindILAttribute g.attrib_CallerMemberNameAttribute p.CustomAttrs let callerInfoInfo = - match isCallerLineNumberArg, isCallerFilePathArg with - | false, false -> NoCallerInfo - | true, false -> CallerLineNumber - | false, true -> CallerFilePath - | true, true -> + match isCallerLineNumberArg, isCallerFilePathArg, isCallerMemberNameArg with + | false, false, false -> NoCallerInfo + | true, false, false -> CallerLineNumber + | false, true, false -> CallerFilePath + | false, false, true -> CallerMemberName + | _, _, _ -> // if multiple caller info attributes are specified, pick the "wrong" one here // so that we get an error later if p.Type.TypeRef.FullName = "System.Int32" then CallerFilePath @@ -1317,13 +1319,15 @@ type MethInfo = let isCallerLineNumberArg = HasFSharpAttribute g g.attrib_CallerLineNumberAttribute argInfo.Attribs let isCallerFilePathArg = HasFSharpAttribute g g.attrib_CallerFilePathAttribute argInfo.Attribs + let isCallerMemberNameArg = HasFSharpAttribute g g.attrib_CallerMemberNameAttribute argInfo.Attribs let callerInfoInfo = - match isCallerLineNumberArg, isCallerFilePathArg with - | false, false -> NoCallerInfo - | true, false -> CallerLineNumber - | false, true -> CallerFilePath - | true, true -> + match isCallerLineNumberArg, isCallerFilePathArg, isCallerMemberNameArg with + | false, false, false -> NoCallerInfo + | true, false, false -> CallerLineNumber + | false, true, false -> CallerFilePath + | false, false, true -> CallerMemberName + | _, _, _ -> // if multiple caller info attributes are specified, pick the "wrong" one here // so that we get an error later match tryDestOptionTy g ty with From 25d73d393a6f07df13bdf4123aa971d5bcb138e6 Mon Sep 17 00:00:00 2001 From: "Avi.Avni" Date: Thu, 28 Apr 2016 15:17:34 +0300 Subject: [PATCH 029/129] add quotation test --- .../CallerInfo/CallerInfoAndQuotiation.fs | 30 +++++++++++++++++++ .../Imported/CallerInfo/env.lst | 1 + 2 files changed, 31 insertions(+) create mode 100644 tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerInfoAndQuotiation.fs diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerInfoAndQuotiation.fs b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerInfoAndQuotiation.fs new file mode 100644 index 00000000000..cd06b29d97f --- /dev/null +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerInfoAndQuotiation.fs @@ -0,0 +1,30 @@ +namespace Test + +open System.Runtime.CompilerServices +open Microsoft.FSharp.Quotations +open Microsoft.FSharp.Quotations.Patterns + +type MyTy() = + static member GetCallerLineNumber([] ?line : int) = + line + +module Program = + [] + let main (_:string[]) = + let expr = <@ MyTy.GetCallerLineNumber () @> + + match expr with + | Call(None, methodInfo, e::[]) + when methodInfo.Name = "GetCallerLineNumber" -> + match e with + | NewUnionCase(uci, value::[]) + when uci.Name = "Some" -> + match value with + | Value(obj, ty) when ty = typeof && obj :?> int = 14 -> () + | _ -> failwith "Unexpected F# CallerLineNumber" + | _ -> + failwith "Unexpected F# CallerLineNumber" + | _ -> + failwith "Unexpected F# CallerLineNumber" + + 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/env.lst b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/env.lst index 6f4189af891..c310757eae2 100644 --- a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/env.lst +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/env.lst @@ -5,3 +5,4 @@ SOURCE=E_MultipleAttrs.fs SCFLAGS="--test:ErrorRanges" # E_MultipleAttrs.fs SOURCE=ViaInteractive.fsx SCFLAGS="--test:ErrorRanges -r CSharpLib.dll" PRECMD="\$CSC_PIPE /t:library CSharpLib.cs" FSIMODE=EXEC COMPILE_ONLY=1 # ViaInteractive.fsx - exec SOURCE=ViaInteractive.fsx SCFLAGS="--test:ErrorRanges -r CSharpLib.dll" PRECMD="\$CSC_PIPE /t:library CSharpLib.cs" FSIMODE=PIPE COMPILE_ONLY=1 # ViaInteractive.fsx - pipe + SOURCE=CallerInfoAndQuotiation.fs SCFLAGS="-r CSharpLib.dll --test:ErrorRanges" PRECMD="\$CSC_PIPE /t:library CSharpLib.cs" # CallerInfoAndQuotiation.fs From 013db2f64d1509e46515957be9c431f5acba3cde Mon Sep 17 00:00:00 2001 From: "Avi.Avni" Date: Thu, 28 Apr 2016 15:39:08 +0300 Subject: [PATCH 030/129] add caller info test with computation expression --- .../CallerInfoAndComputationExpression.fs | 27 +++++++++++++++++++ .../Imported/CallerInfo/env.lst | 1 + 2 files changed, 28 insertions(+) create mode 100644 tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerInfoAndComputationExpression.fs diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerInfoAndComputationExpression.fs b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerInfoAndComputationExpression.fs new file mode 100644 index 00000000000..8c28f251fc8 --- /dev/null +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerInfoAndComputationExpression.fs @@ -0,0 +1,27 @@ +namespace Test + +open System.Runtime.CompilerServices + +type Builder() = + member self.Bind(x, f, [] ?line : int) = + (f x, line) + + member self.Return(x, [] ?line : int) = + (x, line) + +module Program = + let builder = Builder() + + [] + let main (_:string[]) = + let result = + builder { + let! x = 1 + let! y = 2 + return x + y + } + + if result <> (((3, Some 21), Some 20), Some 19) then + failwith "Unexpected F# CallerLineNumber" + + 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/env.lst b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/env.lst index c310757eae2..db596ffae40 100644 --- a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/env.lst +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/env.lst @@ -6,3 +6,4 @@ SOURCE=ViaInteractive.fsx SCFLAGS="--test:ErrorRanges -r CSharpLib.dll" PRECMD="\$CSC_PIPE /t:library CSharpLib.cs" FSIMODE=EXEC COMPILE_ONLY=1 # ViaInteractive.fsx - exec SOURCE=ViaInteractive.fsx SCFLAGS="--test:ErrorRanges -r CSharpLib.dll" PRECMD="\$CSC_PIPE /t:library CSharpLib.cs" FSIMODE=PIPE COMPILE_ONLY=1 # ViaInteractive.fsx - pipe SOURCE=CallerInfoAndQuotiation.fs SCFLAGS="-r CSharpLib.dll --test:ErrorRanges" PRECMD="\$CSC_PIPE /t:library CSharpLib.cs" # CallerInfoAndQuotiation.fs + SOURCE=CallerInfoAndComputationExpression.fs SCFLAGS="-r CSharpLib.dll --test:ErrorRanges" PRECMD="\$CSC_PIPE /t:library CSharpLib.cs" # CallerInfoAndComputationExpression.fs From fcbef0cd69c4bcca2837f0fdd58addf5a37e4dbf Mon Sep 17 00:00:00 2001 From: "Avi.Avni" Date: Sat, 30 Apr 2016 23:35:15 +0300 Subject: [PATCH 031/129] merege branch 'master' into 'latkin-caller-info-attrs' --- .gitignore | 2 - .nuget/NuGet.Config | 4 +- BuildToolsVersion.txt | 1 + DEVGUIDE.md | 14 +- DotnetCLIVersion.txt | 1 + VisualFSharp.sln | 418 --- build.cmd | 155 +- init-tools.cmd | 69 + init-tools.sh | 88 + packages.config | 3 +- src/FSharpSource.Settings.targets | 22 +- src/FSharpSource.targets | 17 +- src/absil/il.fs | 2 +- src/absil/ilascii.fs | 1 - src/absil/illex.fsl | 4 +- src/fsharp-compiler-build.proj | 5 +- src/fsharp/AccessibilityLogic.fs | 333 +++ src/fsharp/AttributeChecking.fs | 499 ++++ src/fsharp/CompileOps.fs | 33 +- src/fsharp/CompileOptions.fs | 2 +- src/fsharp/ConstraintSolver.fs | 26 +- src/fsharp/ConstraintSolver.fsi | 7 +- src/fsharp/FSharp.Build/FSharp.Build.fsproj | 8 +- src/fsharp/FSharp.Build/Fsc.fs | 16 +- .../FSharp.Build/Microsoft.FSharp.targets | 13 +- src/fsharp/FSharp.Build/project.json | 20 + .../FSharp.Compiler-proto.fsproj | 22 +- .../FSharp.Compiler/FSharp.Compiler.fsproj | 22 +- src/fsharp/FSharp.Core/FSharp.Core.fsproj | 1 + src/fsharp/FSharp.Core/printf.fs | 3 +- .../FSharp.LanguageService.Compiler.fsproj | 18 + src/fsharp/FindUnsolved.fs | 4 +- src/fsharp/InfoReader.fs | 727 +++++ src/fsharp/LowerCallsAndSeqs.fs | 9 +- src/fsharp/MethodCalls.fs | 1212 +++++++++ src/fsharp/MethodOverrides.fs | 712 +++++ src/fsharp/NameResolution.fs | 5 +- src/fsharp/NameResolution.fsi | 6 +- src/fsharp/NicePrint.fs | 19 +- src/fsharp/Optimizer.fs | 13 +- src/fsharp/PostInferenceChecks.fs | 8 +- src/fsharp/PostInferenceChecks.fsi | 3 +- src/fsharp/SignatureConformance.fs | 638 +++++ src/fsharp/TypeChecker.fs | 14 +- src/fsharp/TypeChecker.fsi | 3 +- src/fsharp/TypeRelations.fs | 2384 +---------------- src/fsharp/fsc.fs | 25 +- src/fsharp/fsi/fsi.fs | 34 +- src/fsharp/infos.fs | 1655 +----------- src/fsharp/vs/ServiceDeclarations.fs | 16 +- src/fsharp/vs/ServiceDeclarations.fsi | 1 + src/fsharp/vs/Symbols.fs | 13 +- src/fsharp/vs/Symbols.fsi | 11 +- src/fsharp/vs/service.fs | 24 +- src/update.cmd | 4 - tests/RunTests.cmd | 2 +- tests/fsharp/FSharp.Tests.fsproj | 1 + tests/fsharp/FSharpTestSuiteAsserts.fs | 22 + tests/fsharp/core/.gitignore | 8 + tests/fsharp/core/control/test.fsx | 2 + tests/fsharp/core/fsi-shadowcopy/test1.fsx | 5 +- tests/fsharp/core/fsi-shadowcopy/test2.fsx | 5 +- tests/fsharp/core/tests_core.fs | 15 +- tests/fsharp/project.json | 4 +- tests/fsharp/regression/656/run.bat | 33 - tests/fsharp/regression/tests_regression.fs | 17 - .../typeProviders/tests_typeProviders.fs | 14 +- ...cs.il.bsl => CallIntrinsics.il.netfx4.bsl} | 0 .../CodeGen/EmittedIL/TypeProviders/env.lst | 2 +- tests/fsharpqa/Source/test.lst | 2 +- .../EnableOpenSource/EnableOpenSource.csproj | 4 +- .../FSharp.ProjectSystem.FSharp/Project.fs | 28 +- vsintegration/src/fsharp.common.props | 4 +- vsintegration/tests/Salsa/salsa.fs | 4 +- vsintegration/tests/unittests/Tests.Build.fs | 2 +- .../Tests.ProjectSystem.MultiTargeting.fs | 4 +- 76 files changed, 4772 insertions(+), 4775 deletions(-) create mode 100644 BuildToolsVersion.txt create mode 100644 DotnetCLIVersion.txt create mode 100644 init-tools.cmd create mode 100644 init-tools.sh create mode 100644 src/fsharp/AccessibilityLogic.fs create mode 100644 src/fsharp/AttributeChecking.fs create mode 100644 src/fsharp/FSharp.Build/project.json create mode 100644 src/fsharp/InfoReader.fs create mode 100644 src/fsharp/MethodCalls.fs create mode 100644 src/fsharp/MethodOverrides.fs create mode 100644 src/fsharp/SignatureConformance.fs mode change 100755 => 100644 src/fsharp/TypeRelations.fs create mode 100644 tests/fsharp/FSharpTestSuiteAsserts.fs delete mode 100644 tests/fsharp/regression/656/run.bat rename tests/fsharpqa/Source/CodeGen/EmittedIL/TypeProviders/{CallIntrinsics.il.bsl => CallIntrinsics.il.netfx4.bsl} (100%) diff --git a/.gitignore b/.gitignore index 9ed02a63124..49835c4987b 100644 --- a/.gitignore +++ b/.gitignore @@ -29,8 +29,6 @@ src/fsharp/FSharp.Compiler/*.userprefs src/*.log Debug Release -vsdebug -vsrelease Proto sign_temp .libs diff --git a/.nuget/NuGet.Config b/.nuget/NuGet.Config index dfd48a090ff..8ef59b9c202 100644 --- a/.nuget/NuGet.Config +++ b/.nuget/NuGet.Config @@ -8,8 +8,8 @@ - - + + diff --git a/BuildToolsVersion.txt b/BuildToolsVersion.txt new file mode 100644 index 00000000000..cfa9f1b4166 --- /dev/null +++ b/BuildToolsVersion.txt @@ -0,0 +1 @@ +1.0.25-prerelease-00317-01 diff --git a/DEVGUIDE.md b/DEVGUIDE.md index 6a155ce5f11..bfdbefe2b72 100644 --- a/DEVGUIDE.md +++ b/DEVGUIDE.md @@ -30,18 +30,28 @@ There are various qualifiers: build.cmd release -- build release (the default) build.cmd debug -- build debug instead of release + build.cmd proto -- force the rebuild of the Proto bootstrap compiler in addition to other things + build.cmd compiler -- build/tests only the compiler (not the Visual F# IDE Tools) build.cmd vs -- build/tests the Visual F# IDE Tools build.cmd pcls -- build/tests the PCL FSharp.Core libraries build.cmd build -- build, do not test - build.cmd smoke -- build, run smoke tests build.cmd ci -- build, run the same tests as CI build.cmd all -- build, run all tests + build.cmd notests -- turn off testing (used in conjunction with other options) + + build.cmd test-smoke -- build, run smoke tests + build.cmd test-coreunit -- build, run FSharp.Core tests + build.cmd test-coreclr -- build, run CoreCLR tests + build.cmd test-pcls -- build, run PCL tests + build.cmd test-fsharp -- build, run tests\fsharp suite + build.cmd test-fsharpqa -- build, run tests\fsharpqa suite + build.cmd test-vs -- build, run Visual F# IDE Tools unit tests Combinations are also allowed: - build.cmd debug,compiler,smoke -- build the debug compiler and run smoke tests + build.cmd debug,compiler,notests -- build the debug compiler and run smoke tests After you build the first time you can open and use this solution: diff --git a/DotnetCLIVersion.txt b/DotnetCLIVersion.txt new file mode 100644 index 00000000000..34a7239cbdd --- /dev/null +++ b/DotnetCLIVersion.txt @@ -0,0 +1 @@ +1.0.0-beta-002173 \ No newline at end of file diff --git a/VisualFSharp.sln b/VisualFSharp.sln index 60aa9be6fbf..0bc7980829a 100644 --- a/VisualFSharp.sln +++ b/VisualFSharp.sln @@ -136,10 +136,6 @@ Global Proto|x86 = Proto|x86 Release|Any CPU = Release|Any CPU Release|x86 = Release|x86 - VSDebug|Any CPU = VSDebug|Any CPU - VSDebug|x86 = VSDebug|x86 - VSRelease|Any CPU = VSRelease|Any CPU - VSRelease|x86 = VSRelease|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU @@ -154,14 +150,6 @@ Global {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.Release|Any CPU.Build.0 = Release|Any CPU {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.Release|x86.ActiveCfg = Release|Any CPU {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.Release|x86.Build.0 = Release|Any CPU - {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.VSRelease|x86.Build.0 = VSRelease|Any CPU {493D19F9-35A4-4D0B-9B25-CA948823B709}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {493D19F9-35A4-4D0B-9B25-CA948823B709}.Debug|Any CPU.Build.0 = Debug|Any CPU {493D19F9-35A4-4D0B-9B25-CA948823B709}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -174,14 +162,6 @@ Global {493D19F9-35A4-4D0B-9B25-CA948823B709}.Release|Any CPU.Build.0 = Release|Any CPU {493D19F9-35A4-4D0B-9B25-CA948823B709}.Release|x86.ActiveCfg = Release|Any CPU {493D19F9-35A4-4D0B-9B25-CA948823B709}.Release|x86.Build.0 = Release|Any CPU - {493D19F9-35A4-4D0B-9B25-CA948823B709}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {493D19F9-35A4-4D0B-9B25-CA948823B709}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {493D19F9-35A4-4D0B-9B25-CA948823B709}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {493D19F9-35A4-4D0B-9B25-CA948823B709}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {493D19F9-35A4-4D0B-9B25-CA948823B709}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {493D19F9-35A4-4D0B-9B25-CA948823B709}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {493D19F9-35A4-4D0B-9B25-CA948823B709}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {493D19F9-35A4-4D0B-9B25-CA948823B709}.VSRelease|x86.Build.0 = VSRelease|Any CPU {530DF8CA-7996-407A-B533-D0C2873257AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {530DF8CA-7996-407A-B533-D0C2873257AF}.Debug|Any CPU.Build.0 = Debug|Any CPU {530DF8CA-7996-407A-B533-D0C2873257AF}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -194,14 +174,6 @@ Global {530DF8CA-7996-407A-B533-D0C2873257AF}.Release|Any CPU.Build.0 = Release|Any CPU {530DF8CA-7996-407A-B533-D0C2873257AF}.Release|x86.ActiveCfg = Release|Any CPU {530DF8CA-7996-407A-B533-D0C2873257AF}.Release|x86.Build.0 = Release|Any CPU - {530DF8CA-7996-407A-B533-D0C2873257AF}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {530DF8CA-7996-407A-B533-D0C2873257AF}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {530DF8CA-7996-407A-B533-D0C2873257AF}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {530DF8CA-7996-407A-B533-D0C2873257AF}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {530DF8CA-7996-407A-B533-D0C2873257AF}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {530DF8CA-7996-407A-B533-D0C2873257AF}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {530DF8CA-7996-407A-B533-D0C2873257AF}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {530DF8CA-7996-407A-B533-D0C2873257AF}.VSRelease|x86.Build.0 = VSRelease|Any CPU {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.Debug|Any CPU.Build.0 = Debug|Any CPU {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -214,14 +186,6 @@ Global {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.Release|Any CPU.Build.0 = Release|Any CPU {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.Release|x86.ActiveCfg = Release|Any CPU {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.Release|x86.Build.0 = Release|Any CPU - {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.VSRelease|x86.Build.0 = VSRelease|Any CPU {2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}.Debug|Any CPU.Build.0 = Debug|Any CPU {2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -234,14 +198,6 @@ Global {2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}.Release|Any CPU.Build.0 = Release|Any CPU {2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}.Release|x86.ActiveCfg = Release|Any CPU {2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}.Release|x86.Build.0 = Release|Any CPU - {2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}.VSRelease|x86.Build.0 = VSRelease|Any CPU {991DCF75-C2EB-42B6-9A0D-AA1D2409D519}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {991DCF75-C2EB-42B6-9A0D-AA1D2409D519}.Debug|Any CPU.Build.0 = Debug|Any CPU {991DCF75-C2EB-42B6-9A0D-AA1D2409D519}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -254,14 +210,6 @@ Global {991DCF75-C2EB-42B6-9A0D-AA1D2409D519}.Release|Any CPU.Build.0 = Release|Any CPU {991DCF75-C2EB-42B6-9A0D-AA1D2409D519}.Release|x86.ActiveCfg = Release|Any CPU {991DCF75-C2EB-42B6-9A0D-AA1D2409D519}.Release|x86.Build.0 = Release|Any CPU - {991DCF75-C2EB-42B6-9A0D-AA1D2409D519}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {991DCF75-C2EB-42B6-9A0D-AA1D2409D519}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {991DCF75-C2EB-42B6-9A0D-AA1D2409D519}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {991DCF75-C2EB-42B6-9A0D-AA1D2409D519}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {991DCF75-C2EB-42B6-9A0D-AA1D2409D519}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {991DCF75-C2EB-42B6-9A0D-AA1D2409D519}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {991DCF75-C2EB-42B6-9A0D-AA1D2409D519}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {991DCF75-C2EB-42B6-9A0D-AA1D2409D519}.VSRelease|x86.Build.0 = VSRelease|Any CPU {D5870CF0-ED51-4CBC-B3D7-6F56DA84AC06}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D5870CF0-ED51-4CBC-B3D7-6F56DA84AC06}.Debug|Any CPU.Build.0 = Debug|Any CPU {D5870CF0-ED51-4CBC-B3D7-6F56DA84AC06}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -274,14 +222,6 @@ Global {D5870CF0-ED51-4CBC-B3D7-6F56DA84AC06}.Release|Any CPU.Build.0 = Release|Any CPU {D5870CF0-ED51-4CBC-B3D7-6F56DA84AC06}.Release|x86.ActiveCfg = Release|Any CPU {D5870CF0-ED51-4CBC-B3D7-6F56DA84AC06}.Release|x86.Build.0 = Release|Any CPU - {D5870CF0-ED51-4CBC-B3D7-6F56DA84AC06}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {D5870CF0-ED51-4CBC-B3D7-6F56DA84AC06}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {D5870CF0-ED51-4CBC-B3D7-6F56DA84AC06}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {D5870CF0-ED51-4CBC-B3D7-6F56DA84AC06}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {D5870CF0-ED51-4CBC-B3D7-6F56DA84AC06}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {D5870CF0-ED51-4CBC-B3D7-6F56DA84AC06}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {D5870CF0-ED51-4CBC-B3D7-6F56DA84AC06}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {D5870CF0-ED51-4CBC-B3D7-6F56DA84AC06}.VSRelease|x86.Build.0 = VSRelease|Any CPU {DED3BBD7-53F4-428A-8C9F-27968E768605}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {DED3BBD7-53F4-428A-8C9F-27968E768605}.Debug|Any CPU.Build.0 = Debug|Any CPU {DED3BBD7-53F4-428A-8C9F-27968E768605}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -294,14 +234,6 @@ Global {DED3BBD7-53F4-428A-8C9F-27968E768605}.Release|Any CPU.Build.0 = Release|Any CPU {DED3BBD7-53F4-428A-8C9F-27968E768605}.Release|x86.ActiveCfg = Release|Any CPU {DED3BBD7-53F4-428A-8C9F-27968E768605}.Release|x86.Build.0 = Release|Any CPU - {DED3BBD7-53F4-428A-8C9F-27968E768605}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {DED3BBD7-53F4-428A-8C9F-27968E768605}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {DED3BBD7-53F4-428A-8C9F-27968E768605}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {DED3BBD7-53F4-428A-8C9F-27968E768605}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {DED3BBD7-53F4-428A-8C9F-27968E768605}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {DED3BBD7-53F4-428A-8C9F-27968E768605}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {DED3BBD7-53F4-428A-8C9F-27968E768605}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {DED3BBD7-53F4-428A-8C9F-27968E768605}.VSRelease|x86.Build.0 = VSRelease|Any CPU {A437A6EC-5323-47C2-8F86-E2CAC54FF152}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A437A6EC-5323-47C2-8F86-E2CAC54FF152}.Debug|Any CPU.Build.0 = Debug|Any CPU {A437A6EC-5323-47C2-8F86-E2CAC54FF152}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -314,14 +246,6 @@ Global {A437A6EC-5323-47C2-8F86-E2CAC54FF152}.Release|Any CPU.Build.0 = Release|Any CPU {A437A6EC-5323-47C2-8F86-E2CAC54FF152}.Release|x86.ActiveCfg = Release|Any CPU {A437A6EC-5323-47C2-8F86-E2CAC54FF152}.Release|x86.Build.0 = Release|Any CPU - {A437A6EC-5323-47C2-8F86-E2CAC54FF152}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {A437A6EC-5323-47C2-8F86-E2CAC54FF152}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {A437A6EC-5323-47C2-8F86-E2CAC54FF152}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {A437A6EC-5323-47C2-8F86-E2CAC54FF152}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {A437A6EC-5323-47C2-8F86-E2CAC54FF152}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {A437A6EC-5323-47C2-8F86-E2CAC54FF152}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {A437A6EC-5323-47C2-8F86-E2CAC54FF152}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {A437A6EC-5323-47C2-8F86-E2CAC54FF152}.VSRelease|x86.Build.0 = VSRelease|Any CPU {EE85AAB7-CDA0-4C4E-BDA0-A64CCC413E3F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {EE85AAB7-CDA0-4C4E-BDA0-A64CCC413E3F}.Debug|Any CPU.Build.0 = Debug|Any CPU {EE85AAB7-CDA0-4C4E-BDA0-A64CCC413E3F}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -334,14 +258,6 @@ Global {EE85AAB7-CDA0-4C4E-BDA0-A64CCC413E3F}.Release|Any CPU.Build.0 = Release|Any CPU {EE85AAB7-CDA0-4C4E-BDA0-A64CCC413E3F}.Release|x86.ActiveCfg = Release|Any CPU {EE85AAB7-CDA0-4C4E-BDA0-A64CCC413E3F}.Release|x86.Build.0 = Release|Any CPU - {EE85AAB7-CDA0-4C4E-BDA0-A64CCC413E3F}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {EE85AAB7-CDA0-4C4E-BDA0-A64CCC413E3F}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {EE85AAB7-CDA0-4C4E-BDA0-A64CCC413E3F}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {EE85AAB7-CDA0-4C4E-BDA0-A64CCC413E3F}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {EE85AAB7-CDA0-4C4E-BDA0-A64CCC413E3F}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {EE85AAB7-CDA0-4C4E-BDA0-A64CCC413E3F}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {EE85AAB7-CDA0-4C4E-BDA0-A64CCC413E3F}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {EE85AAB7-CDA0-4C4E-BDA0-A64CCC413E3F}.VSRelease|x86.Build.0 = VSRelease|Any CPU {1C5C163C-37EA-4A3C-8CCC-0D34B74BF8EF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1C5C163C-37EA-4A3C-8CCC-0D34B74BF8EF}.Debug|Any CPU.Build.0 = Debug|Any CPU {1C5C163C-37EA-4A3C-8CCC-0D34B74BF8EF}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -354,14 +270,6 @@ Global {1C5C163C-37EA-4A3C-8CCC-0D34B74BF8EF}.Release|Any CPU.Build.0 = Release|Any CPU {1C5C163C-37EA-4A3C-8CCC-0D34B74BF8EF}.Release|x86.ActiveCfg = Release|Any CPU {1C5C163C-37EA-4A3C-8CCC-0D34B74BF8EF}.Release|x86.Build.0 = Release|Any CPU - {1C5C163C-37EA-4A3C-8CCC-0D34B74BF8EF}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {1C5C163C-37EA-4A3C-8CCC-0D34B74BF8EF}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {1C5C163C-37EA-4A3C-8CCC-0D34B74BF8EF}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {1C5C163C-37EA-4A3C-8CCC-0D34B74BF8EF}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {1C5C163C-37EA-4A3C-8CCC-0D34B74BF8EF}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {1C5C163C-37EA-4A3C-8CCC-0D34B74BF8EF}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {1C5C163C-37EA-4A3C-8CCC-0D34B74BF8EF}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {1C5C163C-37EA-4A3C-8CCC-0D34B74BF8EF}.VSRelease|x86.Build.0 = VSRelease|Any CPU {65E0E82A-EACE-4787-8994-888674C2FE87}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {65E0E82A-EACE-4787-8994-888674C2FE87}.Debug|Any CPU.Build.0 = Debug|Any CPU {65E0E82A-EACE-4787-8994-888674C2FE87}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -374,14 +282,6 @@ Global {65E0E82A-EACE-4787-8994-888674C2FE87}.Release|Any CPU.Build.0 = Release|Any CPU {65E0E82A-EACE-4787-8994-888674C2FE87}.Release|x86.ActiveCfg = Release|Any CPU {65E0E82A-EACE-4787-8994-888674C2FE87}.Release|x86.Build.0 = Release|Any CPU - {65E0E82A-EACE-4787-8994-888674C2FE87}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {65E0E82A-EACE-4787-8994-888674C2FE87}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {65E0E82A-EACE-4787-8994-888674C2FE87}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {65E0E82A-EACE-4787-8994-888674C2FE87}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {65E0E82A-EACE-4787-8994-888674C2FE87}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {65E0E82A-EACE-4787-8994-888674C2FE87}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {65E0E82A-EACE-4787-8994-888674C2FE87}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {65E0E82A-EACE-4787-8994-888674C2FE87}.VSRelease|x86.Build.0 = VSRelease|Any CPU {B700E38B-F8C0-4E49-B5EC-DB7B7AC0C4E7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B700E38B-F8C0-4E49-B5EC-DB7B7AC0C4E7}.Debug|Any CPU.Build.0 = Debug|Any CPU {B700E38B-F8C0-4E49-B5EC-DB7B7AC0C4E7}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -394,14 +294,6 @@ Global {B700E38B-F8C0-4E49-B5EC-DB7B7AC0C4E7}.Release|Any CPU.Build.0 = Release|Any CPU {B700E38B-F8C0-4E49-B5EC-DB7B7AC0C4E7}.Release|x86.ActiveCfg = Release|Any CPU {B700E38B-F8C0-4E49-B5EC-DB7B7AC0C4E7}.Release|x86.Build.0 = Release|Any CPU - {B700E38B-F8C0-4E49-B5EC-DB7B7AC0C4E7}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {B700E38B-F8C0-4E49-B5EC-DB7B7AC0C4E7}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {B700E38B-F8C0-4E49-B5EC-DB7B7AC0C4E7}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {B700E38B-F8C0-4E49-B5EC-DB7B7AC0C4E7}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {B700E38B-F8C0-4E49-B5EC-DB7B7AC0C4E7}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {B700E38B-F8C0-4E49-B5EC-DB7B7AC0C4E7}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {B700E38B-F8C0-4E49-B5EC-DB7B7AC0C4E7}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {B700E38B-F8C0-4E49-B5EC-DB7B7AC0C4E7}.VSRelease|x86.Build.0 = VSRelease|Any CPU {FCFB214C-462E-42B3-91CA-FC557EFEE74F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {FCFB214C-462E-42B3-91CA-FC557EFEE74F}.Debug|Any CPU.Build.0 = Debug|Any CPU {FCFB214C-462E-42B3-91CA-FC557EFEE74F}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -414,14 +306,6 @@ Global {FCFB214C-462E-42B3-91CA-FC557EFEE74F}.Release|Any CPU.Build.0 = Release|Any CPU {FCFB214C-462E-42B3-91CA-FC557EFEE74F}.Release|x86.ActiveCfg = Release|Any CPU {FCFB214C-462E-42B3-91CA-FC557EFEE74F}.Release|x86.Build.0 = Release|Any CPU - {FCFB214C-462E-42B3-91CA-FC557EFEE74F}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {FCFB214C-462E-42B3-91CA-FC557EFEE74F}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {FCFB214C-462E-42B3-91CA-FC557EFEE74F}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {FCFB214C-462E-42B3-91CA-FC557EFEE74F}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {FCFB214C-462E-42B3-91CA-FC557EFEE74F}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {FCFB214C-462E-42B3-91CA-FC557EFEE74F}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {FCFB214C-462E-42B3-91CA-FC557EFEE74F}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {FCFB214C-462E-42B3-91CA-FC557EFEE74F}.VSRelease|x86.Build.0 = VSRelease|Any CPU {6196B0F8-CAEA-4CF1-AF82-1B520F77FE44}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {6196B0F8-CAEA-4CF1-AF82-1B520F77FE44}.Debug|Any CPU.Build.0 = Debug|Any CPU {6196B0F8-CAEA-4CF1-AF82-1B520F77FE44}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -434,14 +318,6 @@ Global {6196B0F8-CAEA-4CF1-AF82-1B520F77FE44}.Release|Any CPU.Build.0 = Release|Any CPU {6196B0F8-CAEA-4CF1-AF82-1B520F77FE44}.Release|x86.ActiveCfg = Release|Any CPU {6196B0F8-CAEA-4CF1-AF82-1B520F77FE44}.Release|x86.Build.0 = Release|Any CPU - {6196B0F8-CAEA-4CF1-AF82-1B520F77FE44}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {6196B0F8-CAEA-4CF1-AF82-1B520F77FE44}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {6196B0F8-CAEA-4CF1-AF82-1B520F77FE44}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {6196B0F8-CAEA-4CF1-AF82-1B520F77FE44}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {6196B0F8-CAEA-4CF1-AF82-1B520F77FE44}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {6196B0F8-CAEA-4CF1-AF82-1B520F77FE44}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {6196B0F8-CAEA-4CF1-AF82-1B520F77FE44}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {6196B0F8-CAEA-4CF1-AF82-1B520F77FE44}.VSRelease|x86.Build.0 = VSRelease|Any CPU {FBD4B354-DC6E-4032-8EC7-C81D8DFB1AF7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {FBD4B354-DC6E-4032-8EC7-C81D8DFB1AF7}.Debug|Any CPU.Build.0 = Debug|Any CPU {FBD4B354-DC6E-4032-8EC7-C81D8DFB1AF7}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -454,14 +330,6 @@ Global {FBD4B354-DC6E-4032-8EC7-C81D8DFB1AF7}.Release|Any CPU.Build.0 = Release|Any CPU {FBD4B354-DC6E-4032-8EC7-C81D8DFB1AF7}.Release|x86.ActiveCfg = Release|Any CPU {FBD4B354-DC6E-4032-8EC7-C81D8DFB1AF7}.Release|x86.Build.0 = Release|Any CPU - {FBD4B354-DC6E-4032-8EC7-C81D8DFB1AF7}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {FBD4B354-DC6E-4032-8EC7-C81D8DFB1AF7}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {FBD4B354-DC6E-4032-8EC7-C81D8DFB1AF7}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {FBD4B354-DC6E-4032-8EC7-C81D8DFB1AF7}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {FBD4B354-DC6E-4032-8EC7-C81D8DFB1AF7}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {FBD4B354-DC6E-4032-8EC7-C81D8DFB1AF7}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {FBD4B354-DC6E-4032-8EC7-C81D8DFB1AF7}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {FBD4B354-DC6E-4032-8EC7-C81D8DFB1AF7}.VSRelease|x86.Build.0 = VSRelease|Any CPU {EE85AAB7-CDA0-4C4E-BDA0-A64DDDD13E3F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {EE85AAB7-CDA0-4C4E-BDA0-A64DDDD13E3F}.Debug|Any CPU.Build.0 = Debug|Any CPU {EE85AAB7-CDA0-4C4E-BDA0-A64DDDD13E3F}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -474,14 +342,6 @@ Global {EE85AAB7-CDA0-4C4E-BDA0-A64DDDD13E3F}.Release|Any CPU.Build.0 = Release|Any CPU {EE85AAB7-CDA0-4C4E-BDA0-A64DDDD13E3F}.Release|x86.ActiveCfg = Release|Any CPU {EE85AAB7-CDA0-4C4E-BDA0-A64DDDD13E3F}.Release|x86.Build.0 = Release|Any CPU - {EE85AAB7-CDA0-4C4E-BDA0-A64DDDD13E3F}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {EE85AAB7-CDA0-4C4E-BDA0-A64DDDD13E3F}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {EE85AAB7-CDA0-4C4E-BDA0-A64DDDD13E3F}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {EE85AAB7-CDA0-4C4E-BDA0-A64DDDD13E3F}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {EE85AAB7-CDA0-4C4E-BDA0-A64DDDD13E3F}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {EE85AAB7-CDA0-4C4E-BDA0-A64DDDD13E3F}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {EE85AAB7-CDA0-4C4E-BDA0-A64DDDD13E3F}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {EE85AAB7-CDA0-4C4E-BDA0-A64DDDD13E3F}.VSRelease|x86.Build.0 = VSRelease|Any CPU {DA39AD38-4A58-47BF-9215-E49768295169}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {DA39AD38-4A58-47BF-9215-E49768295169}.Debug|Any CPU.Build.0 = Debug|Any CPU {DA39AD38-4A58-47BF-9215-E49768295169}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -494,14 +354,6 @@ Global {DA39AD38-4A58-47BF-9215-E49768295169}.Release|Any CPU.Build.0 = Release|Any CPU {DA39AD38-4A58-47BF-9215-E49768295169}.Release|x86.ActiveCfg = Release|Any CPU {DA39AD38-4A58-47BF-9215-E49768295169}.Release|x86.Build.0 = Release|Any CPU - {DA39AD38-4A58-47BF-9215-E49768295169}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {DA39AD38-4A58-47BF-9215-E49768295169}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {DA39AD38-4A58-47BF-9215-E49768295169}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {DA39AD38-4A58-47BF-9215-E49768295169}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {DA39AD38-4A58-47BF-9215-E49768295169}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {DA39AD38-4A58-47BF-9215-E49768295169}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {DA39AD38-4A58-47BF-9215-E49768295169}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {DA39AD38-4A58-47BF-9215-E49768295169}.VSRelease|x86.Build.0 = VSRelease|Any CPU {8C2439BD-0E49-4929-A8B1-29CEE228191E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8C2439BD-0E49-4929-A8B1-29CEE228191E}.Debug|Any CPU.Build.0 = Debug|Any CPU {8C2439BD-0E49-4929-A8B1-29CEE228191E}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -514,14 +366,6 @@ Global {8C2439BD-0E49-4929-A8B1-29CEE228191E}.Release|Any CPU.Build.0 = Release|Any CPU {8C2439BD-0E49-4929-A8B1-29CEE228191E}.Release|x86.ActiveCfg = Release|Any CPU {8C2439BD-0E49-4929-A8B1-29CEE228191E}.Release|x86.Build.0 = Release|Any CPU - {8C2439BD-0E49-4929-A8B1-29CEE228191E}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {8C2439BD-0E49-4929-A8B1-29CEE228191E}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {8C2439BD-0E49-4929-A8B1-29CEE228191E}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {8C2439BD-0E49-4929-A8B1-29CEE228191E}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {8C2439BD-0E49-4929-A8B1-29CEE228191E}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {8C2439BD-0E49-4929-A8B1-29CEE228191E}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {8C2439BD-0E49-4929-A8B1-29CEE228191E}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {8C2439BD-0E49-4929-A8B1-29CEE228191E}.VSRelease|x86.Build.0 = VSRelease|Any CPU {F47196DC-186D-4055-BAF2-658282A12F33}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F47196DC-186D-4055-BAF2-658282A12F33}.Debug|Any CPU.Build.0 = Debug|Any CPU {F47196DC-186D-4055-BAF2-658282A12F33}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -534,14 +378,6 @@ Global {F47196DC-186D-4055-BAF2-658282A12F33}.Release|Any CPU.Build.0 = Release|Any CPU {F47196DC-186D-4055-BAF2-658282A12F33}.Release|x86.ActiveCfg = Release|Any CPU {F47196DC-186D-4055-BAF2-658282A12F33}.Release|x86.Build.0 = Release|Any CPU - {F47196DC-186D-4055-BAF2-658282A12F33}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {F47196DC-186D-4055-BAF2-658282A12F33}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {F47196DC-186D-4055-BAF2-658282A12F33}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {F47196DC-186D-4055-BAF2-658282A12F33}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {F47196DC-186D-4055-BAF2-658282A12F33}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {F47196DC-186D-4055-BAF2-658282A12F33}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {F47196DC-186D-4055-BAF2-658282A12F33}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {F47196DC-186D-4055-BAF2-658282A12F33}.VSRelease|x86.Build.0 = VSRelease|Any CPU {D4C88934-5893-467E-A55C-A11ECD6479FE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D4C88934-5893-467E-A55C-A11ECD6479FE}.Debug|Any CPU.Build.0 = Debug|Any CPU {D4C88934-5893-467E-A55C-A11ECD6479FE}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -554,14 +390,6 @@ Global {D4C88934-5893-467E-A55C-A11ECD6479FE}.Release|Any CPU.Build.0 = Release|Any CPU {D4C88934-5893-467E-A55C-A11ECD6479FE}.Release|x86.ActiveCfg = Release|Any CPU {D4C88934-5893-467E-A55C-A11ECD6479FE}.Release|x86.Build.0 = Release|Any CPU - {D4C88934-5893-467E-A55C-A11ECD6479FE}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {D4C88934-5893-467E-A55C-A11ECD6479FE}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {D4C88934-5893-467E-A55C-A11ECD6479FE}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {D4C88934-5893-467E-A55C-A11ECD6479FE}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {D4C88934-5893-467E-A55C-A11ECD6479FE}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {D4C88934-5893-467E-A55C-A11ECD6479FE}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {D4C88934-5893-467E-A55C-A11ECD6479FE}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {D4C88934-5893-467E-A55C-A11ECD6479FE}.VSRelease|x86.Build.0 = VSRelease|Any CPU {6AFF752D-E991-4A08-9ED2-5BF46B0E0F8B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {6AFF752D-E991-4A08-9ED2-5BF46B0E0F8B}.Debug|Any CPU.Build.0 = Debug|Any CPU {6AFF752D-E991-4A08-9ED2-5BF46B0E0F8B}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -574,14 +402,6 @@ Global {6AFF752D-E991-4A08-9ED2-5BF46B0E0F8B}.Release|Any CPU.Build.0 = Release|Any CPU {6AFF752D-E991-4A08-9ED2-5BF46B0E0F8B}.Release|x86.ActiveCfg = Release|Any CPU {6AFF752D-E991-4A08-9ED2-5BF46B0E0F8B}.Release|x86.Build.0 = Release|Any CPU - {6AFF752D-E991-4A08-9ED2-5BF46B0E0F8B}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {6AFF752D-E991-4A08-9ED2-5BF46B0E0F8B}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {6AFF752D-E991-4A08-9ED2-5BF46B0E0F8B}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {6AFF752D-E991-4A08-9ED2-5BF46B0E0F8B}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {6AFF752D-E991-4A08-9ED2-5BF46B0E0F8B}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {6AFF752D-E991-4A08-9ED2-5BF46B0E0F8B}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {6AFF752D-E991-4A08-9ED2-5BF46B0E0F8B}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {6AFF752D-E991-4A08-9ED2-5BF46B0E0F8B}.VSRelease|x86.Build.0 = VSRelease|Any CPU {0B9CDEAF-EE8F-45E0-A4E0-34A8ED6DD09E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {0B9CDEAF-EE8F-45E0-A4E0-34A8ED6DD09E}.Debug|Any CPU.Build.0 = Debug|Any CPU {0B9CDEAF-EE8F-45E0-A4E0-34A8ED6DD09E}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -594,14 +414,6 @@ Global {0B9CDEAF-EE8F-45E0-A4E0-34A8ED6DD09E}.Release|Any CPU.Build.0 = Release|Any CPU {0B9CDEAF-EE8F-45E0-A4E0-34A8ED6DD09E}.Release|x86.ActiveCfg = Release|Any CPU {0B9CDEAF-EE8F-45E0-A4E0-34A8ED6DD09E}.Release|x86.Build.0 = Release|Any CPU - {0B9CDEAF-EE8F-45E0-A4E0-34A8ED6DD09E}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {0B9CDEAF-EE8F-45E0-A4E0-34A8ED6DD09E}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {0B9CDEAF-EE8F-45E0-A4E0-34A8ED6DD09E}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {0B9CDEAF-EE8F-45E0-A4E0-34A8ED6DD09E}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {0B9CDEAF-EE8F-45E0-A4E0-34A8ED6DD09E}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {0B9CDEAF-EE8F-45E0-A4E0-34A8ED6DD09E}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {0B9CDEAF-EE8F-45E0-A4E0-34A8ED6DD09E}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {0B9CDEAF-EE8F-45E0-A4E0-34A8ED6DD09E}.VSRelease|x86.Build.0 = VSRelease|Any CPU {004982C6-93EA-4E70-B4F0-BE7D7219926A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {004982C6-93EA-4E70-B4F0-BE7D7219926A}.Debug|Any CPU.Build.0 = Debug|Any CPU {004982C6-93EA-4E70-B4F0-BE7D7219926A}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -614,14 +426,6 @@ Global {004982C6-93EA-4E70-B4F0-BE7D7219926A}.Release|Any CPU.Build.0 = Release|Any CPU {004982C6-93EA-4E70-B4F0-BE7D7219926A}.Release|x86.ActiveCfg = Release|Any CPU {004982C6-93EA-4E70-B4F0-BE7D7219926A}.Release|x86.Build.0 = Release|Any CPU - {004982C6-93EA-4E70-B4F0-BE7D7219926A}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {004982C6-93EA-4E70-B4F0-BE7D7219926A}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {004982C6-93EA-4E70-B4F0-BE7D7219926A}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {004982C6-93EA-4E70-B4F0-BE7D7219926A}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {004982C6-93EA-4E70-B4F0-BE7D7219926A}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {004982C6-93EA-4E70-B4F0-BE7D7219926A}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {004982C6-93EA-4E70-B4F0-BE7D7219926A}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {004982C6-93EA-4E70-B4F0-BE7D7219926A}.VSRelease|x86.Build.0 = VSRelease|Any CPU {243A81AC-A954-4601-833A-60EEEFB00FCD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {243A81AC-A954-4601-833A-60EEEFB00FCD}.Debug|Any CPU.Build.0 = Debug|Any CPU {243A81AC-A954-4601-833A-60EEEFB00FCD}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -634,14 +438,6 @@ Global {243A81AC-A954-4601-833A-60EEEFB00FCD}.Release|Any CPU.Build.0 = Release|Any CPU {243A81AC-A954-4601-833A-60EEEFB00FCD}.Release|x86.ActiveCfg = Release|Any CPU {243A81AC-A954-4601-833A-60EEEFB00FCD}.Release|x86.Build.0 = Release|Any CPU - {243A81AC-A954-4601-833A-60EEEFB00FCD}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {243A81AC-A954-4601-833A-60EEEFB00FCD}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {243A81AC-A954-4601-833A-60EEEFB00FCD}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {243A81AC-A954-4601-833A-60EEEFB00FCD}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {243A81AC-A954-4601-833A-60EEEFB00FCD}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {243A81AC-A954-4601-833A-60EEEFB00FCD}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {243A81AC-A954-4601-833A-60EEEFB00FCD}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {243A81AC-A954-4601-833A-60EEEFB00FCD}.VSRelease|x86.Build.0 = VSRelease|Any CPU {B4595EB6-053A-400E-AA1B-7727F1BC900F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B4595EB6-053A-400E-AA1B-7727F1BC900F}.Debug|Any CPU.Build.0 = Debug|Any CPU {B4595EB6-053A-400E-AA1B-7727F1BC900F}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -654,14 +450,6 @@ Global {B4595EB6-053A-400E-AA1B-7727F1BC900F}.Release|Any CPU.Build.0 = Release|Any CPU {B4595EB6-053A-400E-AA1B-7727F1BC900F}.Release|x86.ActiveCfg = Release|Any CPU {B4595EB6-053A-400E-AA1B-7727F1BC900F}.Release|x86.Build.0 = Release|Any CPU - {B4595EB6-053A-400E-AA1B-7727F1BC900F}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {B4595EB6-053A-400E-AA1B-7727F1BC900F}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {B4595EB6-053A-400E-AA1B-7727F1BC900F}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {B4595EB6-053A-400E-AA1B-7727F1BC900F}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {B4595EB6-053A-400E-AA1B-7727F1BC900F}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {B4595EB6-053A-400E-AA1B-7727F1BC900F}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {B4595EB6-053A-400E-AA1B-7727F1BC900F}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {B4595EB6-053A-400E-AA1B-7727F1BC900F}.VSRelease|x86.Build.0 = VSRelease|Any CPU {A559D7E8-7EFD-473A-B618-A10B41AB523B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A559D7E8-7EFD-473A-B618-A10B41AB523B}.Debug|Any CPU.Build.0 = Debug|Any CPU {A559D7E8-7EFD-473A-B618-A10B41AB523B}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -674,14 +462,6 @@ Global {A559D7E8-7EFD-473A-B618-A10B41AB523B}.Release|Any CPU.Build.0 = Release|Any CPU {A559D7E8-7EFD-473A-B618-A10B41AB523B}.Release|x86.ActiveCfg = Release|Any CPU {A559D7E8-7EFD-473A-B618-A10B41AB523B}.Release|x86.Build.0 = Release|Any CPU - {A559D7E8-7EFD-473A-B618-A10B41AB523B}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {A559D7E8-7EFD-473A-B618-A10B41AB523B}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {A559D7E8-7EFD-473A-B618-A10B41AB523B}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {A559D7E8-7EFD-473A-B618-A10B41AB523B}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {A559D7E8-7EFD-473A-B618-A10B41AB523B}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {A559D7E8-7EFD-473A-B618-A10B41AB523B}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {A559D7E8-7EFD-473A-B618-A10B41AB523B}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {A559D7E8-7EFD-473A-B618-A10B41AB523B}.VSRelease|x86.Build.0 = VSRelease|Any CPU {AC85EE6D-033C-45F9-B8BA-884BC22EC6D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {AC85EE6D-033C-45F9-B8BA-884BC22EC6D9}.Debug|Any CPU.Build.0 = Debug|Any CPU {AC85EE6D-033C-45F9-B8BA-884BC22EC6D9}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -694,14 +474,6 @@ Global {AC85EE6D-033C-45F9-B8BA-884BC22EC6D9}.Release|Any CPU.Build.0 = Release|Any CPU {AC85EE6D-033C-45F9-B8BA-884BC22EC6D9}.Release|x86.ActiveCfg = Release|Any CPU {AC85EE6D-033C-45F9-B8BA-884BC22EC6D9}.Release|x86.Build.0 = Release|Any CPU - {AC85EE6D-033C-45F9-B8BA-884BC22EC6D9}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {AC85EE6D-033C-45F9-B8BA-884BC22EC6D9}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {AC85EE6D-033C-45F9-B8BA-884BC22EC6D9}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {AC85EE6D-033C-45F9-B8BA-884BC22EC6D9}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {AC85EE6D-033C-45F9-B8BA-884BC22EC6D9}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {AC85EE6D-033C-45F9-B8BA-884BC22EC6D9}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {AC85EE6D-033C-45F9-B8BA-884BC22EC6D9}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {AC85EE6D-033C-45F9-B8BA-884BC22EC6D9}.VSRelease|x86.Build.0 = VSRelease|Any CPU {956BBE41-ABD1-4DBA-9F3B-BA1C9821C98C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {956BBE41-ABD1-4DBA-9F3B-BA1C9821C98C}.Debug|Any CPU.Build.0 = Debug|Any CPU {956BBE41-ABD1-4DBA-9F3B-BA1C9821C98C}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -714,14 +486,6 @@ Global {956BBE41-ABD1-4DBA-9F3B-BA1C9821C98C}.Release|Any CPU.Build.0 = Release|Any CPU {956BBE41-ABD1-4DBA-9F3B-BA1C9821C98C}.Release|x86.ActiveCfg = Release|Any CPU {956BBE41-ABD1-4DBA-9F3B-BA1C9821C98C}.Release|x86.Build.0 = Release|Any CPU - {956BBE41-ABD1-4DBA-9F3B-BA1C9821C98C}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {956BBE41-ABD1-4DBA-9F3B-BA1C9821C98C}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {956BBE41-ABD1-4DBA-9F3B-BA1C9821C98C}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {956BBE41-ABD1-4DBA-9F3B-BA1C9821C98C}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {956BBE41-ABD1-4DBA-9F3B-BA1C9821C98C}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {956BBE41-ABD1-4DBA-9F3B-BA1C9821C98C}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {956BBE41-ABD1-4DBA-9F3B-BA1C9821C98C}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {956BBE41-ABD1-4DBA-9F3B-BA1C9821C98C}.VSRelease|x86.Build.0 = VSRelease|Any CPU {702A7979-BCF9-4C41-853E-3ADFC9897890}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {702A7979-BCF9-4C41-853E-3ADFC9897890}.Debug|Any CPU.Build.0 = Debug|Any CPU {702A7979-BCF9-4C41-853E-3ADFC9897890}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -734,14 +498,6 @@ Global {702A7979-BCF9-4C41-853E-3ADFC9897890}.Release|Any CPU.Build.0 = Release|Any CPU {702A7979-BCF9-4C41-853E-3ADFC9897890}.Release|x86.ActiveCfg = Release|Any CPU {702A7979-BCF9-4C41-853E-3ADFC9897890}.Release|x86.Build.0 = Release|Any CPU - {702A7979-BCF9-4C41-853E-3ADFC9897890}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {702A7979-BCF9-4C41-853E-3ADFC9897890}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {702A7979-BCF9-4C41-853E-3ADFC9897890}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {702A7979-BCF9-4C41-853E-3ADFC9897890}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {702A7979-BCF9-4C41-853E-3ADFC9897890}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {702A7979-BCF9-4C41-853E-3ADFC9897890}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {702A7979-BCF9-4C41-853E-3ADFC9897890}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {702A7979-BCF9-4C41-853E-3ADFC9897890}.VSRelease|x86.Build.0 = VSRelease|Any CPU {C94C257C-3C0A-4858-B5D8-D746498D1F08}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C94C257C-3C0A-4858-B5D8-D746498D1F08}.Debug|Any CPU.Build.0 = Debug|Any CPU {C94C257C-3C0A-4858-B5D8-D746498D1F08}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -754,14 +510,6 @@ Global {C94C257C-3C0A-4858-B5D8-D746498D1F08}.Release|Any CPU.Build.0 = Release|Any CPU {C94C257C-3C0A-4858-B5D8-D746498D1F08}.Release|x86.ActiveCfg = Release|Any CPU {C94C257C-3C0A-4858-B5D8-D746498D1F08}.Release|x86.Build.0 = Release|Any CPU - {C94C257C-3C0A-4858-B5D8-D746498D1F08}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {C94C257C-3C0A-4858-B5D8-D746498D1F08}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {C94C257C-3C0A-4858-B5D8-D746498D1F08}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {C94C257C-3C0A-4858-B5D8-D746498D1F08}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {C94C257C-3C0A-4858-B5D8-D746498D1F08}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {C94C257C-3C0A-4858-B5D8-D746498D1F08}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {C94C257C-3C0A-4858-B5D8-D746498D1F08}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {C94C257C-3C0A-4858-B5D8-D746498D1F08}.VSRelease|x86.Build.0 = VSRelease|Any CPU {CB7D20C4-6506-406D-9144-5342C3595F03}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CB7D20C4-6506-406D-9144-5342C3595F03}.Debug|Any CPU.Build.0 = Debug|Any CPU {CB7D20C4-6506-406D-9144-5342C3595F03}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -774,14 +522,6 @@ Global {CB7D20C4-6506-406D-9144-5342C3595F03}.Release|Any CPU.Build.0 = Release|Any CPU {CB7D20C4-6506-406D-9144-5342C3595F03}.Release|x86.ActiveCfg = Release|Any CPU {CB7D20C4-6506-406D-9144-5342C3595F03}.Release|x86.Build.0 = Release|Any CPU - {CB7D20C4-6506-406D-9144-5342C3595F03}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {CB7D20C4-6506-406D-9144-5342C3595F03}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {CB7D20C4-6506-406D-9144-5342C3595F03}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {CB7D20C4-6506-406D-9144-5342C3595F03}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {CB7D20C4-6506-406D-9144-5342C3595F03}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {CB7D20C4-6506-406D-9144-5342C3595F03}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {CB7D20C4-6506-406D-9144-5342C3595F03}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {CB7D20C4-6506-406D-9144-5342C3595F03}.VSRelease|x86.Build.0 = VSRelease|Any CPU {649FA588-F02E-457C-9FCF-87E46407481E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {649FA588-F02E-457C-9FCF-87E46407481E}.Debug|Any CPU.Build.0 = Debug|Any CPU {649FA588-F02E-457C-9FCF-87E46407481E}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -794,14 +534,6 @@ Global {649FA588-F02E-457C-9FCF-87E46407481E}.Release|Any CPU.Build.0 = Release|Any CPU {649FA588-F02E-457C-9FCF-87E46407481E}.Release|x86.ActiveCfg = Release|Any CPU {649FA588-F02E-457C-9FCF-87E46407481E}.Release|x86.Build.0 = Release|Any CPU - {649FA588-F02E-457C-9FCF-87E46407481E}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {649FA588-F02E-457C-9FCF-87E46407481E}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {649FA588-F02E-457C-9FCF-87E46407481E}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {649FA588-F02E-457C-9FCF-87E46407481E}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {649FA588-F02E-457C-9FCF-87E46407481E}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {649FA588-F02E-457C-9FCF-87E46407481E}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {649FA588-F02E-457C-9FCF-87E46407481E}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {649FA588-F02E-457C-9FCF-87E46407481E}.VSRelease|x86.Build.0 = VSRelease|Any CPU {8B3E283D-B5FE-4055-9D80-7E3A32F3967B}.Debug|Any CPU.ActiveCfg = Debug|x86 {8B3E283D-B5FE-4055-9D80-7E3A32F3967B}.Debug|Any CPU.Build.0 = Debug|x86 {8B3E283D-B5FE-4055-9D80-7E3A32F3967B}.Debug|x86.ActiveCfg = Debug|x86 @@ -813,12 +545,6 @@ Global {8B3E283D-B5FE-4055-9D80-7E3A32F3967B}.Release|Any CPU.Build.0 = Release|x86 {8B3E283D-B5FE-4055-9D80-7E3A32F3967B}.Release|x86.ActiveCfg = Release|x86 {8B3E283D-B5FE-4055-9D80-7E3A32F3967B}.Release|x86.Build.0 = Release|x86 - {8B3E283D-B5FE-4055-9D80-7E3A32F3967B}.VSDebug|Any CPU.ActiveCfg = VSDebug|x86 - {8B3E283D-B5FE-4055-9D80-7E3A32F3967B}.VSDebug|x86.ActiveCfg = VSDebug|x86 - {8B3E283D-B5FE-4055-9D80-7E3A32F3967B}.VSDebug|x86.Build.0 = VSDebug|x86 - {8B3E283D-B5FE-4055-9D80-7E3A32F3967B}.VSRelease|Any CPU.ActiveCfg = VSRelease|x86 - {8B3E283D-B5FE-4055-9D80-7E3A32F3967B}.VSRelease|x86.ActiveCfg = VSRelease|x86 - {8B3E283D-B5FE-4055-9D80-7E3A32F3967B}.VSRelease|x86.Build.0 = VSRelease|x86 {D0E98C0D-490B-4C61-9329-0862F6E87645}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D0E98C0D-490B-4C61-9329-0862F6E87645}.Debug|Any CPU.Build.0 = Debug|Any CPU {D0E98C0D-490B-4C61-9329-0862F6E87645}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -831,14 +557,6 @@ Global {D0E98C0D-490B-4C61-9329-0862F6E87645}.Release|Any CPU.Build.0 = Release|Any CPU {D0E98C0D-490B-4C61-9329-0862F6E87645}.Release|x86.ActiveCfg = Release|Any CPU {D0E98C0D-490B-4C61-9329-0862F6E87645}.Release|x86.Build.0 = Release|Any CPU - {D0E98C0D-490B-4C61-9329-0862F6E87645}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {D0E98C0D-490B-4C61-9329-0862F6E87645}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {D0E98C0D-490B-4C61-9329-0862F6E87645}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {D0E98C0D-490B-4C61-9329-0862F6E87645}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {D0E98C0D-490B-4C61-9329-0862F6E87645}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {D0E98C0D-490B-4C61-9329-0862F6E87645}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {D0E98C0D-490B-4C61-9329-0862F6E87645}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {D0E98C0D-490B-4C61-9329-0862F6E87645}.VSRelease|x86.Build.0 = VSRelease|Any CPU {C163E892-5BF7-4B59-AA99-B0E8079C67C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C163E892-5BF7-4B59-AA99-B0E8079C67C4}.Debug|Any CPU.Build.0 = Debug|Any CPU {C163E892-5BF7-4B59-AA99-B0E8079C67C4}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -851,14 +569,6 @@ Global {C163E892-5BF7-4B59-AA99-B0E8079C67C4}.Release|Any CPU.Build.0 = Release|Any CPU {C163E892-5BF7-4B59-AA99-B0E8079C67C4}.Release|x86.ActiveCfg = Release|Any CPU {C163E892-5BF7-4B59-AA99-B0E8079C67C4}.Release|x86.Build.0 = Release|Any CPU - {C163E892-5BF7-4B59-AA99-B0E8079C67C4}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {C163E892-5BF7-4B59-AA99-B0E8079C67C4}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {C163E892-5BF7-4B59-AA99-B0E8079C67C4}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {C163E892-5BF7-4B59-AA99-B0E8079C67C4}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {C163E892-5BF7-4B59-AA99-B0E8079C67C4}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {C163E892-5BF7-4B59-AA99-B0E8079C67C4}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {C163E892-5BF7-4B59-AA99-B0E8079C67C4}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {C163E892-5BF7-4B59-AA99-B0E8079C67C4}.VSRelease|x86.Build.0 = VSRelease|Any CPU {A8D9641A-9170-4CF4-8FE0-6DB8C134E1B5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A8D9641A-9170-4CF4-8FE0-6DB8C134E1B5}.Debug|Any CPU.Build.0 = Debug|Any CPU {A8D9641A-9170-4CF4-8FE0-6DB8C134E1B5}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -871,14 +581,6 @@ Global {A8D9641A-9170-4CF4-8FE0-6DB8C134E1B5}.Release|Any CPU.Build.0 = Release|Any CPU {A8D9641A-9170-4CF4-8FE0-6DB8C134E1B5}.Release|x86.ActiveCfg = Release|Any CPU {A8D9641A-9170-4CF4-8FE0-6DB8C134E1B5}.Release|x86.Build.0 = Release|Any CPU - {A8D9641A-9170-4CF4-8FE0-6DB8C134E1B5}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {A8D9641A-9170-4CF4-8FE0-6DB8C134E1B5}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {A8D9641A-9170-4CF4-8FE0-6DB8C134E1B5}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {A8D9641A-9170-4CF4-8FE0-6DB8C134E1B5}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {A8D9641A-9170-4CF4-8FE0-6DB8C134E1B5}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {A8D9641A-9170-4CF4-8FE0-6DB8C134E1B5}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {A8D9641A-9170-4CF4-8FE0-6DB8C134E1B5}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {A8D9641A-9170-4CF4-8FE0-6DB8C134E1B5}.VSRelease|x86.Build.0 = VSRelease|Any CPU {88E2D422-6852-46E3-A740-83E391DC7973}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {88E2D422-6852-46E3-A740-83E391DC7973}.Debug|Any CPU.Build.0 = Debug|Any CPU {88E2D422-6852-46E3-A740-83E391DC7973}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -891,14 +593,6 @@ Global {88E2D422-6852-46E3-A740-83E391DC7973}.Release|Any CPU.Build.0 = Release|Any CPU {88E2D422-6852-46E3-A740-83E391DC7973}.Release|x86.ActiveCfg = Release|Any CPU {88E2D422-6852-46E3-A740-83E391DC7973}.Release|x86.Build.0 = Release|Any CPU - {88E2D422-6852-46E3-A740-83E391DC7973}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {88E2D422-6852-46E3-A740-83E391DC7973}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {88E2D422-6852-46E3-A740-83E391DC7973}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {88E2D422-6852-46E3-A740-83E391DC7973}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {88E2D422-6852-46E3-A740-83E391DC7973}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {88E2D422-6852-46E3-A740-83E391DC7973}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {88E2D422-6852-46E3-A740-83E391DC7973}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {88E2D422-6852-46E3-A740-83E391DC7973}.VSRelease|x86.Build.0 = VSRelease|Any CPU {604F0DAA-2D33-48DD-B162-EDF0B672803D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {604F0DAA-2D33-48DD-B162-EDF0B672803D}.Debug|Any CPU.Build.0 = Debug|Any CPU {604F0DAA-2D33-48DD-B162-EDF0B672803D}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -911,14 +605,6 @@ Global {604F0DAA-2D33-48DD-B162-EDF0B672803D}.Release|Any CPU.Build.0 = Release|Any CPU {604F0DAA-2D33-48DD-B162-EDF0B672803D}.Release|x86.ActiveCfg = Release|Any CPU {604F0DAA-2D33-48DD-B162-EDF0B672803D}.Release|x86.Build.0 = Release|Any CPU - {604F0DAA-2D33-48DD-B162-EDF0B672803D}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {604F0DAA-2D33-48DD-B162-EDF0B672803D}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {604F0DAA-2D33-48DD-B162-EDF0B672803D}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {604F0DAA-2D33-48DD-B162-EDF0B672803D}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {604F0DAA-2D33-48DD-B162-EDF0B672803D}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {604F0DAA-2D33-48DD-B162-EDF0B672803D}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {604F0DAA-2D33-48DD-B162-EDF0B672803D}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {604F0DAA-2D33-48DD-B162-EDF0B672803D}.VSRelease|x86.Build.0 = VSRelease|Any CPU {01678CDA-A11F-4DEE-9344-2EDF91CF1AE7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {01678CDA-A11F-4DEE-9344-2EDF91CF1AE7}.Debug|Any CPU.Build.0 = Debug|Any CPU {01678CDA-A11F-4DEE-9344-2EDF91CF1AE7}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -931,14 +617,6 @@ Global {01678CDA-A11F-4DEE-9344-2EDF91CF1AE7}.Release|Any CPU.Build.0 = Release|Any CPU {01678CDA-A11F-4DEE-9344-2EDF91CF1AE7}.Release|x86.ActiveCfg = Release|Any CPU {01678CDA-A11F-4DEE-9344-2EDF91CF1AE7}.Release|x86.Build.0 = Release|Any CPU - {01678CDA-A11F-4DEE-9344-2EDF91CF1AE7}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {01678CDA-A11F-4DEE-9344-2EDF91CF1AE7}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {01678CDA-A11F-4DEE-9344-2EDF91CF1AE7}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {01678CDA-A11F-4DEE-9344-2EDF91CF1AE7}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {01678CDA-A11F-4DEE-9344-2EDF91CF1AE7}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {01678CDA-A11F-4DEE-9344-2EDF91CF1AE7}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {01678CDA-A11F-4DEE-9344-2EDF91CF1AE7}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {01678CDA-A11F-4DEE-9344-2EDF91CF1AE7}.VSRelease|x86.Build.0 = VSRelease|Any CPU {1A8DBF70-4178-4AE3-AF5F-39DDD5692210}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1A8DBF70-4178-4AE3-AF5F-39DDD5692210}.Debug|Any CPU.Build.0 = Debug|Any CPU {1A8DBF70-4178-4AE3-AF5F-39DDD5692210}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -951,14 +629,6 @@ Global {1A8DBF70-4178-4AE3-AF5F-39DDD5692210}.Release|Any CPU.Build.0 = Release|Any CPU {1A8DBF70-4178-4AE3-AF5F-39DDD5692210}.Release|x86.ActiveCfg = Release|Any CPU {1A8DBF70-4178-4AE3-AF5F-39DDD5692210}.Release|x86.Build.0 = Release|Any CPU - {1A8DBF70-4178-4AE3-AF5F-39DDD5692210}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {1A8DBF70-4178-4AE3-AF5F-39DDD5692210}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {1A8DBF70-4178-4AE3-AF5F-39DDD5692210}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {1A8DBF70-4178-4AE3-AF5F-39DDD5692210}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {1A8DBF70-4178-4AE3-AF5F-39DDD5692210}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {1A8DBF70-4178-4AE3-AF5F-39DDD5692210}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {1A8DBF70-4178-4AE3-AF5F-39DDD5692210}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {1A8DBF70-4178-4AE3-AF5F-39DDD5692210}.VSRelease|x86.Build.0 = VSRelease|Any CPU {D9D95330-3626-4199-B7AF-17B8E4AF6D87}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D9D95330-3626-4199-B7AF-17B8E4AF6D87}.Debug|Any CPU.Build.0 = Debug|Any CPU {D9D95330-3626-4199-B7AF-17B8E4AF6D87}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -971,14 +641,6 @@ Global {D9D95330-3626-4199-B7AF-17B8E4AF6D87}.Release|Any CPU.Build.0 = Release|Any CPU {D9D95330-3626-4199-B7AF-17B8E4AF6D87}.Release|x86.ActiveCfg = Release|Any CPU {D9D95330-3626-4199-B7AF-17B8E4AF6D87}.Release|x86.Build.0 = Release|Any CPU - {D9D95330-3626-4199-B7AF-17B8E4AF6D87}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {D9D95330-3626-4199-B7AF-17B8E4AF6D87}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {D9D95330-3626-4199-B7AF-17B8E4AF6D87}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {D9D95330-3626-4199-B7AF-17B8E4AF6D87}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {D9D95330-3626-4199-B7AF-17B8E4AF6D87}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {D9D95330-3626-4199-B7AF-17B8E4AF6D87}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {D9D95330-3626-4199-B7AF-17B8E4AF6D87}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {D9D95330-3626-4199-B7AF-17B8E4AF6D87}.VSRelease|x86.Build.0 = VSRelease|Any CPU {5B739CF3-1116-4EB4-B598-6C16BEA81CE5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {5B739CF3-1116-4EB4-B598-6C16BEA81CE5}.Debug|Any CPU.Build.0 = Debug|Any CPU {5B739CF3-1116-4EB4-B598-6C16BEA81CE5}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -991,14 +653,6 @@ Global {5B739CF3-1116-4EB4-B598-6C16BEA81CE5}.Release|Any CPU.Build.0 = Release|Any CPU {5B739CF3-1116-4EB4-B598-6C16BEA81CE5}.Release|x86.ActiveCfg = Release|Any CPU {5B739CF3-1116-4EB4-B598-6C16BEA81CE5}.Release|x86.Build.0 = Release|Any CPU - {5B739CF3-1116-4EB4-B598-6C16BEA81CE5}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {5B739CF3-1116-4EB4-B598-6C16BEA81CE5}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {5B739CF3-1116-4EB4-B598-6C16BEA81CE5}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {5B739CF3-1116-4EB4-B598-6C16BEA81CE5}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {5B739CF3-1116-4EB4-B598-6C16BEA81CE5}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {5B739CF3-1116-4EB4-B598-6C16BEA81CE5}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {5B739CF3-1116-4EB4-B598-6C16BEA81CE5}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {5B739CF3-1116-4EB4-B598-6C16BEA81CE5}.VSRelease|x86.Build.0 = VSRelease|Any CPU {DB374A0C-7560-479F-9B21-D37C81F7624F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {DB374A0C-7560-479F-9B21-D37C81F7624F}.Debug|Any CPU.Build.0 = Debug|Any CPU {DB374A0C-7560-479F-9B21-D37C81F7624F}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -1011,14 +665,6 @@ Global {DB374A0C-7560-479F-9B21-D37C81F7624F}.Release|Any CPU.Build.0 = Release|Any CPU {DB374A0C-7560-479F-9B21-D37C81F7624F}.Release|x86.ActiveCfg = Release|Any CPU {DB374A0C-7560-479F-9B21-D37C81F7624F}.Release|x86.Build.0 = Release|Any CPU - {DB374A0C-7560-479F-9B21-D37C81F7624F}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {DB374A0C-7560-479F-9B21-D37C81F7624F}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {DB374A0C-7560-479F-9B21-D37C81F7624F}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {DB374A0C-7560-479F-9B21-D37C81F7624F}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {DB374A0C-7560-479F-9B21-D37C81F7624F}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {DB374A0C-7560-479F-9B21-D37C81F7624F}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {DB374A0C-7560-479F-9B21-D37C81F7624F}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {DB374A0C-7560-479F-9B21-D37C81F7624F}.VSRelease|x86.Build.0 = VSRelease|Any CPU {15A57828-F9F5-4FB4-8E1E-AE7622A10F70}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {15A57828-F9F5-4FB4-8E1E-AE7622A10F70}.Debug|Any CPU.Build.0 = Debug|Any CPU {15A57828-F9F5-4FB4-8E1E-AE7622A10F70}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -1031,14 +677,6 @@ Global {15A57828-F9F5-4FB4-8E1E-AE7622A10F70}.Release|Any CPU.Build.0 = Release|Any CPU {15A57828-F9F5-4FB4-8E1E-AE7622A10F70}.Release|x86.ActiveCfg = Release|Any CPU {15A57828-F9F5-4FB4-8E1E-AE7622A10F70}.Release|x86.Build.0 = Release|Any CPU - {15A57828-F9F5-4FB4-8E1E-AE7622A10F70}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {15A57828-F9F5-4FB4-8E1E-AE7622A10F70}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {15A57828-F9F5-4FB4-8E1E-AE7622A10F70}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {15A57828-F9F5-4FB4-8E1E-AE7622A10F70}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {15A57828-F9F5-4FB4-8E1E-AE7622A10F70}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {15A57828-F9F5-4FB4-8E1E-AE7622A10F70}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {15A57828-F9F5-4FB4-8E1E-AE7622A10F70}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {15A57828-F9F5-4FB4-8E1E-AE7622A10F70}.VSRelease|x86.Build.0 = VSRelease|Any CPU {2FACEE44-48BD-40B5-A2EE-B54A0C9BB7C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2FACEE44-48BD-40B5-A2EE-B54A0C9BB7C4}.Debug|Any CPU.Build.0 = Debug|Any CPU {2FACEE44-48BD-40B5-A2EE-B54A0C9BB7C4}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -1051,14 +689,6 @@ Global {2FACEE44-48BD-40B5-A2EE-B54A0C9BB7C4}.Release|Any CPU.Build.0 = Release|Any CPU {2FACEE44-48BD-40B5-A2EE-B54A0C9BB7C4}.Release|x86.ActiveCfg = Release|Any CPU {2FACEE44-48BD-40B5-A2EE-B54A0C9BB7C4}.Release|x86.Build.0 = Release|Any CPU - {2FACEE44-48BD-40B5-A2EE-B54A0C9BB7C4}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {2FACEE44-48BD-40B5-A2EE-B54A0C9BB7C4}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {2FACEE44-48BD-40B5-A2EE-B54A0C9BB7C4}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {2FACEE44-48BD-40B5-A2EE-B54A0C9BB7C4}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {2FACEE44-48BD-40B5-A2EE-B54A0C9BB7C4}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {2FACEE44-48BD-40B5-A2EE-B54A0C9BB7C4}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {2FACEE44-48BD-40B5-A2EE-B54A0C9BB7C4}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {2FACEE44-48BD-40B5-A2EE-B54A0C9BB7C4}.VSRelease|x86.Build.0 = VSRelease|Any CPU {6BA13AA4-C25F-480F-856B-8E8000299A72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {6BA13AA4-C25F-480F-856B-8E8000299A72}.Debug|Any CPU.Build.0 = Debug|Any CPU {6BA13AA4-C25F-480F-856B-8E8000299A72}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -1071,14 +701,6 @@ Global {6BA13AA4-C25F-480F-856B-8E8000299A72}.Release|Any CPU.Build.0 = Release|Any CPU {6BA13AA4-C25F-480F-856B-8E8000299A72}.Release|x86.ActiveCfg = Release|Any CPU {6BA13AA4-C25F-480F-856B-8E8000299A72}.Release|x86.Build.0 = Release|Any CPU - {6BA13AA4-C25F-480F-856B-8E8000299A72}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {6BA13AA4-C25F-480F-856B-8E8000299A72}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {6BA13AA4-C25F-480F-856B-8E8000299A72}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {6BA13AA4-C25F-480F-856B-8E8000299A72}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {6BA13AA4-C25F-480F-856B-8E8000299A72}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {6BA13AA4-C25F-480F-856B-8E8000299A72}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {6BA13AA4-C25F-480F-856B-8E8000299A72}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {6BA13AA4-C25F-480F-856B-8E8000299A72}.VSRelease|x86.Build.0 = VSRelease|Any CPU {12AC2813-E895-4AAA-AE6C-94E21DA09F64}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {12AC2813-E895-4AAA-AE6C-94E21DA09F64}.Debug|Any CPU.Build.0 = Debug|Any CPU {12AC2813-E895-4AAA-AE6C-94E21DA09F64}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -1091,14 +713,6 @@ Global {12AC2813-E895-4AAA-AE6C-94E21DA09F64}.Release|Any CPU.Build.0 = Release|Any CPU {12AC2813-E895-4AAA-AE6C-94E21DA09F64}.Release|x86.ActiveCfg = Release|Any CPU {12AC2813-E895-4AAA-AE6C-94E21DA09F64}.Release|x86.Build.0 = Release|Any CPU - {12AC2813-E895-4AAA-AE6C-94E21DA09F64}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {12AC2813-E895-4AAA-AE6C-94E21DA09F64}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {12AC2813-E895-4AAA-AE6C-94E21DA09F64}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {12AC2813-E895-4AAA-AE6C-94E21DA09F64}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {12AC2813-E895-4AAA-AE6C-94E21DA09F64}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {12AC2813-E895-4AAA-AE6C-94E21DA09F64}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {12AC2813-E895-4AAA-AE6C-94E21DA09F64}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {12AC2813-E895-4AAA-AE6C-94E21DA09F64}.VSRelease|x86.Build.0 = VSRelease|Any CPU {A333B85A-DC23-49B6-9797-B89A7951E92D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A333B85A-DC23-49B6-9797-B89A7951E92D}.Debug|Any CPU.Build.0 = Debug|Any CPU {A333B85A-DC23-49B6-9797-B89A7951E92D}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -1111,14 +725,6 @@ Global {A333B85A-DC23-49B6-9797-B89A7951E92D}.Release|Any CPU.Build.0 = Release|Any CPU {A333B85A-DC23-49B6-9797-B89A7951E92D}.Release|x86.ActiveCfg = Release|Any CPU {A333B85A-DC23-49B6-9797-B89A7951E92D}.Release|x86.Build.0 = Release|Any CPU - {A333B85A-DC23-49B6-9797-B89A7951E92D}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {A333B85A-DC23-49B6-9797-B89A7951E92D}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {A333B85A-DC23-49B6-9797-B89A7951E92D}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {A333B85A-DC23-49B6-9797-B89A7951E92D}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {A333B85A-DC23-49B6-9797-B89A7951E92D}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {A333B85A-DC23-49B6-9797-B89A7951E92D}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {A333B85A-DC23-49B6-9797-B89A7951E92D}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {A333B85A-DC23-49B6-9797-B89A7951E92D}.VSRelease|x86.Build.0 = VSRelease|Any CPU {E3FDD4AC-46B6-4B9F-B672-317D1202CC50}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E3FDD4AC-46B6-4B9F-B672-317D1202CC50}.Debug|Any CPU.Build.0 = Debug|Any CPU {E3FDD4AC-46B6-4B9F-B672-317D1202CC50}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -1131,14 +737,6 @@ Global {E3FDD4AC-46B6-4B9F-B672-317D1202CC50}.Release|Any CPU.Build.0 = Release|Any CPU {E3FDD4AC-46B6-4B9F-B672-317D1202CC50}.Release|x86.ActiveCfg = Release|Any CPU {E3FDD4AC-46B6-4B9F-B672-317D1202CC50}.Release|x86.Build.0 = Release|Any CPU - {E3FDD4AC-46B6-4B9F-B672-317D1202CC50}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {E3FDD4AC-46B6-4B9F-B672-317D1202CC50}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {E3FDD4AC-46B6-4B9F-B672-317D1202CC50}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {E3FDD4AC-46B6-4B9F-B672-317D1202CC50}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {E3FDD4AC-46B6-4B9F-B672-317D1202CC50}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {E3FDD4AC-46B6-4B9F-B672-317D1202CC50}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {E3FDD4AC-46B6-4B9F-B672-317D1202CC50}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {E3FDD4AC-46B6-4B9F-B672-317D1202CC50}.VSRelease|x86.Build.0 = VSRelease|Any CPU {D11FC318-8F5D-4C8C-9287-AB40A016D13C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D11FC318-8F5D-4C8C-9287-AB40A016D13C}.Debug|Any CPU.Build.0 = Debug|Any CPU {D11FC318-8F5D-4C8C-9287-AB40A016D13C}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -1151,14 +749,6 @@ Global {D11FC318-8F5D-4C8C-9287-AB40A016D13C}.Release|Any CPU.Build.0 = Release|Any CPU {D11FC318-8F5D-4C8C-9287-AB40A016D13C}.Release|x86.ActiveCfg = Release|Any CPU {D11FC318-8F5D-4C8C-9287-AB40A016D13C}.Release|x86.Build.0 = Release|Any CPU - {D11FC318-8F5D-4C8C-9287-AB40A016D13C}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {D11FC318-8F5D-4C8C-9287-AB40A016D13C}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {D11FC318-8F5D-4C8C-9287-AB40A016D13C}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {D11FC318-8F5D-4C8C-9287-AB40A016D13C}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {D11FC318-8F5D-4C8C-9287-AB40A016D13C}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {D11FC318-8F5D-4C8C-9287-AB40A016D13C}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {D11FC318-8F5D-4C8C-9287-AB40A016D13C}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {D11FC318-8F5D-4C8C-9287-AB40A016D13C}.VSRelease|x86.Build.0 = VSRelease|Any CPU {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.Debug|Any CPU.Build.0 = Debug|Any CPU {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -1171,14 +761,6 @@ Global {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.Release|Any CPU.Build.0 = Release|Any CPU {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.Release|x86.ActiveCfg = Release|Any CPU {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.Release|x86.Build.0 = Release|Any CPU - {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.VSRelease|x86.Build.0 = VSRelease|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/build.cmd b/build.cmd index e5deb34ec6b..1bdb8c12acd 100644 --- a/build.cmd +++ b/build.cmd @@ -13,7 +13,7 @@ echo Build and run a subset of test suites echo. echo Usage: echo. -echo build.cmd ^ +echo build.cmd ^ echo. echo No arguments default to 'build' echo. @@ -33,6 +33,8 @@ set BUILD_PORTABLE=0 set BUILD_VS=0 set BUILD_CONFIG=release set BUILD_CONFIG_LOWERCASE=release +set BUILD_DIAG= +set BUILD_LOG=con set TEST_COMPILERUNIT=0 set TEST_NET40_COREUNIT=0 @@ -42,6 +44,7 @@ set TEST_VS=0 set TEST_FSHARP_SUITE=0 set TEST_FSHARPQA_SUITE=0 set TEST_TAGS= +set SKIP_EXPENSIVE_TESTS=1 setlocal enableDelayedExpansion set /a counter=0 @@ -75,18 +78,31 @@ if /i '%ARG%' == 'vs' ( set TEST_VS=1 ) +if /i '%ARG%' == 'diag' ( + set BUILD_DIAG=/v:diag + set BUILD_LOG=fsharp_build_log.log +) + if /i '%ARG%' == 'all' ( set BUILD_PROTO=1 set BUILD_NET40=1 set BUILD_CORECLR=1 set BUILD_PORTABLE=1 set BUILD_VS=1 + set TEST_COMPILERUNIT=1 + set TEST_NET40_COREUNIT=1 set TEST_PORTABLE_COREUNIT=1 set TEST_FSHARP_SUITE=1 set TEST_FSHARPQA_SUITE=1 set TEST_CORECLR=1 set TEST_VS=1 + + set SKIP_EXPENSIVE_TESTS=0 +) + +if /i '%ARG%' == 'proto' ( + set BUILD_PROTO=1 ) REM Same as 'all' but smoke testing only @@ -134,20 +150,7 @@ if /i '%ARG%' == 'ci_part2' ( set TEST_FSHARP_SUITE=1 ) -if /i '%ARG%' == 'smoke' ( - REM Smoke tests are a very small quick subset of tests - - set SKIP_EXPENSIVE_TESTS=1 - set TEST_COMPILERUNIT=0 - set TEST_NET40_COREUNIT=0 - set TEST_FSHARP_SUITE=1 - set TEST_FSHARPQA_SUITE=0 - set TEST_TAGS=Smoke -) - if /i '%ARG%' == 'coreclr' ( - REM Smoke tests are a very small quick subset of tests - set BUILD_CORECLR=1 set TEST_CORECLR=1 ) @@ -170,6 +173,52 @@ if /i '%ARG%' == 'notests' ( set TEST_VS=0 set TEST_FSHARP_SUITE=0 set TEST_FSHARPQA_SUITE=0 + set SKIP_EXPENSIVE_TESTS=1 +) + +if /i '%ARG%' == 'test-smoke' ( + REM Smoke tests are a very small quick subset of tests + + set SKIP_EXPENSIVE_TESTS=1 + set TEST_COMPILERUNIT=0 + set TEST_NET40_COREUNIT=0 + set TEST_FSHARP_SUITE=1 + set TEST_FSHARPQA_SUITE=0 + set TEST_TAGS=Smoke +) + +if /i '%ARG%' == 'test-fsharpqa' ( + set BUILD_NET40=1 + set TEST_FSHARPQA_SUITE=1 +) + +if /i '%ARG%' == 'test-compilerunit' ( + set BUILD_NET40=1 + set TEST_COMPILERUNIT=1 +) + +if /i '%ARG%' == 'test-coreunit' ( + set BUILD_NET40=1 + set TEST_NET40_COREUNIT=1 +) + +if /i '%ARG%' == 'test-coreclr' ( + set BUILD_CORECLR=1 + set TEST_CORECLR=1 +) + +if /i '%ARG%' == 'test-pcls' ( + set BUILD_PORTABLE=1 + set TEST_PORTABLE_COREUNIT=1 +) + +if /i '%ARG%' == 'test-vs' ( + set BUILD_VS=1 + set TEST_VS=1 +) + +if /i '%ARG%' == 'test-fsharp' ( + set TEST_FSHARP_SUITE=1 ) goto :EOF @@ -180,6 +229,7 @@ REM after this point, ARG variable should not be used, use only BUILD_* or TEST_ echo Build/Tests configuration: echo. +echo BUILD_PROTO=%BUILD_PROTO% echo BUILD_NET40=%BUILD_NET40% echo BUILD_CORECLR=%BUILD_CORECLR% echo BUILD_PORTABLE=%BUILD_PORTABLE% @@ -188,16 +238,15 @@ echo BUILD_CONFIG=%BUILD_CONFIG% echo BUILD_CONFIG_LOWERCASE=%BUILD_CONFIG_LOWERCASE% echo. echo TEST_COMPILERUNIT=%TEST_COMPILERUNIT% +echo TEST_NET40_COREUNIT=%TEST_NET40_COREUNIT% echo TEST_PORTABLE_COREUNIT=%TEST_PORTABLE_COREUNIT% echo TEST_VS=%TEST_VS% echo TEST_FSHARP_SUITE=%TEST_FSHARP_SUITE% echo TEST_FSHARPQA_SUITE=%TEST_FSHARPQA_SUITE% echo TEST_TAGS=%TEST_TAGS% +echo SKIP_EXPENSIVE_TESTS=%SKIP_EXPENSIVE_TESTS% echo. -REM Remove lingering copies of the OSS FSharp.Core from the GAC -gacutil /u "FSharp.Core, Version=4.4.1.9055, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" - if "%RestorePackages%"=="" ( set RestorePackages=true ) @@ -220,16 +269,21 @@ if '%VisualStudioVersion%' == '' echo Error: Could not find an installation of V if exist "%ProgramFiles(x86)%\MSBuild\%VisualStudioVersion%\Bin\MSBuild.exe" set _msbuildexe="%ProgramFiles(x86)%\MSBuild\%VisualStudioVersion%\Bin\MSBuild.exe" if exist "%ProgramFiles%\MSBuild\%VisualStudioVersion%\Bin\MSBuild.exe" set _msbuildexe="%ProgramFiles%\MSBuild\%VisualStudioVersion%\Bin\MSBuild.exe" if not exist %_msbuildexe% echo Error: Could not find MSBuild.exe. && goto :failure +set _nrswitch=/nr:false +rem uncomment to use coreclr msbuild not ready yet!!!! +rem set _msbuildexe=%~dp0Tools\CoreRun.exe %~dp0Tools\MSBuild.exe +rem set _nrswitch= + :: See if defined APPVEYOR ( - rem See - if exist "C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" ( + rem See + if exist "C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" ( rem HACK HACK HACK - set _msbuildexe=%_msbuildexe% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" - ) + set _msbuildexe=%_msbuildexe% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" + ) ) -set msbuildflags=/maxcpucount +set msbuildflags=/maxcpucount %_nrswitch% set _ngenexe="%SystemRoot%\Microsoft.NET\Framework\v4.0.30319\ngen.exe" if not exist %_ngenexe% echo Error: Could not find ngen.exe. && goto :failure @@ -240,37 +294,37 @@ if '%RestorePackages%' == 'true' ( @if ERRORLEVEL 1 echo Error: Nuget restore failed && goto :failure ) +:: Restore the Tools directory +call %~dp0init-tools.cmd -rem Always do this it installs the dotnet cli and publishes the LKG -rem =============================================================== +set _dotnetexe=%~dp0Tools\dotnetcli\dotnet.exe +pushd .\lkg & %_dotnetexe% restore &popd +@if ERRORLEVEL 1 echo Error: dotnet restore failed && goto :failure -set DOTNET_HOME=.\packages\dotnet -set _dotnetexe=.\packages\dotnet\dotnet.exe -rem check to see if the dotnet cli tool exists -if not exist %_dotnetexe% ( - echo Could not find %_dotnetexe%. Do zipfile install - if not exist packages ( md packages ) - if exist packages\dotnet ( rd packages\dotnet /s /q ) - powershell.exe -executionpolicy unrestricted -command .\scripts\install-dotnetcli.ps1 https://dotnetcli.blob.core.windows.net/dotnet/beta/Binaries/Latest/dotnet-dev-win-x64.latest.zip packages - @if ERRORLEVEL 1 echo Error: fetch dotnetcli failed && goto :failure +pushd .\lkg & %_dotnetexe% publish project.json &popd +@if ERRORLEVEL 1 echo Error: dotnet publish failed && goto :failure - pushd .\lkg & ..\%_dotnetexe% restore &popd - @if ERRORLEVEL 1 echo Error: dotnet restore failed && goto :failure - pushd .\lkg & ..\%_dotnetexe% publish project.json &popd - @if ERRORLEVEL 1 echo Error: dotnet publish failed && goto :failure - - rem rename fsc and coreconsole to allow fsc.exe to to start compiler - pushd .\lkg\bin\debug\dnxcore50\win7-x64\publish - ren fsc.exe fsc.dll +rem rename fsc and coreconsole to allow fsc.exe to to start compiler +pushd .\lkg\bin\debug\dnxcore50\win7-x64\publish +fc fsc.exe corehost.exe >nul +@if ERRORLEVEL 1 ( + copy fsc.exe fsc.dll copy corehost.exe fsc.exe - popd +) +popd - rem rename fsi and coreconsole to allow fsi.exe to to start interative - pushd .\lkg\bin\debug\dnxcore50\win7-x64\publish - ren fsi.exe fsi.dll +rem rename fsc and coreconsole to allow fsc.exe to to start compiler +pushd .\lkg\bin\debug\dnxcore50\win7-x64\publish +fc fsi.exe corehost.exe >nul +@if ERRORLEVEL 1 ( + copy fsi.exe fsi.dll copy corehost.exe fsi.exe - popd ) +popd + +rem copy targestfile into tools directory ... temporary fix until packaging complete. +copy src\fsharp\FSharp.Build\Microsoft.FSharp.targets tools\Microsoft.FSharp.targets +copy src\fsharp\FSharp.Build\Microsoft.Portable.FSharp.targets tools\Microsoft.Portable.FSharp.targets :: Build Proto if NOT EXIST Proto\net40\bin\fsc-proto.exe (set BUILD_PROTO=1) @@ -284,7 +338,7 @@ if '%BUILD_PROTO%' == '1' ( @if ERRORLEVEL 1 echo Error: NGen of proto failed && goto :failure ) -%_msbuildexe% %msbuildflags% build-everything.proj /p:Configuration=%BUILD_CONFIG% +%_msbuildexe% %msbuildflags% build-everything.proj /p:Configuration=%BUILD_CONFIG% %BUILD_DIAG% >%BUILD_LOG% @if ERRORLEVEL 1 echo Error: '%_msbuildexe% %msbuildflags% build-everything.proj /p:Configuration=%BUILD_CONFIG%' failed && goto :failure @echo on @@ -292,6 +346,8 @@ call src\update.cmd %BUILD_CONFIG_LOWERCASE% -ngen pushd tests +if 'TEST_COMPILERUNIT' == '0' and 'TEST_PORTABLE_COREUNIT' == '0' and 'TEST_CORECLR' == '0' and 'TEST_VS' == '0' and 'TEST_FSHARP_SUITE' == '0' and 'TEST_FSHARPQA_SUITE' == '0' goto :finished + @echo on call BuildTestTools.cmd %BUILD_CONFIG_LOWERCASE% @if ERRORLEVEL 1 echo Error: 'BuildTestTools.cmd %BUILD_CONFIG_LOWERCASE%' failed && goto :failed_tests @@ -299,10 +355,6 @@ call BuildTestTools.cmd %BUILD_CONFIG_LOWERCASE% @echo on if '%TEST_FSHARP_SUITE%' == '1' ( set FSHARP_TEST_SUITE_USE_NUNIT_RUNNER=true - - %_msbuildexe% %msbuildflags% fsharp\fsharp.tests.fsproj /p:Configuration=%BUILD_CONFIG% - @if ERRORLEVEL 1 echo Error: fsharp cambridge tests for nunit failed && goto :failed_tests - call RunTests.cmd %BUILD_CONFIG_LOWERCASE% fsharp %TEST_TAGS% @if ERRORLEVEL 1 ( type testresults\FSharpNunit_Error.log @@ -364,6 +416,7 @@ if '%TEST_VS%' == '1' ( @if ERRORLEVEL 1 echo Error: 'RunTests.cmd %BUILD_CONFIG_LOWER% ideunit %TEST_TAGS%' failed && goto :failed_tests ) +:finished @echo "Finished" popd goto :eof diff --git a/init-tools.cmd b/init-tools.cmd new file mode 100644 index 00000000000..d48ff4d1248 --- /dev/null +++ b/init-tools.cmd @@ -0,0 +1,69 @@ +@if "%_echo%" neq "on" echo off +setlocal + +set INIT_TOOLS_LOG=%~dp0init-tools.log +if [%PACKAGES_DIR%]==[] set PACKAGES_DIR=%~dp0packages\ +if [%TOOLRUNTIME_DIR%]==[] set TOOLRUNTIME_DIR=%~dp0Tools +set DOTNET_PATH=%TOOLRUNTIME_DIR%\dotnetcli\ +if [%DOTNET_CMD%]==[] set DOTNET_CMD=%DOTNET_PATH%dotnet.exe +if [%BUILDTOOLS_SOURCE%]==[] set BUILDTOOLS_SOURCE=https://dotnet.myget.org/F/dotnet-buildtools/api/v3/index.json +set /P BUILDTOOLS_VERSION=< %~dp0BuildToolsVersion.txt +set BUILD_TOOLS_PATH=%PACKAGES_DIR%Microsoft.DotNet.BuildTools\%BUILDTOOLS_VERSION%\lib\ +set PROJECT_JSON_PATH=%TOOLRUNTIME_DIR%\%BUILDTOOLS_VERSION% +set PROJECT_JSON_FILE=%PROJECT_JSON_PATH%\project.json +set PROJECT_JSON_CONTENTS={ "dependencies": { "Microsoft.DotNet.BuildTools": "%BUILDTOOLS_VERSION%" }, "frameworks": { "dnxcore50": { } } } +set BUILD_TOOLS_SEMAPHORE=%PROJECT_JSON_PATH%\init-tools.completed + +:: if force option is specified then clean the tool runtime and build tools package directory to force it to get recreated +if [%1]==[force] ( + if exist "%TOOLRUNTIME_DIR%" rmdir /S /Q "%TOOLRUNTIME_DIR%" + if exist "%PACKAGES_DIR%Microsoft.DotNet.BuildTools" rmdir /S /Q "%PACKAGES_DIR%Microsoft.DotNet.BuildTools" +) + +:: If sempahore exists do nothing +if exist "%BUILD_TOOLS_SEMAPHORE%" ( + echo Tools are already initialized. + goto :EOF +) + +if exist "%TOOLRUNTIME_DIR%" rmdir /S /Q "%TOOLRUNTIME_DIR%" + +if NOT exist "%PROJECT_JSON_PATH%" mkdir "%PROJECT_JSON_PATH%" +echo %PROJECT_JSON_CONTENTS% > %PROJECT_JSON_FILE% +echo Running %0 > %INIT_TOOLS_LOG% + +if exist "%DOTNET_CMD%" goto :afterdotnetrestore + +echo Installing dotnet cli... +if NOT exist "%DOTNET_PATH%" mkdir "%DOTNET_PATH%" +set /p DOTNET_VERSION=< %~dp0DotnetCLIVersion.txt +set DOTNET_ZIP_NAME=dotnet-dev-win-x64.%DOTNET_VERSION%.zip +set DOTNET_REMOTE_PATH=https://dotnetcli.blob.core.windows.net/dotnet/beta/Binaries/%DOTNET_VERSION%/%DOTNET_ZIP_NAME% +set DOTNET_LOCAL_PATH=%DOTNET_PATH%%DOTNET_ZIP_NAME% +echo Installing '%DOTNET_REMOTE_PATH%' to '%DOTNET_LOCAL_PATH%' >> %INIT_TOOLS_LOG% +powershell -NoProfile -ExecutionPolicy unrestricted -Command "(New-Object Net.WebClient).DownloadFile('%DOTNET_REMOTE_PATH%', '%DOTNET_LOCAL_PATH%'); Add-Type -Assembly 'System.IO.Compression.FileSystem' -ErrorVariable AddTypeErrors; if ($AddTypeErrors.Count -eq 0) { [System.IO.Compression.ZipFile]::ExtractToDirectory('%DOTNET_LOCAL_PATH%', '%DOTNET_PATH%') } else { (New-Object -com shell.application).namespace('%DOTNET_PATH%').CopyHere((new-object -com shell.application).namespace('%DOTNET_LOCAL_PATH%').Items(),16) }" >> %INIT_TOOLS_LOG% +if NOT exist "%DOTNET_LOCAL_PATH%" ( + echo ERROR: Could not install dotnet cli correctly. See '%INIT_TOOLS_LOG%' for more details. + goto :EOF +) + +:afterdotnetrestore + +if exist "%BUILD_TOOLS_PATH%" goto :afterbuildtoolsrestore +echo Restoring BuildTools version %BUILDTOOLS_VERSION%... +echo Running: "%DOTNET_CMD%" restore "%PROJECT_JSON_FILE%" --packages %PACKAGES_DIR% --source "%BUILDTOOLS_SOURCE%" >> %INIT_TOOLS_LOG% +call "%DOTNET_CMD%" restore "%PROJECT_JSON_FILE%" --packages %PACKAGES_DIR% --source "%BUILDTOOLS_SOURCE%" >> %INIT_TOOLS_LOG% +if NOT exist "%BUILD_TOOLS_PATH%init-tools.cmd" ( + echo ERROR: Could not restore build tools correctly. See '%INIT_TOOLS_LOG%' for more details. + goto :EOF +) + +:afterbuildtoolsrestore + +echo Initializing BuildTools ... +echo Running: "%BUILD_TOOLS_PATH%init-tools.cmd" "%~dp0" "%DOTNET_CMD%" "%TOOLRUNTIME_DIR%" >> %INIT_TOOLS_LOG% +call "%BUILD_TOOLS_PATH%init-tools.cmd" "%~dp0" "%DOTNET_CMD%" "%TOOLRUNTIME_DIR%" >> %INIT_TOOLS_LOG% + +:: Create sempahore file +echo Done initializing tools. +echo Init-Tools.cmd completed for BuildTools Version: %BUILDTOOLS_VERSION% > "%BUILD_TOOLS_SEMAPHORE%" \ No newline at end of file diff --git a/init-tools.sh b/init-tools.sh new file mode 100644 index 00000000000..033a652cde5 --- /dev/null +++ b/init-tools.sh @@ -0,0 +1,88 @@ +#!/usr/bin/env bash + +__scriptpath=$(cd "$(dirname "$0")"; pwd -P) +__init_tools_log=$__scriptpath/init-tools.log +__PACKAGES_DIR=$__scriptpath/packages +__TOOLRUNTIME_DIR=$__scriptpath/Tools +__DOTNET_PATH=$__TOOLRUNTIME_DIR/dotnetcli +__DOTNET_CMD=$__DOTNET_PATH/dotnet +if [ -z "$__BUILDTOOLS_SOURCE" ]; then __BUILDTOOLS_SOURCE=https://dotnet.myget.org/F/dotnet-buildtools/api/v3/index.json; fi +__BUILD_TOOLS_PACKAGE_VERSION=$(cat $__scriptpath/BuildToolsVersion.txt) +__DOTNET_TOOLS_VERSION=$(cat $__scriptpath/DotnetCLIVersion.txt) +__BUILD_TOOLS_PATH=$__PACKAGES_DIR/Microsoft.DotNet.BuildTools/$__BUILD_TOOLS_PACKAGE_VERSION/lib +__PROJECT_JSON_PATH=$__TOOLRUNTIME_DIR/$__BUILD_TOOLS_PACKAGE_VERSION +__PROJECT_JSON_FILE=$__PROJECT_JSON_PATH/project.json +__PROJECT_JSON_CONTENTS="{ \"dependencies\": { \"Microsoft.DotNet.BuildTools\": \"$__BUILD_TOOLS_PACKAGE_VERSION\" }, \"frameworks\": { \"dnxcore50\": { } } }" + +OSName=$(uname -s) +case $OSName in + Darwin) + OS=OSX + __DOTNET_PKG=dotnet-dev-osx-x64 + ulimit -n 2048 + ;; + + Linux) + OS=Linux + source /etc/os-release + if [ "$ID" == "centos" -o "$ID" == "rhel" ]; then + __DOTNET_PKG=dotnet-dev-centos-x64 + elif [ "$ID" == "ubuntu" -o "$ID" == "debian" ]; then + __DOTNET_PKG=dotnet-dev-ubuntu-x64 + else + echo "Unsupported Linux distribution '$ID' detected. Downloading ubuntu-x64 tools." + __DOTNET_PKG=dotnet-dev-ubuntu-x64 + fi + ;; + + *) + echo "Unsupported OS '$OSName' detected. Downloading ubuntu-x64 tools." + OS=Linux + __DOTNET_PKG=dotnet-dev-ubuntu-x64 + ;; +esac + +if [ ! -e $__PROJECT_JSON_FILE ]; then + if [ -e $__TOOLRUNTIME_DIR ]; then rm -rf -- $__TOOLRUNTIME_DIR; fi + echo "Running: $__scriptpath/init-tools.sh" > $__init_tools_log + if [ ! -e $__DOTNET_PATH ]; then + echo "Installing dotnet cli..." + __DOTNET_LOCATION="https://dotnetcli.blob.core.windows.net/dotnet/beta/Binaries/${__DOTNET_TOOLS_VERSION}/${__DOTNET_PKG}.${__DOTNET_TOOLS_VERSION}.tar.gz" + # curl has HTTPS CA trust-issues less often than wget, so lets try that first. + echo "Installing '${__DOTNET_LOCATION}' to '$__DOTNET_PATH/dotnet.tar'" >> $__init_tools_log + which curl > /dev/null 2> /dev/null + if [ $? -ne 0 ]; then + mkdir -p "$__DOTNET_PATH" + wget -q -O $__DOTNET_PATH/dotnet.tar ${__DOTNET_LOCATION} + else + curl -sSL --create-dirs -o $__DOTNET_PATH/dotnet.tar ${__DOTNET_LOCATION} + fi + cd $__DOTNET_PATH + tar -xf $__DOTNET_PATH/dotnet.tar + if [ -n "$BUILDTOOLS_OVERRIDE_RUNTIME" ]; then + find $__DOTNET_PATH -name *.ni.* | xargs rm 2>/dev/null + cp -R $BUILDTOOLS_OVERRIDE_RUNTIME/* $__DOTNET_PATH/bin + cp -R $BUILDTOOLS_OVERRIDE_RUNTIME/* $__DOTNET_PATH/bin/dnx + cp -R $BUILDTOOLS_OVERRIDE_RUNTIME/* $__DOTNET_PATH/runtime/coreclr + fi + + cd $__scriptpath + fi + + if [ ! -d "$__PROJECT_JSON_PATH" ]; then mkdir "$__PROJECT_JSON_PATH"; fi + echo $__PROJECT_JSON_CONTENTS > "$__PROJECT_JSON_FILE" + + if [ ! -e $__BUILD_TOOLS_PATH ]; then + echo "Restoring BuildTools version $__BUILD_TOOLS_PACKAGE_VERSION..." + echo "Running: $__DOTNET_CMD restore \"$__PROJECT_JSON_FILE\" --packages $__PACKAGES_DIR --source $__BUILDTOOLS_SOURCE" >> $__init_tools_log + $__DOTNET_CMD restore "$__PROJECT_JSON_FILE" --packages $__PACKAGES_DIR --source $__BUILDTOOLS_SOURCE >> $__init_tools_log + if [ ! -e "$__BUILD_TOOLS_PATH/init-tools.sh" ]; then echo "ERROR: Could not restore build tools correctly. See '$__init_tools_log' for more details."; fi + fi + + echo "Initializing BuildTools..." + echo "Running: $__BUILD_TOOLS_PATH/init-tools.sh $__scriptpath $__DOTNET_CMD $__TOOLRUNTIME_DIR" >> $__init_tools_log + $__BUILD_TOOLS_PATH/init-tools.sh $__scriptpath $__DOTNET_CMD $__TOOLRUNTIME_DIR >> $__init_tools_log + echo "Done initializing tools." +else + echo "Tools are already initialized" +fi diff --git a/packages.config b/packages.config index 14439234ef2..176d60691ff 100644 --- a/packages.config +++ b/packages.config @@ -1,17 +1,16 @@ - + - diff --git a/src/FSharpSource.Settings.targets b/src/FSharpSource.Settings.targets index ccc53d04c91..1bc0b2a965c 100644 --- a/src/FSharpSource.Settings.targets +++ b/src/FSharpSource.Settings.targets @@ -12,7 +12,10 @@ FSharp true true + $(MSBuildThisFileDirectory)..\Tools\ + $(ToolsDir)net45\ + false @@ -41,25 +44,6 @@ false - - full - prompt - AnyCPU - $(OtherFlags) --no-jit-optimize --jit-tracking - DEBUG;TRACE;CODE_ANALYSIS;$(DefineConstants) - DEBUG=True,TRACE=True,CODE_ANALYSIS=True,$(DefineConstants) - true - - - - pdbonly - true - TRACE;$(DefineConstants) - TRACE=True,$(DefineConstants) - prompt - true - - true diff --git a/src/FSharpSource.targets b/src/FSharpSource.targets index 3aa7acbb6b1..800286a3b47 100644 --- a/src/FSharpSource.targets +++ b/src/FSharpSource.targets @@ -11,7 +11,7 @@ 3.259.41.0 - + false true @@ -159,7 +159,6 @@ - v4.5 $(DefineConstants);FSHARP_CORE_4_5 $(DefineConstants);FX_ATLEAST_45 $(DefineConstants);FX_ATLEAST_40 @@ -174,12 +173,12 @@ $(DefineConstants);FX_RESX_RESOURCE_READER $(DefineConstants);FX_RESIDENT_COMPILER $(DefineConstants);SHADOW_COPY_REFERENCES + v4.5 - v4.5 $(DefineConstants);FSHARP_CORE_4_5 $(DefineConstants);FX_NO_BEGINEND_READWRITE $(DefineConstants);FX_ATLEAST_45 @@ -191,7 +190,7 @@ $(DefineConstants);FX_ATLEAST_LINQ $(DefineConstants);FX_RESHAPED_GLOBALIZATION $(DefineConstants);FX_RESHAPED_REFLECTION - $(DefineConstants);FX_RESHAPED_REFLECTION_CORECLR + $(DefineConstants);FX_RESHAPED_REFLECTION_CORECLR $(DefineConstants);RESHAPED_MSBUILD $(DefineConstants);FX_NO_CONVERTER $(DefineConstants);FX_NO_ARRAY_LONG_LENGTH @@ -230,8 +229,11 @@ $(DefineConstants);NO_LOADER_OPTIMIZATION $(DefineConstants);SILVERLIGHT_COMPILER_FSHARP_CORE $(DefineConstants);I_DONT_KNOW_HOW_TO_DO_THIS_YET - profile7 + $(OtherFlags) --simpleresolution + + v5.0 false + true @@ -796,9 +798,6 @@ $(FSharpSourcesRoot)\..\packages - - $(MSBuildThisFileDirectory)..\packages\Microsoft.DotNet.BuildTools.1.0.25-prerelease-00140\lib\ - $(NuGetPackagesPath)\ @@ -819,7 +818,7 @@ so we ignore the pre-calculation in the lock file and calculate asset applicability in the build task --> true - + diff --git a/src/absil/il.fs b/src/absil/il.fs index b731eaed7c3..cf71760fe39 100755 --- a/src/absil/il.fs +++ b/src/absil/il.fs @@ -10,9 +10,9 @@ module internal Microsoft.FSharp.Compiler.AbstractIL.IL open Internal.Utilities open Microsoft.FSharp.Compiler.AbstractIL +open Microsoft.FSharp.Compiler.AbstractIL.Diagnostics open Microsoft.FSharp.Compiler.AbstractIL.Internal open Microsoft.FSharp.Compiler.AbstractIL.Internal.Library -open Microsoft.FSharp.Compiler.AbstractIL.Diagnostics open System.Collections open System.Collections.Generic open System.Collections.Concurrent diff --git a/src/absil/ilascii.fs b/src/absil/ilascii.fs index 695b0340f79..42f63f21ee0 100644 --- a/src/absil/ilascii.fs +++ b/src/absil/ilascii.fs @@ -8,7 +8,6 @@ open Internal.Utilities.Collections open Microsoft.FSharp.Compiler.AbstractIL open Microsoft.FSharp.Compiler.AbstractIL.Internal open Microsoft.FSharp.Compiler.AbstractIL.Internal.Library -open Microsoft.FSharp.Compiler.AbstractIL.Diagnostics open Microsoft.FSharp.Compiler.AbstractIL.Extensions.ILX.Types open Microsoft.FSharp.Compiler.AbstractIL.IL diff --git a/src/absil/illex.fsl b/src/absil/illex.fsl index ed6494092f2..478126cac29 100644 --- a/src/absil/illex.fsl +++ b/src/absil/illex.fsl @@ -12,15 +12,13 @@ open Microsoft.FSharp.Compiler.AbstractIL open Microsoft.FSharp.Compiler.AbstractIL.Internal open Microsoft.FSharp.Compiler.AbstractIL.Internal.Library -open Microsoft.FSharp.Compiler.AbstractIL.Diagnostics open Microsoft.FSharp.Compiler.AbstractIL.Internal.AsciiParser open Microsoft.FSharp.Compiler.AbstractIL.Internal.AsciiConstants let lexeme (lexbuf : LexBuffer) = new System.String(lexbuf.Lexeme) -let unexpectedChar lexbuf = - dprintf "Unexpected character '%s'" (lexeme lexbuf); +let unexpectedChar _lexbuf = raise Parsing.RecoverableParseError ;; // -------------------------------------------------------------------- diff --git a/src/fsharp-compiler-build.proj b/src/fsharp-compiler-build.proj index 478927e20ea..4c338446f7c 100644 --- a/src/fsharp-compiler-build.proj +++ b/src/fsharp-compiler-build.proj @@ -8,8 +8,9 @@ - - + + + diff --git a/src/fsharp/AccessibilityLogic.fs b/src/fsharp/AccessibilityLogic.fs new file mode 100644 index 00000000000..38354e674e2 --- /dev/null +++ b/src/fsharp/AccessibilityLogic.fs @@ -0,0 +1,333 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +/// The basic logic of private/internal/protected/InternalsVisibleTo/public accessibility +module internal Microsoft.FSharp.Compiler.AccessibilityLogic + +open Internal.Utilities +open Microsoft.FSharp.Compiler.AbstractIL +open Microsoft.FSharp.Compiler.AbstractIL.IL +open Microsoft.FSharp.Compiler +open Microsoft.FSharp.Compiler.Ast +open Microsoft.FSharp.Compiler.ErrorLogger +open Microsoft.FSharp.Compiler.Infos +open Microsoft.FSharp.Compiler.Tast +open Microsoft.FSharp.Compiler.Tastops +open Microsoft.FSharp.Compiler.TcGlobals + +#if EXTENSIONTYPING +open Microsoft.FSharp.Compiler.ExtensionTyping +#endif + +/// Represents the 'keys' a particular piece of code can use to access other constructs?. +[] +type AccessorDomain = + /// AccessibleFrom(cpaths, tyconRefOpt) + /// + /// cpaths: indicates we have the keys to access any members private to the given paths + /// tyconRefOpt: indicates we have the keys to access any protected members of the super types of 'TyconRef' + | AccessibleFrom of CompilationPath list * TyconRef option + + /// An AccessorDomain which returns public items + | AccessibleFromEverywhere + + /// An AccessorDomain which returns everything but .NET private/internal items. + /// This is used + /// - when solving member trait constraints, which are solved independently of accessibility + /// - for failure paths in error reporting, e.g. to produce an error that an F# item is not accessible + /// - an adhoc use in service.fs to look up a delegate signature + | AccessibleFromSomeFSharpCode + + /// An AccessorDomain which returns all items + | AccessibleFromSomewhere + + // Hashing and comparison is used for the memoization tables keyed by an accessor domain. + // It is dependent on a TcGlobals because of the TyconRef in the data structure + static member CustomGetHashCode(ad:AccessorDomain) = + match ad with + | AccessibleFrom _ -> 1 + | AccessibleFromEverywhere -> 2 + | AccessibleFromSomeFSharpCode -> 3 + | AccessibleFromSomewhere -> 4 + static member CustomEquals(g:TcGlobals, ad1:AccessorDomain, ad2:AccessorDomain) = + match ad1, ad2 with + | AccessibleFrom(cs1,tc1), AccessibleFrom(cs2,tc2) -> (cs1 = cs2) && (match tc1,tc2 with None,None -> true | Some tc1, Some tc2 -> tyconRefEq g tc1 tc2 | _ -> false) + | AccessibleFromEverywhere, AccessibleFromEverywhere -> true + | AccessibleFromSomeFSharpCode, AccessibleFromSomeFSharpCode -> true + | AccessibleFromSomewhere, AccessibleFromSomewhere -> true + | _ -> false + +/// Indicates if an F# item is accessible +let IsAccessible ad taccess = + match ad with + | AccessibleFromEverywhere -> canAccessFromEverywhere taccess + | AccessibleFromSomeFSharpCode -> canAccessFromSomewhere taccess + | AccessibleFromSomewhere -> true + | AccessibleFrom (cpaths,_tcrefViewedFromOption) -> + List.exists (canAccessFrom taccess) cpaths + +/// Indicates if an IL member is accessible (ignoring its enclosing type) +let private IsILMemberAccessible g amap m (tcrefOfViewedItem : TyconRef) ad access = + match ad with + | AccessibleFromEverywhere -> + access = ILMemberAccess.Public + | AccessibleFromSomeFSharpCode -> + (access = ILMemberAccess.Public || + access = ILMemberAccess.Family || + access = ILMemberAccess.FamilyOrAssembly) + | AccessibleFrom (cpaths,tcrefViewedFromOption) -> + let accessibleByFamily = + ((access = ILMemberAccess.Family || + access = ILMemberAccess.FamilyOrAssembly) && + match tcrefViewedFromOption with + | None -> false + | Some tcrefViewedFrom -> + ExistsHeadTypeInEntireHierarchy g amap m (generalizedTyconRef tcrefViewedFrom) tcrefOfViewedItem) + let accessibleByInternalsVisibleTo = + (access = ILMemberAccess.Assembly && canAccessFromOneOf cpaths tcrefOfViewedItem.CompilationPath) + (access = ILMemberAccess.Public) || accessibleByFamily || accessibleByInternalsVisibleTo + | AccessibleFromSomewhere -> + true + +/// Indicates if tdef is accessible. If tdef.Access = ILTypeDefAccess.Nested then encTyconRefOpt s TyconRef of enclosing type +/// and visibility of tdef is obtained using member access rules +let private IsILTypeDefAccessible (amap : Import.ImportMap) m ad encTyconRefOpt (tdef: ILTypeDef) = + match tdef.Access with + | ILTypeDefAccess.Nested nestedAccess -> + match encTyconRefOpt with + | None -> assert false; true + | Some encTyconRef -> IsILMemberAccessible amap.g amap m encTyconRef ad nestedAccess + | _ -> + match ad with + | AccessibleFromSomewhere -> true + | AccessibleFromEverywhere + | AccessibleFromSomeFSharpCode + | AccessibleFrom _ -> tdef.Access = ILTypeDefAccess.Public + +/// Indicates if a TyconRef is visible through the AccessibleFrom(cpaths,_). +/// Note that InternalsVisibleTo extends those cpaths. +let private IsTyconAccessibleViaVisibleTo ad (tcrefOfViewedItem:TyconRef) = + match ad with + | AccessibleFromEverywhere + | AccessibleFromSomewhere + | AccessibleFromSomeFSharpCode -> false + | AccessibleFrom (cpaths,_tcrefViewedFromOption) -> + canAccessFromOneOf cpaths tcrefOfViewedItem.CompilationPath + +/// Indicates if given IL based TyconRef is accessible. If TyconRef is nested then we'll +/// walk though the list of enclosing types and test if all of them are accessible +let private IsILTypeInfoAccessible amap m ad (tcrefOfViewedItem : TyconRef) = + let scoref, enc, tdef = tcrefOfViewedItem.ILTyconInfo + let rec check parentTycon path = + let ilTypeDefAccessible = + match parentTycon with + | None -> + match path with + | [] -> assert false; true // in this case path should have at least one element + | [x] -> IsILTypeDefAccessible amap m ad None x // shortcut for non-nested types + | x::xs -> + // check if enclosing type x is accessible. + // if yes - create parent tycon for type 'x' and continue with the rest of the path + IsILTypeDefAccessible amap m ad None x && + ( + let parentILTyRef = mkRefForNestedILTypeDef scoref ([], x) + let parentTycon = Import.ImportILTypeRef amap m parentILTyRef + check (Some (parentTycon, [x])) xs + ) + | (Some (parentTycon, parentPath)) -> + match path with + | [] -> true // end of path is reached - success + | x::xs -> + // check if x is accessible from the parent tycon + // if yes - create parent tycon for type 'x' and continue with the rest of the path + IsILTypeDefAccessible amap m ad (Some parentTycon) x && + ( + let parentILTyRef = mkRefForNestedILTypeDef scoref (parentPath, x) + let parentTycon = Import.ImportILTypeRef amap m parentILTyRef + check (Some (parentTycon, parentPath @ [x])) xs + ) + ilTypeDefAccessible || IsTyconAccessibleViaVisibleTo ad tcrefOfViewedItem + + check None (enc @ [tdef]) + +/// Indicates if an IL member associated with the given ILType is accessible +let private IsILTypeAndMemberAccessible g amap m adType ad (ILTypeInfo(tcrefOfViewedItem, _, _, _)) access = + IsILTypeInfoAccessible amap m adType tcrefOfViewedItem && IsILMemberAccessible g amap m tcrefOfViewedItem ad access + +/// Indicates if an entity is accessible +let IsEntityAccessible amap m ad (tcref:TyconRef) = + if tcref.IsILTycon then + IsILTypeInfoAccessible amap m ad tcref + else + tcref.Accessibility |> IsAccessible ad + +/// Check that an entity is accessible +let CheckTyconAccessible amap m ad tcref = + let res = IsEntityAccessible amap m ad tcref + if not res then + errorR(Error(FSComp.SR.typeIsNotAccessible tcref.DisplayName,m)) + res + +/// Indicates if a type definition and its representation contents are accessible +let IsTyconReprAccessible amap m ad tcref = + IsEntityAccessible amap m ad tcref && + IsAccessible ad tcref.TypeReprAccessibility + +/// Check that a type definition and its representation contents are accessible +let CheckTyconReprAccessible amap m ad tcref = + CheckTyconAccessible amap m ad tcref && + (let res = IsAccessible ad tcref.TypeReprAccessibility + if not res then + errorR (Error (FSComp.SR.unionCasesAreNotAccessible tcref.DisplayName,m)) + res) + +/// Indicates if a type is accessible (both definition and instantiation) +let rec IsTypeAccessible g amap m ad ty = + not (isAppTy g ty) || + let tcref,tinst = destAppTy g ty + IsEntityAccessible amap m ad tcref && IsTypeInstAccessible g amap m ad tinst + +and IsTypeInstAccessible g amap m ad tinst = + match tinst with + | [] -> true + | _ -> List.forall (IsTypeAccessible g amap m ad) tinst + +/// Indicate if a provided member is accessible +let IsProvidedMemberAccessible (amap:Import.ImportMap) m ad ty access = + let g = amap.g + let isTyAccessible = IsTypeAccessible g amap m ad ty + if not isTyAccessible then false + else + not (isAppTy g ty) || + let tcrefOfViewedItem,_ = destAppTy g ty + IsILMemberAccessible g amap m tcrefOfViewedItem ad access + +/// Compute the accessibility of a provided member +let ComputeILAccess isPublic isFamily isFamilyOrAssembly isFamilyAndAssembly = + if isPublic then ILMemberAccess.Public + elif isFamily then ILMemberAccess.Family + elif isFamilyOrAssembly then ILMemberAccess.FamilyOrAssembly + elif isFamilyAndAssembly then ILMemberAccess.FamilyAndAssembly + else ILMemberAccess.Private + +/// IndiCompute the accessibility of a provided member +let IsILFieldInfoAccessible g amap m ad x = + match x with + | ILFieldInfo (tinfo,fd) -> IsILTypeAndMemberAccessible g amap m ad ad tinfo fd.Access +#if EXTENSIONTYPING + | ProvidedField (amap, tpfi, m) as pfi -> + let access = tpfi.PUntaint((fun fi -> ComputeILAccess fi.IsPublic fi.IsFamily fi.IsFamilyOrAssembly fi.IsFamilyAndAssembly), m) + IsProvidedMemberAccessible amap m ad pfi.EnclosingType access +#endif + +let GetILAccessOfILEventInfo (ILEventInfo (tinfo,edef)) = + (resolveILMethodRef tinfo.RawMetadata edef.AddMethod).Access + +let IsILEventInfoAccessible g amap m ad einfo = + let access = GetILAccessOfILEventInfo einfo + IsILTypeAndMemberAccessible g amap m ad ad einfo.ILTypeInfo access + +let private IsILMethInfoAccessible g amap m adType ad ilminfo = + match ilminfo with + | ILMethInfo (_,typ,None,mdef,_) -> IsILTypeAndMemberAccessible g amap m adType ad (ILTypeInfo.FromType g typ) mdef.Access + | ILMethInfo (_,_,Some declaringTyconRef,mdef,_) -> IsILMemberAccessible g amap m declaringTyconRef ad mdef.Access + +let GetILAccessOfILPropInfo (ILPropInfo(tinfo,pdef)) = + let tdef = tinfo.RawMetadata + let ilAccess = + match pdef.GetMethod with + | Some mref -> (resolveILMethodRef tdef mref).Access + | None -> + match pdef.SetMethod with + | None -> ILMemberAccess.Public + | Some mref -> (resolveILMethodRef tdef mref).Access + ilAccess + +let IsILPropInfoAccessible g amap m ad pinfo = + let ilAccess = GetILAccessOfILPropInfo pinfo + IsILTypeAndMemberAccessible g amap m ad ad pinfo.ILTypeInfo ilAccess + +let IsValAccessible ad (vref:ValRef) = + vref.Accessibility |> IsAccessible ad + +let CheckValAccessible m ad (vref:ValRef) = + if not (IsValAccessible ad vref) then + errorR (Error (FSComp.SR.valueIsNotAccessible vref.DisplayName,m)) + +let IsUnionCaseAccessible amap m ad (ucref:UnionCaseRef) = + IsTyconReprAccessible amap m ad ucref.TyconRef && + IsAccessible ad ucref.UnionCase.Accessibility + +let CheckUnionCaseAccessible amap m ad (ucref:UnionCaseRef) = + CheckTyconReprAccessible amap m ad ucref.TyconRef && + (let res = IsAccessible ad ucref.UnionCase.Accessibility + if not res then + errorR (Error (FSComp.SR.unionCaseIsNotAccessible ucref.CaseName,m)) + res) + +let IsRecdFieldAccessible amap m ad (rfref:RecdFieldRef) = + IsTyconReprAccessible amap m ad rfref.TyconRef && + IsAccessible ad rfref.RecdField.Accessibility + +let CheckRecdFieldAccessible amap m ad (rfref:RecdFieldRef) = + CheckTyconReprAccessible amap m ad rfref.TyconRef && + (let res = IsAccessible ad rfref.RecdField.Accessibility + if not res then + errorR (Error (FSComp.SR.fieldIsNotAccessible rfref.FieldName,m)) + res) + +let CheckRecdFieldInfoAccessible amap m ad (rfinfo:RecdFieldInfo) = + CheckRecdFieldAccessible amap m ad rfinfo.RecdFieldRef |> ignore + +let CheckILFieldInfoAccessible g amap m ad finfo = + if not (IsILFieldInfoAccessible g amap m ad finfo) then + errorR (Error (FSComp.SR.structOrClassFieldIsNotAccessible finfo.FieldName,m)) + +/// Uses a separate accessibility domains for containing type and method itself +/// This makes sense cases like +/// type A() = +/// type protected B() = +/// member this.Public() = () +/// member protected this.Protected() = () +/// type C() = +/// inherit A() +/// let x = A.B() +/// do x.Public() +/// when calling x.SomeMethod() we need to use 'adTyp' do verify that type of x is accessible from C +/// and 'ad' to determine accessibility of SomeMethod. +/// I.e when calling x.Public() and x.Protected() -in both cases first check should succeed and second - should fail in the latter one. +let IsTypeAndMethInfoAccessible amap m adTyp ad = function + | ILMeth (g,x,_) -> IsILMethInfoAccessible g amap m adTyp ad x + | FSMeth (_,_,vref,_) -> IsValAccessible ad vref + | DefaultStructCtor(g,typ) -> IsTypeAccessible g amap m ad typ +#if EXTENSIONTYPING + | ProvidedMeth(amap,tpmb,_,m) as etmi -> + let access = tpmb.PUntaint((fun mi -> ComputeILAccess mi.IsPublic mi.IsFamily mi.IsFamilyOrAssembly mi.IsFamilyAndAssembly), m) + IsProvidedMemberAccessible amap m ad etmi.EnclosingType access +#endif +let IsMethInfoAccessible amap m ad minfo = IsTypeAndMethInfoAccessible amap m ad ad minfo + +let IsPropInfoAccessible g amap m ad = function + | ILProp (_,x) -> IsILPropInfoAccessible g amap m ad x + | FSProp (_,_,Some vref,_) + | FSProp (_,_,_,Some vref) -> IsValAccessible ad vref +#if EXTENSIONTYPING + | ProvidedProp (amap, tppi, m) as pp-> + let access = + let a = tppi.PUntaint((fun ppi -> + let tryGetILAccessForProvidedMethodBase (mi : ProvidedMethodBase) = + match mi with + | null -> None + | mi -> Some(ComputeILAccess mi.IsPublic mi.IsFamily mi.IsFamilyOrAssembly mi.IsFamilyAndAssembly) + match tryGetILAccessForProvidedMethodBase(ppi.GetGetMethod()) with + | None -> tryGetILAccessForProvidedMethodBase(ppi.GetSetMethod()) + | x -> x), m) + defaultArg a ILMemberAccess.Public + IsProvidedMemberAccessible amap m ad pp.EnclosingType access +#endif + | _ -> false + +let IsFieldInfoAccessible ad (rfref:RecdFieldInfo) = + IsAccessible ad rfref.RecdField.Accessibility + + + diff --git a/src/fsharp/AttributeChecking.fs b/src/fsharp/AttributeChecking.fs new file mode 100644 index 00000000000..661b5ede03d --- /dev/null +++ b/src/fsharp/AttributeChecking.fs @@ -0,0 +1,499 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +/// Logic associated with checking "ObsoleteAttribute" and other attributes +/// on items from name resolution +module internal Microsoft.FSharp.Compiler.AttributeChecking + +open Internal.Utilities +open Microsoft.FSharp.Compiler.AbstractIL +open Microsoft.FSharp.Compiler.AbstractIL.IL +open Microsoft.FSharp.Compiler.AbstractIL.Internal.Library + +open Microsoft.FSharp.Compiler +open Microsoft.FSharp.Compiler.AccessibilityLogic +open Microsoft.FSharp.Compiler.Ast +open Microsoft.FSharp.Compiler.Range +open Microsoft.FSharp.Compiler.ErrorLogger +open Microsoft.FSharp.Compiler.Infos +open Microsoft.FSharp.Compiler.Tast +open Microsoft.FSharp.Compiler.Tastops +open Microsoft.FSharp.Compiler.TcGlobals + +#if EXTENSIONTYPING +open Microsoft.FSharp.Compiler.ExtensionTyping +open Microsoft.FSharp.Core.CompilerServices +#endif + +exception ObsoleteWarning of string * range +exception ObsoleteError of string * range + +let fail() = failwith "This custom attribute has an argument that can not yet be converted using this API" + +let rec private evalILAttribElem e = + match e with + | ILAttribElem.String (Some x) -> box x + | ILAttribElem.String None -> null + | ILAttribElem.Bool x -> box x + | ILAttribElem.Char x -> box x + | ILAttribElem.SByte x -> box x + | ILAttribElem.Int16 x -> box x + | ILAttribElem.Int32 x -> box x + | ILAttribElem.Int64 x -> box x + | ILAttribElem.Byte x -> box x + | ILAttribElem.UInt16 x -> box x + | ILAttribElem.UInt32 x -> box x + | ILAttribElem.UInt64 x -> box x + | ILAttribElem.Single x -> box x + | ILAttribElem.Double x -> box x + | ILAttribElem.Null -> null + | ILAttribElem.Array (_, a) -> box [| for i in a -> evalILAttribElem i |] + // TODO: typeof<..> in attribute values + | ILAttribElem.Type (Some _t) -> fail() + | ILAttribElem.Type None -> null + | ILAttribElem.TypeRef (Some _t) -> fail() + | ILAttribElem.TypeRef None -> null + +let rec private evalFSharpAttribArg g e = + match e with + | Expr.Const(c,_,_) -> + match c with + | Const.Bool b -> box b + | Const.SByte i -> box i + | Const.Int16 i -> box i + | Const.Int32 i -> box i + | Const.Int64 i -> box i + | Const.Byte i -> box i + | Const.UInt16 i -> box i + | Const.UInt32 i -> box i + | Const.UInt64 i -> box i + | Const.Single i -> box i + | Const.Double i -> box i + | Const.Char i -> box i + | Const.Zero -> null + | Const.String s -> box s + | _ -> fail() + | Expr.Op (TOp.Array,_,a,_) -> box [| for i in a -> evalFSharpAttribArg g i |] + | TypeOfExpr g ty -> box ty + // TODO: | TypeDefOfExpr g ty + | _ -> fail() + +type AttribInfo = + | FSAttribInfo of TcGlobals * Attrib + | ILAttribInfo of TcGlobals * Import.ImportMap * ILScopeRef * ILAttribute * range + + member x.TyconRef = + match x with + | FSAttribInfo(_g,Attrib(tcref,_,_,_,_,_,_)) -> tcref + | ILAttribInfo (g, amap, scoref, a, m) -> + let ty = ImportILType scoref amap m [] a.Method.EnclosingType + tcrefOfAppTy g ty + + member x.ConstructorArguments = + match x with + | FSAttribInfo(g,Attrib(_,_,unnamedArgs,_,_,_,_)) -> + unnamedArgs + |> List.map (fun (AttribExpr(origExpr,evaluatedExpr)) -> + let ty = tyOfExpr g origExpr + let obj = evalFSharpAttribArg g evaluatedExpr + ty,obj) + | ILAttribInfo (g, amap, scoref, cattr, m) -> + let parms, _args = decodeILAttribData g.ilg cattr + [ for (argty,argval) in Seq.zip cattr.Method.FormalArgTypes parms -> + let ty = ImportILType scoref amap m [] argty + let obj = evalILAttribElem argval + ty,obj ] + + member x.NamedArguments = + match x with + | FSAttribInfo(g,Attrib(_,_,_,namedArgs,_,_,_)) -> + namedArgs + |> List.map (fun (AttribNamedArg(nm,_,isField,AttribExpr(origExpr,evaluatedExpr))) -> + let ty = tyOfExpr g origExpr + let obj = evalFSharpAttribArg g evaluatedExpr + ty, nm, isField, obj) + | ILAttribInfo (g, amap, scoref, cattr, m) -> + let _parms, namedArgs = decodeILAttribData g.ilg cattr + [ for (nm, argty, isProp, argval) in namedArgs -> + let ty = ImportILType scoref amap m [] argty + let obj = evalILAttribElem argval + let isField = not isProp + ty, nm, isField, obj ] + + +/// Check custom attributes. This is particularly messy because custom attributes come in in three different +/// formats. +let AttribInfosOfIL g amap scoref m (attribs: ILAttributes) = + attribs.AsList |> List.map (fun a -> ILAttribInfo (g, amap, scoref, a, m)) + +let AttribInfosOfFS g attribs = + attribs |> List.map (fun a -> FSAttribInfo (g, a)) + +let GetAttribInfosOfEntity g amap m (tcref:TyconRef) = + match metadataOfTycon tcref.Deref with +#if EXTENSIONTYPING + // TODO: provided attributes + | ProvidedTypeMetadata _info -> [] + //let provAttribs = info.ProvidedType.PApply((fun a -> (a :> IProvidedCustomAttributeProvider)),m) + //match provAttribs.PUntaint((fun a -> a. .GetAttributeConstructorArgs(provAttribs.TypeProvider.PUntaintNoFailure(id), atref.FullName)),m) with + //| Some args -> f3 args + //| None -> None +#endif + | ILTypeMetadata (scoref,tdef) -> + tdef.CustomAttrs |> AttribInfosOfIL g amap scoref m + | FSharpOrArrayOrByrefOrTupleOrExnTypeMetadata -> + tcref.Attribs |> List.map (fun a -> FSAttribInfo (g, a)) + + +let GetAttribInfosOfMethod amap m minfo = + match minfo with + | ILMeth (g,ilminfo,_) -> ilminfo.RawMetadata.CustomAttrs |> AttribInfosOfIL g amap ilminfo.MetadataScope m + | FSMeth (g,_,vref,_) -> vref.Attribs |> AttribInfosOfFS g + | DefaultStructCtor _ -> [] +#if EXTENSIONTYPING + // TODO: provided attributes + | ProvidedMeth (_,_mi,_,_m) -> + [] + +#endif + +let GetAttribInfosOfProp amap m pinfo = + match pinfo with + | ILProp(g,ilpinfo) -> ilpinfo.RawMetadata.CustomAttrs |> AttribInfosOfIL g amap ilpinfo.ILTypeInfo.ILScopeRef m + | FSProp(g,_,Some vref,_) + | FSProp(g,_,_,Some vref) -> vref.Attribs |> AttribInfosOfFS g + | FSProp _ -> failwith "GetAttribInfosOfProp: unreachable" +#if EXTENSIONTYPING + // TODO: provided attributes + | ProvidedProp _ -> [] +#endif + +let GetAttribInfosOfEvent amap m einfo = + match einfo with + | ILEvent(g, x) -> x.RawMetadata.CustomAttrs |> AttribInfosOfIL g amap x.ILTypeInfo.ILScopeRef m + | FSEvent(_, pi, _vref1, _vref2) -> GetAttribInfosOfProp amap m pi +#if EXTENSIONTYPING + // TODO: provided attributes + | ProvidedEvent _ -> [] +#endif + +/// Analyze three cases for attributes declared on type definitions: IL-declared attributes, F#-declared attributes and +/// provided attributes. +// +// This is used for AttributeUsageAttribute, DefaultMemberAttribute and ConditionalAttribute (on attribute types) +let TryBindTyconRefAttribute g m (AttribInfo (atref,_) as args) (tcref:TyconRef) f1 f2 f3 = + ignore m; ignore f3 + match metadataOfTycon tcref.Deref with +#if EXTENSIONTYPING + | ProvidedTypeMetadata info -> + let provAttribs = info.ProvidedType.PApply((fun a -> (a :> IProvidedCustomAttributeProvider)),m) + match provAttribs.PUntaint((fun a -> a.GetAttributeConstructorArgs(provAttribs.TypeProvider.PUntaintNoFailure(id), atref.FullName)),m) with + | Some args -> f3 args + | None -> None +#endif + | ILTypeMetadata (_,tdef) -> + match TryDecodeILAttribute g atref tdef.CustomAttrs with + | Some attr -> f1 attr + | _ -> None + | FSharpOrArrayOrByrefOrTupleOrExnTypeMetadata -> + match TryFindFSharpAttribute g args tcref.Attribs with + | Some attr -> f2 attr + | _ -> None + +/// Analyze three cases for attributes declared on methods: IL-declared attributes, F#-declared attributes and +/// provided attributes. +let BindMethInfoAttributes m minfo f1 f2 f3 = + ignore m; ignore f3 + match minfo with + | ILMeth (_,x,_) -> f1 x.RawMetadata.CustomAttrs + | FSMeth (_,_,vref,_) -> f2 vref.Attribs + | DefaultStructCtor _ -> f2 [] +#if EXTENSIONTYPING + | ProvidedMeth (_,mi,_,_) -> f3 (mi.PApply((fun st -> (st :> IProvidedCustomAttributeProvider)),m)) +#endif + +/// Analyze three cases for attributes declared on methods: IL-declared attributes, F#-declared attributes and +/// provided attributes. +let TryBindMethInfoAttribute g m (AttribInfo(atref,_) as attribSpec) minfo f1 f2 f3 = +#if EXTENSIONTYPING +#else + // to prevent unused parameter warning + ignore f3 +#endif + BindMethInfoAttributes m minfo + (fun ilAttribs -> TryDecodeILAttribute g atref ilAttribs |> Option.bind f1) + (fun fsAttribs -> TryFindFSharpAttribute g attribSpec fsAttribs |> Option.bind f2) +#if EXTENSIONTYPING + (fun provAttribs -> + match provAttribs.PUntaint((fun a -> a.GetAttributeConstructorArgs(provAttribs.TypeProvider.PUntaintNoFailure(id), atref.FullName)),m) with + | Some args -> f3 args + | None -> None) +#else + (fun _provAttribs -> None) +#endif + +/// Try to find a specific attribute on a method, where the attribute accepts a string argument. +/// +/// This is just used for the 'ConditionalAttribute' attribute +let TryFindMethInfoStringAttribute g m attribSpec minfo = + TryBindMethInfoAttribute g m attribSpec minfo + (function ([ILAttribElem.String (Some msg) ],_) -> Some msg | _ -> None) + (function (Attrib(_,_,[ AttribStringArg msg ],_,_,_,_)) -> Some msg | _ -> None) + (function ([ Some ((:? string as msg) : obj) ],_) -> Some msg | _ -> None) + +/// Check if a method has a specific attribute. +let MethInfoHasAttribute g m attribSpec minfo = + TryBindMethInfoAttribute g m attribSpec minfo + (fun _ -> Some ()) + (fun _ -> Some ()) + (fun _ -> Some ()) + |> Option.isSome + + + +/// Check IL attributes for 'ObsoleteAttribute', returning errors and warnings as data +let private CheckILAttributes g cattrs m = + let (AttribInfo(tref,_)) = g.attrib_SystemObsolete + match TryDecodeILAttribute g tref cattrs with + | Some ([ILAttribElem.String (Some msg) ],_) -> + WarnD(ObsoleteWarning(msg,m)) + | Some ([ILAttribElem.String (Some msg); ILAttribElem.Bool isError ],_) -> + if isError then + ErrorD (ObsoleteError(msg,m)) + else + WarnD (ObsoleteWarning(msg,m)) + | Some ([ILAttribElem.String None ],_) -> + WarnD(ObsoleteWarning("",m)) + | Some _ -> + WarnD(ObsoleteWarning("",m)) + | None -> + CompleteD + +/// Check F# attributes for 'ObsoleteAttribute', 'CompilerMessageAttribute' and 'ExperimentalAttribute', +/// returning errors and warnings as data +let CheckFSharpAttributes g attribs m = + if isNil attribs then CompleteD + else + (match TryFindFSharpAttribute g g.attrib_SystemObsolete attribs with + | Some(Attrib(_,_,[ AttribStringArg s ],_,_,_,_)) -> + WarnD(ObsoleteWarning(s,m)) + | Some(Attrib(_,_,[ AttribStringArg s; AttribBoolArg(isError) ],_,_,_,_)) -> + if isError then + ErrorD (ObsoleteError(s,m)) + else + WarnD (ObsoleteWarning(s,m)) + | Some _ -> + WarnD(ObsoleteWarning("", m)) + | None -> + CompleteD + ) ++ (fun () -> + + match TryFindFSharpAttribute g g.attrib_CompilerMessageAttribute attribs with + | Some(Attrib(_,_,[ AttribStringArg s ; AttribInt32Arg n ],namedArgs,_,_,_)) -> + let msg = UserCompilerMessage(s,n,m) + let isError = + match namedArgs with + | ExtractAttribNamedArg "IsError" (AttribBoolArg v) -> v + | _ -> false + if isError then ErrorD msg else WarnD msg + + | _ -> + CompleteD + ) ++ (fun () -> + + match TryFindFSharpAttribute g g.attrib_ExperimentalAttribute attribs with + | Some(Attrib(_,_,[ AttribStringArg(s) ],_,_,_,_)) -> + WarnD(Experimental(s,m)) + | Some _ -> + WarnD(Experimental(FSComp.SR.experimentalConstruct (), m)) + | _ -> + CompleteD + ) ++ (fun () -> + + match TryFindFSharpAttribute g g.attrib_UnverifiableAttribute attribs with + | Some _ -> + WarnD(PossibleUnverifiableCode(m)) + | _ -> + CompleteD + ) + +#if EXTENSIONTYPING +/// Check a list of provided attributes for 'ObsoleteAttribute', returning errors and warnings as data +let private CheckProvidedAttributes g m (provAttribs: Tainted) = + let (AttribInfo(tref,_)) = g.attrib_SystemObsolete + match provAttribs.PUntaint((fun a -> a.GetAttributeConstructorArgs(provAttribs.TypeProvider.PUntaintNoFailure(id), tref.FullName)),m) with + | Some ([ Some (:? string as msg) ], _) -> WarnD(ObsoleteWarning(msg,m)) + | Some ([ Some (:? string as msg); Some (:?bool as isError) ], _) -> + if isError then + ErrorD (ObsoleteError(msg,m)) + else + WarnD (ObsoleteWarning(msg,m)) + | Some ([ None ], _) -> + WarnD(ObsoleteWarning("",m)) + | Some _ -> + WarnD(ObsoleteWarning("",m)) + | None -> + CompleteD +#endif + +/// Indicate if a list of IL attributes contains 'ObsoleteAttribute'. Used to suppress the item in intellisense. +let CheckILAttributesForUnseen g cattrs _m = + let (AttribInfo(tref,_)) = g.attrib_SystemObsolete + isSome (TryDecodeILAttribute g tref cattrs) + +/// Checks the attributes for CompilerMessageAttribute, which has an IsHidden argument that allows +/// items to be suppressed from intellisense. +let CheckFSharpAttributesForHidden g attribs = + nonNil attribs && + (match TryFindFSharpAttribute g g.attrib_CompilerMessageAttribute attribs with + | Some(Attrib(_,_,[AttribStringArg _; AttribInt32Arg messageNumber], + ExtractAttribNamedArg "IsHidden" (AttribBoolArg v),_,_,_)) -> + // Message number 62 is for "ML Compatibility". Items labelled with this are visible in intellisense + // when mlCompatibility is set. + v && not (messageNumber = 62 && g.mlCompatibility) + | _ -> false) + +/// Indicate if a list of F# attributes contains 'ObsoleteAttribute'. Used to suppress the item in intellisense. +let CheckFSharpAttributesForObsolete g attribs = + nonNil attribs && (HasFSharpAttribute g g.attrib_SystemObsolete attribs) + +/// Indicate if a list of F# attributes contains 'ObsoleteAttribute'. Used to suppress the item in intellisense. +/// Also check the attributes for CompilerMessageAttribute, which has an IsHidden argument that allows +/// items to be suppressed from intellisense. +let CheckFSharpAttributesForUnseen g attribs _m = + nonNil attribs && + (CheckFSharpAttributesForObsolete g attribs || + CheckFSharpAttributesForHidden g attribs) + +#if EXTENSIONTYPING +/// Indicate if a list of provided attributes contains 'ObsoleteAttribute'. Used to suppress the item in intellisense. +let CheckProvidedAttributesForUnseen (provAttribs: Tainted) m = + provAttribs.PUntaint((fun a -> a.GetAttributeConstructorArgs(provAttribs.TypeProvider.PUntaintNoFailure(id), typeof.FullName).IsSome),m) +#endif + +/// Check the attributes associated with a property, returning warnings and errors as data. +let CheckPropInfoAttributes pinfo m = + match pinfo with + | ILProp(g,ILPropInfo(_,pdef)) -> CheckILAttributes g pdef.CustomAttrs m + | FSProp(g,_,Some vref,_) + | FSProp(g,_,_,Some vref) -> CheckFSharpAttributes g vref.Attribs m + | FSProp _ -> failwith "CheckPropInfoAttributes: unreachable" +#if EXTENSIONTYPING + | ProvidedProp (amap,pi,m) -> + CheckProvidedAttributes amap.g m (pi.PApply((fun st -> (st :> IProvidedCustomAttributeProvider)),m)) + +#endif + + +/// Check the attributes associated with a IL field, returning warnings and errors as data. +let CheckILFieldAttributes g (finfo:ILFieldInfo) m = + match finfo with + | ILFieldInfo(_,pd) -> + CheckILAttributes g pd.CustomAttrs m |> CommitOperationResult +#if EXTENSIONTYPING + | ProvidedField (amap,fi,m) -> + CheckProvidedAttributes amap.g m (fi.PApply((fun st -> (st :> IProvidedCustomAttributeProvider)),m)) |> CommitOperationResult +#endif + +/// Check the attributes associated with a method, returning warnings and errors as data. +let CheckMethInfoAttributes g m tyargsOpt minfo = + let search = + BindMethInfoAttributes m minfo + (fun ilAttribs -> Some(CheckILAttributes g ilAttribs m)) + (fun fsAttribs -> + let res = + CheckFSharpAttributes g fsAttribs m ++ (fun () -> + if isNone tyargsOpt && HasFSharpAttribute g g.attrib_RequiresExplicitTypeArgumentsAttribute fsAttribs then + ErrorD(Error(FSComp.SR.tcFunctionRequiresExplicitTypeArguments(minfo.LogicalName),m)) + else + CompleteD) + Some res) +#if EXTENSIONTYPING + (fun provAttribs -> Some (CheckProvidedAttributes g m provAttribs)) +#else + (fun _provAttribs -> None) +#endif + match search with + | Some res -> res + | None -> CompleteD // no attribute = no errors + +/// Indicate if a method has 'Obsolete', 'CompilerMessageAttribute' or 'TypeProviderEditorHideMethodsAttribute'. +/// Used to suppress the item in intellisense. +let MethInfoIsUnseen g m typ minfo = + let isUnseenByObsoleteAttrib = + match BindMethInfoAttributes m minfo + (fun ilAttribs -> Some(CheckILAttributesForUnseen g ilAttribs m)) + (fun fsAttribs -> Some(CheckFSharpAttributesForUnseen g fsAttribs m)) +#if EXTENSIONTYPING + (fun provAttribs -> Some(CheckProvidedAttributesForUnseen provAttribs m)) +#else + (fun _provAttribs -> None) +#endif + with + | Some res -> res + | None -> false + + let isUnseenByHidingAttribute = +#if EXTENSIONTYPING + not (isObjTy g typ) && + isAppTy g typ && + isObjTy g minfo.EnclosingType && + let tcref = tcrefOfAppTy g typ + match tcref.TypeReprInfo with + | TProvidedTypeExtensionPoint info -> + info.ProvidedType.PUntaint((fun st -> (st :> IProvidedCustomAttributeProvider).GetHasTypeProviderEditorHideMethodsAttribute(info.ProvidedType.TypeProvider.PUntaintNoFailure(id))), m) + | _ -> + // This attribute check is done by name to ensure compilation doesn't take a dependency + // on Microsoft.FSharp.Core.CompilerServices.TypeProviderEditorHideMethodsAttribute. + // + // We are only interested in filtering out the method on System.Object, so it is sufficient + // just to look at the attributes on IL methods. + if tcref.IsILTycon then + tcref.ILTyconRawMetadata.CustomAttrs.AsList + |> List.exists (fun attr -> attr.Method.EnclosingType.TypeSpec.Name = typeof.FullName) + else + false +#else + typ |> ignore + false +#endif + isUnseenByObsoleteAttrib || isUnseenByHidingAttribute + +/// Indicate if a property has 'Obsolete' or 'CompilerMessageAttribute'. +/// Used to suppress the item in intellisense. +let PropInfoIsUnseen m pinfo = + match pinfo with + | ILProp (g,ILPropInfo(_,pdef)) -> CheckILAttributesForUnseen g pdef.CustomAttrs m + | FSProp (g,_,Some vref,_) + | FSProp (g,_,_,Some vref) -> CheckFSharpAttributesForUnseen g vref.Attribs m + | FSProp _ -> failwith "CheckPropInfoAttributes: unreachable" +#if EXTENSIONTYPING + | ProvidedProp (_amap,pi,m) -> + CheckProvidedAttributesForUnseen (pi.PApply((fun st -> (st :> IProvidedCustomAttributeProvider)),m)) m +#endif + +/// Check the attributes on an entity, returning errors and warnings as data. +let CheckEntityAttributes g (x:TyconRef) m = + if x.IsILTycon then + CheckILAttributes g x.ILTyconRawMetadata.CustomAttrs m + else + CheckFSharpAttributes g x.Attribs m + +/// Check the attributes on a union case, returning errors and warnings as data. +let CheckUnionCaseAttributes g (x:UnionCaseRef) m = + CheckEntityAttributes g x.TyconRef m ++ (fun () -> + CheckFSharpAttributes g x.Attribs m) + +/// Check the attributes on a record field, returning errors and warnings as data. +let CheckRecdFieldAttributes g (x:RecdFieldRef) m = + CheckEntityAttributes g x.TyconRef m ++ (fun () -> + CheckFSharpAttributes g x.PropertyAttribs m) + +/// Check the attributes on an F# value, returning errors and warnings as data. +let CheckValAttributes g (x:ValRef) m = + CheckFSharpAttributes g x.Attribs m + +/// Check the attributes on a record field, returning errors and warnings as data. +let CheckRecdFieldInfoAttributes g (x:RecdFieldInfo) m = + CheckRecdFieldAttributes g x.RecdFieldRef m + + diff --git a/src/fsharp/CompileOps.fs b/src/fsharp/CompileOps.fs index 9c6ac439041..f7950c34dba 100644 --- a/src/fsharp/CompileOps.fs +++ b/src/fsharp/CompileOps.fs @@ -7,26 +7,29 @@ open System open System.Text open System.IO open System.Collections.Generic +open System.Runtime.CompilerServices + open Internal.Utilities open Internal.Utilities.Text -open Microsoft.FSharp.Compiler +open Internal.Utilities.Collections +open Internal.Utilities.Filename + open Microsoft.FSharp.Compiler.AbstractIL open Microsoft.FSharp.Compiler.AbstractIL.IL open Microsoft.FSharp.Compiler.AbstractIL.Internal open Microsoft.FSharp.Compiler.AbstractIL.Internal.Library open Microsoft.FSharp.Compiler.AbstractIL.Extensions.ILX open Microsoft.FSharp.Compiler.AbstractIL.Diagnostics + +open Microsoft.FSharp.Compiler open Microsoft.FSharp.Compiler.TastPickle open Microsoft.FSharp.Compiler.Range open Microsoft.FSharp.Compiler.TypeChecker open Microsoft.FSharp.Compiler.SR open Microsoft.FSharp.Compiler.DiagnosticMessage - -module Tc = Microsoft.FSharp.Compiler.TypeChecker - -open Microsoft.FSharp.Compiler.AbstractIL.IL open Microsoft.FSharp.Compiler.Range open Microsoft.FSharp.Compiler.Ast +open Microsoft.FSharp.Compiler.AttributeChecking open Microsoft.FSharp.Compiler.ErrorLogger open Microsoft.FSharp.Compiler.Tast open Microsoft.FSharp.Compiler.Tastops @@ -38,17 +41,17 @@ open Microsoft.FSharp.Compiler.Infos open Microsoft.FSharp.Compiler.ConstraintSolver open Microsoft.FSharp.Compiler.MSBuildResolver open Microsoft.FSharp.Compiler.TypeRelations +open Microsoft.FSharp.Compiler.SignatureConformance +open Microsoft.FSharp.Compiler.MethodOverrides open Microsoft.FSharp.Compiler.NameResolution open Microsoft.FSharp.Compiler.PrettyNaming -open Internal.Utilities.Collections -open Internal.Utilities.Filename open Microsoft.FSharp.Compiler.Import + #if EXTENSIONTYPING open Microsoft.FSharp.Compiler.ExtensionTyping open Microsoft.FSharp.Core.CompilerServices #endif -open System.Runtime.CompilerServices #if FX_RESHAPED_REFLECTION open Microsoft.FSharp.Core.ReflectionAdapters @@ -4602,7 +4605,7 @@ let RequireDLL (tcImports:TcImports, tcEnv, thisAssemblyName, m, file) = let g = tcImports.GetTcGlobals() let amap = tcImports.GetImportMap() - let tcEnv = (tcEnv, asms) ||> List.fold (fun tcEnv asm -> Tc.AddCcuToTcEnv(g,amap,m,tcEnv,thisAssemblyName,asm.FSharpViewOfMetadata,asm.AssemblyAutoOpenAttributes,asm.AssemblyInternalsVisibleToAttributes)) + let tcEnv = (tcEnv, asms) ||> List.fold (fun tcEnv asm -> AddCcuToTcEnv(g,amap,m,tcEnv,thisAssemblyName,asm.FSharpViewOfMetadata,asm.AssemblyAutoOpenAttributes,asm.AssemblyInternalsVisibleToAttributes)) tcEnv,(dllinfos,asms) @@ -5030,11 +5033,11 @@ let GetInitialTcEnv (thisAssemblyName:string, initm:range, tcConfig:TcConfig, tc let amap = tcImports.GetImportMap() - let tcEnv = Tc.CreateInitialTcEnv(tcGlobals, amap, initm, thisAssemblyName, ccus) + let tcEnv = CreateInitialTcEnv(tcGlobals, amap, initm, thisAssemblyName, ccus) let tcEnv = if tcConfig.checkOverflow then - Tc.TcOpenDecl TcResultsSink.NoSink tcGlobals amap initm initm tcEnv (pathToSynLid initm (splitNamespace FSharpLib.CoreOperatorsCheckedName)) + TcOpenDecl TcResultsSink.NoSink tcGlobals amap initm initm tcEnv (pathToSynLid initm (splitNamespace FSharpLib.CoreOperatorsCheckedName)) else tcEnv tcEnv @@ -5162,7 +5165,7 @@ let TypeCheckOneInputEventually // Typecheck the signature file let! (tcEnvAtEnd,tcEnv,smodulTypeRoot) = - Tc.TypeCheckOneSigFile (tcGlobals,tcState.tcsNiceNameGen,amap,tcState.tcsCcu,checkForErrors,tcConfig.conditionalCompilationDefines,tcSink) tcState.tcsTcSigEnv file + TypeCheckOneSigFile (tcGlobals,tcState.tcsNiceNameGen,amap,tcState.tcsCcu,checkForErrors,tcConfig.conditionalCompilationDefines,tcSink) tcState.tcsTcSigEnv file let rootSigs = Zmap.add qualNameOfFile smodulTypeRoot rootSigs @@ -5192,7 +5195,7 @@ let TypeCheckOneInputEventually // Typecheck the implementation file let! topAttrs,implFile,tcEnvAtEnd = - Tc.TypeCheckOneImplFile (tcGlobals,tcState.tcsNiceNameGen,amap,tcState.tcsCcu,checkForErrors,tcConfig.conditionalCompilationDefines,tcSink) tcImplEnv rootSigOpt file + TypeCheckOneImplFile (tcGlobals,tcState.tcsNiceNameGen,amap,tcState.tcsCcu,checkForErrors,tcConfig.conditionalCompilationDefines,tcSink) tcImplEnv rootSigOpt file let hadSig = isSome rootSigOpt let implFileSigType = SigTypeOfImplFile implFile @@ -5204,12 +5207,12 @@ let TypeCheckOneInputEventually let m = qualNameOfFile.Range // Add the implementation as to the implementation env - let tcImplEnv = Tc.AddLocalRootModuleOrNamespace TcResultsSink.NoSink tcGlobals amap m tcImplEnv implFileSigType + let tcImplEnv = AddLocalRootModuleOrNamespace TcResultsSink.NoSink tcGlobals amap m tcImplEnv implFileSigType // Add the implementation as to the signature env (unless it had an explicit signature) let tcSigEnv = if hadSig then tcState.tcsTcSigEnv - else Tc.AddLocalRootModuleOrNamespace TcResultsSink.NoSink tcGlobals amap m tcState.tcsTcSigEnv implFileSigType + else AddLocalRootModuleOrNamespace TcResultsSink.NoSink tcGlobals amap m tcState.tcsTcSigEnv implFileSigType // Open the prefixPath for fsi.exe (tcImplEnv) let tcImplEnv = diff --git a/src/fsharp/CompileOptions.fs b/src/fsharp/CompileOptions.fs index de7d14ac5bd..60f34d73267 100644 --- a/src/fsharp/CompileOptions.fs +++ b/src/fsharp/CompileOptions.fs @@ -33,7 +33,7 @@ open Microsoft.FSharp.Compiler.IlxGen #endif #if FX_RESHAPED_REFLECTION - open Microsoft.FSharp.Core.ReflectionAdapters +open Microsoft.FSharp.Core.ReflectionAdapters #endif module Attributes = diff --git a/src/fsharp/ConstraintSolver.fs b/src/fsharp/ConstraintSolver.fs index 45fb086f907..c3fe9f8608d 100644 --- a/src/fsharp/ConstraintSolver.fs +++ b/src/fsharp/ConstraintSolver.fs @@ -32,26 +32,28 @@ module internal Microsoft.FSharp.Compiler.ConstraintSolver open Internal.Utilities open Internal.Utilities.Collections + +open Microsoft.FSharp.Compiler open Microsoft.FSharp.Compiler.AbstractIL +open Microsoft.FSharp.Compiler.AbstractIL.Diagnostics open Microsoft.FSharp.Compiler.AbstractIL.Internal open Microsoft.FSharp.Compiler.AbstractIL.Internal.Library -open Microsoft.FSharp.Compiler - -open Microsoft.FSharp.Compiler.AbstractIL.Diagnostics -open Microsoft.FSharp.Compiler.Range -open Microsoft.FSharp.Compiler.Rational open Microsoft.FSharp.Compiler.Ast open Microsoft.FSharp.Compiler.ErrorLogger +open Microsoft.FSharp.Compiler.Infos +open Microsoft.FSharp.Compiler.AccessibilityLogic +open Microsoft.FSharp.Compiler.AttributeChecking +open Microsoft.FSharp.Compiler.Lib +open Microsoft.FSharp.Compiler.MethodCalls +open Microsoft.FSharp.Compiler.PrettyNaming +open Microsoft.FSharp.Compiler.Range +open Microsoft.FSharp.Compiler.Rational +open Microsoft.FSharp.Compiler.InfoReader open Microsoft.FSharp.Compiler.Tast open Microsoft.FSharp.Compiler.Tastops open Microsoft.FSharp.Compiler.Tastops.DebugPrint open Microsoft.FSharp.Compiler.TcGlobals -open Microsoft.FSharp.Compiler.Lib -open Microsoft.FSharp.Compiler.Infos -open Microsoft.FSharp.Compiler.Infos.AccessibilityLogic -open Microsoft.FSharp.Compiler.Infos.AttributeChecking open Microsoft.FSharp.Compiler.TypeRelations -open Microsoft.FSharp.Compiler.PrettyNaming //------------------------------------------------------------------------- // Generate type variables and record them in within the scope of the @@ -1290,7 +1292,7 @@ and MemberConstraintSolutionOfMethInfo css m minfo minst = let minst = [] // GENERIC TYPE PROVIDERS: for generics, we would have an minst here let allArgVars, allArgs = minfo.GetParamTypes(amap, m, minst) |> List.concat |> List.mapi (fun i ty -> mkLocal m ("arg"+string i) ty) |> List.unzip let objArgVars, objArgs = (if minfo.IsInstance then [mkLocal m "this" minfo.EnclosingType] else []) |> List.unzip - let callMethInfoOpt, callExpr,callExprTy = TypeRelations.ProvidedMethodCalls.BuildInvokerExpressionForProvidedMethodCall css.TcVal (g, amap, mi, objArgs, NeverMutates, false, ValUseFlag.NormalValUse, allArgs, m) + let callMethInfoOpt, callExpr,callExprTy = ProvidedMethodCalls.BuildInvokerExpressionForProvidedMethodCall css.TcVal (g, amap, mi, objArgs, NeverMutates, false, ValUseFlag.NormalValUse, allArgs, m) let closedExprSln = ClosedExprSln (mkLambdas m [] (objArgVars@allArgVars) (callExpr, callExprTy) ) // If the call is a simple call to an IL method with all the arguments in the natural order, then revert to use ILMethSln. // This is important for calls to operators on generated provided types. There is an (unchecked) condition @@ -2539,7 +2541,7 @@ let CodegenWitnessThatTypSupportsTraitConstraint tcVal g amap m (traitInfo:Trait let wrap,h' = mkExprAddrOfExpr g true false PossiblyMutates h None m ResultD (Some (wrap (Expr.Op(TOp.TraitCall(traitInfo), [], (h' :: t), m)))) else - ResultD (Some (Infos.MakeMethInfoCall amap m minfo methArgTys argExprs )) + ResultD (Some (MakeMethInfoCall amap m minfo methArgTys argExprs )) | Choice2Of4 (tinst,rfref,isSet) -> let res = diff --git a/src/fsharp/ConstraintSolver.fsi b/src/fsharp/ConstraintSolver.fsi index 75dda149237..7f648f99ca7 100644 --- a/src/fsharp/ConstraintSolver.fsi +++ b/src/fsharp/ConstraintSolver.fsi @@ -9,6 +9,7 @@ open Microsoft.FSharp.Compiler.AbstractIL open Microsoft.FSharp.Compiler.AbstractIL.Internal open Microsoft.FSharp.Compiler.AbstractIL.Internal.Library open Microsoft.FSharp.Compiler +open Microsoft.FSharp.Compiler.AccessibilityLogic open Microsoft.FSharp.Compiler.Ast open Microsoft.FSharp.Compiler.ErrorLogger open Microsoft.FSharp.Compiler.Tast @@ -18,6 +19,8 @@ open Microsoft.FSharp.Compiler.Tastops open Microsoft.FSharp.Compiler.Tast open Microsoft.FSharp.Compiler.TcGlobals open Microsoft.FSharp.Compiler.Infos +open Microsoft.FSharp.Compiler.MethodCalls +open Microsoft.FSharp.Compiler.InfoReader /// Create a type variable representing the use of a "_" in F# code val NewAnonTypar : TyparKind * range * TyparRigidity * TyparStaticReq * TyparDynamicReq -> Typar @@ -83,8 +86,8 @@ val SimplifyMeasuresInTypeScheme : TcGlobals -> bool -> Typars -> TT val SolveTyparEqualsTyp : ConstraintSolverEnv -> int -> range -> OptionalTrace -> TType -> TType -> OperationResult val SolveTypEqualsTypKeepAbbrevs : ConstraintSolverEnv -> int -> range -> OptionalTrace -> TType -> TType -> OperationResult val CanonicalizeRelevantMemberConstraints : ConstraintSolverEnv -> int -> OptionalTrace -> Typars -> OperationResult -val ResolveOverloading : ConstraintSolverEnv -> OptionalTrace -> string -> ndeep: int -> bool -> int * int -> AccessorDomain -> TypeRelations.CalledMeth list -> bool -> TType option -> TypeRelations.CalledMeth option * OperationResult -val UnifyUniqueOverloading : ConstraintSolverEnv -> int * int -> string -> AccessorDomain -> TypeRelations.CalledMeth list -> TType -> OperationResult +val ResolveOverloading : ConstraintSolverEnv -> OptionalTrace -> string -> ndeep: int -> bool -> int * int -> AccessorDomain -> CalledMeth list -> bool -> TType option -> CalledMeth option * OperationResult +val UnifyUniqueOverloading : ConstraintSolverEnv -> int * int -> string -> AccessorDomain -> CalledMeth list -> TType -> OperationResult val EliminateConstraintsForGeneralizedTypars : ConstraintSolverEnv -> OptionalTrace -> Typars -> unit val CheckDeclaredTypars : DisplayEnv -> ConstraintSolverState -> range -> Typars -> Typars -> unit diff --git a/src/fsharp/FSharp.Build/FSharp.Build.fsproj b/src/fsharp/FSharp.Build/FSharp.Build.fsproj index 3312403732b..407bc789856 100644 --- a/src/fsharp/FSharp.Build/FSharp.Build.fsproj +++ b/src/fsharp/FSharp.Build/FSharp.Build.fsproj @@ -12,6 +12,8 @@ FSharp.Build true {702A7979-BCF9-4C41-853E-3ADFC9897890} + $(OtherFlags) --targetprofile:netcore + true @@ -32,6 +34,7 @@ Utilities/CompilerLocationUtils.fs + @@ -49,7 +52,7 @@ Content - + @@ -57,13 +60,14 @@ + + {DED3BBD7-53F4-428A-8C9F-27968E768605} FSharp.Core - diff --git a/src/fsharp/FSharp.Build/Fsc.fs b/src/fsharp/FSharp.Build/Fsc.fs index 69c01ba3e09..122fd082a28 100644 --- a/src/fsharp/FSharp.Build/Fsc.fs +++ b/src/fsharp/FSharp.Build/Fsc.fs @@ -17,6 +17,10 @@ open Internal.Utilities do() +#if FX_RESHAPED_REFLECTION +open Microsoft.FSharp.Core.ReflectionAdapters +#endif + type FscCommandLineBuilder() = // In addition to generating a command-line that will be handed to cmd.exe, we also generate // an array of individual arguments. The former needs to be quoted (and cmd.exe will strip the @@ -347,18 +351,14 @@ type [ - base.ExecuteTool(pathToTool, responseFileCommands, commandLineCommands) + | null -> base.ExecuteTool(pathToTool, responseFileCommands, commandLineCommands) | _ -> let sources = sources|>Array.map(fun i->i.ItemSpec) - let baseCall = fun (dummy : int) -> fsc.BaseExecuteTool(pathToTool, responseFileCommands, commandLineCommands) - // We are using a Converter rather than a "unit->int" because it is too hard to - // figure out how to pass an F# function object via reflection. - let baseCallDelegate = new System.Converter(baseCall) + let baseCallDelegate = new Func(fun () -> fsc.BaseExecuteTool(pathToTool, responseFileCommands, commandLineCommands) ) try let ret = (host.GetType()).InvokeMember("Compile", BindingFlags.Public ||| BindingFlags.NonPublic ||| BindingFlags.InvokeMethod ||| BindingFlags.Instance, null, host, - [| box baseCallDelegate; box (capturedArguments |> List.toArray); box (capturedFilenames |> List.toArray) |], + [| baseCallDelegate; box (capturedArguments |> List.toArray); box (capturedFilenames |> List.toArray) |], System.Globalization.CultureInfo.InvariantCulture) unbox ret with @@ -368,7 +368,7 @@ type [ System.Diagnostics.Debug.Assert(false, "HostObject received by Fsc task did not have a Compile method or the compile method threw an exception. "+(e.ToString())) reraise() - + override fsc.GenerateCommandLineCommands() = let builder = new FscCommandLineBuilder() diff --git a/src/fsharp/FSharp.Build/Microsoft.FSharp.targets b/src/fsharp/FSharp.Build/Microsoft.FSharp.targets index cdaaf9563a8..b81b7dedf99 100644 --- a/src/fsharp/FSharp.Build/Microsoft.FSharp.targets +++ b/src/fsharp/FSharp.Build/Microsoft.FSharp.targets @@ -201,14 +201,15 @@ this file. - + ============================================================ + --> diff --git a/src/fsharp/FSharp.Build/project.json b/src/fsharp/FSharp.Build/project.json new file mode 100644 index 00000000000..6aeadada7ed --- /dev/null +++ b/src/fsharp/FSharp.Build/project.json @@ -0,0 +1,20 @@ +{ + "dependencies": { + "Microsoft.Build": "0.1.0-preview-00022", + "Microsoft.Build.Framework": "0.1.0-preview-00022", + "Microsoft.Build.Tasks.Core": "0.1.0-preview-00022", + "Microsoft.Build.Utilities.Core": "0.1.0-preview-00022", + "Microsoft.NETCore.Platforms": "1.0.1-rc2-23911", + "Microsoft.Win32.Registry": { + "version": "4.0.0-rc2-23923", + "exclude": "Compile" + }, + "System.AppContext": "4.1.0-rc2-23911", + "System.Diagnostics.Tools": "4.0.1-rc2-23911", + }, + "frameworks": { + "dnxcore50": { + "imports": "portable-net45+win8" + } + } +} \ No newline at end of file diff --git a/src/fsharp/FSharp.Compiler-proto/FSharp.Compiler-proto.fsproj b/src/fsharp/FSharp.Compiler-proto/FSharp.Compiler-proto.fsproj index a01b57f9932..9731adc082c 100644 --- a/src/fsharp/FSharp.Compiler-proto/FSharp.Compiler-proto.fsproj +++ b/src/fsharp/FSharp.Compiler-proto/FSharp.Compiler-proto.fsproj @@ -323,6 +323,15 @@ infos.fs + + Logic\AccessibilityLogic.fs + + + Logic\AttributeChecking.fs + + + Logic\InfoReader.fs + NicePrint.fs @@ -341,6 +350,15 @@ TypeRelations.fs + + Logic\SignatureConformance.fs + + + Logic\MethodOverrides.fs + + + MethodCalls.fs + PatternMatchCompilation.fsi @@ -443,13 +461,13 @@ - + - ..\..\..\packages\Microsoft.DiaSymReader.PortablePdb.1.3.20160301.3\lib\portable-net45+win8\Microsoft.DiaSymReader.PortablePdb.dll + ..\..\..\packages\Microsoft.DiaSymReader.PortablePdb.1.0.0-rc-60301\lib\portable-net45+win8\Microsoft.DiaSymReader.PortablePdb.dll ..\..\..\packages\Microsoft.DiaSymReader.1.0.7\lib\portable-net45+win8\Microsoft.DiaSymReader.dll ..\..\..\packages\System.Reflection.Metadata.1.3.0-beta-23816\lib\portable-net45+win8\System.Reflection.Metadata.dll ..\..\..\packages\System.Collections.Immutable.1.2.0-rc3-23805\lib\portable-net45+win8+wp8+wpa81 diff --git a/src/fsharp/FSharp.Compiler/FSharp.Compiler.fsproj b/src/fsharp/FSharp.Compiler/FSharp.Compiler.fsproj index d6cfc802eae..c66d8802668 100644 --- a/src/fsharp/FSharp.Compiler/FSharp.Compiler.fsproj +++ b/src/fsharp/FSharp.Compiler/FSharp.Compiler.fsproj @@ -24,8 +24,6 @@ $(OtherFlags) --targetprofile:netcore - - $(FSharpSourcesRoot)\..\loc\lcl\{Lang}\$(AssemblyName).dll.lcl @@ -371,6 +369,15 @@ Logic\infos.fs + + Logic\AccessibilityLogic.fs + + + Logic\AttributeChecking.fs + + + Logic\InfoReader.fs + Logic\NicePrint.fs @@ -389,6 +396,15 @@ Logic\TypeRelations.fs + + Logic\SignatureConformance.fs + + + Logic\MethodOverrides.fs + + + Logic\MethodCalls.fs + Logic\PatternMatchCompilation.fsi @@ -512,6 +528,8 @@ FSharp.Core + + diff --git a/src/fsharp/FSharp.Core/FSharp.Core.fsproj b/src/fsharp/FSharp.Core/FSharp.Core.fsproj index ce716d8c430..2300e09f2c2 100644 --- a/src/fsharp/FSharp.Core/FSharp.Core.fsproj +++ b/src/fsharp/FSharp.Core/FSharp.Core.fsproj @@ -16,6 +16,7 @@ 0x05000000 true true + true $(OtherFlags) --warnon:1182 --compiling-fslib --optimize --maxerrors:20 --extraoptimizationloops:1 $(OtherFlags) --compiling-fslib-20:"$(SystemRoot)\Microsoft.NET\Framework\v4.0.30319\mscorlib.dll" $(OtherFlags) --compiling-fslib-40 diff --git a/src/fsharp/FSharp.Core/printf.fs b/src/fsharp/FSharp.Core/printf.fs index 1e175192de1..6dfb7cfa3a4 100644 --- a/src/fsharp/FSharp.Core/printf.fs +++ b/src/fsharp/FSharp.Core/printf.fs @@ -42,11 +42,10 @@ module internal PrintfImpl = open Microsoft.FSharp.Core.Operators open Microsoft.FSharp.Collections open LanguagePrimitives.IntrinsicOperators -#if FX_RESHAPED_REFLECTION +#if FX_RESHAPED_REFLECTION open Microsoft.FSharp.Core.PrimReflectionAdapters open Microsoft.FSharp.Core.ReflectionAdapters - #endif open System.IO diff --git a/src/fsharp/FSharp.LanguageService.Compiler/FSharp.LanguageService.Compiler.fsproj b/src/fsharp/FSharp.LanguageService.Compiler/FSharp.LanguageService.Compiler.fsproj index e3aa019fc9b..5f1c72cf2f6 100644 --- a/src/fsharp/FSharp.LanguageService.Compiler/FSharp.LanguageService.Compiler.fsproj +++ b/src/fsharp/FSharp.LanguageService.Compiler/FSharp.LanguageService.Compiler.fsproj @@ -359,6 +359,15 @@ Logic\infos.fs + + Logic\AccessibilityLogic.fs + + + Logic\AttributeChecking.fs + + + Logic\InfoReader.fs + Logic\NicePrint.fs @@ -377,6 +386,15 @@ Logic\TypeRelations.fs + + Logic\SignatureConformance.fs + + + Logic\MethodOverrides.fs + + + Logic\MethodCalls.fs + Logic\PatternMatchCompilation.fsi diff --git a/src/fsharp/FindUnsolved.fs b/src/fsharp/FindUnsolved.fs index f682746abc9..ef53a03fc3e 100644 --- a/src/fsharp/FindUnsolved.fs +++ b/src/fsharp/FindUnsolved.fs @@ -7,12 +7,12 @@ module internal Microsoft.FSharp.Compiler.FindUnsolved open Internal.Utilities + +open Microsoft.FSharp.Compiler open Microsoft.FSharp.Compiler.AbstractIL open Microsoft.FSharp.Compiler.AbstractIL.IL open Microsoft.FSharp.Compiler.AbstractIL.Internal open Microsoft.FSharp.Compiler.AbstractIL.Internal.Library -open Microsoft.FSharp.Compiler - open Microsoft.FSharp.Compiler.AbstractIL.Diagnostics open Microsoft.FSharp.Compiler.Range open Microsoft.FSharp.Compiler.Ast diff --git a/src/fsharp/InfoReader.fs b/src/fsharp/InfoReader.fs new file mode 100644 index 00000000000..237c54ad208 --- /dev/null +++ b/src/fsharp/InfoReader.fs @@ -0,0 +1,727 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + + +/// Select members from a type by name, searching the type hierarchy if needed +module internal Microsoft.FSharp.Compiler.InfoReader + +open Internal.Utilities + +open Microsoft.FSharp.Compiler.AbstractIL +open Microsoft.FSharp.Compiler.AbstractIL.Diagnostics +open Microsoft.FSharp.Compiler.AbstractIL.IL +open Microsoft.FSharp.Compiler.AbstractIL.Internal +open Microsoft.FSharp.Compiler.AbstractIL.Internal.Library + +open Microsoft.FSharp.Compiler +open Microsoft.FSharp.Compiler.AccessibilityLogic +open Microsoft.FSharp.Compiler.Ast +open Microsoft.FSharp.Compiler.AttributeChecking +open Microsoft.FSharp.Compiler.ErrorLogger +open Microsoft.FSharp.Compiler.Infos +open Microsoft.FSharp.Compiler.Range +open Microsoft.FSharp.Compiler.Tast +open Microsoft.FSharp.Compiler.Tastops +open Microsoft.FSharp.Compiler.TcGlobals + +/// Use the given function to select some of the member values from the members of an F# type +let private SelectImmediateMemberVals g optFilter f (tcref:TyconRef) = + let chooser (vref:ValRef) = + match vref.MemberInfo with + // The 'when' condition is a workaround for the fact that values providing + // override and interface implementations are published in inferred module types + // These cannot be selected directly via the "." notation. + // However, it certainly is useful to be able to publish these values, as we can in theory + // optimize code to make direct calls to these methods. + | Some membInfo when not (ValRefIsExplicitImpl g vref) -> + f membInfo vref + | _ -> + None + + match optFilter with + | None -> tcref.MembersOfFSharpTyconByName |> NameMultiMap.chooseRange chooser + | Some nm -> tcref.MembersOfFSharpTyconByName |> NameMultiMap.find nm |> List.choose chooser + +/// Check whether a name matches an optional filter +let private checkFilter optFilter (nm:string) = match optFilter with None -> true | Some n2 -> nm = n2 + +/// Try to select an F# value when querying members, and if so return a MethInfo that wraps the F# value. +let TrySelectMemberVal g optFilter typ pri _membInfo (vref:ValRef) = + if checkFilter optFilter vref.LogicalName then + Some(FSMeth(g,typ,vref,pri)) + else + None + +/// Query the immediate methods of an F# type, not taking into account inherited methods. The optFilter +/// parameter is an optional name to restrict the set of properties returned. +let GetImmediateIntrinsicMethInfosOfType (optFilter,ad) g amap m typ = + let minfos = + + match metadataOfTy g typ with +#if EXTENSIONTYPING + | ProvidedTypeMetadata info -> + let st = info.ProvidedType + let meths = + match optFilter with + | Some name -> st.PApplyArray ((fun st -> st.GetMethods() |> Array.filter (fun mi -> mi.Name = name) ), "GetMethods", m) + | None -> st.PApplyArray ((fun st -> st.GetMethods()), "GetMethods", m) + [ for mi in meths -> ProvidedMeth(amap,mi.Coerce(m),None,m) ] +#endif + | ILTypeMetadata (_,tdef) -> + let mdefs = tdef.Methods + let mdefs = (match optFilter with None -> mdefs.AsList | Some nm -> mdefs.FindByName nm) + mdefs |> List.map (fun mdef -> MethInfo.CreateILMeth(amap, m, typ, mdef)) + | FSharpOrArrayOrByrefOrTupleOrExnTypeMetadata -> + if not (isAppTy g typ) then [] + else SelectImmediateMemberVals g optFilter (TrySelectMemberVal g optFilter typ None) (tcrefOfAppTy g typ) + let minfos = minfos |> List.filter (IsMethInfoAccessible amap m ad) + minfos + +/// A helper type to help collect properties. +/// +/// Join up getters and setters which are not associated in the F# data structure +type PropertyCollector(g,amap,m,typ,optFilter,ad) = + + let hashIdentity = + Microsoft.FSharp.Collections.HashIdentity.FromFunctions + (fun (pinfo:PropInfo) -> hash pinfo.PropertyName) + (fun pinfo1 pinfo2 -> + pinfo1.IsStatic = pinfo2.IsStatic && + PropInfosEquivByNameAndPartialSig EraseNone g amap m pinfo1 pinfo2 && + pinfo1.IsDefiniteFSharpOverride = pinfo2.IsDefiniteFSharpOverride ) + let props = new System.Collections.Generic.Dictionary(hashIdentity) + let add pinfo = + if props.ContainsKey(pinfo) then + match props.[pinfo], pinfo with + | FSProp (_,typ,Some vref1,_), FSProp (_,_,_,Some vref2) + | FSProp (_,typ,_,Some vref2), FSProp (_,_,Some vref1,_) -> + let pinfo = FSProp (g,typ,Some vref1,Some vref2) + props.[pinfo] <- pinfo + | _ -> + // This assert fires while editing bad code. We will give a warning later in check.fs + //assert ("unexpected case"= "") + () + else + props.[pinfo] <- pinfo + + member x.Collect(membInfo:ValMemberInfo,vref:ValRef) = + match membInfo.MemberFlags.MemberKind with + | MemberKind.PropertyGet -> + let pinfo = FSProp(g,typ,Some vref,None) + if checkFilter optFilter vref.PropertyName && IsPropInfoAccessible g amap m ad pinfo then + add pinfo + | MemberKind.PropertySet -> + let pinfo = FSProp(g,typ,None,Some vref) + if checkFilter optFilter vref.PropertyName && IsPropInfoAccessible g amap m ad pinfo then + add pinfo + | _ -> + () + + member x.Close() = [ for KeyValue(_,pinfo) in props -> pinfo ] + +/// Query the immediate properties of an F# type, not taking into account inherited properties. The optFilter +/// parameter is an optional name to restrict the set of properties returned. +let GetImmediateIntrinsicPropInfosOfType (optFilter,ad) g amap m typ = + let pinfos = + + match metadataOfTy g typ with +#if EXTENSIONTYPING + | ProvidedTypeMetadata info -> + let st = info.ProvidedType + let matchingProps = + match optFilter with + | Some name -> + match st.PApply((fun st -> st.GetProperty name), m) with + | Tainted.Null -> [||] + | pi -> [|pi|] + | None -> + st.PApplyArray((fun st -> st.GetProperties()), "GetProperties", m) + matchingProps + |> Seq.map(fun pi -> ProvidedProp(amap,pi,m)) + |> List.ofSeq +#endif + | ILTypeMetadata (_,tdef) -> + let tinfo = ILTypeInfo.FromType g typ + let pdefs = tdef.Properties + let pdefs = match optFilter with None -> pdefs.AsList | Some nm -> pdefs.LookupByName nm + pdefs |> List.map (fun pd -> ILProp(g,ILPropInfo(tinfo,pd))) + | FSharpOrArrayOrByrefOrTupleOrExnTypeMetadata -> + + if not (isAppTy g typ) then [] + else + let propCollector = new PropertyCollector(g,amap,m,typ,optFilter,ad) + SelectImmediateMemberVals g None + (fun membInfo vref -> propCollector.Collect(membInfo,vref); None) + (tcrefOfAppTy g typ) |> ignore + propCollector.Close() + + let pinfos = pinfos |> List.filter (IsPropInfoAccessible g amap m ad) + pinfos + + +/// Sets of methods up the hierarchy, ignoring duplicates by name and sig. +/// Used to collect sets of virtual methods, protected methods, protected +/// properties etc. +type HierarchyItem = + | MethodItem of MethInfo list list + | PropertyItem of PropInfo list list + | RecdFieldItem of RecdFieldInfo + | EventItem of EventInfo list + | ILFieldItem of ILFieldInfo list + +/// An InfoReader is an object to help us read and cache infos. +/// We create one of these for each file we typecheck. +type InfoReader(g:TcGlobals, amap:Import.ImportMap) = + + /// Get the declared IL fields of a type, not including inherited fields + let GetImmediateIntrinsicILFieldsOfType (optFilter,ad) m typ = + let infos = + match metadataOfTy g typ with +#if EXTENSIONTYPING + | ProvidedTypeMetadata info -> + let st = info.ProvidedType + match optFilter with + | None -> + [ for fi in st.PApplyArray((fun st -> st.GetFields()), "GetFields" , m) -> ProvidedField(amap,fi,m) ] + | Some name -> + match st.PApply ((fun st -> st.GetField name), m) with + | Tainted.Null -> [] + | fi -> [ ProvidedField(amap,fi,m) ] +#endif + | ILTypeMetadata (_,tdef) -> + let tinfo = ILTypeInfo.FromType g typ + let fdefs = tdef.Fields + let fdefs = match optFilter with None -> fdefs.AsList | Some nm -> fdefs.LookupByName nm + fdefs |> List.map (fun pd -> ILFieldInfo(tinfo,pd)) + | FSharpOrArrayOrByrefOrTupleOrExnTypeMetadata -> + [] + let infos = infos |> List.filter (IsILFieldInfoAccessible g amap m ad) + infos + + /// Get the declared events of a type, not including inherited events + let ComputeImmediateIntrinsicEventsOfType (optFilter,ad) m typ = + let infos = + match metadataOfTy g typ with +#if EXTENSIONTYPING + | ProvidedTypeMetadata info -> + let st = info.ProvidedType + match optFilter with + | None -> + [ for ei in st.PApplyArray((fun st -> st.GetEvents()), "GetEvents" , m) -> ProvidedEvent(amap,ei,m) ] + | Some name -> + match st.PApply ((fun st -> st.GetEvent name), m) with + | Tainted.Null -> [] + | ei -> [ ProvidedEvent(amap,ei,m) ] +#endif + | ILTypeMetadata (_,tdef) -> + let tinfo = ILTypeInfo.FromType g typ + let edefs = tdef.Events + let edefs = match optFilter with None -> edefs.AsList | Some nm -> edefs.LookupByName nm + [ for edef in edefs do + let einfo = ILEventInfo(tinfo,edef) + if IsILEventInfoAccessible g amap m ad einfo then + yield ILEvent(g,einfo) ] + | FSharpOrArrayOrByrefOrTupleOrExnTypeMetadata -> + [] + infos + + /// Make a reference to a record or class field + let MakeRecdFieldInfo g typ (tcref:TyconRef) fspec = + RecdFieldInfo(argsOfAppTy g typ,tcref.MakeNestedRecdFieldRef fspec) + + /// Get the F#-declared record fields or class 'val' fields of a type + let GetImmediateIntrinsicRecdOrClassFieldsOfType (optFilter,_ad) _m typ = + match tryDestAppTy g typ with + | None -> [] + | Some tcref -> + // Note;secret fields are not allowed in lookups here, as we're only looking + // up user-visible fields in name resolution. + match optFilter with + | Some nm -> + match tcref.GetFieldByName nm with + | Some rfield when not rfield.IsCompilerGenerated -> [MakeRecdFieldInfo g typ tcref rfield] + | _ -> [] + | None -> + [ for fdef in tcref.AllFieldsArray do + if not fdef.IsCompilerGenerated then + yield MakeRecdFieldInfo g typ tcref fdef ] + + + /// The primitive reader for the method info sets up a hierarchy + let GetIntrinsicMethodSetsUncached ((optFilter,ad,allowMultiIntfInst),m,typ) = + FoldPrimaryHierarchyOfType (fun typ acc -> GetImmediateIntrinsicMethInfosOfType (optFilter,ad) g amap m typ :: acc) g amap m allowMultiIntfInst typ [] + + /// The primitive reader for the property info sets up a hierarchy + let GetIntrinsicPropertySetsUncached ((optFilter,ad,allowMultiIntfInst),m,typ) = + FoldPrimaryHierarchyOfType (fun typ acc -> GetImmediateIntrinsicPropInfosOfType (optFilter,ad) g amap m typ :: acc) g amap m allowMultiIntfInst typ [] + + let GetIntrinsicILFieldInfosUncached ((optFilter,ad),m,typ) = + FoldPrimaryHierarchyOfType (fun typ acc -> GetImmediateIntrinsicILFieldsOfType (optFilter,ad) m typ @ acc) g amap m AllowMultiIntfInstantiations.Yes typ [] + + let GetIntrinsicEventInfosUncached ((optFilter,ad),m,typ) = + FoldPrimaryHierarchyOfType (fun typ acc -> ComputeImmediateIntrinsicEventsOfType (optFilter,ad) m typ @ acc) g amap m AllowMultiIntfInstantiations.Yes typ [] + + let GetIntrinsicRecdOrClassFieldInfosUncached ((optFilter,ad),m,typ) = + FoldPrimaryHierarchyOfType (fun typ acc -> GetImmediateIntrinsicRecdOrClassFieldsOfType (optFilter,ad) m typ @ acc) g amap m AllowMultiIntfInstantiations.Yes typ [] + + let GetEntireTypeHierachyUncached (allowMultiIntfInst,m,typ) = + FoldEntireHierarchyOfType (fun typ acc -> typ :: acc) g amap m allowMultiIntfInst typ [] + + let GetPrimaryTypeHierachyUncached (allowMultiIntfInst,m,typ) = + FoldPrimaryHierarchyOfType (fun typ acc -> typ :: acc) g amap m allowMultiIntfInst typ [] + + /// The primitive reader for the named items up a hierarchy + let GetIntrinsicNamedItemsUncached ((nm,ad),m,typ) = + if nm = ".ctor" then None else // '.ctor' lookups only ever happen via constructor syntax + let optFilter = Some nm + FoldPrimaryHierarchyOfType (fun typ acc -> + let minfos = GetImmediateIntrinsicMethInfosOfType (optFilter,ad) g amap m typ + let pinfos = GetImmediateIntrinsicPropInfosOfType (optFilter,ad) g amap m typ + let finfos = GetImmediateIntrinsicILFieldsOfType (optFilter,ad) m typ + let einfos = ComputeImmediateIntrinsicEventsOfType (optFilter,ad) m typ + let rfinfos = GetImmediateIntrinsicRecdOrClassFieldsOfType (optFilter,ad) m typ + match acc with + | Some(MethodItem(inheritedMethSets)) when nonNil minfos -> Some(MethodItem (minfos::inheritedMethSets)) + | _ when nonNil minfos -> Some(MethodItem ([minfos])) + | Some(PropertyItem(inheritedPropSets)) when nonNil pinfos -> Some(PropertyItem(pinfos::inheritedPropSets)) + | _ when nonNil pinfos -> Some(PropertyItem([pinfos])) + | _ when nonNil finfos -> Some(ILFieldItem(finfos)) + | _ when nonNil einfos -> Some(EventItem(einfos)) + | _ when nonNil rfinfos -> + match rfinfos with + | [single] -> Some(RecdFieldItem(single)) + | _ -> failwith "Unexpected multiple fields with the same name" // Because an explicit name (i.e., nm) was supplied, there will be only one element at most. + | _ -> acc) + g amap m + AllowMultiIntfInstantiations.Yes + typ + None + + /// Make a cache for function 'f' keyed by type (plus some additional 'flags') that only + /// caches computations for monomorphic types. + + let MakeInfoCache f (flagsEq : System.Collections.Generic.IEqualityComparer<_>) = + new MemoizationTable<_,_> + (compute=f, + // Only cache closed, monomorphic types (closed = all members for the type + // have been processed). Generic type instantiations could be processed if we had + // a decent hash function for these. + canMemoize=(fun (_flags,(_:range),typ) -> + match stripTyEqns g typ with + | TType_app(tcref,[]) -> tcref.TypeContents.tcaug_closed + | _ -> false), + + keyComparer= + { new System.Collections.Generic.IEqualityComparer<_> with + member x.Equals((flags1,_,typ1),(flags2,_,typ2)) = + // Ignoring the ranges - that's OK. + flagsEq.Equals(flags1,flags2) && + match stripTyEqns g typ1, stripTyEqns g typ2 with + | TType_app(tcref1,[]),TType_app(tcref2,[]) -> tyconRefEq g tcref1 tcref2 + | _ -> false + member x.GetHashCode((flags,_,typ)) = + // Ignoring the ranges - that's OK. + flagsEq.GetHashCode flags + + (match stripTyEqns g typ with + | TType_app(tcref,[]) -> hash tcref.LogicalName + | _ -> 0) }) + + + let hashFlags0 = + { new System.Collections.Generic.IEqualityComparer<_> with + member x.GetHashCode((filter: string option, ad: AccessorDomain, _allowMultiIntfInst1)) = hash filter + AccessorDomain.CustomGetHashCode ad + member x.Equals((filter1, ad1, allowMultiIntfInst1), (filter2,ad2, allowMultiIntfInst2)) = + (filter1 = filter2) && AccessorDomain.CustomEquals(g,ad1,ad2) && allowMultiIntfInst1 = allowMultiIntfInst2 } + + let hashFlags1 = + { new System.Collections.Generic.IEqualityComparer<_> with + member x.GetHashCode((filter: string option,ad: AccessorDomain)) = hash filter + AccessorDomain.CustomGetHashCode ad + member x.Equals((filter1,ad1), (filter2,ad2)) = (filter1 = filter2) && AccessorDomain.CustomEquals(g,ad1,ad2) } + + let hashFlags2 = + { new System.Collections.Generic.IEqualityComparer<_> with + member x.GetHashCode((nm: string,ad: AccessorDomain)) = hash nm + AccessorDomain.CustomGetHashCode ad + member x.Equals((nm1,ad1), (nm2,ad2)) = (nm1 = nm2) && AccessorDomain.CustomEquals(g,ad1,ad2) } + + let methodInfoCache = MakeInfoCache GetIntrinsicMethodSetsUncached hashFlags0 + let propertyInfoCache = MakeInfoCache GetIntrinsicPropertySetsUncached hashFlags0 + let recdOrClassFieldInfoCache = MakeInfoCache GetIntrinsicRecdOrClassFieldInfosUncached hashFlags1 + let ilFieldInfoCache = MakeInfoCache GetIntrinsicILFieldInfosUncached hashFlags1 + let eventInfoCache = MakeInfoCache GetIntrinsicEventInfosUncached hashFlags1 + let namedItemsCache = MakeInfoCache GetIntrinsicNamedItemsUncached hashFlags2 + + let entireTypeHierarchyCache = MakeInfoCache GetEntireTypeHierachyUncached HashIdentity.Structural + let primaryTypeHierarchyCache = MakeInfoCache GetPrimaryTypeHierachyUncached HashIdentity.Structural + + member x.g = g + member x.amap = amap + + /// Read the raw method sets of a type, including inherited ones. Cache the result for monomorphic types + member x.GetRawIntrinsicMethodSetsOfType (optFilter,ad,allowMultiIntfInst,m,typ) = + methodInfoCache.Apply(((optFilter,ad,allowMultiIntfInst),m,typ)) + + /// Read the raw property sets of a type, including inherited ones. Cache the result for monomorphic types + member x.GetRawIntrinsicPropertySetsOfType (optFilter,ad,allowMultiIntfInst,m,typ) = + propertyInfoCache.Apply(((optFilter,ad,allowMultiIntfInst),m,typ)) + + /// Read the record or class fields of a type, including inherited ones. Cache the result for monomorphic types. + member x.GetRecordOrClassFieldsOfType (optFilter,ad,m,typ) = + recdOrClassFieldInfoCache.Apply(((optFilter,ad),m,typ)) + + /// Read the IL fields of a type, including inherited ones. Cache the result for monomorphic types. + member x.GetILFieldInfosOfType (optFilter,ad,m,typ) = + ilFieldInfoCache.Apply(((optFilter,ad),m,typ)) + + member x.GetImmediateIntrinsicEventsOfType (optFilter,ad,m,typ) = ComputeImmediateIntrinsicEventsOfType (optFilter,ad) m typ + + /// Read the events of a type, including inherited ones. Cache the result for monomorphic types. + member x.GetEventInfosOfType (optFilter,ad,m,typ) = + eventInfoCache.Apply(((optFilter,ad),m,typ)) + + /// Try and find a record or class field for a type. + member x.TryFindRecdOrClassFieldInfoOfType (nm,m,typ) = + match recdOrClassFieldInfoCache.Apply((Some nm,AccessibleFromSomewhere),m,typ) with + | [] -> None + | [single] -> Some single + | flds -> + // multiple fields with the same name can come from different classes, + // so filter them by the given type name + match tryDestAppTy g typ with + | None -> None + | Some tcref -> + match flds |> List.filter (fun rfinfo -> tyconRefEq g tcref rfinfo.TyconRef) with + | [] -> None + | [single] -> Some single + | _ -> failwith "unexpected multiple fields with same name" // Because it should have been already reported as duplicate fields + + /// Try and find an item with the given name in a type. + member x.TryFindNamedItemOfType (nm,ad,m,typ) = + namedItemsCache.Apply(((nm,ad),m,typ)) + + /// Get the super-types of a type, including interface types. + member x.GetEntireTypeHierachy (allowMultiIntfInst,m,typ) = + entireTypeHierarchyCache.Apply((allowMultiIntfInst,m,typ)) + + /// Get the super-types of a type, excluding interface types. + member x.GetPrimaryTypeHierachy (allowMultiIntfInst,m,typ) = + primaryTypeHierarchyCache.Apply((allowMultiIntfInst,m,typ)) + + +//------------------------------------------------------------------------- +// Constructor infos + + +/// Get the declared constructors of any F# type +let GetIntrinsicConstructorInfosOfType (infoReader:InfoReader) m ty = + let g = infoReader.g + let amap = infoReader.amap + if isAppTy g ty then + match metadataOfTy g ty with +#if EXTENSIONTYPING + | ProvidedTypeMetadata info -> + let st = info.ProvidedType + [ for ci in st.PApplyArray((fun st -> st.GetConstructors()), "GetConstructors", m) do + yield ProvidedMeth(amap,ci.Coerce(m),None,m) ] +#endif + | ILTypeMetadata _ -> + let tinfo = ILTypeInfo.FromType g ty + tinfo.RawMetadata.Methods.FindByName ".ctor" + |> List.filter (fun md -> match md.mdKind with MethodKind.Ctor -> true | _ -> false) + |> List.map (fun mdef -> MethInfo.CreateILMeth (amap, m, ty, mdef)) + + | FSharpOrArrayOrByrefOrTupleOrExnTypeMetadata -> + let tcref = tcrefOfAppTy g ty + tcref.MembersOfFSharpTyconByName + |> NameMultiMap.find ".ctor" + |> List.choose(fun vref -> + match vref.MemberInfo with + | Some membInfo when (membInfo.MemberFlags.MemberKind = MemberKind.Constructor) -> Some vref + | _ -> None) + |> List.map (fun x -> FSMeth(g,ty,x,None)) + else [] + +//------------------------------------------------------------------------- +// Collecting methods and properties taking into account hiding rules in the hierarchy + + +/// Indicates if we prefer overrides or abstract slots. +type FindMemberFlag = + /// Prefer items toward the top of the hierarchy, which we do if the items are virtual + /// but not when resolving base calls. + | IgnoreOverrides + /// Get overrides instead of abstract slots when measuring whether a class/interface implements all its required slots. + | PreferOverrides + +/// The input list is sorted from most-derived to least-derived type, so any System.Object methods +/// are at the end of the list. Return a filtered list where prior/subsequent members matching by name and +/// that are in the same equivalence class have been removed. We keep a name-indexed table to +/// be more efficient when we check to see if we've already seen a particular named method. +type private IndexedList<'T>(itemLists: 'T list list, itemsByName: NameMultiMap<'T>) = + + /// Get the item sets + member x.Items = itemLists + + /// Get the items with a particular name + member x.ItemsWithName(nm) = NameMultiMap.find nm itemsByName + + /// Add new items, extracting the names using the given function. + member x.AddItems(items,nmf) = IndexedList<'T>(items::itemLists,List.foldBack (fun x acc -> NameMultiMap.add (nmf x) x acc) items itemsByName ) + + /// Get an empty set of items + static member Empty = IndexedList<'T>([],NameMultiMap.empty) + + /// Filter a set of new items to add according to the content of the list. Only keep an item + /// if it passes 'keepTest' for all matching items already in the list. + member x.FilterNewItems keepTest nmf itemsToAdd = + // Have we already seen an item with the same name and that is in the same equivalence class? + // If so, ignore this one. Note we can check against the original incoming 'ilist' because we are assuming that + // none the elements of 'itemsToAdd' are equivalent. + itemsToAdd |> List.filter (fun item -> List.forall (keepTest item) (x.ItemsWithName(nmf item))) + +/// Add all the items to the IndexedList, preferring the ones in the super-types. This is used to hide methods +/// in super classes and/or hide overrides of methods in subclasses. +/// +/// Assume no items in 'items' are equivalent according to 'equivTest'. This is valid because each step in a +/// .NET class hierarchy introduces a consistent set of methods, none of which hide each other within the +/// given set. This is an important optimization because it means we don't have filter for equivalence between the +/// large overload sets introduced by methods like System.WriteLine. +/// +/// Assume items can be given names by 'nmf', where two items with different names are +/// not equivalent. + +let private FilterItemsInSubTypesBasedOnItemsInSuperTypes nmf keepTest itemLists = + let rec loop itemLists = + match itemLists with + | [] -> IndexedList.Empty + | items :: itemsInSuperTypes -> + let ilist = loop itemsInSuperTypes + let itemsToAdd = ilist.FilterNewItems keepTest nmf items + ilist.AddItems(itemsToAdd,nmf) + (loop itemLists).Items + +/// Add all the items to the IndexedList, preferring the ones in the sub-types. +let private FilterItemsInSuperTypesBasedOnItemsInSubTypes nmf keepTest itemLists = + let rec loop itemLists (indexedItemsInSubTypes:IndexedList<_>) = + match itemLists with + | [] -> List.rev indexedItemsInSubTypes.Items + | items :: itemsInSuperTypes -> + let itemsToAdd = items |> List.filter (fun item -> keepTest item (indexedItemsInSubTypes.ItemsWithName(nmf item))) + let ilist = indexedItemsInSubTypes.AddItems(itemsToAdd,nmf) + loop itemsInSuperTypes ilist + + loop itemLists IndexedList.Empty + +let private ExcludeItemsInSuperTypesBasedOnEquivTestWithItemsInSubTypes nmf equivTest itemLists = + FilterItemsInSuperTypesBasedOnItemsInSubTypes nmf (fun item1 items -> not (items |> List.exists (fun item2 -> equivTest item1 item2))) itemLists + +/// Filter the overrides of methods or properties, either keeping the overrides or keeping the dispatch slots. +let private FilterOverrides findFlag (isVirt:'a->bool,isNewSlot,isDefiniteOverride,isFinal,equivSigs,nmf:'a->string) items = + let equivVirts x y = isVirt x && isVirt y && equivSigs x y + + match findFlag with + | PreferOverrides -> + items + // For each F#-declared override, get rid of any equivalent abstract member in the same type + // This is because F# abstract members with default overrides give rise to two members with the + // same logical signature in the same type, e.g. + // type ClassType1() = + // abstract VirtualMethod1: string -> int + // default x.VirtualMethod1(s) = 3 + + |> List.map (fun items -> + let definiteOverrides = items |> List.filter isDefiniteOverride + items |> List.filter (fun item -> (isDefiniteOverride item || not (List.exists (equivVirts item) definiteOverrides)))) + + // only keep virtuals that are not signature-equivalent to virtuals in subtypes + |> ExcludeItemsInSuperTypesBasedOnEquivTestWithItemsInSubTypes nmf equivVirts + | IgnoreOverrides -> + let equivNewSlots x y = isNewSlot x && isNewSlot y && equivSigs x y + items + // Remove any F#-declared overrides. THese may occur in the same type as the abstract member (unlike with .NET metadata) + // Include any 'newslot' declared methods. + |> List.map (List.filter (fun x -> not (isDefiniteOverride x))) + + // Remove any virtuals that are signature-equivalent to virtuals in subtypes, except for newslots + // That is, keep if it's + /// (a) not virtual + // (b) is a new slot or + // (c) not equivalent + // We keep virtual finals around for error detection later on + |> FilterItemsInSubTypesBasedOnItemsInSuperTypes nmf (fun newItem priorItem -> + (isVirt newItem && isFinal newItem) || not (isVirt newItem) || isNewSlot newItem || not (equivVirts newItem priorItem) ) + + // Remove any abstract slots in supertypes that are (a) hidden by another newslot and (b) implemented + // We leave unimplemented ones around to give errors, e.g. for + // [] + // type PA() = + // abstract M : int -> unit + // + // [] + // type PB<'a>() = + // inherit PA() + // abstract M : 'a -> unit + // + // [] + // type PC() = + // inherit PB() + // // Here, PA.M and PB.M have the same signature, so PA.M is unimplementable. + // // REVIEW: in future we may give a friendly error at this point + // + // type PD() = + // inherit PC() + // override this.M(x:int) = () + + |> FilterItemsInSuperTypesBasedOnItemsInSubTypes nmf (fun item1 superTypeItems -> + not (isNewSlot item1 && + superTypeItems |> List.exists (equivNewSlots item1) && + superTypeItems |> List.exists (fun item2 -> isDefiniteOverride item1 && equivVirts item1 item2))) + + +/// Filter the overrides of methods, either keeping the overrides or keeping the dispatch slots. +let private FilterOverridesOfMethInfos findFlag g amap m minfos = + FilterOverrides findFlag ((fun (minfo:MethInfo) -> minfo.IsVirtual),(fun minfo -> minfo.IsNewSlot),(fun minfo -> minfo.IsDefiniteFSharpOverride),(fun minfo -> minfo.IsFinal),MethInfosEquivByNameAndSig EraseNone true g amap m,(fun minfo -> minfo.LogicalName)) minfos + +/// Filter the overrides of properties, either keeping the overrides or keeping the dispatch slots. +let private FilterOverridesOfPropInfos findFlag g amap m props = + FilterOverrides findFlag ((fun (pinfo:PropInfo) -> pinfo.IsVirtualProperty),(fun pinfo -> pinfo.IsNewSlot),(fun pinfo -> pinfo.IsDefiniteFSharpOverride),(fun _ -> false),PropInfosEquivByNameAndSig EraseNone g amap m, (fun pinfo -> pinfo.PropertyName)) props + +/// Exclude methods from super types which have the same signature as a method in a more specific type. +let ExcludeHiddenOfMethInfos g amap m (minfos:MethInfo list list) = + minfos + |> ExcludeItemsInSuperTypesBasedOnEquivTestWithItemsInSubTypes + (fun minfo -> minfo.LogicalName) + (fun m1 m2 -> + // only hide those truly from super classes + not (tyconRefEq g (tcrefOfAppTy g m1.EnclosingType) (tcrefOfAppTy g m2.EnclosingType)) && + MethInfosEquivByNameAndPartialSig EraseNone true g amap m m1 m2) + + |> List.concat + +/// Exclude properties from super types which have the same name as a property in a more specific type. +let ExcludeHiddenOfPropInfos g amap m pinfos = + pinfos + |> ExcludeItemsInSuperTypesBasedOnEquivTestWithItemsInSubTypes (fun (pinfo:PropInfo) -> pinfo.PropertyName) (PropInfosEquivByNameAndPartialSig EraseNone g amap m) + |> List.concat + +/// Get the sets of intrinsic methods in the hierarchy (not including extension methods) +let GetIntrinsicMethInfoSetsOfType (infoReader:InfoReader) (optFilter,ad,allowMultiIntfInst) findFlag m typ = + infoReader.GetRawIntrinsicMethodSetsOfType(optFilter,ad,allowMultiIntfInst,m,typ) + |> FilterOverridesOfMethInfos findFlag infoReader.g infoReader.amap m + +/// Get the sets intrinsic properties in the hierarchy (not including extension properties) +let GetIntrinsicPropInfoSetsOfType (infoReader:InfoReader) (optFilter,ad,allowMultiIntfInst) findFlag m typ = + infoReader.GetRawIntrinsicPropertySetsOfType(optFilter,ad,allowMultiIntfInst,m,typ) + |> FilterOverridesOfPropInfos findFlag infoReader.g infoReader.amap m + +/// Get the flattened list of intrinsic methods in the hierarchy +let GetIntrinsicMethInfosOfType infoReader (optFilter,ad,allowMultiIntfInst) findFlag m typ = + GetIntrinsicMethInfoSetsOfType infoReader (optFilter,ad,allowMultiIntfInst) findFlag m typ |> List.concat + +/// Get the flattened list of intrinsic properties in the hierarchy +let GetIntrinsicPropInfosOfType infoReader (optFilter,ad,allowMultiIntfInst) findFlag m typ = + GetIntrinsicPropInfoSetsOfType infoReader (optFilter,ad,allowMultiIntfInst) findFlag m typ |> List.concat + +/// Perform type-directed name resolution of a particular named member in an F# type +let TryFindIntrinsicNamedItemOfType (infoReader:InfoReader) (nm,ad) findFlag m typ = + match infoReader.TryFindNamedItemOfType(nm, ad, m, typ) with + | Some item -> + match item with + | PropertyItem psets -> Some(PropertyItem (psets |> FilterOverridesOfPropInfos findFlag infoReader.g infoReader.amap m)) + | MethodItem msets -> Some(MethodItem (msets |> FilterOverridesOfMethInfos findFlag infoReader.g infoReader.amap m)) + | _ -> Some(item) + | None -> None + +/// Try to detect the existence of a method on a type. +/// Used for +/// -- getting the GetEnumerator, get_Current, MoveNext methods for enumerable types +/// -- getting the Dispose method when resolving the 'use' construct +/// -- getting the various methods used to desugar the computation expression syntax +let TryFindIntrinsicMethInfo infoReader m ad nm ty = + GetIntrinsicMethInfosOfType infoReader (Some nm,ad,AllowMultiIntfInstantiations.Yes) IgnoreOverrides m ty + +/// Try to find a particular named property on a type. Only used to ensure that local 'let' definitions and property names +/// are distinct, a somewhat adhoc check in tc.fs. +let TryFindPropInfo infoReader m ad nm ty = + GetIntrinsicPropInfosOfType infoReader (Some nm,ad,AllowMultiIntfInstantiations.Yes) IgnoreOverrides m ty + +//------------------------------------------------------------------------- +// Helpers related to delegates and events - these use method searching hence are in this file +//------------------------------------------------------------------------- + +/// The Invoke MethInfo, the function argument types, the function return type +/// and the overall F# function type for the function type associated with a .NET delegate type +[] +type SigOfFunctionForDelegate = SigOfFunctionForDelegate of MethInfo * TType list * TType * TType + +/// Given a delegate type work out the minfo, argument types, return type +/// and F# function type by looking at the Invoke signature of the delegate. +let GetSigOfFunctionForDelegate (infoReader:InfoReader) delty m ad = + let g = infoReader.g + let amap = infoReader.amap + let invokeMethInfo = + match GetIntrinsicMethInfosOfType infoReader (Some "Invoke",ad,AllowMultiIntfInstantiations.Yes) IgnoreOverrides m delty with + | [h] -> h + | [] -> error(Error(FSComp.SR.noInvokeMethodsFound (),m)) + | h :: _ -> warning(InternalError(FSComp.SR.moreThanOneInvokeMethodFound (),m)); h + + let minst = [] // a delegate's Invoke method is never generic + let compiledViewOfDelArgTys = + match invokeMethInfo.GetParamTypes(amap, m, minst) with + | [args] -> args + | _ -> error(Error(FSComp.SR.delegatesNotAllowedToHaveCurriedSignatures (),m)) + let fsharpViewOfDelArgTys = + match compiledViewOfDelArgTys with + | [] -> [g.unit_ty] + | _ -> compiledViewOfDelArgTys + let delRetTy = invokeMethInfo.GetFSharpReturnTy(amap, m, minst) + CheckMethInfoAttributes g m None invokeMethInfo |> CommitOperationResult + let fty = mkIteratedFunTy fsharpViewOfDelArgTys delRetTy + SigOfFunctionForDelegate(invokeMethInfo,compiledViewOfDelArgTys,delRetTy,fty) + +/// Try and interpret a delegate type as a "standard" .NET delegate type associated with an event, with a "sender" parameter. +let TryDestStandardDelegateTyp (infoReader:InfoReader) m ad delTy = + let g = infoReader.g + let (SigOfFunctionForDelegate(_,compiledViewOfDelArgTys,delRetTy,_)) = GetSigOfFunctionForDelegate infoReader delTy m ad + match compiledViewOfDelArgTys with + | senderTy :: argTys when (isObjTy g senderTy) && not (List.exists (isByrefTy g) argTys) -> Some(mkTupledTy g argTys,delRetTy) + | _ -> None + + +/// Indicates if an event info is associated with a delegate type that is a "standard" .NET delegate type +/// with a sender parameter. +// +/// In the F# design, we take advantage of the following idiom to simplify away the bogus "object" parameter of the +/// of the "Add" methods associated with events. If you want to access it you +/// can use AddHandler instead. + +/// The .NET Framework guidelines indicate that the delegate type used for +/// an event should take two parameters, an "object source" parameter +/// indicating the source of the event, and an "e" parameter that +/// encapsulates any additional information about the event. The type of +/// the "e" parameter should derive from the EventArgs class. For events +/// that do not use any additional information, the .NET Framework has +/// already defined an appropriate delegate type: EventHandler. +/// (from http://msdn.microsoft.com/library/default.asp?url=/library/en-us/csref/html/vcwlkEventsTutorial.asp) +let IsStandardEventInfo (infoReader:InfoReader) m ad (einfo:EventInfo) = + let dty = einfo.GetDelegateType(infoReader.amap,m) + match TryDestStandardDelegateTyp infoReader m ad dty with + | Some _ -> true + | None -> false + +/// Get the (perhaps tupled) argument type accepted by an event +let ArgsTypOfEventInfo (infoReader:InfoReader) m ad (einfo:EventInfo) = + let amap = infoReader.amap + let dty = einfo.GetDelegateType(amap,m) + match TryDestStandardDelegateTyp infoReader m ad dty with + | Some(argtys,_) -> argtys + | None -> error(nonStandardEventError einfo.EventName m) + +/// Get the type of the event when looked at as if it is a property +/// Used when displaying the property in Intellisense +let PropTypOfEventInfo (infoReader:InfoReader) m ad (einfo:EventInfo) = + let g = infoReader.g + let amap = infoReader.amap + let delTy = einfo.GetDelegateType(amap,m) + let argsTy = ArgsTypOfEventInfo infoReader m ad einfo + mkIEventType g delTy argsTy + + diff --git a/src/fsharp/LowerCallsAndSeqs.fs b/src/fsharp/LowerCallsAndSeqs.fs index 9d6ea75debf..571997f761f 100644 --- a/src/fsharp/LowerCallsAndSeqs.fs +++ b/src/fsharp/LowerCallsAndSeqs.fs @@ -4,21 +4,24 @@ module internal Microsoft.FSharp.Compiler.LowerCallsAndSeqs open Internal.Utilities open Microsoft.FSharp.Compiler.AbstractIL +open Microsoft.FSharp.Compiler.AbstractIL.Diagnostics open Microsoft.FSharp.Compiler.AbstractIL.IL open Microsoft.FSharp.Compiler.AbstractIL.Internal open Microsoft.FSharp.Compiler.AbstractIL.Internal.Library -open Microsoft.FSharp.Compiler -open Microsoft.FSharp.Compiler.AbstractIL.Diagnostics +open Microsoft.FSharp.Compiler +open Microsoft.FSharp.Compiler.AccessibilityLogic +open Microsoft.FSharp.Compiler.Ast open Microsoft.FSharp.Compiler.Range open Microsoft.FSharp.Compiler.Infos -open Microsoft.FSharp.Compiler.Ast open Microsoft.FSharp.Compiler.ErrorLogger open Microsoft.FSharp.Compiler.Tast open Microsoft.FSharp.Compiler.Tastops open Microsoft.FSharp.Compiler.Lib open Microsoft.FSharp.Compiler.TcGlobals open Microsoft.FSharp.Compiler.PrettyNaming +open Microsoft.FSharp.Compiler.InfoReader +open Microsoft.FSharp.Compiler.MethodCalls //---------------------------------------------------------------------------- // Eta-expansion of calls to top-level-methods diff --git a/src/fsharp/MethodCalls.fs b/src/fsharp/MethodCalls.fs new file mode 100644 index 00000000000..14c41717483 --- /dev/null +++ b/src/fsharp/MethodCalls.fs @@ -0,0 +1,1212 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +/// Logic associated with resolving method calls. +module internal Microsoft.FSharp.Compiler.MethodCalls + +open Internal.Utilities +open System.Text + +open Microsoft.FSharp.Compiler +open Microsoft.FSharp.Compiler.AbstractIL +open Microsoft.FSharp.Compiler.AbstractIL.IL +open Microsoft.FSharp.Compiler.AbstractIL.Internal +open Microsoft.FSharp.Compiler.AbstractIL.Internal.Library +open Microsoft.FSharp.Compiler.Range +open Microsoft.FSharp.Compiler.Ast +open Microsoft.FSharp.Compiler.ErrorLogger +open Microsoft.FSharp.Compiler.Lib +open Microsoft.FSharp.Compiler.Infos +open Microsoft.FSharp.Compiler.AccessibilityLogic +open Microsoft.FSharp.Compiler.NameResolution +open Microsoft.FSharp.Compiler.PrettyNaming +open Microsoft.FSharp.Compiler.AbstractIL.Diagnostics +open Microsoft.FSharp.Compiler.InfoReader +open Microsoft.FSharp.Compiler.Tast +open Microsoft.FSharp.Compiler.Tastops +open Microsoft.FSharp.Compiler.Tastops.DebugPrint +open Microsoft.FSharp.Compiler.TcGlobals +open Microsoft.FSharp.Compiler.TypeRelations + +#if EXTENSIONTYPING +open Microsoft.FSharp.Compiler.ExtensionTyping +#endif + + + +//------------------------------------------------------------------------- +// Sets of methods involved in overload resolution and trait constraint +// satisfaction. +//------------------------------------------------------------------------- + +/// In the following, 'T gets instantiated to: +/// 1. the expression being supplied for an argument +/// 2. "unit", when simply checking for the existence of an overload that satisfies +/// a signature, or when finding the corresponding witness. +/// Note the parametricity helps ensure that overload resolution doesn't depend on the +/// expression on the callside (though it is in some circumstances allowed +/// to depend on some type information inferred syntactically from that +/// expression, e.g. a lambda expression may be converted to a delegate as +/// an adhoc conversion. +/// +/// The bool indicates if named using a '?' +type CallerArg<'T> = + /// CallerArg(ty, range, isOpt, exprInfo) + | CallerArg of TType * range * bool * 'T + member x.Type = (let (CallerArg(ty,_,_,_)) = x in ty) + member x.Range = (let (CallerArg(_,m,_,_)) = x in m) + member x.IsOptional = (let (CallerArg(_,_,isOpt,_)) = x in isOpt) + member x.Expr = (let (CallerArg(_,_,_,expr)) = x in expr) + +/// Represents the information about an argument in the method being called +type CalledArg = + { Position: (int * int) + IsParamArray : bool + OptArgInfo : OptionalArgInfo + CallerInfoInfo : CallerInfoInfo + IsOutArg: bool + ReflArgInfo: ReflectedArgInfo + NameOpt: Ident option + CalledArgumentType : TType } + +let CalledArg(pos,isParamArray,optArgInfo,callerInfoInfo,isOutArg,nameOpt,reflArgInfo,calledArgTy) = + { Position=pos + IsParamArray=isParamArray + OptArgInfo =optArgInfo + CallerInfoInfo = callerInfoInfo + IsOutArg=isOutArg + ReflArgInfo=reflArgInfo + NameOpt=nameOpt + CalledArgumentType = calledArgTy } + +/// Represents a match between a caller argument and a called argument, arising from either +/// a named argument or an unnamed argument. +type AssignedCalledArg<'T> = + { /// The identifier for a named argument, if any + NamedArgIdOpt : Ident option + /// The called argument in the method + CalledArg: CalledArg + /// The argument on the caller side + CallerArg: CallerArg<'T> } + member x.Position = x.CalledArg.Position + +/// Represents the possibilities for a named-setter argument (a property, field , or a record field setter) +type AssignedItemSetterTarget = + | AssignedPropSetter of PropInfo * MethInfo * TypeInst (* the MethInfo is a non-indexer setter property *) + | AssignedILFieldSetter of ILFieldInfo + | AssignedRecdFieldSetter of RecdFieldInfo + +/// Represents the resolution of a caller argument as a named-setter argument +type AssignedItemSetter<'T> = AssignedItemSetter of Ident * AssignedItemSetterTarget * CallerArg<'T> + +type CallerNamedArg<'T> = + | CallerNamedArg of Ident * CallerArg<'T> + member x.Ident = (let (CallerNamedArg(id,_)) = x in id) + member x.Name = x.Ident.idText + member x.CallerArg = (let (CallerNamedArg(_,a)) = x in a) + +//------------------------------------------------------------------------- +// Callsite conversions +//------------------------------------------------------------------------- + +// F# supports three adhoc conversions at method callsites (note C# supports more, though ones +// such as implicit conversions interact badly with type inference). +// +// 1. The use of "(fun x y -> ...)" when a delegate it expected. This is not part of +// the ":>" coercion relationship or inference constraint problem as +// such, but is a special rule applied only to method arguments. +// +// The function AdjustCalledArgType detects this case based on types and needs to know that the type being applied +// is a function type. +// +// 2. The use of "(fun x y -> ...)" when Expression it expected. This is similar to above. +// +// 3. Two ways to pass a value where a byref is expected. The first (default) +// is to use a reference cell, and the interior address is taken automatically +// The second is an explicit use of the "address-of" operator "&e". Here we detect the second case, +// and record the presence of the sytnax "&e" in the pre-inferred actual type for the method argument. +// The function AdjustCalledArgType detects this and refuses to apply the default byref-to-ref transformation. +// +// The function AdjustCalledArgType also adjusts for optional arguments. +let AdjustCalledArgType (infoReader:InfoReader) isConstraint (calledArg: CalledArg) (callerArg: CallerArg<_>) = + let g = infoReader.g + // #424218 - when overload resolution is part of constraint solving - do not perform type-directed conversions + let calledArgTy = calledArg.CalledArgumentType + let callerArgTy = callerArg.Type + let m = callerArg.Range + if isConstraint then calledArgTy else + // If the called method argument is a byref type, then the caller may provide a byref or ref + if isByrefTy g calledArgTy then + if isByrefTy g callerArgTy then + calledArgTy + else + mkRefCellTy g (destByrefTy g calledArgTy) + else + // If the called method argument is a delegate type, then the caller may provide a function + let calledArgTy = + let adjustDelegateTy calledTy = + let (SigOfFunctionForDelegate(_,delArgTys,_,fty)) = GetSigOfFunctionForDelegate infoReader calledTy m AccessibleFromSomeFSharpCode + let delArgTys = (if isNil delArgTys then [g.unit_ty] else delArgTys) + if (fst (stripFunTy g callerArgTy)).Length = delArgTys.Length + then fty + else calledArgTy + + if isDelegateTy g calledArgTy && isFunTy g callerArgTy then + adjustDelegateTy calledArgTy + + elif isLinqExpressionTy g calledArgTy && isFunTy g callerArgTy then + let origArgTy = calledArgTy + let calledArgTy = destLinqExpressionTy g calledArgTy + if isDelegateTy g calledArgTy then + adjustDelegateTy calledArgTy + else + // BUG 435170: called arg is Expr<'t> where 't is not delegate - such conversion is not legal -> return original type + origArgTy + + elif calledArg.ReflArgInfo.AutoQuote && isQuotedExprTy g calledArgTy && not (isQuotedExprTy g callerArgTy) then + destQuotedExprTy g calledArgTy + + else calledArgTy + + // Adjust the called argument type to take into account whether the caller's argument is M(?arg=Some(3)) or M(arg=1) + // If the called method argument is optional with type Option, then the caller may provide a T, unless their argument is propogating-optional (i.e. isOptCallerArg) + let calledArgTy = + match calledArg.OptArgInfo with + | NotOptional -> calledArgTy + | CalleeSide when not callerArg.IsOptional && isOptionTy g calledArgTy -> destOptionTy g calledArgTy + | CalleeSide | CallerSide _ -> calledArgTy + calledArgTy + + +//------------------------------------------------------------------------- +// CalledMeth +//------------------------------------------------------------------------- + +type CalledMethArgSet<'T> = + { /// The called arguments corresponding to "unnamed" arguments + UnnamedCalledArgs : CalledArg list + /// Any unnamed caller arguments not otherwise assigned + UnnamedCallerArgs : CallerArg<'T> list + /// The called "ParamArray" argument, if any + ParamArrayCalledArgOpt : CalledArg option + /// Any unnamed caller arguments assigned to a "param array" argument + ParamArrayCallerArgs : CallerArg<'T> list + /// Named args + AssignedNamedArgs: AssignedCalledArg<'T> list } + member x.NumUnnamedCallerArgs = x.UnnamedCallerArgs.Length + member x.NumAssignedNamedArgs = x.AssignedNamedArgs.Length + member x.NumUnnamedCalledArgs = x.UnnamedCalledArgs.Length + + +let MakeCalledArgs amap m (minfo:MethInfo) minst = + // Mark up the arguments with their position, so we can sort them back into order later + let paramDatas = minfo.GetParamDatas(amap, m, minst) + paramDatas |> List.mapiSquared (fun i j (ParamData(isParamArrayArg,isOutArg,optArgInfo,callerInfoFlags,nmOpt,reflArgInfo,typeOfCalledArg)) -> + { Position=(i,j) + IsParamArray=isParamArrayArg + OptArgInfo=optArgInfo + CallerInfoInfo = callerInfoFlags + IsOutArg=isOutArg + ReflArgInfo=reflArgInfo + NameOpt=nmOpt + CalledArgumentType=typeOfCalledArg }) + +/// Represents the syntactic matching between a caller of a method and the called method. +/// +/// The constructor takes all the information about the caller and called side of a method, match up named arguments, property setters etc., +/// and returns a CalledMeth object for further analysis. +type CalledMeth<'T> + (infoReader:InfoReader, + nameEnv: NameResolutionEnv option, + isCheckingAttributeCall, + freshenMethInfo,// a function to help generate fresh type variables the property setters methods in generic classes + m, + ad, // the access domain of the place where the call is taking place + minfo:MethInfo, // the method we're attempting to call + calledTyArgs, // the 'called type arguments', i.e. the fresh generic instantiation of the method we're attempting to call + callerTyArgs: TType list, // the 'caller type arguments', i.e. user-given generic instantiation of the method we're attempting to call + pinfoOpt: PropInfo option, // the property related to the method we're attempting to call, if any + callerObjArgTys: TType list, // the types of the actual object argument, if any + curriedCallerArgs: (CallerArg<'T> list * CallerNamedArg<'T> list) list, // the data about any arguments supplied by the caller + allowParamArgs:bool, // do we allow the use of a param args method in its "expanded" form? + allowOutAndOptArgs: bool, // do we allow the use of the transformation that converts out arguments as tuple returns? + tyargsOpt : TType option) // method parameters + = + let g = infoReader.g + let methodRetTy = minfo.GetFSharpReturnTy(infoReader.amap, m, calledTyArgs) + + let fullCurriedCalledArgs = MakeCalledArgs infoReader.amap m minfo calledTyArgs + do assert (fullCurriedCalledArgs.Length = fullCurriedCalledArgs.Length) + + let argSetInfos = + (curriedCallerArgs, fullCurriedCalledArgs) ||> List.map2 (fun (unnamedCallerArgs,namedCallerArgs) fullCalledArgs -> + // Find the arguments not given by name + let unnamedCalledArgs = + fullCalledArgs |> List.filter (fun calledArg -> + match calledArg.NameOpt with + | Some nm -> namedCallerArgs |> List.forall (fun (CallerNamedArg(nm2,_e)) -> nm.idText <> nm2.idText) + | None -> true) + + // See if any of them are 'out' arguments being returned as part of a return tuple + let unnamedCalledArgs, unnamedCalledOptArgs, unnamedCalledOutArgs = + let nUnnamedCallerArgs = unnamedCallerArgs.Length + if allowOutAndOptArgs && nUnnamedCallerArgs < unnamedCalledArgs.Length then + let unnamedCalledArgsTrimmed,unnamedCalledOptOrOutArgs = List.chop nUnnamedCallerArgs unnamedCalledArgs + + // Check if all optional/out arguments are byref-out args + if unnamedCalledOptOrOutArgs |> List.forall (fun x -> x.IsOutArg && isByrefTy g x.CalledArgumentType) then + unnamedCalledArgsTrimmed,[],unnamedCalledOptOrOutArgs + // Check if all optional/out arguments are optional args + elif unnamedCalledOptOrOutArgs |> List.forall (fun x -> x.OptArgInfo.IsOptional) then + unnamedCalledArgsTrimmed,unnamedCalledOptOrOutArgs,[] + // Otherwise drop them on the floor + else + unnamedCalledArgs,[],[] + else + unnamedCalledArgs,[],[] + + let (unnamedCallerArgs,paramArrayCallerArgs),unnamedCalledArgs,paramArrayCalledArgOpt = + let minArgs = unnamedCalledArgs.Length - 1 + let supportsParamArgs = + allowParamArgs && + minArgs >= 0 && + unnamedCalledArgs |> List.last |> (fun calledArg -> calledArg.IsParamArray && isArray1DTy g calledArg.CalledArgumentType) + + if supportsParamArgs && unnamedCallerArgs.Length >= minArgs then + let a,b = List.frontAndBack unnamedCalledArgs + List.chop minArgs unnamedCallerArgs, a, Some(b) + else + (unnamedCallerArgs, []),unnamedCalledArgs, None + + let assignedNamedArgs = + fullCalledArgs |> List.choose (fun calledArg -> + match calledArg.NameOpt with + | Some nm -> + namedCallerArgs |> List.tryPick (fun (CallerNamedArg(nm2,callerArg)) -> + if nm.idText = nm2.idText then Some { NamedArgIdOpt = Some nm2; CallerArg=callerArg; CalledArg=calledArg } + else None) + | _ -> None) + + let unassignedNamedItem = + namedCallerArgs |> List.filter (fun (CallerNamedArg(nm,_e)) -> + fullCalledArgs |> List.forall (fun calledArg -> + match calledArg.NameOpt with + | Some nm2 -> nm.idText <> nm2.idText + | None -> true)) + + let attributeAssignedNamedItems,unassignedNamedItem = + if isCheckingAttributeCall then + // the assignment of names to properties is substantially for attribute specifications + // permits bindings of names to non-mutable fields and properties, so we do that using the old + // reliable code for this later on. + unassignedNamedItem,[] + else + [],unassignedNamedItem + + let assignedNamedProps,unassignedNamedItem = + let returnedObjTy = if minfo.IsConstructor then minfo.EnclosingType else methodRetTy + unassignedNamedItem |> List.splitChoose (fun (CallerNamedArg(id,e) as arg) -> + let nm = id.idText + let pinfos = GetIntrinsicPropInfoSetsOfType infoReader (Some(nm),ad,AllowMultiIntfInstantiations.Yes) IgnoreOverrides id.idRange returnedObjTy + let pinfos = pinfos |> ExcludeHiddenOfPropInfos g infoReader.amap m + match pinfos with + | [pinfo] when pinfo.HasSetter && not pinfo.IsIndexer -> + let pminfo = pinfo.SetterMethod + let pminst = freshenMethInfo m pminfo + Choice1Of2(AssignedItemSetter(id,AssignedPropSetter(pinfo,pminfo, pminst), e)) + | _ -> + let epinfos = + match nameEnv with + | Some(ne) -> ExtensionPropInfosOfTypeInScope infoReader ne (Some(nm), ad) m returnedObjTy + | _ -> [] + match epinfos with + | [pinfo] when pinfo.HasSetter && not pinfo.IsIndexer -> + let pminfo = pinfo.SetterMethod + let pminst = match minfo with + | MethInfo.FSMeth(_,TType.TType_app(_,types),_,_) -> types + | _ -> freshenMethInfo m pminfo + + let pminst = match tyargsOpt with + | Some(TType.TType_app(_, types)) -> types + | _ -> pminst + Choice1Of2(AssignedItemSetter(id,AssignedPropSetter(pinfo,pminfo, pminst), e)) + | _ -> + match infoReader.GetILFieldInfosOfType(Some(nm),ad,m,returnedObjTy) with + | finfo :: _ -> + Choice1Of2(AssignedItemSetter(id,AssignedILFieldSetter(finfo), e)) + | _ -> + match infoReader.TryFindRecdOrClassFieldInfoOfType(nm,m,returnedObjTy) with + | Some rfinfo -> + Choice1Of2(AssignedItemSetter(id,AssignedRecdFieldSetter(rfinfo), e)) + | None -> + Choice2Of2(arg)) + + let names = namedCallerArgs |> List.map (fun (CallerNamedArg(nm,_)) -> nm.idText) + + if (List.noRepeats String.order names).Length <> namedCallerArgs.Length then + errorR(Error(FSComp.SR.typrelNamedArgumentHasBeenAssignedMoreThenOnce(),m)) + + let argSet = { UnnamedCalledArgs=unnamedCalledArgs; UnnamedCallerArgs=unnamedCallerArgs; ParamArrayCalledArgOpt=paramArrayCalledArgOpt; ParamArrayCallerArgs=paramArrayCallerArgs; AssignedNamedArgs=assignedNamedArgs } + + (argSet,assignedNamedProps,unassignedNamedItem,attributeAssignedNamedItems,unnamedCalledOptArgs,unnamedCalledOutArgs)) + + let argSets = argSetInfos |> List.map (fun (x,_,_,_,_,_) -> x) + let assignedNamedProps = argSetInfos |> List.collect (fun (_,x,_,_,_,_) -> x) + let unassignedNamedItems = argSetInfos |> List.collect (fun (_,_,x,_,_,_) -> x) + let attributeAssignedNamedItems = argSetInfos |> List.collect (fun (_,_,_,x,_,_) -> x) + let unnamedCalledOptArgs = argSetInfos |> List.collect (fun (_,_,_,_,x,_) -> x) + let unnamedCalledOutArgs = argSetInfos |> List.collect (fun (_,_,_,_,_,x) -> x) + + member x.infoReader = infoReader + member x.amap = infoReader.amap + + /// the method we're attempting to call + member x.Method=minfo + /// the instantiation of the method we're attempting to call + member x.CalledTyArgs=calledTyArgs + /// the formal instantiation of the method we're attempting to call + member x.CallerTyArgs=callerTyArgs + /// The types of the actual object arguments, if any + member x.CallerObjArgTys=callerObjArgTys + /// The argument analysis for each set of curried arguments + member x.ArgSets=argSets + /// return type + member x.ReturnType=methodRetTy + /// named setters + member x.AssignedItemSetters=assignedNamedProps + /// the property related to the method we're attempting to call, if any + member x.AssociatedPropertyInfo=pinfoOpt + /// unassigned args + member x.UnassignedNamedArgs=unassignedNamedItems + /// args assigned to specify values for attribute fields and properties (these are not necessarily "property sets") + member x.AttributeAssignedNamedArgs=attributeAssignedNamedItems + /// unnamed called optional args: pass defaults for these + member x.UnnamedCalledOptArgs=unnamedCalledOptArgs + /// unnamed called out args: return these as part of the return tuple + member x.UnnamedCalledOutArgs=unnamedCalledOutArgs + + static member GetMethod (x:CalledMeth<'T>) = x.Method + + member x.NumArgSets = x.ArgSets.Length + + member x.HasOptArgs = nonNil x.UnnamedCalledOptArgs + member x.HasOutArgs = nonNil x.UnnamedCalledOutArgs + member x.UsesParamArrayConversion = x.ArgSets |> List.exists (fun argSet -> argSet.ParamArrayCalledArgOpt.IsSome) + member x.ParamArrayCalledArgOpt = x.ArgSets |> List.tryPick (fun argSet -> argSet.ParamArrayCalledArgOpt) + member x.ParamArrayCallerArgs = x.ArgSets |> List.tryPick (fun argSet -> if isSome argSet.ParamArrayCalledArgOpt then Some argSet.ParamArrayCallerArgs else None ) + member x.ParamArrayElementType = + assert (x.UsesParamArrayConversion) + x.ParamArrayCalledArgOpt.Value.CalledArgumentType |> destArrayTy x.amap.g + member x.NumAssignedProps = x.AssignedItemSetters.Length + member x.CalledObjArgTys(m) = x.Method.GetObjArgTypes(x.amap, m, x.CalledTyArgs) + member x.NumCalledTyArgs = x.CalledTyArgs.Length + member x.NumCallerTyArgs = x.CallerTyArgs.Length + + member x.AssignsAllNamedArgs = isNil x.UnassignedNamedArgs + + member x.HasCorrectArity = + (x.NumCalledTyArgs = x.NumCallerTyArgs) && + x.ArgSets |> List.forall (fun argSet -> argSet.NumUnnamedCalledArgs = argSet.NumUnnamedCallerArgs) + + member x.HasCorrectGenericArity = + (x.NumCalledTyArgs = x.NumCallerTyArgs) + + member x.IsAccessible(m,ad) = + IsMethInfoAccessible x.amap m ad x.Method + + member x.HasCorrectObjArgs(m) = + x.CalledObjArgTys(m).Length = x.CallerObjArgTys.Length + + member x.IsCandidate(m,ad) = + x.IsAccessible(m,ad) && + x.HasCorrectArity && + x.HasCorrectObjArgs(m) && + x.AssignsAllNamedArgs + + member x.AssignedUnnamedArgs = + // We use Seq.map2 to tolerate there being mismatched caller/called args + x.ArgSets |> List.map (fun argSet -> + (argSet.UnnamedCalledArgs, argSet.UnnamedCallerArgs) ||> Seq.map2 (fun calledArg callerArg -> + { NamedArgIdOpt=None; CalledArg=calledArg; CallerArg=callerArg }) |> Seq.toList) + + member x.AssignedNamedArgs = + x.ArgSets |> List.map (fun argSet -> argSet.AssignedNamedArgs) + + member x.AllUnnamedCalledArgs = x.ArgSets |> List.collect (fun x -> x.UnnamedCalledArgs) + member x.TotalNumUnnamedCalledArgs = x.ArgSets |> List.sumBy (fun x -> x.NumUnnamedCalledArgs) + member x.TotalNumUnnamedCallerArgs = x.ArgSets |> List.sumBy (fun x -> x.NumUnnamedCallerArgs) + member x.TotalNumAssignedNamedArgs = x.ArgSets |> List.sumBy (fun x -> x.NumAssignedNamedArgs) + +let NamesOfCalledArgs (calledArgs: CalledArg list) = + calledArgs |> List.choose (fun x -> x.NameOpt) + +//------------------------------------------------------------------------- +// Helpers dealing with propagating type information in method overload resolution +//------------------------------------------------------------------------- + +type ArgumentAnalysis = + | NoInfo + | ArgDoesNotMatch + | CallerLambdaHasArgTypes of TType list + | CalledArgMatchesType of TType + +let InferLambdaArgsForLambdaPropagation origRhsExpr = + let rec loop e = + match e with + | SynExpr.Lambda(_,_,_,rest,_) -> 1 + loop rest + | SynExpr.MatchLambda _ -> 1 + | _ -> 0 + loop origRhsExpr + +let ExamineArgumentForLambdaPropagation (infoReader:InfoReader) (arg: AssignedCalledArg) = + let g = infoReader.g + // Find the explicit lambda arguments of the caller. Ignore parentheses. + let argExpr = match arg.CallerArg.Expr with SynExpr.Paren(x,_,_,_) -> x | x -> x + let countOfCallerLambdaArg = InferLambdaArgsForLambdaPropagation argExpr + // Adjust for Expression<_>, Func<_,_>, ... + let adjustedCalledArgTy = AdjustCalledArgType infoReader false arg.CalledArg arg.CallerArg + if countOfCallerLambdaArg > 0 then + // Decompose the explicit function type of the target + let calledLambdaArgTys,_calledLambdaRetTy = Tastops.stripFunTy g adjustedCalledArgTy + if calledLambdaArgTys.Length >= countOfCallerLambdaArg then + // success + CallerLambdaHasArgTypes calledLambdaArgTys + elif isDelegateTy g (if isLinqExpressionTy g adjustedCalledArgTy then destLinqExpressionTy g adjustedCalledArgTy else adjustedCalledArgTy) then + ArgDoesNotMatch // delegate arity mismatch + else + NoInfo // not a function type on the called side - no information + else CalledArgMatchesType(adjustedCalledArgTy) // not a lambda on the caller side - push information from caller to called + +let ExamineMethodForLambdaPropagation(x:CalledMeth) = + let unnamedInfo = x.AssignedUnnamedArgs |> List.mapSquared (ExamineArgumentForLambdaPropagation x.infoReader) + let namedInfo = x.AssignedNamedArgs |> List.mapSquared (fun arg -> (arg.NamedArgIdOpt.Value, ExamineArgumentForLambdaPropagation x.infoReader arg)) + if unnamedInfo |> List.existsSquared (function CallerLambdaHasArgTypes _ -> true | _ -> false) || + namedInfo |> List.existsSquared (function (_,CallerLambdaHasArgTypes _) -> true | _ -> false) then + Some (unnamedInfo, namedInfo) + else + None + +//------------------------------------------------------------------------- +// Additional helpers for building method calls and doing TAST generation +//------------------------------------------------------------------------- + +/// Is this a 'base' call (in the sense of C#) +let IsBaseCall objArgs = + match objArgs with + | [Expr.Val(v,_,_)] when v.BaseOrThisInfo = BaseVal -> true + | _ -> false + +/// Compute whether we insert a 'coerce' on the 'this' pointer for an object model call +/// For example, when calling an interface method on a struct, or a method on a constrained +/// variable type. +let ComputeConstrainedCallInfo g amap m (objArgs,minfo:MethInfo) = + match objArgs with + | [objArgExpr] when not minfo.IsExtensionMember -> + let methObjTy = minfo.EnclosingType + let objArgTy = tyOfExpr g objArgExpr + if TypeDefinitelySubsumesTypeNoCoercion 0 g amap m methObjTy objArgTy + // Constrained calls to class types can only ever be needed for the three class types that + // are base types of value types + || (isClassTy g methObjTy && + (not (typeEquiv g methObjTy g.system_Object_typ || + typeEquiv g methObjTy g.system_Value_typ || + typeEquiv g methObjTy g.system_Enum_typ))) then + None + else + // The object argument is a value type or variable type and the target method is an interface or System.Object + // type. A .NET 2.0 generic constrained call is required + Some objArgTy + | _ -> + None + + +/// Adjust the 'this' pointer before making a call +/// Take the address of a struct, and coerce to an interface/base/constraint type if necessary +let TakeObjAddrForMethodCall g amap (minfo:MethInfo) isMutable m objArgs f = + let ccallInfo = ComputeConstrainedCallInfo g amap m (objArgs,minfo) + let mustTakeAddress = + (minfo.IsStruct && not minfo.IsExtensionMember) // don't take the address of a struct when passing to an extension member + || + (match ccallInfo with + | Some _ -> true + | None -> false) + let wrap,objArgs = + match objArgs with + | [objArgExpr] -> + let objArgTy = tyOfExpr g objArgExpr + let wrap,objArgExpr' = mkExprAddrOfExpr g mustTakeAddress (isSome ccallInfo) isMutable objArgExpr None m + + // Extension members and calls to class constraints may need a coercion for their object argument + let objArgExpr' = + if isNone ccallInfo && // minfo.IsExtensionMember && minfo.IsStruct && + not (TypeDefinitelySubsumesTypeNoCoercion 0 g amap m minfo.EnclosingType objArgTy) then + mkCoerceExpr(objArgExpr',minfo.EnclosingType,m,objArgTy) + else + objArgExpr' + + wrap,[objArgExpr'] + + | _ -> + (fun x -> x), objArgs + let e,ety = f ccallInfo objArgs + wrap e,ety + +//------------------------------------------------------------------------- +// Build method calls. +//------------------------------------------------------------------------- + +//------------------------------------------------------------------------- +// Build calls +//------------------------------------------------------------------------- + + +/// Build an expression node that is a call to a .NET method. +let BuildILMethInfoCall g amap m isProp (minfo:ILMethInfo) valUseFlags minst direct args = + let valu = isStructTy g minfo.ApparentEnclosingType + let ctor = minfo.IsConstructor + if minfo.IsClassConstructor then + error (InternalError (minfo.ILName+": cannot call a class constructor",m)) + let useCallvirt = + not valu && not direct && minfo.IsVirtual + let isProtected = minfo.IsProtectedAccessibility + let ilMethRef = minfo.ILMethodRef + let newobj = ctor && (match valUseFlags with NormalValUse -> true | _ -> false) + let exprTy = if ctor then minfo.ApparentEnclosingType else minfo.GetFSharpReturnTy(amap, m, minst) + let retTy = (if not ctor && (ilMethRef.ReturnType = ILType.Void) then [] else [exprTy]) + let isDllImport = minfo.IsDllImport g + Expr.Op(TOp.ILCall(useCallvirt,isProtected,valu,newobj,valUseFlags,isProp,isDllImport,ilMethRef,minfo.DeclaringTypeInst,minst,retTy),[],args,m), + exprTy + +/// Build a call to the System.Object constructor taking no arguments, +let BuildObjCtorCall g m = + let ilMethRef = (mkILCtorMethSpecForTy(g.ilg.typ_Object,[])).MethodRef + Expr.Op(TOp.ILCall(false,false,false,false,CtorValUsedAsSuperInit,false,true,ilMethRef,[],[],[g.obj_ty]),[],[],m) + + +/// Build a call to an F# method. +/// +/// Consume the arguments in chunks and build applications. This copes with various F# calling signatures +/// all of which ultimately become 'methods'. +/// +/// QUERY: this looks overly complex considering that we are doing a fundamentally simple +/// thing here. +let BuildFSharpMethodApp g m (vref: ValRef) vexp vexprty (args: Exprs) = + let arities = (arityOfVal vref.Deref).AritiesOfArgs + + let args3,(leftover,retTy) = + ((args,vexprty), arities) ||> List.mapFold (fun (args,fty) arity -> + match arity,args with + | (0|1),[] when typeEquiv g (domainOfFunTy g fty) g.unit_ty -> mkUnit g m, (args, rangeOfFunTy g fty) + | 0,(arg::argst)-> + warning(InternalError(sprintf "Unexpected zero arity, args = %s" (Layout.showL (Layout.sepListL (Layout.rightL ";") (List.map exprL args))),m)); + arg, (argst, rangeOfFunTy g fty) + | 1,(arg :: argst) -> arg, (argst, rangeOfFunTy g fty) + | 1,[] -> error(InternalError("expected additional arguments here",m)) + | _ -> + if args.Length < arity then error(InternalError("internal error in getting arguments, n = "+string arity+", #args = "+string args.Length,m)); + let tupargs,argst = List.chop arity args + let tuptys = tupargs |> List.map (tyOfExpr g) + (mkTupled g m tupargs tuptys), + (argst, rangeOfFunTy g fty) ) + if not leftover.IsEmpty then error(InternalError("Unexpected "+string(leftover.Length)+" remaining arguments in method application",m)) + mkApps g ((vexp,vexprty),[],args3,m), + retTy + +/// Build a call to an F# method. +let BuildFSharpMethodCall g m (typ,vref:ValRef) valUseFlags minst args = + let vexp = Expr.Val (vref,valUseFlags,m) + let vexpty = vref.Type + let tpsorig,tau = vref.TypeScheme + let vtinst = argsOfAppTy g typ @ minst + if tpsorig.Length <> vtinst.Length then error(InternalError("BuildFSharpMethodCall: unexpected List.length mismatch",m)) + let expr = mkTyAppExpr m (vexp,vexpty) vtinst + let exprty = instType (mkTyparInst tpsorig vtinst) tau + BuildFSharpMethodApp g m vref expr exprty args + + +/// Make a call to a method info. Used by the optimizer and code generator to build +/// calls to the type-directed solutions to member constraints. +let MakeMethInfoCall amap m minfo minst args = + let valUseFlags = NormalValUse // correct unless if we allow wild trait constraints like "T has a ctor and can be used as a parent class" + match minfo with + | ILMeth(g,ilminfo,_) -> + let direct = not minfo.IsVirtual + let isProp = false // not necessarily correct, but this is only used post-creflect where this flag is irrelevant + BuildILMethInfoCall g amap m isProp ilminfo valUseFlags minst direct args |> fst + | FSMeth(g,typ,vref,_) -> + BuildFSharpMethodCall g m (typ,vref) valUseFlags minst args |> fst + | DefaultStructCtor(_,typ) -> + mkDefault (m,typ) +#if EXTENSIONTYPING + | ProvidedMeth(amap,mi,_,m) -> + let isProp = false // not necessarily correct, but this is only used post-creflect where this flag is irrelevant + let ilMethodRef = Import.ImportProvidedMethodBaseAsILMethodRef amap m mi + let isConstructor = mi.PUntaint((fun c -> c.IsConstructor), m) + let valu = mi.PUntaint((fun c -> c.DeclaringType.IsValueType), m) + let actualTypeInst = [] // GENERIC TYPE PROVIDERS: for generics, we would have something here + let actualMethInst = [] // GENERIC TYPE PROVIDERS: for generics, we would have something here + let ilReturnTys = Option.toList (minfo.GetCompiledReturnTy(amap, m, [])) // GENERIC TYPE PROVIDERS: for generics, we would have more here + // REVIEW: Should we allow protected calls? + Expr.Op(TOp.ILCall(false,false, valu, isConstructor,valUseFlags,isProp,false,ilMethodRef,actualTypeInst,actualMethInst, ilReturnTys),[],args,m) + +#endif + +#if EXTENSIONTYPING +// This imports a provided method, and checks if it is a known compiler intrinsic like "1 + 2" +let TryImportProvidedMethodBaseAsLibraryIntrinsic (amap:Import.ImportMap, m:range, mbase: Tainted) = + let methodName = mbase.PUntaint((fun x -> x.Name),m) + let declaringType = Import.ImportProvidedType amap m (mbase.PApply((fun x -> x.DeclaringType),m)) + if isAppTy amap.g declaringType then + let declaringEntity = tcrefOfAppTy amap.g declaringType + if not declaringEntity.IsLocalRef && ccuEq declaringEntity.nlr.Ccu amap.g.fslibCcu then + match amap.g.knownIntrinsics.TryGetValue ((declaringEntity.LogicalName, methodName)) with + | true,vref -> Some vref + | _ -> + match amap.g.knownFSharpCoreModules.TryGetValue(declaringEntity.LogicalName) with + | true,modRef -> + match modRef.ModuleOrNamespaceType.AllValsByLogicalName |> Seq.tryPick (fun (KeyValue(_,v)) -> if v.CompiledName = methodName then Some v else None) with + | Some v -> Some (mkNestedValRef modRef v) + | None -> None + | _ -> None + else + None + else + None +#endif + + +/// Build an expression that calls a given method info. +/// This is called after overload resolution, and also to call other +/// methods such as 'setters' for properties. +// tcVal: used to convert an F# value into an expression. See tc.fs. +// isProp: is it a property get? +// minst: the instantiation to apply for a generic method +// objArgs: the 'this' argument, if any +// args: the arguments, if any +let BuildMethodCall tcVal g amap isMutable m isProp minfo valUseFlags minst objArgs args = + + let direct = IsBaseCall objArgs + + TakeObjAddrForMethodCall g amap minfo isMutable m objArgs (fun ccallInfo objArgs -> + let allArgs = (objArgs @ args) + let valUseFlags = + if (direct && (match valUseFlags with NormalValUse -> true | _ -> false)) then + VSlotDirectCall + else + match ccallInfo with + | Some ty -> + // printfn "possible constrained call to '%s' at %A" minfo.LogicalName m + PossibleConstrainedCall ty + | None -> + valUseFlags + + match minfo with +#if EXTENSIONTYPING + // By this time this is an erased method info, e.g. one returned from an expression + // REVIEW: copied from tastops, which doesn't allow protected methods + | ProvidedMeth (amap,providedMeth,_,_) -> + // TODO: there is a fair bit of duplication here with mk_il_minfo_call. We should be able to merge these + + /// Build an expression node that is a call to a extension method in a generated assembly + let enclTy = minfo.EnclosingType + // prohibit calls to methods that are declared in specific array types (Get,Set,Address) + // these calls are provided by the runtime and should not be called from the user code + if isArrayTy g enclTy then + let tpe = TypeProviderError(FSComp.SR.tcRuntimeSuppliedMethodCannotBeUsedInUserCode(minfo.DisplayName), providedMeth.TypeProviderDesignation, m) + error (tpe) + let valu = isStructTy g enclTy + let isCtor = minfo.IsConstructor + if minfo.IsClassConstructor then + error (InternalError (minfo.LogicalName ^": cannot call a class constructor",m)) + let useCallvirt = not valu && not direct && minfo.IsVirtual + let isProtected = minfo.IsProtectedAccessiblity + let exprTy = if isCtor then enclTy else minfo.GetFSharpReturnTy(amap, m, minst) + match TryImportProvidedMethodBaseAsLibraryIntrinsic (amap, m, providedMeth) with + | Some fsValRef -> + //reraise() calls are converted to TOp.Reraise in the type checker. So if a provided expression includes a reraise call + // we must put it in that form here. + if valRefEq amap.g fsValRef amap.g.reraise_vref then + mkReraise m exprTy, exprTy + else + let vexp, vexpty = tcVal fsValRef valUseFlags (minfo.DeclaringTypeInst @ minst) m + BuildFSharpMethodApp g m fsValRef vexp vexpty allArgs + | None -> + let ilMethRef = Import.ImportProvidedMethodBaseAsILMethodRef amap m providedMeth + let isNewObj = isCtor && (match valUseFlags with NormalValUse -> true | _ -> false) + let actualTypeInst = + if isTupleTy g enclTy then argsOfAppTy g (mkCompiledTupleTy g (destTupleTy g enclTy)) // provided expressions can include method calls that get properties of tuple types + elif isFunTy g enclTy then [ domainOfFunTy g enclTy; rangeOfFunTy g enclTy ] // provided expressions can call Invoke + else minfo.DeclaringTypeInst + let actualMethInst = minst + let retTy = (if not isCtor && (ilMethRef.ReturnType = ILType.Void) then [] else [exprTy]) + let noTailCall = false + let expr = Expr.Op(TOp.ILCall(useCallvirt,isProtected,valu,isNewObj,valUseFlags,isProp,noTailCall,ilMethRef,actualTypeInst,actualMethInst, retTy),[],allArgs,m) + expr,exprTy + +#endif + + // Build a call to a .NET method + | ILMeth(_,ilMethInfo,_) -> + BuildILMethInfoCall g amap m isProp ilMethInfo valUseFlags minst direct allArgs + + // Build a call to an F# method + | FSMeth(_, _, vref, _) -> + + // Go see if this is a use of a recursive definition... Note we know the value instantiation + // we want to use so we pass that in order not to create a new one. + let vexp, vexpty = tcVal vref valUseFlags (minfo.DeclaringTypeInst @ minst) m + BuildFSharpMethodApp g m vref vexp vexpty allArgs + + // Build a 'call' to a struct default constructor + | DefaultStructCtor (g,typ) -> + if not (TypeHasDefaultValue g m typ) then + errorR(Error(FSComp.SR.tcDefaultStructConstructorCall(),m)) + mkDefault (m,typ), typ) + +//------------------------------------------------------------------------- +// Build delegate constructions (lambdas/functions to delegates) +//------------------------------------------------------------------------- + +/// Implements the elaborated form of adhoc conversions from functions to delegates at member callsites +let BuildNewDelegateExpr (eventInfoOpt:EventInfo option, g, amap, delegateTy, invokeMethInfo:MethInfo, delArgTys, f, fty, m) = + let slotsig = invokeMethInfo.GetSlotSig(amap, m) + let delArgVals,expr = + let topValInfo = ValReprInfo([],List.replicate (List.length delArgTys) ValReprInfo.unnamedTopArg, ValReprInfo.unnamedRetVal) + + // Try to pull apart an explicit lambda and use it directly + // Don't do this in the case where we're adjusting the arguments of a function used to build a .NET-compatible event handler + let lambdaContents = + if isSome eventInfoOpt then + None + else + tryDestTopLambda g amap topValInfo (f, fty) + match lambdaContents with + | None -> + + if List.exists (isByrefTy g) delArgTys then + error(Error(FSComp.SR.tcFunctionRequiresExplicitLambda(List.length delArgTys),m)) + + let delArgVals = delArgTys |> List.map (fun argty -> fst (mkCompGenLocal m "delegateArg" argty)) + let expr = + let args = + match eventInfoOpt with + | Some einfo -> + match delArgVals with + | [] -> error(nonStandardEventError einfo.EventName m) + | h :: _ when not (isObjTy g h.Type) -> error(nonStandardEventError einfo.EventName m) + | h :: t -> [exprForVal m h; mkTupledVars g m t] + | None -> + if isNil delArgTys then [mkUnit g m] else List.map (exprForVal m) delArgVals + mkApps g ((f,fty),[],args,m) + delArgVals,expr + + | Some _ -> + if isNil delArgTys then [], mkApps g ((f,fty),[],[mkUnit g m],m) + else + let _,_,_,vsl,body,_ = IteratedAdjustArityOfLambda g amap topValInfo f + List.concat vsl, body + + let meth = TObjExprMethod(slotsig, [], [], [delArgVals], expr, m) + mkObjExpr(delegateTy,None,BuildObjCtorCall g m,[meth],[],m) + +let CoerceFromFSharpFuncToDelegate g amap infoReader ad callerArgTy m callerArgExpr delegateTy = + let (SigOfFunctionForDelegate(invokeMethInfo,delArgTys,_,_)) = GetSigOfFunctionForDelegate infoReader delegateTy m ad + BuildNewDelegateExpr (None, g, amap, delegateTy, invokeMethInfo, delArgTys, callerArgExpr, callerArgTy, m) + + +//------------------------------------------------------------------------- +// Import provided expressions +//------------------------------------------------------------------------- + + +#if EXTENSIONTYPING +// This file is not a great place for this functionality to sit, it's here because of BuildMethodCall +module ProvidedMethodCalls = + + let private convertConstExpr g amap m (constant : Tainted) = + let (obj,objTy) = constant.PApply2(id,m) + let ty = Import.ImportProvidedType amap m objTy + let normTy = normalizeEnumTy g ty + obj.PUntaint((fun v -> + let fail() = raise <| TypeProviderError(FSComp.SR.etUnsupportedConstantType(v.GetType().ToString()), constant.TypeProviderDesignation, m) + try + match v with + | null -> mkNull m ty + | _ when typeEquiv g normTy g.bool_ty -> Expr.Const(Const.Bool(v :?> bool), m, ty) + | _ when typeEquiv g normTy g.sbyte_ty -> Expr.Const(Const.SByte(v :?> sbyte), m, ty) + | _ when typeEquiv g normTy g.byte_ty -> Expr.Const(Const.Byte(v :?> byte), m, ty) + | _ when typeEquiv g normTy g.int16_ty -> Expr.Const(Const.Int16(v :?> int16), m, ty) + | _ when typeEquiv g normTy g.uint16_ty -> Expr.Const(Const.UInt16(v :?> uint16), m, ty) + | _ when typeEquiv g normTy g.int32_ty -> Expr.Const(Const.Int32(v :?> int32), m, ty) + | _ when typeEquiv g normTy g.uint32_ty -> Expr.Const(Const.UInt32(v :?> uint32), m, ty) + | _ when typeEquiv g normTy g.int64_ty -> Expr.Const(Const.Int64(v :?> int64), m, ty) + | _ when typeEquiv g normTy g.uint64_ty -> Expr.Const(Const.UInt64(v :?> uint64), m, ty) + | _ when typeEquiv g normTy g.nativeint_ty -> Expr.Const(Const.IntPtr(v :?> int64), m, ty) + | _ when typeEquiv g normTy g.unativeint_ty -> Expr.Const(Const.UIntPtr(v :?> uint64), m, ty) + | _ when typeEquiv g normTy g.float32_ty -> Expr.Const(Const.Single(v :?> float32), m, ty) + | _ when typeEquiv g normTy g.float_ty -> Expr.Const(Const.Double(v :?> float), m, ty) + | _ when typeEquiv g normTy g.char_ty -> Expr.Const(Const.Char(v :?> char), m, ty) + | _ when typeEquiv g normTy g.string_ty -> Expr.Const(Const.String(v :?> string), m, ty) + | _ when typeEquiv g normTy g.decimal_ty -> Expr.Const(Const.Decimal(v :?> decimal), m, ty) + | _ when typeEquiv g normTy g.unit_ty -> Expr.Const(Const.Unit, m, ty) + | _ -> fail() + with _ -> + fail() + ), range=m) + + /// Erasure over System.Type. + /// + /// This is a reimplementation of the logic of provided-type erasure, working entirely over (tainted, provided) System.Type + /// values. This is used when preparing ParameterInfo objects to give to the provider in GetInvokerExpression. + /// These ParameterInfo have erased ParameterType - giving the provider an erased type makes it considerably easier + /// to implement a correct GetInvokerExpression. + /// + /// Ideally we would implement this operation by converting to an F# TType using ImportSystemType, and then erasing, and then converting + /// back to System.Type. However, there is currently no way to get from an arbitrary F# TType (even the TType for + /// System.Object) to a System.Type to give to the type provider. + let eraseSystemType (amap,m,inputType) = + let rec loop (st:Tainted) = + if st.PUntaint((fun st -> st.IsGenericParameter),m) then st + elif st.PUntaint((fun st -> st.IsArray),m) then + let et = st.PApply((fun st -> st.GetElementType()),m) + let rank = st.PUntaint((fun st -> st.GetArrayRank()),m) + (loop et).PApply((fun st -> ProvidedType.CreateNoContext(if rank = 1 then st.RawSystemType.MakeArrayType() else st.RawSystemType.MakeArrayType(rank))),m) + elif st.PUntaint((fun st -> st.IsByRef),m) then + let et = st.PApply((fun st -> st.GetElementType()),m) + (loop et).PApply((fun st -> ProvidedType.CreateNoContext(st.RawSystemType.MakeByRefType())),m) + elif st.PUntaint((fun st -> st.IsPointer),m) then + let et = st.PApply((fun st -> st.GetElementType()),m) + (loop et).PApply((fun st -> ProvidedType.CreateNoContext(st.RawSystemType.MakePointerType())),m) + else + let isGeneric = st.PUntaint((fun st -> st.IsGenericType),m) + let headType = if isGeneric then st.PApply((fun st -> st.GetGenericTypeDefinition()),m) else st + // We import in order to use IsProvidedErasedTycon, to make sure we at least don't reinvent that + let headTypeAsFSharpType = Import.ImportProvidedNamedType amap m headType + if headTypeAsFSharpType.IsProvidedErasedTycon then + let baseType = + st.PApply((fun st -> + match st.BaseType with + | null -> ProvidedType.CreateNoContext(typeof) // it might be an interface + | st -> st),m) + loop baseType + else + if isGeneric then + let genericArgs = st.PApplyArray((fun st -> st.GetGenericArguments()),"GetGenericArguments",m) + let typars = headTypeAsFSharpType.Typars(m) + // Drop the generic arguments that don't correspond to type arguments, i.e. are units-of-measure + let genericArgs = + [| for (genericArg,tp) in Seq.zip genericArgs typars do + if tp.Kind = TyparKind.Type then + yield genericArg |] + + if genericArgs.Length = 0 then + headType + else + let erasedArgTys = genericArgs |> Array.map loop + headType.PApply((fun st -> + let erasedArgTys = erasedArgTys |> Array.map (fun a -> a.PUntaintNoFailure (fun x -> x.RawSystemType)) + ProvidedType.CreateNoContext(st.RawSystemType.MakeGenericType erasedArgTys)),m) + else + st + loop inputType + + let convertProvidedExpressionToExprAndWitness tcVal (thisArg:Expr option, + allArgs:Exprs, + paramVars:Tainted[], + g,amap,mut,isProp,isSuperInit,m, + expr:Tainted) = + let varConv = + [ for (v,e) in Seq.zip (paramVars |> Seq.map (fun x -> x.PUntaint(id,m))) (Option.toList thisArg @ allArgs) do + yield (v,(None,e)) ] + |> Dictionary.ofList + + let rec exprToExprAndWitness top (ea:Tainted) = + let fail() = error(Error(FSComp.SR.etUnsupportedProvidedExpression(ea.PUntaint((fun etree -> etree.UnderlyingExpressionString), m)),m)) + match ea with + | Tainted.Null -> error(Error(FSComp.SR.etNullProvidedExpression(ea.TypeProviderDesignation),m)) + | _ -> + match ea.PApplyOption((function ProvidedTypeAsExpr x -> Some x | _ -> None), m) with + | Some info -> + let (expr,targetTy) = info.PApply2(id,m) + let srcExpr = exprToExpr expr + let targetTy = Import.ImportProvidedType amap m (targetTy.PApply(id,m)) + let sourceTy = Import.ImportProvidedType amap m (expr.PApply((fun e -> e.Type),m)) + let te = mkCoerceIfNeeded g targetTy sourceTy srcExpr + None, (te, tyOfExpr g te) + | None -> + match ea.PApplyOption((function ProvidedTypeTestExpr x -> Some x | _ -> None), m) with + | Some info -> + let (expr,targetTy) = info.PApply2(id,m) + let srcExpr = exprToExpr expr + let targetTy = Import.ImportProvidedType amap m (targetTy.PApply(id,m)) + let te = mkCallTypeTest g m targetTy srcExpr + None, (te, tyOfExpr g te) + | None -> + match ea.PApplyOption((function ProvidedIfThenElseExpr x -> Some x | _ -> None), m) with + | Some info -> + let test,thenBranch,elseBranch = info.PApply3(id,m) + let testExpr = exprToExpr test + let ifTrueExpr = exprToExpr thenBranch + let ifFalseExpr = exprToExpr elseBranch + let te = mkCond NoSequencePointAtStickyBinding SuppressSequencePointAtTarget m (tyOfExpr g ifTrueExpr) testExpr ifTrueExpr ifFalseExpr + None, (te, tyOfExpr g te) + | None -> + match ea.PApplyOption((function ProvidedVarExpr x -> Some x | _ -> None), m) with + | Some info -> + let _,vTe = varToExpr info + None, (vTe, tyOfExpr g vTe) + | None -> + match ea.PApplyOption((function ProvidedConstantExpr x -> Some x | _ -> None), m) with + | Some info -> + let ce = convertConstExpr g amap m info + None, (ce, tyOfExpr g ce) + | None -> + match ea.PApplyOption((function ProvidedNewTupleExpr x -> Some x | _ -> None), m) with + | Some info -> + let elems = info.PApplyArray(id, "GetInvokerExpresson",m) + let elemsT = elems |> Array.map exprToExpr |> Array.toList + let exprT = mkTupledNoTypes g m elemsT + None, (exprT, tyOfExpr g exprT) + | None -> + match ea.PApplyOption((function ProvidedNewArrayExpr x -> Some x | _ -> None), m) with + | Some info -> + let ty,elems = info.PApply2(id,m) + let tyT = Import.ImportProvidedType amap m ty + let elems = elems.PApplyArray(id, "GetInvokerExpresson",m) + let elemsT = elems |> Array.map exprToExpr |> Array.toList + let exprT = Expr.Op(TOp.Array, [tyT],elemsT,m) + None, (exprT, tyOfExpr g exprT) + | None -> + match ea.PApplyOption((function ProvidedTupleGetExpr x -> Some x | _ -> None), m) with + | Some info -> + let inp,n = info.PApply2(id, m) + let inpT = inp |> exprToExpr + // if type of expression is erased type then we need convert it to the underlying base type + let typeOfExpr = + let t = tyOfExpr g inpT + stripTyEqnsWrtErasure EraseMeasures g t + let tysT = tryDestTupleTy g typeOfExpr + let exprT = mkTupleFieldGet (inpT, tysT, n.PUntaint(id,m), m) + None, (exprT, tyOfExpr g exprT) + | None -> + match ea.PApplyOption((function ProvidedLambdaExpr x -> Some x | _ -> None), m) with + | Some info -> + let v,b = info.PApply2(id, m) + let vT = addVar v + let bT = exprToExpr b + removeVar v + let exprT = mkLambda m vT (bT, tyOfExpr g bT) + None, (exprT, tyOfExpr g exprT) + | None -> + match ea.PApplyOption((function ProvidedLetExpr x -> Some x | _ -> None), m) with + | Some info -> + let v,e,b = info.PApply3(id, m) + let eT = exprToExpr e + let vT = addVar v + let bT = exprToExpr b + removeVar v + let exprT = mkCompGenLet m vT eT bT + None, (exprT, tyOfExpr g exprT) + | None -> + match ea.PApplyOption((function ProvidedVarSetExpr x -> Some x | _ -> None), m) with + | Some info -> + let v,e = info.PApply2(id, m) + let eT = exprToExpr e + let vTopt,_ = varToExpr v + match vTopt with + | None -> + fail() + | Some vT -> + let exprT = mkValSet m (mkLocalValRef vT) eT + None, (exprT, tyOfExpr g exprT) + | None -> + match ea.PApplyOption((function ProvidedWhileLoopExpr x -> Some x | _ -> None), m) with + | Some info -> + let guardExpr,bodyExpr = info.PApply2(id, m) + let guardExprT = exprToExpr guardExpr + let bodyExprT = exprToExpr bodyExpr + let exprT = mkWhile g (SequencePointInfoForWhileLoop.NoSequencePointAtWhileLoop,SpecialWhileLoopMarker.NoSpecialWhileLoopMarker, guardExprT, bodyExprT, m) + None, (exprT, tyOfExpr g exprT) + | None -> + match ea.PApplyOption((function ProvidedForIntegerRangeLoopExpr x -> Some x | _ -> None), m) with + | Some info -> + let v,e1,e2,e3 = info.PApply4(id, m) + let e1T = exprToExpr e1 + let e2T = exprToExpr e2 + let vT = addVar v + let e3T = exprToExpr e3 + removeVar v + let exprT = mkFastForLoop g (SequencePointInfoForForLoop.NoSequencePointAtForLoop,m,vT,e1T,true,e2T,e3T) + None, (exprT, tyOfExpr g exprT) + | None -> + match ea.PApplyOption((function ProvidedNewDelegateExpr x -> Some x | _ -> None), m) with + | Some info -> + let delegateTy,boundVars,delegateBodyExpr = info.PApply3(id, m) + let delegateTyT = Import.ImportProvidedType amap m delegateTy + let vs = boundVars.PApplyArray(id, "GetInvokerExpresson",m) |> Array.toList + let vsT = List.map addVar vs + let delegateBodyExprT = exprToExpr delegateBodyExpr + List.iter removeVar vs + let lambdaExpr = mkLambdas m [] vsT (delegateBodyExprT, tyOfExpr g delegateBodyExprT) + let lambdaExprTy = tyOfExpr g lambdaExpr + let infoReader = InfoReader(g, amap) + let exprT = CoerceFromFSharpFuncToDelegate g amap infoReader AccessorDomain.AccessibleFromSomewhere lambdaExprTy m lambdaExpr delegateTyT + None, (exprT, tyOfExpr g exprT) + | None -> +#if PROVIDED_ADDRESS_OF + match ea.PApplyOption((function ProvidedAddressOfExpr x -> Some x | _ -> None), m) with + | Some e -> + let eT = exprToExpr e + let wrap,ce = mkExprAddrOfExpr g true false DefinitelyMutates eT None m + let ce = wrap ce + None, (ce, tyOfExpr g ce) + | None -> +#endif + match ea.PApplyOption((function ProvidedDefaultExpr x -> Some x | _ -> None), m) with + | Some pty -> + let ty = Import.ImportProvidedType amap m pty + let ce = mkDefault (m, ty) + None, (ce, tyOfExpr g ce) + | None -> + match ea.PApplyOption((function ProvidedCallExpr c -> Some c | _ -> None), m) with + | Some info -> + methodCallToExpr top ea info + | None -> + match ea.PApplyOption((function ProvidedSequentialExpr c -> Some c | _ -> None), m) with + | Some info -> + let e1,e2 = info.PApply2(id, m) + let e1T = exprToExpr e1 + let e2T = exprToExpr e2 + let ce = mkCompGenSequential m e1T e2T + None, (ce, tyOfExpr g ce) + | None -> + match ea.PApplyOption((function ProvidedTryFinallyExpr c -> Some c | _ -> None), m) with + | Some info -> + let e1,e2 = info.PApply2(id, m) + let e1T = exprToExpr e1 + let e2T = exprToExpr e2 + let ce = mkTryFinally g (e1T,e2T,m,tyOfExpr g e1T,SequencePointInfoForTry.NoSequencePointAtTry,SequencePointInfoForFinally.NoSequencePointAtFinally) + None, (ce, tyOfExpr g ce) + | None -> + match ea.PApplyOption((function ProvidedTryWithExpr c -> Some c | _ -> None), m) with + | Some info -> + let bT = exprToExpr (info.PApply((fun (x,_,_,_,_) -> x), m)) + let v1 = info.PApply((fun (_,x,_,_,_) -> x), m) + let v1T = addVar v1 + let e1T = exprToExpr (info.PApply((fun (_,_,x,_,_) -> x), m)) + removeVar v1 + let v2 = info.PApply((fun (_,_,_,x,_) -> x), m) + let v2T = addVar v2 + let e2T = exprToExpr (info.PApply((fun (_,_,_,_,x) -> x), m)) + removeVar v2 + let ce = mkTryWith g (bT,v1T,e1T,v2T,e2T,m,tyOfExpr g bT,SequencePointInfoForTry.NoSequencePointAtTry,SequencePointInfoForWith.NoSequencePointAtWith) + None, (ce, tyOfExpr g ce) + | None -> + match ea.PApplyOption((function ProvidedNewObjectExpr c -> Some c | _ -> None), m) with + | Some info -> + None, ctorCallToExpr info + | None -> + fail() + + + and ctorCallToExpr (ne:Tainted<_>) = + let (ctor,args) = ne.PApply2(id,m) + let targetMethInfo = ProvidedMeth(amap,ctor.PApply((fun ne -> upcast ne),m),None,m) + let objArgs = [] + let arguments = [ for ea in args.PApplyArray(id, "GetInvokerExpresson", m) -> exprToExpr ea ] + let callExpr = BuildMethodCall tcVal g amap Mutates.PossiblyMutates m false targetMethInfo isSuperInit [] objArgs arguments + callExpr + + and addVar (v:Tainted) = + let nm = v.PUntaint ((fun v -> v.Name),m) + let mut = v.PUntaint ((fun v -> v.IsMutable),m) + let vRaw = v.PUntaint (id,m) + let tyT = Import.ImportProvidedType amap m (v.PApply ((fun v -> v.Type),m)) + let vT,vTe = if mut then mkMutableCompGenLocal m nm tyT else mkCompGenLocal m nm tyT + varConv.[vRaw] <- (Some vT,vTe) + vT + + and removeVar (v:Tainted) = + let vRaw = v.PUntaint (id,m) + varConv.Remove vRaw |> ignore + + and methodCallToExpr top _origExpr (mce:Tainted<_>) = + let (objOpt,meth,args) = mce.PApply3(id,m) + let targetMethInfo = ProvidedMeth(amap,meth.PApply((fun mce -> upcast mce), m),None,m) + let objArgs = + match objOpt.PApplyOption(id, m) with + | None -> [] + | Some objExpr -> [exprToExpr objExpr] + + let arguments = [ for ea in args.PApplyArray(id, "GetInvokerExpresson", m) -> exprToExpr ea ] + let genericArguments = + if meth.PUntaint((fun m -> m.IsGenericMethod), m) then + meth.PApplyArray((fun m -> m.GetGenericArguments()), "GetGenericArguments", m) + else + [| |] + let replacementGenericArguments = genericArguments |> Array.map (fun t->Import.ImportProvidedType amap m t) |> List.ofArray + + let mut = if top then mut else PossiblyMutates + let isSuperInit = if top then isSuperInit else ValUseFlag.NormalValUse + let isProp = if top then isProp else false + let callExpr = BuildMethodCall tcVal g amap mut m isProp targetMethInfo isSuperInit replacementGenericArguments objArgs arguments + Some meth, callExpr + + and varToExpr (pe:Tainted) = + // sub in the appropriate argument + // REVIEW: "thisArg" pointer should be first, if present + let vRaw = pe.PUntaint(id,m) + if not (varConv.ContainsKey vRaw) then + let typeProviderDesignation = ExtensionTyping.DisplayNameOfTypeProvider (pe.TypeProvider, m) + error(NumberedError(FSComp.SR.etIncorrectParameterExpression(typeProviderDesignation,vRaw.Name), m)) + varConv.[vRaw] + + and exprToExpr expr = + let _, (resExpr, _) = exprToExprAndWitness false expr + resExpr + + exprToExprAndWitness true expr + + + // fill in parameter holes in the expression + let TranslateInvokerExpressionForProvidedMethodCall tcVal (g, amap, mut, isProp, isSuperInit, mi:Tainted, objArgs, allArgs, m) = + let parameters = + mi.PApplyArray((fun mi -> mi.GetParameters()), "GetParameters", m) + let paramTys = + parameters + |> Array.map (fun p -> p.PApply((fun st -> st.ParameterType),m)) + let erasedParamTys = + paramTys + |> Array.map (fun pty -> eraseSystemType (amap,m,pty)) + let paramVars = + erasedParamTys + |> Array.mapi (fun i erasedParamTy -> erasedParamTy.PApply((fun ty -> ProvidedVar.Fresh("arg" + i.ToString(),ty)),m)) + + + // encode "this" as the first ParameterExpression, if applicable + let thisArg, paramVars = + match objArgs with + | [objArg] -> + let erasedThisTy = eraseSystemType (amap,m,mi.PApply((fun mi -> mi.DeclaringType),m)) + let thisVar = erasedThisTy.PApply((fun ty -> ProvidedVar.Fresh("this", ty)), m) + Some objArg , Array.append [| thisVar |] paramVars + | [] -> None , paramVars + | _ -> failwith "multiple objArgs?" + + let ea = mi.PApplyWithProvider((fun (methodInfo,provider) -> ExtensionTyping.GetInvokerExpression(provider, methodInfo, [| for p in paramVars -> p.PUntaintNoFailure id |])), m) + + convertProvidedExpressionToExprAndWitness tcVal (thisArg,allArgs,paramVars,g,amap,mut,isProp,isSuperInit,m,ea) + + + let BuildInvokerExpressionForProvidedMethodCall tcVal (g, amap, mi:Tainted, objArgs, mut, isProp, isSuperInit, allArgs, m) = + try + let methInfoOpt, (expr, retTy) = TranslateInvokerExpressionForProvidedMethodCall tcVal (g, amap, mut, isProp, isSuperInit, mi, objArgs, allArgs, m) + + let exprty = GetCompiledReturnTyOfProvidedMethodInfo amap m mi |> GetFSharpViewOfReturnType g + let expr = mkCoerceIfNeeded g exprty retTy expr + methInfoOpt, expr, exprty + with + | :? TypeProviderError as tpe -> + let typeName = mi.PUntaint((fun mb -> mb.DeclaringType.FullName), m) + let methName = mi.PUntaint((fun mb -> mb.Name), m) + raise( tpe.WithContext(typeName, methName) ) // loses original stack trace +#endif diff --git a/src/fsharp/MethodOverrides.fs b/src/fsharp/MethodOverrides.fs new file mode 100644 index 00000000000..6b46480c4f1 --- /dev/null +++ b/src/fsharp/MethodOverrides.fs @@ -0,0 +1,712 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +/// Primary logic related to method overrides. +module internal Microsoft.FSharp.Compiler.MethodOverrides + +open Internal.Utilities +open System.Text + +open Microsoft.FSharp.Compiler +open Microsoft.FSharp.Compiler.AbstractIL +open Microsoft.FSharp.Compiler.AbstractIL.IL +open Microsoft.FSharp.Compiler.AbstractIL.Internal +open Microsoft.FSharp.Compiler.AbstractIL.Internal.Library +open Microsoft.FSharp.Compiler.AbstractIL.Diagnostics +open Microsoft.FSharp.Compiler.Ast +open Microsoft.FSharp.Compiler.ErrorLogger +open Microsoft.FSharp.Compiler.Lib +open Microsoft.FSharp.Compiler.Infos +open Microsoft.FSharp.Compiler.AccessibilityLogic +open Microsoft.FSharp.Compiler.NameResolution +open Microsoft.FSharp.Compiler.PrettyNaming +open Microsoft.FSharp.Compiler.Range +open Microsoft.FSharp.Compiler.InfoReader +open Microsoft.FSharp.Compiler.Tast +open Microsoft.FSharp.Compiler.Tastops +open Microsoft.FSharp.Compiler.Tastops.DebugPrint +open Microsoft.FSharp.Compiler.TcGlobals +open Microsoft.FSharp.Compiler.TypeRelations + +//------------------------------------------------------------------------- +// Completeness of classes +//------------------------------------------------------------------------- + +type OverrideCanImplement = + | CanImplementAnyInterfaceSlot + | CanImplementAnyClassHierarchySlot + | CanImplementAnySlot + | CanImplementNoSlots + +/// The overall information about a method implementation in a class or object expression +type OverrideInfo = + | Override of OverrideCanImplement * TyconRef * Ident * (Typars * TyparInst) * TType list list * TType option * bool * bool + member x.CanImplement = let (Override(a,_,_,_,_,_,_,_)) = x in a + member x.BoundingTyconRef = let (Override(_,ty,_,_,_,_,_,_)) = x in ty + member x.LogicalName = let (Override(_,_,id,_,_,_,_,_)) = x in id.idText + member x.Range = let (Override(_,_,id,_,_,_,_,_)) = x in id.idRange + member x.IsFakeEventProperty = let (Override(_,_,_,_,_,_,b,_)) = x in b + member x.ArgTypes = let (Override(_,_,_,_,b,_,_,_)) = x in b + member x.ReturnType = let (Override(_,_,_,_,_,b,_,_)) = x in b + member x.IsCompilerGenerated = let (Override(_,_,_,_,_,_,_,b)) = x in b + +// If the bool is true then the slot is optional, i.e. is an interface slot +// which does not _have_ to be implemented, because an inherited implementation +// is available. +type RequiredSlot = RequiredSlot of MethInfo * (* isOptional: *) bool + +type SlotImplSet = SlotImplSet of RequiredSlot list * NameMultiMap * OverrideInfo list * PropInfo list + +exception TypeIsImplicitlyAbstract of range +exception OverrideDoesntOverride of DisplayEnv * OverrideInfo * MethInfo option * TcGlobals * Import.ImportMap * range + +module DispatchSlotChecking = + + /// Print the signature of an override to a buffer as part of an error message + let PrintOverrideToBuffer denv os (Override(_,_,id,(mtps,memberToParentInst),argTys,retTy,_,_)) = + let denv = { denv with showTyparBinding = true } + let retTy = (retTy |> GetFSharpViewOfReturnType denv.g) + let argInfos = + match argTys with + | [] -> [[(denv.g.unit_ty,ValReprInfo.unnamedTopArg1)]] + | _ -> argTys |> List.mapSquared (fun ty -> (ty, ValReprInfo.unnamedTopArg1)) + Layout.bufferL os (NicePrint.layoutMemberSig denv (memberToParentInst,id.idText,mtps, argInfos, retTy)) + + /// Print the signature of a MethInfo to a buffer as part of an error message + let PrintMethInfoSigToBuffer g amap m denv os minfo = + let denv = { denv with showTyparBinding = true } + let (CompiledSig(argTys,retTy,fmtps,ttpinst)) = CompiledSigOfMeth g amap m minfo + let retTy = (retTy |> GetFSharpViewOfReturnType g) + let argInfos = argTys |> List.mapSquared (fun ty -> (ty, ValReprInfo.unnamedTopArg1)) + let nm = minfo.LogicalName + Layout.bufferL os (NicePrint.layoutMemberSig denv (ttpinst,nm,fmtps, argInfos, retTy)) + + /// Format the signature of an override as a string as part of an error message + let FormatOverride denv d = bufs (fun buf -> PrintOverrideToBuffer denv buf d) + + /// Format the signature of a MethInfo as a string as part of an error message + let FormatMethInfoSig g amap m denv d = bufs (fun buf -> PrintMethInfoSigToBuffer g amap m denv buf d) + + /// Get the override info for an existing (inherited) method being used to implement a dispatch slot. + let GetInheritedMemberOverrideInfo g amap m parentType (minfo:MethInfo) = + let nm = minfo.LogicalName + let (CompiledSig (argTys,retTy,fmtps,ttpinst)) = CompiledSigOfMeth g amap m minfo + + let isFakeEventProperty = minfo.IsFSharpEventPropertyMethod + Override(parentType,tcrefOfAppTy g minfo.EnclosingType,mkSynId m nm, (fmtps,ttpinst),argTys,retTy,isFakeEventProperty,false) + + /// Get the override info for a value being used to implement a dispatch slot. + let GetTypeMemberOverrideInfo g reqdTy (overrideBy:ValRef) = + let _,argInfos,retTy,_ = GetTypeOfMemberInMemberForm g overrideBy + let nm = overrideBy.LogicalName + + let argTys = argInfos |> List.mapSquared fst + + let memberMethodTypars,memberToParentInst,argTys,retTy = + match PartitionValRefTypars g overrideBy with + | Some(_,_,memberMethodTypars,memberToParentInst,_tinst) -> + let argTys = argTys |> List.mapSquared (instType memberToParentInst) + let retTy = retTy |> Option.map (instType memberToParentInst) + memberMethodTypars, memberToParentInst,argTys, retTy + | None -> + error(Error(FSComp.SR.typrelMethodIsOverconstrained(),overrideBy.Range)) + let implKind = + if ValRefIsExplicitImpl g overrideBy then + + let belongsToReqdTy = + match overrideBy.MemberInfo.Value.ImplementedSlotSigs with + | [] -> false + | ss :: _ -> isInterfaceTy g ss.ImplementedType && typeEquiv g reqdTy ss.ImplementedType + if belongsToReqdTy then + CanImplementAnyInterfaceSlot + else + CanImplementNoSlots + else if overrideBy.IsDispatchSlotMember then + CanImplementNoSlots + // abstract slots can only implement interface slots + //CanImplementAnyInterfaceSlot <<----- Change to this to enable implicit interface implementation + + else + CanImplementAnyClassHierarchySlot + //CanImplementAnySlot <<----- Change to this to enable implicit interface implementation + + let isFakeEventProperty = overrideBy.IsFSharpEventProperty(g) + Override(implKind,overrideBy.MemberApparentParent, mkSynId overrideBy.Range nm, (memberMethodTypars,memberToParentInst),argTys,retTy,isFakeEventProperty, overrideBy.IsCompilerGenerated) + + /// Get the override information for an object expression method being used to implement dispatch slots + let GetObjectExprOverrideInfo g amap (implty, id:Ident, memberFlags, ty, arityInfo, bindingAttribs, rhsExpr) = + // Dissect the type + let tps, argInfos, retTy, _ = GetMemberTypeInMemberForm g memberFlags arityInfo ty id.idRange + let argTys = argInfos |> List.mapSquared fst + // Dissect the implementation + let _, ctorThisValOpt, baseValOpt, vsl, rhsExpr,_ = destTopLambda g amap arityInfo (rhsExpr,ty) + assert ctorThisValOpt.IsNone + + // Drop 'this' + match vsl with + | [thisv]::vs -> + // Check for empty variable list from a () arg + let vs = if vs.Length = 1 && argInfos.IsEmpty then [] else vs + let implKind = + if isInterfaceTy g implty then + CanImplementAnyInterfaceSlot + else + CanImplementAnyClassHierarchySlot + //CanImplementAnySlot <<----- Change to this to enable implicit interface implementation + let isFakeEventProperty = CompileAsEvent g bindingAttribs + let overrideByInfo = Override(implKind, tcrefOfAppTy g implty, id, (tps,[]), argTys, retTy, isFakeEventProperty, false) + overrideByInfo, (baseValOpt, thisv, vs, bindingAttribs, rhsExpr) + | _ -> + error(InternalError("Unexpected shape for object expression override",id.idRange)) + + /// Check if an override matches a dispatch slot by name + let IsNameMatch (dispatchSlot:MethInfo) (overrideBy: OverrideInfo) = + (overrideBy.LogicalName = dispatchSlot.LogicalName) + + /// Check if an override matches a dispatch slot by name + let IsImplMatch g (dispatchSlot:MethInfo) (overrideBy: OverrideInfo) = + // If the override is listed as only relevant to one type, and we're matching it against an abstract slot of an interface type, + // then check that interface type is the right type. + (match overrideBy.CanImplement with + | CanImplementNoSlots -> false + | CanImplementAnySlot -> true + | CanImplementAnyClassHierarchySlot -> not (isInterfaceTy g dispatchSlot.EnclosingType) + //| CanImplementSpecificInterfaceSlot parentTy -> isInterfaceTy g dispatchSlot.EnclosingType && typeEquiv g parentTy dispatchSlot.EnclosingType + | CanImplementAnyInterfaceSlot -> isInterfaceTy g dispatchSlot.EnclosingType) + + /// Check if the kinds of type parameters match between a dispatch slot and an override. + let IsTyparKindMatch g amap m (dispatchSlot:MethInfo) (Override(_,_,_,(mtps,_),_,_,_,_)) = + let (CompiledSig(_,_,fvmtps,_)) = CompiledSigOfMeth g amap m dispatchSlot + List.lengthsEqAndForall2 (fun (tp1:Typar) (tp2:Typar) -> tp1.Kind = tp2.Kind) mtps fvmtps + + /// Check if an override is a partial match for the requirements for a dispatch slot + let IsPartialMatch g amap m (dispatchSlot:MethInfo) (Override(_,_,_,(mtps,_),argTys,_retTy,_,_) as overrideBy) = + IsNameMatch dispatchSlot overrideBy && + let (CompiledSig (vargtys,_,fvmtps,_)) = CompiledSigOfMeth g amap m dispatchSlot + mtps.Length = fvmtps.Length && + IsTyparKindMatch g amap m dispatchSlot overrideBy && + argTys.Length = vargtys.Length && + IsImplMatch g dispatchSlot overrideBy + + /// Compute the reverse of a type parameter renaming. + let ReverseTyparRenaming g tinst = + tinst |> List.map (fun (tp,ty) -> (destTyparTy g ty, mkTyparTy tp)) + + /// Compose two instantiations of type parameters. + let ComposeTyparInsts inst1 inst2 = + inst1 |> List.map (map2Of2 (instType inst2)) + + /// Check if an override exactly matches the requirements for a dispatch slot + let IsExactMatch g amap m dispatchSlot (Override(_,_,_,(mtps,mtpinst),argTys,retTy,_,_) as overrideBy) = + IsPartialMatch g amap m dispatchSlot overrideBy && + let (CompiledSig (vargtys,vrty,fvmtps,ttpinst)) = CompiledSigOfMeth g amap m dispatchSlot + + // Compare the types. CompiledSigOfMeth, GetObjectExprOverrideInfo and GetTypeMemberOverrideInfo have already + // applied all relevant substitutions except the renamings from fvtmps <-> mtps + + let aenv = TypeEquivEnv.FromEquivTypars fvmtps mtps + + List.forall2 (List.lengthsEqAndForall2 (typeAEquiv g aenv)) vargtys argTys && + returnTypesAEquiv g aenv vrty retTy && + + // Comparing the method typars and their constraints is much trickier since the substitutions have not been applied + // to the constraints of these babies. This is partly because constraints are directly attached to typars so it's + // difficult to apply substitutions to them unless we separate them off at some point, which we don't as yet. + // + // Given C + // D + // dispatchSlot : C.M(...) + // overrideBy: parent: D value: ! (...) + // + // where X[dtps] indicates that X may involve free type variables dtps + // + // we have + // ttpinst maps ctps --> ctys[dtps] + // mtpinst maps ttps --> dtps + // + // compare fvtmps[ctps] and mtps[ttps] by + // fvtmps[ctps] @ ttpinst -- gives fvtmps[dtps] + // fvtmps[dtps] @ rev(mtpinst) -- gives fvtmps[ttps] + // + // Now fvtmps[ttps] and mtpinst[ttps] are comparable, i.e. have constraints w.r.t. the same set of type variables + // + // i.e. Compose the substitutions ttpinst and rev(mtpinst) + + let ttpinst = + // check we can reverse - in some error recovery situations we can't + if mtpinst |> List.exists (snd >> isTyparTy g >> not) then ttpinst + else ComposeTyparInsts ttpinst (ReverseTyparRenaming g mtpinst) + + // Compare under the composed substitutions + let aenv = TypeEquivEnv.FromTyparInst ttpinst + + typarsAEquiv g aenv fvmtps mtps + + /// Check if an override implements a dispatch slot + let OverrideImplementsDispatchSlot g amap m dispatchSlot availPriorOverride = + IsExactMatch g amap m dispatchSlot availPriorOverride && + // The override has to actually be in some subtype of the dispatch slot + ExistsHeadTypeInEntireHierarchy g amap m (generalizedTyconRef availPriorOverride.BoundingTyconRef) (tcrefOfAppTy g dispatchSlot.EnclosingType) + + /// Check if a dispatch slot is already implemented + let DispatchSlotIsAlreadyImplemented g amap m availPriorOverridesKeyed (dispatchSlot: MethInfo) = + availPriorOverridesKeyed + |> NameMultiMap.find dispatchSlot.LogicalName + |> List.exists (OverrideImplementsDispatchSlot g amap m dispatchSlot) + + + /// Check all dispatch slots are implemented by some override. + let CheckDispatchSlotsAreImplemented (denv,g,amap,m, + nenv,sink:TcResultsSink, + isOverallTyAbstract, + reqdTy, + dispatchSlots:RequiredSlot list, + availPriorOverrides:OverrideInfo list, + overrides:OverrideInfo list) = + + let isReqdTyInterface = isInterfaceTy g reqdTy + let showMissingMethodsAndRaiseErrors = (isReqdTyInterface || not isOverallTyAbstract) + let res = ref true + let fail exn = (res := false ; if showMissingMethodsAndRaiseErrors then errorR exn) + + // Index the availPriorOverrides and overrides by name + let availPriorOverridesKeyed = availPriorOverrides |> NameMultiMap.initBy (fun ov -> ov.LogicalName) + let overridesKeyed = overrides |> NameMultiMap.initBy (fun ov -> ov.LogicalName) + + dispatchSlots |> List.iter (fun (RequiredSlot(dispatchSlot,isOptional)) -> + + match NameMultiMap.find dispatchSlot.LogicalName overridesKeyed + |> List.filter (OverrideImplementsDispatchSlot g amap m dispatchSlot) with + | [ovd] -> + if not ovd.IsCompilerGenerated then + let item = Item.MethodGroup(ovd.LogicalName,[dispatchSlot],None) + CallNameResolutionSink sink (ovd.Range,nenv,item,item,ItemOccurence.Implemented,denv,AccessorDomain.AccessibleFromSomewhere) + sink |> ignore + () + | [] -> + if not isOptional && + // Check that no available prior override implements this dispatch slot + not (DispatchSlotIsAlreadyImplemented g amap m availPriorOverridesKeyed dispatchSlot) then + // error reporting path + let (CompiledSig (vargtys,_vrty,fvmtps,_)) = CompiledSigOfMeth g amap m dispatchSlot + let noimpl() = if isReqdTyInterface then fail(Error(FSComp.SR.typrelNoImplementationGivenWithSuggestion(NicePrint.stringOfMethInfo amap m denv dispatchSlot), m)) + else fail(Error(FSComp.SR.typrelNoImplementationGiven(NicePrint.stringOfMethInfo amap m denv dispatchSlot), m)) + match overrides |> List.filter (IsPartialMatch g amap m dispatchSlot) with + | [] -> + match overrides |> List.filter (fun overrideBy -> IsNameMatch dispatchSlot overrideBy && + IsImplMatch g dispatchSlot overrideBy) with + | [] -> + noimpl() + | [ Override(_,_,_,(mtps,_),argTys,_,_,_) as overrideBy ] -> + let error_msg = + if argTys.Length <> vargtys.Length then FSComp.SR.typrelMemberDoesNotHaveCorrectNumberOfArguments(FormatOverride denv overrideBy, FormatMethInfoSig g amap m denv dispatchSlot) + elif mtps.Length <> fvmtps.Length then FSComp.SR.typrelMemberDoesNotHaveCorrectNumberOfTypeParameters(FormatOverride denv overrideBy, FormatMethInfoSig g amap m denv dispatchSlot) + elif not (IsTyparKindMatch g amap m dispatchSlot overrideBy) then FSComp.SR.typrelMemberDoesNotHaveCorrectKindsOfGenericParameters(FormatOverride denv overrideBy, FormatMethInfoSig g amap m denv dispatchSlot) + else FSComp.SR.typrelMemberCannotImplement(FormatOverride denv overrideBy, NicePrint.stringOfMethInfo amap m denv dispatchSlot, FormatMethInfoSig g amap m denv dispatchSlot) + fail(Error(error_msg, overrideBy.Range)) + | overrideBy :: _ -> + errorR(Error(FSComp.SR.typrelOverloadNotFound(FormatMethInfoSig g amap m denv dispatchSlot, FormatMethInfoSig g amap m denv dispatchSlot),overrideBy.Range)) + + | [ overrideBy ] -> + + match dispatchSlots |> List.filter (fun (RequiredSlot(dispatchSlot,_)) -> OverrideImplementsDispatchSlot g amap m dispatchSlot overrideBy) with + | [] -> + // Error will be reported below in CheckOverridesAreAllUsedOnce + () + | _ -> + noimpl() + + | _ -> + fail(Error(FSComp.SR.typrelOverrideWasAmbiguous(FormatMethInfoSig g amap m denv dispatchSlot),m)) + | _ -> fail(Error(FSComp.SR.typrelMoreThenOneOverride(FormatMethInfoSig g amap m denv dispatchSlot),m))) + !res + + /// Check all implementations implement some dispatch slot. + let CheckOverridesAreAllUsedOnce(denv, g, amap, isObjExpr, reqdTy, + dispatchSlotsKeyed: NameMultiMap, + availPriorOverrides: OverrideInfo list, + overrides: OverrideInfo list) = + let availPriorOverridesKeyed = availPriorOverrides |> NameMultiMap.initBy (fun ov -> ov.LogicalName) + for overrideBy in overrides do + if not overrideBy.IsFakeEventProperty then + let m = overrideBy.Range + let relevantVirts = NameMultiMap.find overrideBy.LogicalName dispatchSlotsKeyed + let relevantVirts = relevantVirts |> List.map (fun (RequiredSlot(dispatchSlot,_)) -> dispatchSlot) + + match relevantVirts |> List.filter (fun dispatchSlot -> OverrideImplementsDispatchSlot g amap m dispatchSlot overrideBy) with + | [] -> + // This is all error reporting + match relevantVirts |> List.filter (fun dispatchSlot -> IsPartialMatch g amap m dispatchSlot overrideBy) with + | [dispatchSlot] -> + errorR(OverrideDoesntOverride(denv,overrideBy,Some dispatchSlot,g,amap,m)) + | _ -> + match relevantVirts |> List.filter (fun dispatchSlot -> IsNameMatch dispatchSlot overrideBy) with + | [dispatchSlot] -> + errorR(OverrideDoesntOverride(denv, overrideBy, Some dispatchSlot, g, amap, m)) + | _ -> + errorR(OverrideDoesntOverride(denv,overrideBy,None,g,amap,m)) + + + | [dispatchSlot] -> + if dispatchSlot.IsFinal && (isObjExpr || not (typeEquiv g reqdTy dispatchSlot.EnclosingType)) then + errorR(Error(FSComp.SR.typrelMethodIsSealed(NicePrint.stringOfMethInfo amap m denv dispatchSlot),m)) + | dispatchSlots -> + match dispatchSlots |> List.filter (fun dispatchSlot -> + isInterfaceTy g dispatchSlot.EnclosingType || + not (DispatchSlotIsAlreadyImplemented g amap m availPriorOverridesKeyed dispatchSlot)) with + | h1 :: h2 :: _ -> + errorR(Error(FSComp.SR.typrelOverrideImplementsMoreThenOneSlot((FormatOverride denv overrideBy), (NicePrint.stringOfMethInfo amap m denv h1), (NicePrint.stringOfMethInfo amap m denv h2)),m)) + | _ -> + // dispatch slots are ordered from the derived classes to base + // so we can check the topmost dispatch slot if it is final + match dispatchSlots with + | meth::_ when meth.IsFinal -> errorR(Error(FSComp.SR.tcCannotOverrideSealedMethod((sprintf "%s::%s" (meth.EnclosingType.ToString()) (meth.LogicalName))), m)) + | _ -> () + + + + /// Get the slots of a type that can or must be implemented. This depends + /// partly on the full set of interface types that are being implemented + /// simultaneously, e.g. + /// { new C with interface I2 = ... interface I3 = ... } + /// allReqdTys = {C;I2;I3} + /// + /// allReqdTys can include one class/record/union type. + let GetSlotImplSets (infoReader:InfoReader) denv isObjExpr allReqdTys = + + let g = infoReader.g + let amap = infoReader.amap + + let availImpliedInterfaces : TType list = + [ for (reqdTy,m) in allReqdTys do + if not (isInterfaceTy g reqdTy) then + let baseTyOpt = if isObjExpr then Some reqdTy else GetSuperTypeOfType g amap m reqdTy + match baseTyOpt with + | None -> () + | Some baseTy -> yield! AllInterfacesOfType g amap m AllowMultiIntfInstantiations.Yes baseTy ] + + // For each implemented type, get a list containing the transitive closure of + // interface types implied by the type. This includes the implemented type itself if the implemented type + // is an interface type. + let intfSets = + allReqdTys |> List.mapi (fun i (reqdTy,m) -> + let interfaces = AllInterfacesOfType g amap m AllowMultiIntfInstantiations.Yes reqdTy + let impliedTys = (if isInterfaceTy g reqdTy then interfaces else reqdTy :: interfaces) + (i, reqdTy, impliedTys,m)) + + // For each implemented type, reduce its list of implied interfaces by subtracting out those implied + // by another implemented interface type. + // + // REVIEW: Note complexity O(ity*jty) + let reqdTyInfos = + intfSets |> List.map (fun (i,reqdTy,impliedTys,m) -> + let reduced = + (impliedTys,intfSets) ||> List.fold (fun acc (j,jty,impliedTys2,m) -> + if i <> j && TypeFeasiblySubsumesType 0 g amap m jty CanCoerce reqdTy + then ListSet.subtract (TypesFeasiblyEquiv 0 g amap m) acc impliedTys2 + else acc ) + (i, reqdTy, m, reduced)) + + // Check that, for each implemented type, at least one implemented type is implied. This is enough to capture + // duplicates. + for (_i, reqdTy, m, impliedTys) in reqdTyInfos do + if isInterfaceTy g reqdTy && isNil impliedTys then + errorR(Error(FSComp.SR.typrelDuplicateInterface(),m)) + + // Check that no interface type is implied twice + // + // Note complexity O(reqdTy*reqdTy) + for (i, _reqdTy, reqdTyRange, impliedTys) in reqdTyInfos do + for (j,_,_,impliedTys2) in reqdTyInfos do + if i > j then + let overlap = ListSet.intersect (TypesFeasiblyEquiv 0 g amap reqdTyRange) impliedTys impliedTys2 + overlap |> List.iter (fun overlappingTy -> + if nonNil(GetImmediateIntrinsicMethInfosOfType (None,AccessibleFromSomewhere) g amap reqdTyRange overlappingTy |> List.filter (fun minfo -> minfo.IsVirtual)) then + errorR(Error(FSComp.SR.typrelNeedExplicitImplementation(NicePrint.minimalStringOfType denv (List.head overlap)),reqdTyRange))) + + // Get the SlotImplSet for each implemented type + // This contains the list of required members and the list of available members + [ for (_,reqdTy,reqdTyRange,impliedTys) in reqdTyInfos do + + // Build a set of the implied interface types, for quicker lookup, by nominal type + let isImpliedInterfaceTable = + impliedTys + |> List.filter (isInterfaceTy g) + |> List.map (fun ty -> tcrefOfAppTy g ty, ()) + |> TyconRefMap.OfList + + // Is a member an abstract slot of one of the implied interface types? + let isImpliedInterfaceType ty = + isImpliedInterfaceTable.ContainsKey (tcrefOfAppTy g ty) && + impliedTys |> List.exists (TypesFeasiblyEquiv 0 g amap reqdTyRange ty) + + //let isSlotImpl (minfo:MethInfo) = + // not minfo.IsAbstract && minfo.IsVirtual + + // Compute the abstract slots that require implementations + let dispatchSlots = + [ if isInterfaceTy g reqdTy then + for impliedTy in impliedTys do + // Check if the interface has an inherited implementation + // If so, you do not have to implement all the methods - each + // specific method is "optionally" implemented. + let isOptional = + ListSet.contains (typeEquiv g) impliedTy availImpliedInterfaces + for reqdSlot in GetImmediateIntrinsicMethInfosOfType (None,AccessibleFromSomewhere) g amap reqdTyRange impliedTy do + yield RequiredSlot(reqdSlot, isOptional) + else + + // In the normal case, the requirements for a class are precisely all the abstract slots up the whole hierarchy. + // So here we get and yield all of those. + for minfo in reqdTy |> GetIntrinsicMethInfosOfType infoReader (None,AccessibleFromSomewhere,AllowMultiIntfInstantiations.Yes) IgnoreOverrides reqdTyRange do + if minfo.IsDispatchSlot then + yield RequiredSlot(minfo,(*isOptional=*)false) ] + + + // Compute the methods that are available to implement abstract slots from the base class + // + // This is used in CheckDispatchSlotsAreImplemented when we think a dispatch slot may not + // have been implemented. + let availPriorOverrides : OverrideInfo list = + if isInterfaceTy g reqdTy then + [] + else + let reqdTy = + let baseTyOpt = if isObjExpr then Some reqdTy else GetSuperTypeOfType g amap reqdTyRange reqdTy + match baseTyOpt with + | None -> reqdTy + | Some baseTy -> baseTy + [ // Get any class hierarchy methods on this type + // + // NOTE: What we have below is an over-approximation that will get too many methods + // and not always correctly relate them to the slots they implement. For example, + // we may get an override from a base class and believe it implements a fresh, new abstract + // slot in a subclass. + for minfos in infoReader.GetRawIntrinsicMethodSetsOfType(None,AccessibleFromSomewhere,AllowMultiIntfInstantiations.Yes,reqdTyRange,reqdTy) do + for minfo in minfos do + if not minfo.IsAbstract then + yield GetInheritedMemberOverrideInfo g amap reqdTyRange CanImplementAnyClassHierarchySlot minfo ] + + // We also collect up the properties. This is used for abstract slot inference when overriding properties + let isRelevantRequiredProperty (x:PropInfo) = + (x.IsVirtualProperty && not (isInterfaceTy g reqdTy)) || + isImpliedInterfaceType x.EnclosingType + + let reqdProperties = + GetIntrinsicPropInfosOfType infoReader (None,AccessibleFromSomewhere,AllowMultiIntfInstantiations.Yes) IgnoreOverrides reqdTyRange reqdTy + |> List.filter isRelevantRequiredProperty + + let dispatchSlotsKeyed = dispatchSlots |> NameMultiMap.initBy (fun (RequiredSlot(v,_)) -> v.LogicalName) + yield SlotImplSet(dispatchSlots, dispatchSlotsKeyed, availPriorOverrides, reqdProperties) ] + + + /// Check that a type definition implements all its required interfaces after processing all declarations + /// within a file. + let CheckImplementationRelationAtEndOfInferenceScope (infoReader :InfoReader,denv,nenv,sink,tycon:Tycon,isImplementation) = + + let g = infoReader.g + let amap = infoReader.amap + + let tcaug = tycon.TypeContents + let interfaces = tycon.ImmediateInterfacesOfFSharpTycon |> List.map (fun (ity,_compgen,m) -> (ity,m)) + + let overallTy = generalizedTyconRef (mkLocalTyconRef tycon) + + let allReqdTys = (overallTy,tycon.Range) :: interfaces + + // Get all the members that are immediately part of this type + // Include the auto-generated members + let allImmediateMembers = tycon.MembersOfFSharpTyconSorted @ tycon.AllGeneratedValues + + // Get all the members we have to implement, organized by each type we explicitly implement + let slotImplSets = GetSlotImplSets infoReader denv false allReqdTys + + let allImpls = List.zip allReqdTys slotImplSets + + // Find the methods relevant to implementing the abstract slots listed under the reqdType being checked. + let allImmediateMembersThatMightImplementDispatchSlots = + allImmediateMembers |> List.filter (fun overrideBy -> + overrideBy.IsInstanceMember && // exclude static + overrideBy.IsVirtualMember && // exclude non virtual (e.g. keep override/default). [4469] + not overrideBy.IsDispatchSlotMember) + + let mustOverrideSomething reqdTy (overrideBy:ValRef) = + let memberInfo = overrideBy.MemberInfo.Value + not (overrideBy.IsFSharpEventProperty(g)) && + memberInfo.MemberFlags.IsOverrideOrExplicitImpl && + + match memberInfo.ImplementedSlotSigs with + | [] -> + // Are we looking at the implementation of the class hierarchy? If so include all the override members + not (isInterfaceTy g reqdTy) + | ss -> + ss |> List.forall (fun ss -> + let ty = ss.ImplementedType + if isInterfaceTy g ty then + // Is this a method impl listed under the reqdTy? + typeEquiv g ty reqdTy + else + not (isInterfaceTy g reqdTy) ) + + + // We check all the abstracts related to the class hierarchy and then check each interface implementation + for ((reqdTy,m),slotImplSet) in allImpls do + let (SlotImplSet(dispatchSlots, dispatchSlotsKeyed, availPriorOverrides,_)) = slotImplSet + try + + // Now extract the information about each overriding method relevant to this SlotImplSet + let allImmediateMembersThatMightImplementDispatchSlots = + allImmediateMembersThatMightImplementDispatchSlots + |> List.map (fun overrideBy -> overrideBy,GetTypeMemberOverrideInfo g reqdTy overrideBy) + + // Now check the implementation + // We don't give missing method errors for abstract classes + + if isImplementation && not (isInterfaceTy g overallTy) then + let overrides = allImmediateMembersThatMightImplementDispatchSlots |> List.map snd + let allCorrect = CheckDispatchSlotsAreImplemented (denv,g,amap,m,nenv,sink,tcaug.tcaug_abstract,reqdTy,dispatchSlots,availPriorOverrides,overrides) + + // Tell the user to mark the thing abstract if it was missing implementations + if not allCorrect && not tcaug.tcaug_abstract && not (isInterfaceTy g reqdTy) then + errorR(TypeIsImplicitlyAbstract(m)) + + let overridesToCheck = + allImmediateMembersThatMightImplementDispatchSlots + |> List.filter (fst >> mustOverrideSomething reqdTy) + |> List.map snd + + CheckOverridesAreAllUsedOnce (denv, g, amap, false, reqdTy, dispatchSlotsKeyed, availPriorOverrides, overridesToCheck) + + with e -> errorRecovery e m + + // Now record the full slotsigs of the abstract members implemented by each override. + // This is used to generate IL MethodImpls in the code generator. + allImmediateMembersThatMightImplementDispatchSlots |> List.iter (fun overrideBy -> + + let isFakeEventProperty = overrideBy.IsFSharpEventProperty(g) + let overriden = + if isFakeEventProperty then + let slotsigs = overrideBy.MemberInfo.Value.ImplementedSlotSigs + slotsigs |> List.map (ReparentSlotSigToUseMethodTypars g overrideBy.Range overrideBy) + else + [ for ((reqdTy,m),(SlotImplSet(_dispatchSlots,dispatchSlotsKeyed,_,_))) in allImpls do + let overrideByInfo = GetTypeMemberOverrideInfo g reqdTy overrideBy + let overridenForThisSlotImplSet = + [ for (RequiredSlot(dispatchSlot,_)) in NameMultiMap.find overrideByInfo.LogicalName dispatchSlotsKeyed do + if OverrideImplementsDispatchSlot g amap m dispatchSlot overrideByInfo then + if tyconRefEq g overrideByInfo.BoundingTyconRef (tcrefOfAppTy g dispatchSlot.EnclosingType) then + match dispatchSlot.ArbitraryValRef with + | Some virtMember -> + if virtMember.MemberInfo.Value.IsImplemented then errorR(Error(FSComp.SR.tcDefaultImplementationAlreadyExists(),overrideByInfo.Range)) + virtMember.MemberInfo.Value.IsImplemented <- true + | None -> () // not an F# slot + + // Get the slotsig of the overridden method + let slotsig = dispatchSlot.GetSlotSig(amap, m) + + // The slotsig from the overridden method is in terms of the type parameters on the parent type of the overriding method, + // Modify map the slotsig so it is in terms of the type parameters for the overriding method + let slotsig = ReparentSlotSigToUseMethodTypars g m overrideBy slotsig + + // Record the slotsig via mutation + yield slotsig ] + //if mustOverrideSomething reqdTy overrideBy then + // assert nonNil overridenForThisSlotImplSet + yield! overridenForThisSlotImplSet ] + + overrideBy.MemberInfo.Value.ImplementedSlotSigs <- overriden) + + + +//------------------------------------------------------------------------- +// "Type Completion" inference and a few other checks at the end of the inference scope +//------------------------------------------------------------------------- + + +/// "Type Completion" inference and a few other checks at the end of the inference scope +let FinalTypeDefinitionChecksAtEndOfInferenceScope (infoReader:InfoReader, nenv, sink, isImplementation, denv) (tycon:Tycon) = + + let g = infoReader.g + let amap = infoReader.amap + + let tcaug = tycon.TypeContents + tcaug.tcaug_closed <- true + + // Note you only have to explicitly implement 'System.IComparable' to customize structural comparison AND equality on F# types + if isImplementation && +#if EXTENSIONTYPING + not tycon.IsProvidedGeneratedTycon && +#endif + isNone tycon.GeneratedCompareToValues && + tycon.HasInterface g g.mk_IComparable_ty && + not (tycon.HasOverride g "Equals" [g.obj_ty]) && + not tycon.IsFSharpInterfaceTycon + then + (* Warn when we're doing this for class types *) + if AugmentWithHashCompare.TyconIsCandidateForAugmentationWithEquals g tycon then + warning(Error(FSComp.SR.typrelTypeImplementsIComparableShouldOverrideObjectEquals(tycon.DisplayName),tycon.Range)) + else + warning(Error(FSComp.SR.typrelTypeImplementsIComparableDefaultObjectEqualsProvided(tycon.DisplayName),tycon.Range)) + + AugmentWithHashCompare.CheckAugmentationAttribs isImplementation g amap tycon + // Check some conditions about generic comparison and hashing. We can only check this condition after we've done the augmentation + if isImplementation +#if EXTENSIONTYPING + && not tycon.IsProvidedGeneratedTycon +#endif + then + let tcaug = tycon.TypeContents + let m = tycon.Range + let hasExplicitObjectGetHashCode = tycon.HasOverride g "GetHashCode" [] + let hasExplicitObjectEqualsOverride = tycon.HasOverride g "Equals" [g.obj_ty] + + if (isSome tycon.GeneratedHashAndEqualsWithComparerValues) && + (hasExplicitObjectGetHashCode || hasExplicitObjectEqualsOverride) then + errorR(Error(FSComp.SR.typrelExplicitImplementationOfGetHashCodeOrEquals(tycon.DisplayName),m)) + + if not hasExplicitObjectEqualsOverride && hasExplicitObjectGetHashCode then + warning(Error(FSComp.SR.typrelExplicitImplementationOfGetHashCode(tycon.DisplayName),m)) + + if hasExplicitObjectEqualsOverride && not hasExplicitObjectGetHashCode then + warning(Error(FSComp.SR.typrelExplicitImplementationOfEquals(tycon.DisplayName),m)) + + + // remember these values to ensure we don't generate these methods during codegen + tcaug.SetHasObjectGetHashCode hasExplicitObjectGetHashCode + + if not tycon.IsHiddenReprTycon + && not tycon.IsTypeAbbrev + && not tycon.IsMeasureableReprTycon + && not tycon.IsAsmReprTycon + && not tycon.IsFSharpInterfaceTycon + && not tycon.IsFSharpDelegateTycon then + + DispatchSlotChecking.CheckImplementationRelationAtEndOfInferenceScope (infoReader,denv,nenv,sink,tycon,isImplementation) + +/// Get the methods relevant to determining if a uniquely-identified-override exists based on the syntactic information +/// at the member signature prior to type inference. This is used to pre-assign type information if it does +let GetAbstractMethInfosForSynMethodDecl(infoReader:InfoReader,ad,memberName:Ident,bindm,typToSearchForAbstractMembers,valSynData) = + let minfos = + match typToSearchForAbstractMembers with + | _,Some(SlotImplSet(_, dispatchSlotsKeyed,_,_)) -> + NameMultiMap.find memberName.idText dispatchSlotsKeyed |> List.map (fun (RequiredSlot(dispatchSlot,_)) -> dispatchSlot) + | ty, None -> + GetIntrinsicMethInfosOfType infoReader (Some(memberName.idText), ad, AllowMultiIntfInstantiations.Yes) IgnoreOverrides bindm ty + let dispatchSlots = minfos |> List.filter (fun minfo -> minfo.IsDispatchSlot) + let topValSynArities = SynInfo.AritiesOfArgs valSynData + let topValSynArities = if topValSynArities.Length > 0 then topValSynArities.Tail else topValSynArities + let dispatchSlotsArityMatch = dispatchSlots |> List.filter (fun minfo -> minfo.NumArgs = topValSynArities) + dispatchSlots,dispatchSlotsArityMatch + +/// Get the properties relevant to determining if a uniquely-identified-override exists based on the syntactic information +/// at the member signature prior to type inference. This is used to pre-assign type information if it does +let GetAbstractPropInfosForSynPropertyDecl(infoReader:InfoReader,ad,memberName:Ident,bindm,typToSearchForAbstractMembers,_k,_valSynData) = + let pinfos = + match typToSearchForAbstractMembers with + | _,Some(SlotImplSet(_,_,_,reqdProps)) -> + reqdProps |> List.filter (fun pinfo -> pinfo.PropertyName = memberName.idText) + | ty, None -> + GetIntrinsicPropInfosOfType infoReader (Some(memberName.idText), ad, AllowMultiIntfInstantiations.Yes) IgnoreOverrides bindm ty + + let dispatchSlots = pinfos |> List.filter (fun pinfo -> pinfo.IsVirtualProperty) + dispatchSlots + diff --git a/src/fsharp/NameResolution.fs b/src/fsharp/NameResolution.fs index 89408ce27da..8c5b65ebd89 100755 --- a/src/fsharp/NameResolution.fs +++ b/src/fsharp/NameResolution.fs @@ -24,8 +24,9 @@ open Microsoft.FSharp.Compiler.AbstractIL.Internal.Library.ResultOrException open Microsoft.FSharp.Compiler.AbstractIL.Diagnostics open Microsoft.FSharp.Compiler.AbstractIL.IL // Abstract IL open Microsoft.FSharp.Compiler.Infos -open Microsoft.FSharp.Compiler.Infos.AccessibilityLogic -open Microsoft.FSharp.Compiler.Infos.AttributeChecking +open Microsoft.FSharp.Compiler.AccessibilityLogic +open Microsoft.FSharp.Compiler.AttributeChecking +open Microsoft.FSharp.Compiler.InfoReader open Microsoft.FSharp.Compiler.Layout open Microsoft.FSharp.Compiler.PrettyNaming open System.Collections.Generic diff --git a/src/fsharp/NameResolution.fsi b/src/fsharp/NameResolution.fsi index 02a629728ea..ccad006c207 100755 --- a/src/fsharp/NameResolution.fsi +++ b/src/fsharp/NameResolution.fsi @@ -3,18 +3,18 @@ module internal Microsoft.FSharp.Compiler.NameResolution open Microsoft.FSharp.Compiler +open Microsoft.FSharp.Compiler.AccessibilityLogic open Microsoft.FSharp.Compiler.Ast open Microsoft.FSharp.Compiler.Infos open Microsoft.FSharp.Compiler.Range open Microsoft.FSharp.Compiler.Import +open Microsoft.FSharp.Compiler.InfoReader open Microsoft.FSharp.Compiler.Tast open Microsoft.FSharp.Compiler.Tastops open Microsoft.FSharp.Compiler.TcGlobals open Microsoft.FSharp.Compiler.AbstractIL.Internal.Library open Microsoft.FSharp.Compiler.PrettyNaming - - /// A NameResolver is a context for name resolution. It primarily holds an InfoReader. type NameResolver = new : g:TcGlobals * amap:ImportMap * infoReader:InfoReader * instantiationGenerator:(range -> Typars -> TypeInst) -> NameResolver @@ -410,4 +410,4 @@ type ResolveCompletionTargets = | SettablePropertiesAndFields /// Resolve a (possibly incomplete) long identifier to a set of possible resolutions, qualified by type. -val ResolveCompletionsInType : NameResolver -> NameResolutionEnv -> ResolveCompletionTargets -> Range.range -> Infos.AccessorDomain -> bool -> TType -> Item list +val ResolveCompletionsInType : NameResolver -> NameResolutionEnv -> ResolveCompletionTargets -> Range.range -> AccessorDomain -> bool -> TType -> Item list diff --git a/src/fsharp/NicePrint.fs b/src/fsharp/NicePrint.fs index a9b829834c6..28c0570250f 100755 --- a/src/fsharp/NicePrint.fs +++ b/src/fsharp/NicePrint.fs @@ -10,11 +10,11 @@ module internal Microsoft.FSharp.Compiler.NicePrint open Internal.Utilities open Microsoft.FSharp.Compiler.AbstractIL +open Microsoft.FSharp.Compiler.AbstractIL.Diagnostics open Microsoft.FSharp.Compiler.AbstractIL.IL open Microsoft.FSharp.Compiler.AbstractIL.Internal open Microsoft.FSharp.Compiler.AbstractIL.Internal.Library open Microsoft.FSharp.Compiler -open Microsoft.FSharp.Compiler.AbstractIL.Diagnostics open Microsoft.FSharp.Compiler.Range open Microsoft.FSharp.Compiler.Rational open Microsoft.FSharp.Compiler.Ast @@ -23,17 +23,20 @@ open Microsoft.FSharp.Compiler.Tast open Microsoft.FSharp.Compiler.Tastops open Microsoft.FSharp.Compiler.Tastops.DebugPrint open Microsoft.FSharp.Compiler.TcGlobals -open Microsoft.FSharp.Compiler.AbstractIL.IL (* Abstract IL *) open Microsoft.FSharp.Compiler.Lib open Microsoft.FSharp.Compiler.Infos +open Microsoft.FSharp.Compiler.InfoReader +open Microsoft.FSharp.Compiler.AttributeChecking +open Microsoft.FSharp.Compiler.Layout +open Microsoft.FSharp.Compiler.PrettyNaming + open Microsoft.FSharp.Core.Printf + #if EXTENSIONTYPING open Microsoft.FSharp.Compiler.ExtensionTyping open Microsoft.FSharp.Core.CompilerServices #endif -open Microsoft.FSharp.Compiler.Layout -open Microsoft.FSharp.Compiler.PrettyNaming [] module internal PrintUtilities = @@ -1448,8 +1451,8 @@ module private TastDefinitionPrinting = match valRef with | None -> true | Some(vr) -> - (denv.showObsoleteMembers || not (Infos.AttributeChecking.CheckFSharpAttributesForObsolete denv.g vr.Attribs)) && - (denv.showHiddenMembers || not (Infos.AttributeChecking.CheckFSharpAttributesForHidden denv.g vr.Attribs)) + (denv.showObsoleteMembers || not (CheckFSharpAttributesForObsolete denv.g vr.Attribs)) && + (denv.showHiddenMembers || not (CheckFSharpAttributesForHidden denv.g vr.Attribs)) let ctors = GetIntrinsicConstructorInfosOfType infoReader m ty @@ -1582,8 +1585,8 @@ module private TastDefinitionPrinting = // Don't print individual methods forming interface implementations - these are currently never exported not (isInterfaceTy denv.g oty) | [] -> true) - |> List.filter (fun v -> denv.showObsoleteMembers || not (Infos.AttributeChecking.CheckFSharpAttributesForObsolete denv.g v.Attribs)) - |> List.filter (fun v -> denv.showHiddenMembers || not (Infos.AttributeChecking.CheckFSharpAttributesForHidden denv.g v.Attribs)) + |> List.filter (fun v -> denv.showObsoleteMembers || not (CheckFSharpAttributesForObsolete denv.g v.Attribs)) + |> List.filter (fun v -> denv.showHiddenMembers || not (CheckFSharpAttributesForHidden denv.g v.Attribs)) // sort let sortKey (v:ValRef) = (not v.IsConstructor, // constructors before others v.Id.idText, // sort by name diff --git a/src/fsharp/Optimizer.fs b/src/fsharp/Optimizer.fs index 1130f7d1868..0bb9b2dfe87 100644 --- a/src/fsharp/Optimizer.fs +++ b/src/fsharp/Optimizer.fs @@ -11,28 +11,27 @@ module internal Microsoft.FSharp.Compiler.Optimizer open Internal.Utilities open Microsoft.FSharp.Compiler.AbstractIL +open Microsoft.FSharp.Compiler.AbstractIL.Diagnostics +open Microsoft.FSharp.Compiler.AbstractIL.IL open Microsoft.FSharp.Compiler.AbstractIL.Internal open Microsoft.FSharp.Compiler.AbstractIL.Internal.Library open Microsoft.FSharp.Compiler.AbstractIL.Extensions.ILX -open Microsoft.FSharp.Compiler -open Microsoft.FSharp.Compiler.AbstractIL.IL -open Microsoft.FSharp.Compiler.AbstractIL.Diagnostics - -open Microsoft.FSharp.Compiler.TastPickle +open Microsoft.FSharp.Compiler +open Microsoft.FSharp.Compiler.Lib open Microsoft.FSharp.Compiler.Range open Microsoft.FSharp.Compiler.Ast open Microsoft.FSharp.Compiler.ErrorLogger +open Microsoft.FSharp.Compiler.Infos open Microsoft.FSharp.Compiler.PrettyNaming open Microsoft.FSharp.Compiler.Tast +open Microsoft.FSharp.Compiler.TastPickle open Microsoft.FSharp.Compiler.Tastops open Microsoft.FSharp.Compiler.Tastops.DebugPrint open Microsoft.FSharp.Compiler.TypeChecker open Microsoft.FSharp.Compiler.TcGlobals -open Microsoft.FSharp.Compiler.Lib open Microsoft.FSharp.Compiler.Layout open Microsoft.FSharp.Compiler.TypeRelations -open Microsoft.FSharp.Compiler.Infos open System.Collections.Generic diff --git a/src/fsharp/PostInferenceChecks.fs b/src/fsharp/PostInferenceChecks.fs index 4d0f15a4ab9..bf05aca6eaa 100644 --- a/src/fsharp/PostInferenceChecks.fs +++ b/src/fsharp/PostInferenceChecks.fs @@ -13,18 +13,20 @@ open Microsoft.FSharp.Compiler.AbstractIL.IL open Microsoft.FSharp.Compiler.AbstractIL.Internal open Microsoft.FSharp.Compiler.AbstractIL.Internal.Library open Microsoft.FSharp.Compiler.AbstractIL.Diagnostics -open Microsoft.FSharp.Compiler.Range + +open Microsoft.FSharp.Compiler.AccessibilityLogic open Microsoft.FSharp.Compiler.Ast open Microsoft.FSharp.Compiler.ErrorLogger +open Microsoft.FSharp.Compiler.Range open Microsoft.FSharp.Compiler.Tast open Microsoft.FSharp.Compiler.Tastops open Microsoft.FSharp.Compiler.TcGlobals open Microsoft.FSharp.Compiler.Lib open Microsoft.FSharp.Compiler.Layout -open Microsoft.FSharp.Compiler.AbstractIL.IL -open Microsoft.FSharp.Compiler.TypeRelations open Microsoft.FSharp.Compiler.Infos open Microsoft.FSharp.Compiler.PrettyNaming +open Microsoft.FSharp.Compiler.InfoReader +open Microsoft.FSharp.Compiler.TypeRelations diff --git a/src/fsharp/PostInferenceChecks.fsi b/src/fsharp/PostInferenceChecks.fsi index 834cd92b6ac..d6a58bd9cb9 100644 --- a/src/fsharp/PostInferenceChecks.fsi +++ b/src/fsharp/PostInferenceChecks.fsi @@ -6,6 +6,7 @@ module internal Microsoft.FSharp.Compiler.PostTypeCheckSemanticChecks open Microsoft.FSharp.Compiler open Microsoft.FSharp.Compiler.TcGlobals +open Microsoft.FSharp.Compiler.InfoReader val testFlagMemberBody : bool ref -val CheckTopImpl : TcGlobals * Import.ImportMap * bool * Infos.InfoReader * Tast.CompilationPath list * Tast.CcuThunk * Tastops.DisplayEnv * Tast.ModuleOrNamespaceExprWithSig * Tast.Attribs * bool -> bool +val CheckTopImpl : TcGlobals * Import.ImportMap * bool * InfoReader * Tast.CompilationPath list * Tast.CcuThunk * Tastops.DisplayEnv * Tast.ModuleOrNamespaceExprWithSig * Tast.Attribs * bool -> bool diff --git a/src/fsharp/SignatureConformance.fs b/src/fsharp/SignatureConformance.fs new file mode 100644 index 00000000000..28db41d7146 --- /dev/null +++ b/src/fsharp/SignatureConformance.fs @@ -0,0 +1,638 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +/// Primary relations on types and signatures, with the exception of +/// constraint solving and method overload resolution. +module internal Microsoft.FSharp.Compiler.SignatureConformance + +open Internal.Utilities +open System.Text + +open Microsoft.FSharp.Compiler +open Microsoft.FSharp.Compiler.AbstractIL +open Microsoft.FSharp.Compiler.AbstractIL.IL +open Microsoft.FSharp.Compiler.AbstractIL.Internal +open Microsoft.FSharp.Compiler.AbstractIL.Internal.Library +open Microsoft.FSharp.Compiler.AbstractIL.Diagnostics +open Microsoft.FSharp.Compiler.Range +open Microsoft.FSharp.Compiler.Ast +open Microsoft.FSharp.Compiler.ErrorLogger +open Microsoft.FSharp.Compiler.Tast +open Microsoft.FSharp.Compiler.Tastops +open Microsoft.FSharp.Compiler.Tastops.DebugPrint +open Microsoft.FSharp.Compiler.TcGlobals +open Microsoft.FSharp.Compiler.AbstractIL.IL +open Microsoft.FSharp.Compiler.Lib +open Microsoft.FSharp.Compiler.Infos +open Microsoft.FSharp.Compiler.PrettyNaming +open Microsoft.FSharp.Compiler.AccessibilityLogic +open Microsoft.FSharp.Compiler.NameResolution +open Microsoft.FSharp.Compiler.TypeRelations + +#if EXTENSIONTYPING +open Microsoft.FSharp.Compiler.ExtensionTyping +#endif + + +exception RequiredButNotSpecified of DisplayEnv * Tast.ModuleOrNamespaceRef * string * (StringBuilder -> unit) * range +exception ValueNotContained of DisplayEnv * Tast.ModuleOrNamespaceRef * Val * Val * (string * string * string -> string) +exception ConstrNotContained of DisplayEnv * UnionCase * UnionCase * (string * string -> string) +exception ExnconstrNotContained of DisplayEnv * Tycon * Tycon * (string * string -> string) +exception FieldNotContained of DisplayEnv * RecdField * RecdField * (string * string -> string) +exception InterfaceNotRevealed of DisplayEnv * TType * range + + +// Use a type to capture the constant, common parameters +type Checker(g, amap, denv, remapInfo: SignatureRepackageInfo, checkingSig) = + + // Build a remap that maps tcrefs in the signature to tcrefs in the implementation + // Used when checking attributes. + let sigToImplRemap = + let remap = Remap.Empty + let remap = (remapInfo.mrpiEntities,remap) ||> List.foldBack (fun (implTcref ,signTcref) acc -> addTyconRefRemap signTcref implTcref acc) + let remap = (remapInfo.mrpiVals ,remap) ||> List.foldBack (fun (implValRef,signValRef) acc -> addValRemap signValRef.Deref implValRef.Deref acc) + remap + + // For all attributable elements (types, modules, exceptions, record fields, unions, parameters, generic type parameters) + // + // (a) Start with lists AImpl and ASig containing the attributes in the implementation and signature, in declaration order + // (b) Each attribute in AImpl is checked against the available attributes in ASig. + // a. If an attribute is found in ASig which is an exact match (after evaluating attribute arguments), then the attribute in the implementation is ignored, the attribute is removed from ASig, and checking continues + // b. If an attribute is found in ASig that has the same attribute type, then a warning is given and the attribute in the implementation is ignored + // c. Otherwise, the attribute in the implementation is kept + // (c) The attributes appearing in the compiled element are the compiled forms of the attributes from the signature and the kept attributes from the implementation + let checkAttribs _aenv (implAttribs:Attribs) (sigAttribs:Attribs) fixup = + + // Remap the signature attributes to make them look as if they were declared in + // the implementation. This allows us to compare them and propagate them to the implementation + // if needed. + let sigAttribs = sigAttribs |> List.map (remapAttrib g sigToImplRemap) + + // Helper to check for equality of evaluated attribute expressions + let attribExprEq (AttribExpr(_,e1)) (AttribExpr(_,e2)) = EvaledAttribExprEquality g e1 e2 + + // Helper to check for equality of evaluated named attribute arguments + let attribNamedArgEq (AttribNamedArg(nm1,ty1,isProp1,e1)) (AttribNamedArg(nm2,ty2,isProp2,e2)) = + (nm1 = nm2) && + typeEquiv g ty1 ty2 && + (isProp1 = isProp2) && + attribExprEq e1 e2 + + let attribsEq attrib1 attrib2 = + let (Attrib(implTcref,_,implArgs,implNamedArgs,_,_,_implRange)) = attrib1 + let (Attrib(signTcref,_,signArgs,signNamedArgs,_,_,_signRange)) = attrib2 + tyconRefEq g signTcref implTcref && + (implArgs,signArgs) ||> List.lengthsEqAndForall2 attribExprEq && + (implNamedArgs, signNamedArgs) ||> List.lengthsEqAndForall2 attribNamedArgEq + + let attribsHaveSameTycon attrib1 attrib2 = + let (Attrib(implTcref,_,_,_,_,_,_)) = attrib1 + let (Attrib(signTcref,_,_,_,_,_,_)) = attrib2 + tyconRefEq g signTcref implTcref + + // For each implementation attribute, only keep if it is not mentioned in the signature. + // Emit a warning if it is mentioned in the signature and the arguments to the attributes are + // not identical. + let rec check keptImplAttribsRev implAttribs sigAttribs = + match implAttribs with + | [] -> keptImplAttribsRev |> List.rev + | implAttrib :: remainingImplAttribs -> + + // Look for an attribute in the signature that matches precisely. If so, remove it + let lookForMatchingAttrib = sigAttribs |> List.tryRemove (attribsEq implAttrib) + match lookForMatchingAttrib with + | Some (_, remainingSigAttribs) -> check keptImplAttribsRev remainingImplAttribs remainingSigAttribs + | None -> + + // Look for an attribute in the signature that has the same type. If so, give a warning + let existsSimilarAttrib = sigAttribs |> List.exists (attribsHaveSameTycon implAttrib) + + if existsSimilarAttrib then + let (Attrib(implTcref,_,_,_,_,_,implRange)) = implAttrib + warning(Error(FSComp.SR.tcAttribArgsDiffer(implTcref.DisplayName), implRange)) + check keptImplAttribsRev remainingImplAttribs sigAttribs + else + check (implAttrib :: keptImplAttribsRev) remainingImplAttribs sigAttribs + + let keptImplAttribs = check [] implAttribs sigAttribs + + fixup (sigAttribs @ keptImplAttribs) + true + + let rec checkTypars m (aenv: TypeEquivEnv) (implTypars:Typars) (sigTypars:Typars) = + if implTypars.Length <> sigTypars.Length then + errorR (Error(FSComp.SR.typrelSigImplNotCompatibleParamCountsDiffer(),m)) + false + else + let aenv = aenv.BindEquivTypars implTypars sigTypars + (implTypars,sigTypars) ||> List.forall2 (fun implTypar sigTypar -> + let m = sigTypar.Range + if implTypar.StaticReq <> sigTypar.StaticReq then + errorR (Error(FSComp.SR.typrelSigImplNotCompatibleCompileTimeRequirementsDiffer(), m)) + + // Adjust the actual type parameter name to look like the signature + implTypar.SetIdent (mkSynId implTypar.Range sigTypar.Id.idText) + + // Mark it as "not compiler generated", now that we've got a good name for it + implTypar.SetCompilerGenerated false + + // Check the constraints in the implementation are present in the signature + implTypar.Constraints |> List.forall (fun implTyparCx -> + match implTyparCx with + // defaults can be dropped in the signature + | TyparConstraint.DefaultsTo(_,_acty,_) -> true + | _ -> + if not (List.exists (typarConstraintsAEquiv g aenv implTyparCx) sigTypar.Constraints) + then (errorR(Error(FSComp.SR.typrelSigImplNotCompatibleConstraintsDiffer(sigTypar.Name, Layout.showL(NicePrint.layoutTyparConstraint denv (implTypar,implTyparCx))),m)); false) + else true) && + + // Check the constraints in the signature are present in the implementation + sigTypar.Constraints |> List.forall (fun sigTyparCx -> + match sigTyparCx with + // defaults can be present in the signature and not in the implementation because they are erased + | TyparConstraint.DefaultsTo(_,_acty,_) -> true + // 'comparison' and 'equality' constraints can be present in the signature and not in the implementation because they are erased + | TyparConstraint.SupportsComparison _ -> true + | TyparConstraint.SupportsEquality _ -> true + | _ -> + if not (List.exists (fun implTyparCx -> typarConstraintsAEquiv g aenv implTyparCx sigTyparCx) implTypar.Constraints) then + (errorR(Error(FSComp.SR.typrelSigImplNotCompatibleConstraintsDifferRemove(sigTypar.Name, Layout.showL(NicePrint.layoutTyparConstraint denv (sigTypar,sigTyparCx))),m)); false) + else + true) && + (not checkingSig || checkAttribs aenv implTypar.Attribs sigTypar.Attribs (fun attribs -> implTypar.Data.typar_attribs <- attribs))) + + and checkTypeDef (aenv: TypeEquivEnv) (implTycon:Tycon) (sigTycon:Tycon) = + let m = implTycon.Range + // Propagate defn location information from implementation to signature . + sigTycon.SetOtherRange (implTycon.Range, true) + implTycon.SetOtherRange (sigTycon.Range, false) + let err f = Error(f(implTycon.TypeOrMeasureKind.ToString()), m) + if implTycon.LogicalName <> sigTycon.LogicalName then (errorR (err (FSComp.SR.DefinitionsInSigAndImplNotCompatibleNamesDiffer)); false) else + if implTycon.CompiledName <> sigTycon.CompiledName then (errorR (err (FSComp.SR.DefinitionsInSigAndImplNotCompatibleNamesDiffer)); false) else + checkExnInfo (fun f -> ExnconstrNotContained(denv,implTycon,sigTycon,f)) aenv implTycon.ExceptionInfo sigTycon.ExceptionInfo && + let implTypars = implTycon.Typars m + let sigTypars = sigTycon.Typars m + if implTypars.Length <> sigTypars.Length then + errorR (err(FSComp.SR.DefinitionsInSigAndImplNotCompatibleParameterCountsDiffer)) + false + elif isLessAccessible implTycon.Accessibility sigTycon.Accessibility then + errorR(err(FSComp.SR.DefinitionsInSigAndImplNotCompatibleAccessibilityDiffer)) + false + else + let aenv = aenv.BindEquivTypars implTypars sigTypars + + let aintfs = implTycon.ImmediateInterfaceTypesOfFSharpTycon + let fintfs = sigTycon.ImmediateInterfaceTypesOfFSharpTycon + let aintfsUser = implTycon.TypeContents.tcaug_interfaces |> List.filter (fun (_,compgen,_) -> not compgen) |> List.map p13 + let flatten tys = + tys + |> List.collect (AllSuperTypesOfType g amap m AllowMultiIntfInstantiations.Yes) + |> ListSet.setify (typeEquiv g) + |> List.filter (isInterfaceTy g) + let aintfs = flatten aintfs + let aintfsUser = flatten aintfsUser + let fintfs = flatten fintfs + + let unimpl = ListSet.subtract (fun fity aity -> typeAEquiv g aenv aity fity) fintfs aintfs + (unimpl |> List.forall (fun ity -> errorR (err (fun x -> FSComp.SR.DefinitionsInSigAndImplNotCompatibleMissingInterface(x, NicePrint.minimalStringOfType denv ity))); false)) && + let hidden = ListSet.subtract (typeAEquiv g aenv) aintfsUser fintfs + hidden |> List.iter (fun ity -> (if implTycon.IsFSharpInterfaceTycon then error else warning) (InterfaceNotRevealed(denv,ity,implTycon.Range))) + + let aNull = IsUnionTypeWithNullAsTrueValue g implTycon + let fNull = IsUnionTypeWithNullAsTrueValue g sigTycon + if aNull && not fNull then + errorR(err(FSComp.SR.DefinitionsInSigAndImplNotCompatibleImplementationSaysNull)) + elif fNull && not aNull then + errorR(err(FSComp.SR.DefinitionsInSigAndImplNotCompatibleSignatureSaysNull)) + + let aNull2 = TypeNullIsExtraValue g m (generalizedTyconRef (mkLocalTyconRef implTycon)) + let fNull2 = TypeNullIsExtraValue g m (generalizedTyconRef (mkLocalTyconRef implTycon)) + if aNull2 && not fNull2 then + errorR(err(FSComp.SR.DefinitionsInSigAndImplNotCompatibleImplementationSaysNull2)) + elif fNull2 && not aNull2 then + errorR(err(FSComp.SR.DefinitionsInSigAndImplNotCompatibleSignatureSaysNull2)) + + let aSealed = isSealedTy g (generalizedTyconRef (mkLocalTyconRef implTycon)) + let fSealed = isSealedTy g (generalizedTyconRef (mkLocalTyconRef sigTycon)) + if aSealed && not fSealed then + errorR(err(FSComp.SR.DefinitionsInSigAndImplNotCompatibleImplementationSealed)) + if not aSealed && fSealed then + errorR(err(FSComp.SR.DefinitionsInSigAndImplNotCompatibleImplementationIsNotSealed)) + + let aPartial = isAbstractTycon implTycon + let fPartial = isAbstractTycon sigTycon + if aPartial && not fPartial then + errorR(err(FSComp.SR.DefinitionsInSigAndImplNotCompatibleImplementationIsAbstract)) + + if not aPartial && fPartial then + errorR(err(FSComp.SR.DefinitionsInSigAndImplNotCompatibleSignatureIsAbstract)) + + if not (typeAEquiv g aenv (superOfTycon g implTycon) (superOfTycon g sigTycon)) then + errorR (err(FSComp.SR.DefinitionsInSigAndImplNotCompatibleTypesHaveDifferentBaseTypes)) + + checkTypars m aenv implTypars sigTypars && + checkTypeRepr err aenv implTycon.TypeReprInfo sigTycon.TypeReprInfo && + checkTypeAbbrev err aenv implTycon.TypeOrMeasureKind sigTycon.TypeOrMeasureKind implTycon.TypeAbbrev sigTycon.TypeAbbrev && + checkAttribs aenv implTycon.Attribs sigTycon.Attribs (fun attribs -> implTycon.Data.entity_attribs <- attribs) && + checkModuleOrNamespaceContents implTycon.Range aenv (mkLocalEntityRef implTycon) sigTycon.ModuleOrNamespaceType + + and checkValInfo aenv err (implVal : Val) (sigVal : Val) = + let id = implVal.Id + match implVal.ValReprInfo, sigVal.ValReprInfo with + | _,None -> true + | None, Some _ -> err(FSComp.SR.ValueNotContainedMutabilityArityNotInferred) + | Some (ValReprInfo (implTyparNames,implArgInfos,implRetInfo) as implValInfo), Some (ValReprInfo (sigTyparNames,sigArgInfos,sigRetInfo) as sigValInfo) -> + let ntps = implTyparNames.Length + let mtps = sigTyparNames.Length + if ntps <> mtps then + err(fun(x, y, z) -> FSComp.SR.ValueNotContainedMutabilityGenericParametersDiffer(x, y, z, string mtps, string ntps)) + elif implValInfo.KindsOfTypars <> sigValInfo.KindsOfTypars then + err(FSComp.SR.ValueNotContainedMutabilityGenericParametersAreDifferentKinds) + elif not (sigArgInfos.Length <= implArgInfos.Length && List.forall2 (fun x y -> List.length x <= List.length y) sigArgInfos (fst (List.chop sigArgInfos.Length implArgInfos))) then + err(fun(x, y, z) -> FSComp.SR.ValueNotContainedMutabilityAritiesDiffer(x, y, z, id.idText, string sigArgInfos.Length, id.idText, id.idText)) + else + let implArgInfos = implArgInfos |> List.take sigArgInfos.Length + let implArgInfos = (implArgInfos, sigArgInfos) ||> List.map2 (fun l1 l2 -> l1 |> List.take l2.Length) + // Propagate some information signature to implementation. + + // Check the attributes on each argument, and update the ValReprInfo for + // the value to reflect the information in the signature. + // This ensures that the compiled form of the value matches the signature rather than + // the implementation. This also propagates argument names from signature to implementation + let res = + (implArgInfos,sigArgInfos) ||> List.forall2 (List.forall2 (fun implArgInfo sigArgInfo -> + checkAttribs aenv implArgInfo.Attribs sigArgInfo.Attribs (fun attribs -> + implArgInfo.Name <- sigArgInfo.Name + implArgInfo.Attribs <- attribs))) && + + checkAttribs aenv implRetInfo.Attribs sigRetInfo.Attribs (fun attribs -> + implRetInfo.Name <- sigRetInfo.Name + implRetInfo.Attribs <- attribs) + + implVal.SetValReprInfo (Some (ValReprInfo (sigTyparNames,implArgInfos,implRetInfo))) + res + + and checkVal implModRef (aenv:TypeEquivEnv) (implVal:Val) (sigVal:Val) = + + // Propagate defn location information from implementation to signature . + sigVal.SetOtherRange (implVal.Range, true) + implVal.SetOtherRange (sigVal.Range, false) + + let mk_err denv f = ValueNotContained(denv,implModRef,implVal,sigVal,f) + let err denv f = errorR(mk_err denv f); false + let m = implVal.Range + if implVal.IsMutable <> sigVal.IsMutable then (err denv FSComp.SR.ValueNotContainedMutabilityAttributesDiffer) + elif implVal.LogicalName <> sigVal.LogicalName then (err denv FSComp.SR.ValueNotContainedMutabilityNamesDiffer) + elif implVal.CompiledName <> sigVal.CompiledName then (err denv FSComp.SR.ValueNotContainedMutabilityCompiledNamesDiffer) + elif implVal.DisplayName <> sigVal.DisplayName then (err denv FSComp.SR.ValueNotContainedMutabilityDisplayNamesDiffer) + elif isLessAccessible implVal.Accessibility sigVal.Accessibility then (err denv FSComp.SR.ValueNotContainedMutabilityAccessibilityMore) + elif implVal.MustInline <> sigVal.MustInline then (err denv FSComp.SR.ValueNotContainedMutabilityInlineFlagsDiffer) + elif implVal.LiteralValue <> sigVal.LiteralValue then (err denv FSComp.SR.ValueNotContainedMutabilityLiteralConstantValuesDiffer) + elif implVal.IsTypeFunction <> sigVal.IsTypeFunction then (err denv FSComp.SR.ValueNotContainedMutabilityOneIsTypeFunction) + else + let implTypars,atau = implVal.TypeScheme + let sigTypars,ftau = sigVal.TypeScheme + if implTypars.Length <> sigTypars.Length then (err {denv with showTyparBinding=true} FSComp.SR.ValueNotContainedMutabilityParameterCountsDiffer) else + let aenv = aenv.BindEquivTypars implTypars sigTypars + checkTypars m aenv implTypars sigTypars && + if not (typeAEquiv g aenv atau ftau) then err denv (FSComp.SR.ValueNotContainedMutabilityTypesDiffer) + elif not (checkValInfo aenv (err denv) implVal sigVal) then false + elif not (implVal.IsExtensionMember = sigVal.IsExtensionMember) then err denv (FSComp.SR.ValueNotContainedMutabilityExtensionsDiffer) + elif not (checkMemberDatasConform (err denv) (implVal.Attribs, implVal,implVal.MemberInfo) (sigVal.Attribs,sigVal,sigVal.MemberInfo)) then false + else checkAttribs aenv implVal.Attribs sigVal.Attribs (fun attribs -> implVal.Data.val_attribs <- attribs) + + + and checkExnInfo err aenv implTypeRepr sigTypeRepr = + match implTypeRepr,sigTypeRepr with + | TExnAsmRepr _, TExnFresh _ -> + (errorR (err FSComp.SR.ExceptionDefsNotCompatibleHiddenBySignature); false) + | TExnAsmRepr tcr1, TExnAsmRepr tcr2 -> + if tcr1 <> tcr2 then (errorR (err FSComp.SR.ExceptionDefsNotCompatibleDotNetRepresentationsDiffer); false) else true + | TExnAbbrevRepr _, TExnFresh _ -> + (errorR (err FSComp.SR.ExceptionDefsNotCompatibleAbbreviationHiddenBySignature); false) + | TExnAbbrevRepr ecr1, TExnAbbrevRepr ecr2 -> + if not (tcrefAEquiv g aenv ecr1 ecr2) then + (errorR (err FSComp.SR.ExceptionDefsNotCompatibleSignaturesDiffer); false) + else true + | TExnFresh r1, TExnFresh r2-> checkRecordFieldsForExn g denv err aenv r1 r2 + | TExnNone,TExnNone -> true + | _ -> + (errorR (err FSComp.SR.ExceptionDefsNotCompatibleExceptionDeclarationsDiffer); false) + + and checkUnionCase aenv implUnionCase sigUnionCase = + let err f = errorR(ConstrNotContained(denv,implUnionCase,sigUnionCase,f));false + sigUnionCase.OtherRangeOpt <- Some (implUnionCase.Range, true) + implUnionCase.OtherRangeOpt <- Some (sigUnionCase.Range, false) + if implUnionCase.Id.idText <> sigUnionCase.Id.idText then err FSComp.SR.ModuleContainsConstructorButNamesDiffer + elif implUnionCase.RecdFields.Length <> sigUnionCase.RecdFields.Length then err FSComp.SR.ModuleContainsConstructorButDataFieldsDiffer + elif not (List.forall2 (checkField aenv) implUnionCase.RecdFields sigUnionCase.RecdFields) then err FSComp.SR.ModuleContainsConstructorButTypesOfFieldsDiffer + elif isLessAccessible implUnionCase.Accessibility sigUnionCase.Accessibility then err FSComp.SR.ModuleContainsConstructorButAccessibilityDiffers + else checkAttribs aenv implUnionCase.Attribs sigUnionCase.Attribs (fun attribs -> implUnionCase.Attribs <- attribs) + + and checkField aenv implField sigField = + let err f = errorR(FieldNotContained(denv,implField,sigField,f)); false + sigField.rfield_other_range <- Some (implField.Range, true) + implField.rfield_other_range <- Some (sigField.Range, false) + if implField.rfield_id.idText <> sigField.rfield_id.idText then err FSComp.SR.FieldNotContainedNamesDiffer + elif isLessAccessible implField.Accessibility sigField.Accessibility then err FSComp.SR.FieldNotContainedAccessibilitiesDiffer + elif implField.IsStatic <> sigField.IsStatic then err FSComp.SR.FieldNotContainedStaticsDiffer + elif implField.IsMutable <> sigField.IsMutable then err FSComp.SR.FieldNotContainedMutablesDiffer + elif implField.LiteralValue <> sigField.LiteralValue then err FSComp.SR.FieldNotContainedLiteralsDiffer + elif not (typeAEquiv g aenv implField.FormalType sigField.FormalType) then err FSComp.SR.FieldNotContainedTypesDiffer + else + checkAttribs aenv implField.FieldAttribs sigField.FieldAttribs (fun attribs -> implField.rfield_fattribs <- attribs) && + checkAttribs aenv implField.PropertyAttribs sigField.PropertyAttribs (fun attribs -> implField.rfield_pattribs <- attribs) + + and checkMemberDatasConform err (_implAttrs,implVal,implMemberInfo) (_sigAttrs, sigVal,sigMemberInfo) = + match implMemberInfo,sigMemberInfo with + | None,None -> true + | Some implMembInfo, Some sigMembInfo -> + if not (implVal.CompiledName = sigVal.CompiledName) then + err(FSComp.SR.ValueNotContainedMutabilityDotNetNamesDiffer) + elif not (implMembInfo.MemberFlags.IsInstance = sigMembInfo.MemberFlags.IsInstance) then + err(FSComp.SR.ValueNotContainedMutabilityStaticsDiffer) + elif false then + err(FSComp.SR.ValueNotContainedMutabilityVirtualsDiffer) + elif not (implMembInfo.MemberFlags.IsDispatchSlot = sigMembInfo.MemberFlags.IsDispatchSlot) then + err(FSComp.SR.ValueNotContainedMutabilityAbstractsDiffer) + // The final check is an implication: + // classes have non-final CompareTo/Hash methods + // abstract have non-final CompareTo/Hash methods + // records have final CompareTo/Hash methods + // unions have final CompareTo/Hash methods + // This is an example where it is OK for the signature to say 'non-final' when the implementation says 'final' + elif not implMembInfo.MemberFlags.IsFinal && sigMembInfo.MemberFlags.IsFinal then + err(FSComp.SR.ValueNotContainedMutabilityFinalsDiffer) + elif not (implMembInfo.MemberFlags.IsOverrideOrExplicitImpl = sigMembInfo.MemberFlags.IsOverrideOrExplicitImpl) then + err(FSComp.SR.ValueNotContainedMutabilityOverridesDiffer) + elif not (implMembInfo.MemberFlags.MemberKind = sigMembInfo.MemberFlags.MemberKind) then + err(FSComp.SR.ValueNotContainedMutabilityOneIsConstructor) + else + let finstance = ValSpecIsCompiledAsInstance g sigVal + let ainstance = ValSpecIsCompiledAsInstance g implVal + if finstance && not ainstance then + err(FSComp.SR.ValueNotContainedMutabilityStaticButInstance) + elif not finstance && ainstance then + err(FSComp.SR.ValueNotContainedMutabilityInstanceButStatic) + else true + + | _ -> false + + // ------------------------------------------------------------------------------- + // WARNING!!!! + // checkRecordFields and checkRecordFieldsForExn are the EXACT SAME FUNCTION. + // The only difference is the signature for err - this is because err is a function + // that reports errors, and checkRecordFields is called with a different + // sig for err then checkRecordFieldsForExn. + // ------------------------------------------------------------------------------- + + and checkRecordFields _g _amap _denv err aenv (implFields:TyconRecdFields) (sigFields:TyconRecdFields) = + let implFields = implFields.TrueFieldsAsList + let sigFields = sigFields.TrueFieldsAsList + let m1 = implFields |> NameMap.ofKeyedList (fun rfld -> rfld.Name) + let m2 = sigFields |> NameMap.ofKeyedList (fun rfld -> rfld.Name) + NameMap.suball2 (fun s _ -> errorR(err (fun x -> FSComp.SR.DefinitionsInSigAndImplNotCompatibleFieldRequiredButNotSpecified(x, s))); false) (checkField aenv) m1 m2 && + NameMap.suball2 (fun s _ -> errorR(err (fun x -> FSComp.SR.DefinitionsInSigAndImplNotCompatibleFieldWasPresent(x, s))); false) (fun x y -> checkField aenv y x) m2 m1 && + // This check is required because constructors etc. are externally visible + // and thus compiled representations do pick up dependencies on the field order + (if List.forall2 (checkField aenv) implFields sigFields + then true + else (errorR(err (FSComp.SR.DefinitionsInSigAndImplNotCompatibleFieldOrderDiffer)); false)) + + and checkRecordFieldsForExn _g _denv err aenv (implFields:TyconRecdFields) (sigFields:TyconRecdFields) = + let implFields = implFields.TrueFieldsAsList + let sigFields = sigFields.TrueFieldsAsList + let m1 = implFields |> NameMap.ofKeyedList (fun rfld -> rfld.Name) + let m2 = sigFields |> NameMap.ofKeyedList (fun rfld -> rfld.Name) + NameMap.suball2 (fun s _ -> errorR(err (fun (x, y) -> FSComp.SR.ExceptionDefsNotCompatibleFieldInSigButNotImpl(s, x, y))); false) (checkField aenv) m1 m2 && + NameMap.suball2 (fun s _ -> errorR(err (fun (x, y) -> FSComp.SR.ExceptionDefsNotCompatibleFieldInImplButNotSig(s, x, y))); false) (fun x y -> checkField aenv y x) m2 m1 && + // This check is required because constructors etc. are externally visible + // and thus compiled representations do pick up dependencies on the field order + (if List.forall2 (checkField aenv) implFields sigFields + then true + else (errorR(err (FSComp.SR.ExceptionDefsNotCompatibleFieldOrderDiffers)); false)) + + and checkVirtualSlots _g denv err _aenv implAbstractSlots sigAbstractSlots = + let m1 = NameMap.ofKeyedList (fun (v:ValRef) -> v.DisplayName) implAbstractSlots + let m2 = NameMap.ofKeyedList (fun (v:ValRef) -> v.DisplayName) sigAbstractSlots + (m1,m2) ||> NameMap.suball2 (fun _s vref -> errorR(err (fun x -> FSComp.SR.DefinitionsInSigAndImplNotCompatibleAbstractMemberMissingInImpl(x, NicePrint.stringValOrMember denv vref.Deref))); false) (fun _x _y -> true) && + (m2,m1) ||> NameMap.suball2 (fun _s vref -> errorR(err (fun x -> FSComp.SR.DefinitionsInSigAndImplNotCompatibleAbstractMemberMissingInSig(x, NicePrint.stringValOrMember denv vref.Deref))); false) (fun _x _y -> true) + + and checkClassFields isStruct _g _amap _denv err aenv (implFields:TyconRecdFields) (sigFields:TyconRecdFields) = + let implFields = implFields.TrueFieldsAsList + let sigFields = sigFields.TrueFieldsAsList + let m1 = implFields |> NameMap.ofKeyedList (fun rfld -> rfld.Name) + let m2 = sigFields |> NameMap.ofKeyedList (fun rfld -> rfld.Name) + NameMap.suball2 (fun s _ -> errorR(err (fun x -> FSComp.SR.DefinitionsInSigAndImplNotCompatibleFieldRequiredButNotSpecified(x, s))); false) (checkField aenv) m1 m2 && + (if isStruct then + NameMap.suball2 (fun s _ -> warning(err (fun x -> FSComp.SR.DefinitionsInSigAndImplNotCompatibleFieldIsInImplButNotSig(x, s))); true) (fun x y -> checkField aenv y x) m2 m1 + else + true) + + + and checkTypeRepr err aenv implTypeRepr sigTypeRepr = + let reportNiceError k s1 s2 = + let aset = NameSet.ofList s1 + let fset = NameSet.ofList s2 + match Zset.elements (Zset.diff aset fset) with + | [] -> + match Zset.elements (Zset.diff fset aset) with + | [] -> (errorR (err (fun x -> FSComp.SR.DefinitionsInSigAndImplNotCompatibleNumbersDiffer(x, k))); false) + | l -> (errorR (err (fun x -> FSComp.SR.DefinitionsInSigAndImplNotCompatibleSignatureDefinesButImplDoesNot(x, k, String.concat ";" l))); false) + | l -> (errorR (err (fun x -> FSComp.SR.DefinitionsInSigAndImplNotCompatibleImplDefinesButSignatureDoesNot(x, k, String.concat ";" l))); false) + + match implTypeRepr,sigTypeRepr with + | (TRecdRepr _ + | TFiniteUnionRepr _ + | TILObjModelRepr _ +#if EXTENSIONTYPING + | TProvidedTypeExtensionPoint _ + | TProvidedNamespaceExtensionPoint _ +#endif + ), TNoRepr -> true + | (TFsObjModelRepr r), TNoRepr -> + match r.fsobjmodel_kind with + | TTyconStruct | TTyconEnum -> + (errorR (err FSComp.SR.DefinitionsInSigAndImplNotCompatibleImplDefinesStruct); false) + | _ -> + true + | (TAsmRepr _), TNoRepr -> + (errorR (err FSComp.SR.DefinitionsInSigAndImplNotCompatibleDotNetTypeRepresentationIsHidden); false) + | (TMeasureableRepr _), TNoRepr -> + (errorR (err FSComp.SR.DefinitionsInSigAndImplNotCompatibleTypeIsHidden); false) + | (TFiniteUnionRepr r1), (TFiniteUnionRepr r2) -> + let ucases1 = r1.UnionCasesAsList + let ucases2 = r2.UnionCasesAsList + if ucases1.Length <> ucases2.Length then + let names (l: UnionCase list) = l |> List.map (fun c -> c.Id.idText) + reportNiceError "union case" (names ucases1) (names ucases2) + else List.forall2 (checkUnionCase aenv) ucases1 ucases2 + | (TRecdRepr implFields), (TRecdRepr sigFields) -> + checkRecordFields g amap denv err aenv implFields sigFields + | (TFsObjModelRepr r1), (TFsObjModelRepr r2) -> + if not (match r1.fsobjmodel_kind,r2.fsobjmodel_kind with + | TTyconClass,TTyconClass -> true + | TTyconInterface,TTyconInterface -> true + | TTyconStruct,TTyconStruct -> true + | TTyconEnum, TTyconEnum -> true + | TTyconDelegate (TSlotSig(_,typ1,ctps1,mtps1,ps1, rty1)), + TTyconDelegate (TSlotSig(_,typ2,ctps2,mtps2,ps2, rty2)) -> + (typeAEquiv g aenv typ1 typ2) && + (ctps1.Length = ctps2.Length) && + (let aenv = aenv.BindEquivTypars ctps1 ctps2 + (typarsAEquiv g aenv ctps1 ctps2) && + (mtps1.Length = mtps2.Length) && + (let aenv = aenv.BindEquivTypars mtps1 mtps2 + (typarsAEquiv g aenv mtps1 mtps2) && + ((ps1,ps2) ||> List.lengthsEqAndForall2 (List.lengthsEqAndForall2 (fun p1 p2 -> typeAEquiv g aenv p1.Type p2.Type))) && + (returnTypesAEquiv g aenv rty1 rty2))) + | _,_ -> false) then + (errorR (err FSComp.SR.DefinitionsInSigAndImplNotCompatibleTypeIsDifferentKind); false) + else + let isStruct = (match r1.fsobjmodel_kind with TTyconStruct -> true | _ -> false) + checkClassFields isStruct g amap denv err aenv r1.fsobjmodel_rfields r2.fsobjmodel_rfields && + checkVirtualSlots g denv err aenv r1.fsobjmodel_vslots r2.fsobjmodel_vslots + | (TAsmRepr tcr1), (TAsmRepr tcr2) -> + if tcr1 <> tcr2 then (errorR (err FSComp.SR.DefinitionsInSigAndImplNotCompatibleILDiffer); false) else true + | (TMeasureableRepr ty1), (TMeasureableRepr ty2) -> + if typeAEquiv g aenv ty1 ty2 then true else (errorR (err FSComp.SR.DefinitionsInSigAndImplNotCompatibleRepresentationsDiffer); false) + | TNoRepr, TNoRepr -> true +#if EXTENSIONTYPING + | TProvidedTypeExtensionPoint info1 , TProvidedTypeExtensionPoint info2 -> + Tainted.EqTainted info1.ProvidedType.TypeProvider info2.ProvidedType.TypeProvider && ProvidedType.TaintedEquals(info1.ProvidedType,info2.ProvidedType) + | TProvidedNamespaceExtensionPoint _, TProvidedNamespaceExtensionPoint _ -> + System.Diagnostics.Debug.Assert(false, "unreachable: TProvidedNamespaceExtensionPoint only on namespaces, not types" ) + true +#endif + | TNoRepr, _ -> (errorR (err FSComp.SR.DefinitionsInSigAndImplNotCompatibleRepresentationsDiffer); false) + | _, _ -> (errorR (err FSComp.SR.DefinitionsInSigAndImplNotCompatibleRepresentationsDiffer); false) + + and checkTypeAbbrev err aenv kind1 kind2 implTypeAbbrev sigTypeAbbrev = + if kind1 <> kind2 then (errorR (err (fun x -> FSComp.SR.DefinitionsInSigAndImplNotCompatibleSignatureDeclaresDiffer(x, kind2.ToString(), kind1.ToString()))); false) + else + match implTypeAbbrev,sigTypeAbbrev with + | Some ty1, Some ty2 -> + if not (typeAEquiv g aenv ty1 ty2) then + let s1, s2, _ = NicePrint.minimalStringsOfTwoTypes denv ty1 ty2 + errorR (err (fun x -> FSComp.SR.DefinitionsInSigAndImplNotCompatibleAbbreviationsDiffer(x, s1, s2))) + false + else + true + | None,None -> true + | Some _, None -> (errorR (err (FSComp.SR.DefinitionsInSigAndImplNotCompatibleAbbreviationHiddenBySig)); false) + | None, Some _ -> (errorR (err FSComp.SR.DefinitionsInSigAndImplNotCompatibleSigHasAbbreviation); false) + + and checkModuleOrNamespaceContents m aenv (implModRef:ModuleOrNamespaceRef) (signModType:ModuleOrNamespaceType) = + let implModType = implModRef.ModuleOrNamespaceType + (if implModType.ModuleOrNamespaceKind <> signModType.ModuleOrNamespaceKind then errorR(Error(FSComp.SR.typrelModuleNamespaceAttributesDifferInSigAndImpl(),m))) + + + (implModType.TypesByMangledName , signModType.TypesByMangledName) + ||> NameMap.suball2 + (fun s _fx -> errorR(RequiredButNotSpecified(denv,implModRef,"type",(fun os -> Printf.bprintf os "%s" s),m)); false) + (checkTypeDef aenv) && + + + (implModType.ModulesAndNamespacesByDemangledName, signModType.ModulesAndNamespacesByDemangledName ) + ||> NameMap.suball2 + (fun s fx -> errorR(RequiredButNotSpecified(denv,implModRef,(if fx.IsModule then "module" else "namespace"),(fun os -> Printf.bprintf os "%s" s),m)); false) + (fun x1 x2 -> checkModuleOrNamespace aenv (mkLocalModRef x1) x2) && + + let sigValHadNoMatchingImplementation (fx:Val) (_closeActualVal: Val option) = + errorR(RequiredButNotSpecified(denv,implModRef,"value",(fun os -> + (* In the case of missing members show the full required enclosing type and signature *) + if fx.IsMember then + NicePrint.outputQualifiedValOrMember denv os fx + else + Printf.bprintf os "%s" fx.DisplayName),m)) + + let valuesPartiallyMatch (av:Val) (fv:Val) = + (av.LinkagePartialKey.MemberParentMangledName = fv.LinkagePartialKey.MemberParentMangledName) && + (av.LinkagePartialKey.LogicalName = fv.LinkagePartialKey.LogicalName) && + (av.LinkagePartialKey.TotalArgCount = fv.LinkagePartialKey.TotalArgCount) + + (implModType.AllValsAndMembersByLogicalNameUncached, signModType.AllValsAndMembersByLogicalNameUncached) + ||> NameMap.suball2 + (fun _s (fxs:Val list) -> sigValHadNoMatchingImplementation fxs.Head None; false) + (fun avs fvs -> + match avs,fvs with + | [],_ | _,[] -> failwith "unreachable" + | [av],[fv] -> + if valuesPartiallyMatch av fv then + checkVal implModRef aenv av fv + else + sigValHadNoMatchingImplementation fv None + false + | _ -> + // for each formal requirement, try to find a precisely matching actual requirement + let matchingPairs = + fvs |> List.choose (fun fv -> + match avs |> List.tryFind (fun av -> + let res = valLinkageAEquiv g aenv av fv + //if res then printfn "%s" (bufs (fun buf -> Printf.bprintf buf "YES MATCH: fv '%a', av '%a'" (NicePrint.outputQualifiedValOrMember denv) fv (NicePrint.outputQualifiedValOrMember denv) av)) + //else printfn "%s" (bufs (fun buf -> Printf.bprintf buf "NO MATCH: fv '%a', av '%a'" (NicePrint.outputQualifiedValOrMember denv) fv (NicePrint.outputQualifiedValOrMember denv) av)) + res) with + | None -> None + | Some av -> Some(fv,av)) + + // Check the ones with matching linkage + let allPairsOk = matchingPairs |> List.map (fun (fv,av) -> checkVal implModRef aenv av fv) |> List.forall id + let someNotOk = matchingPairs.Length < fvs.Length + // Report an error for those that don't. Try pairing up by enclosing-type/name + if someNotOk then + let noMatches,partialMatchingPairs = + fvs |> List.splitChoose (fun fv -> + match avs |> List.tryFind (fun av -> valuesPartiallyMatch av fv) with + | None -> Choice1Of2 fv + | Some av -> Choice2Of2(fv,av)) + for (fv,av) in partialMatchingPairs do + checkVal implModRef aenv av fv |> ignore + for fv in noMatches do + sigValHadNoMatchingImplementation fv None + allPairsOk && not someNotOk) + + + and checkModuleOrNamespace aenv implModRef sigModRef = + // Propagate defn location information from implementation to signature . + sigModRef.SetOtherRange (implModRef.Range, true) + implModRef.Deref.SetOtherRange (sigModRef.Range, false) + checkModuleOrNamespaceContents implModRef.Range aenv implModRef sigModRef.ModuleOrNamespaceType && + checkAttribs aenv implModRef.Attribs sigModRef.Attribs implModRef.Deref.SetAttribs + + member __.CheckSignature aenv (implModRef:ModuleOrNamespaceRef) (signModType:ModuleOrNamespaceType) = + checkModuleOrNamespaceContents implModRef.Range aenv implModRef signModType + + member __.CheckTypars m aenv (implTypars: Typars) (signTypars: Typars) = + checkTypars m aenv implTypars signTypars + + +/// Check the names add up between a signature and its implementation. We check this first. +let rec CheckNamesOfModuleOrNamespaceContents denv (implModRef:ModuleOrNamespaceRef) (signModType:ModuleOrNamespaceType) = + let m = implModRef.Range + let implModType = implModRef.ModuleOrNamespaceType + NameMap.suball2 + (fun s _fx -> errorR(RequiredButNotSpecified(denv,implModRef,"type",(fun os -> Printf.bprintf os "%s" s),m)); false) + (fun _ _ -> true) + implModType.TypesByMangledName + signModType.TypesByMangledName && + + (implModType.ModulesAndNamespacesByDemangledName, signModType.ModulesAndNamespacesByDemangledName ) + ||> NameMap.suball2 + (fun s fx -> errorR(RequiredButNotSpecified(denv,implModRef,(if fx.IsModule then "module" else "namespace"),(fun os -> Printf.bprintf os "%s" s),m)); false) + (fun x1 (x2:ModuleOrNamespace) -> CheckNamesOfModuleOrNamespace denv (mkLocalModRef x1) x2.ModuleOrNamespaceType) && + + (implModType.AllValsAndMembersByLogicalNameUncached , signModType.AllValsAndMembersByLogicalNameUncached) + ||> NameMap.suball2 + (fun _s (fxs:Val list) -> + let fx = fxs.Head + errorR(RequiredButNotSpecified(denv,implModRef,"value",(fun os -> + // In the case of missing members show the full required enclosing type and signature + if isSome fx.MemberInfo then + NicePrint.outputQualifiedValOrMember denv os fx + else + Printf.bprintf os "%s" fx.DisplayName),m)); false) + (fun _ _ -> true) + + +and CheckNamesOfModuleOrNamespace denv (implModRef:ModuleOrNamespaceRef) signModType = + CheckNamesOfModuleOrNamespaceContents denv implModRef signModType + diff --git a/src/fsharp/TypeChecker.fs b/src/fsharp/TypeChecker.fs index b20e3b909d6..2276413f89a 100755 --- a/src/fsharp/TypeChecker.fs +++ b/src/fsharp/TypeChecker.fs @@ -6,8 +6,12 @@ module internal Microsoft.FSharp.Compiler.TypeChecker #nowarn "44" // This construct is deprecated. please use List.item +open System +open System.Collections.Generic + open Internal.Utilities open Internal.Utilities.Collections + open Microsoft.FSharp.Compiler.AbstractIL open Microsoft.FSharp.Compiler.AbstractIL.IL open Microsoft.FSharp.Compiler.AbstractIL.Internal @@ -25,18 +29,18 @@ open Microsoft.FSharp.Compiler.Tastops open Microsoft.FSharp.Compiler.Tastops.DebugPrint open Microsoft.FSharp.Compiler.PatternMatchCompilation open Microsoft.FSharp.Compiler.TcGlobals -open Microsoft.FSharp.Compiler.AbstractIL.IL open Microsoft.FSharp.Compiler.Lib open Microsoft.FSharp.Compiler.Layout open Microsoft.FSharp.Compiler.Infos -open Microsoft.FSharp.Compiler.Infos.AccessibilityLogic -open Microsoft.FSharp.Compiler.Infos.AttributeChecking +open Microsoft.FSharp.Compiler.AccessibilityLogic +open Microsoft.FSharp.Compiler.AttributeChecking open Microsoft.FSharp.Compiler.TypeRelations +open Microsoft.FSharp.Compiler.MethodCalls +open Microsoft.FSharp.Compiler.MethodOverrides open Microsoft.FSharp.Compiler.ConstraintSolver open Microsoft.FSharp.Compiler.NameResolution open Microsoft.FSharp.Compiler.PrettyNaming -open System -open System.Collections.Generic +open Microsoft.FSharp.Compiler.InfoReader #if EXTENSIONTYPING open Microsoft.FSharp.Compiler.ExtensionTyping diff --git a/src/fsharp/TypeChecker.fsi b/src/fsharp/TypeChecker.fsi index db581d85dfe..51a346c35e9 100644 --- a/src/fsharp/TypeChecker.fsi +++ b/src/fsharp/TypeChecker.fsi @@ -8,8 +8,9 @@ open Microsoft.FSharp.Compiler.AbstractIL open Microsoft.FSharp.Compiler.AbstractIL.IL open Microsoft.FSharp.Compiler.AbstractIL.Internal open Microsoft.FSharp.Compiler.AbstractIL.Internal.Library -open Microsoft.FSharp.Compiler.Range +open Microsoft.FSharp.Compiler.AccessibilityLogic open Microsoft.FSharp.Compiler.Ast +open Microsoft.FSharp.Compiler.Range open Microsoft.FSharp.Compiler.ErrorLogger open Microsoft.FSharp.Compiler.Tast open Microsoft.FSharp.Compiler.Tastops diff --git a/src/fsharp/TypeRelations.fs b/src/fsharp/TypeRelations.fs old mode 100755 new mode 100644 index 8875cc13c78..b0bb80e9824 --- a/src/fsharp/TypeRelations.fs +++ b/src/fsharp/TypeRelations.fs @@ -24,13 +24,9 @@ open Microsoft.FSharp.Compiler.AbstractIL.IL open Microsoft.FSharp.Compiler.Lib open Microsoft.FSharp.Compiler.Infos open Microsoft.FSharp.Compiler.PrettyNaming -open Microsoft.FSharp.Compiler.Infos.AccessibilityLogic +open Microsoft.FSharp.Compiler.AccessibilityLogic open Microsoft.FSharp.Compiler.NameResolution -#if EXTENSIONTYPING -open Microsoft.FSharp.Compiler.ExtensionTyping -#endif - //------------------------------------------------------------------------- // a :> b without coercion based on finalized (no type variable) types //------------------------------------------------------------------------- @@ -291,1726 +287,6 @@ let IteratedAdjustArityOfLambda g amap topValInfo e = tps,ctorThisValOpt,baseValOpt,vsl,body,bodyty -exception RequiredButNotSpecified of DisplayEnv * Tast.ModuleOrNamespaceRef * string * (StringBuilder -> unit) * range -exception ValueNotContained of DisplayEnv * Tast.ModuleOrNamespaceRef * Val * Val * (string * string * string -> string) -exception ConstrNotContained of DisplayEnv * UnionCase * UnionCase * (string * string -> string) -exception ExnconstrNotContained of DisplayEnv * Tycon * Tycon * (string * string -> string) -exception FieldNotContained of DisplayEnv * RecdField * RecdField * (string * string -> string) -exception InterfaceNotRevealed of DisplayEnv * TType * range - - -/// Containment relation for module types -module SignatureConformance = begin - - // Use a type to capture the constant, common parameters - type Checker(g, amap, denv, remapInfo: SignatureRepackageInfo, checkingSig) = - - // Build a remap that maps tcrefs in the signature to tcrefs in the implementation - // Used when checking attributes. - let sigToImplRemap = - let remap = Remap.Empty - let remap = (remapInfo.mrpiEntities,remap) ||> List.foldBack (fun (implTcref ,signTcref) acc -> addTyconRefRemap signTcref implTcref acc) - let remap = (remapInfo.mrpiVals ,remap) ||> List.foldBack (fun (implValRef,signValRef) acc -> addValRemap signValRef.Deref implValRef.Deref acc) - remap - - // For all attributable elements (types, modules, exceptions, record fields, unions, parameters, generic type parameters) - // - // (a) Start with lists AImpl and ASig containing the attributes in the implementation and signature, in declaration order - // (b) Each attribute in AImpl is checked against the available attributes in ASig. - // a. If an attribute is found in ASig which is an exact match (after evaluating attribute arguments), then the attribute in the implementation is ignored, the attribute is removed from ASig, and checking continues - // b. If an attribute is found in ASig that has the same attribute type, then a warning is given and the attribute in the implementation is ignored - // c. Otherwise, the attribute in the implementation is kept - // (c) The attributes appearing in the compiled element are the compiled forms of the attributes from the signature and the kept attributes from the implementation - let checkAttribs _aenv (implAttribs:Attribs) (sigAttribs:Attribs) fixup = - - // Remap the signature attributes to make them look as if they were declared in - // the implementation. This allows us to compare them and propagate them to the implementation - // if needed. - let sigAttribs = sigAttribs |> List.map (remapAttrib g sigToImplRemap) - - // Helper to check for equality of evaluated attribute expressions - let attribExprEq (AttribExpr(_,e1)) (AttribExpr(_,e2)) = EvaledAttribExprEquality g e1 e2 - - // Helper to check for equality of evaluated named attribute arguments - let attribNamedArgEq (AttribNamedArg(nm1,ty1,isProp1,e1)) (AttribNamedArg(nm2,ty2,isProp2,e2)) = - (nm1 = nm2) && - typeEquiv g ty1 ty2 && - (isProp1 = isProp2) && - attribExprEq e1 e2 - - let attribsEq attrib1 attrib2 = - let (Attrib(implTcref,_,implArgs,implNamedArgs,_,_,_implRange)) = attrib1 - let (Attrib(signTcref,_,signArgs,signNamedArgs,_,_,_signRange)) = attrib2 - tyconRefEq g signTcref implTcref && - (implArgs,signArgs) ||> List.lengthsEqAndForall2 attribExprEq && - (implNamedArgs, signNamedArgs) ||> List.lengthsEqAndForall2 attribNamedArgEq - - let attribsHaveSameTycon attrib1 attrib2 = - let (Attrib(implTcref,_,_,_,_,_,_)) = attrib1 - let (Attrib(signTcref,_,_,_,_,_,_)) = attrib2 - tyconRefEq g signTcref implTcref - - // For each implementation attribute, only keep if it is not mentioned in the signature. - // Emit a warning if it is mentioned in the signature and the arguments to the attributes are - // not identical. - let rec check keptImplAttribsRev implAttribs sigAttribs = - match implAttribs with - | [] -> keptImplAttribsRev |> List.rev - | implAttrib :: remainingImplAttribs -> - - // Look for an attribute in the signature that matches precisely. If so, remove it - let lookForMatchingAttrib = sigAttribs |> List.tryRemove (attribsEq implAttrib) - match lookForMatchingAttrib with - | Some (_, remainingSigAttribs) -> check keptImplAttribsRev remainingImplAttribs remainingSigAttribs - | None -> - - // Look for an attribute in the signature that has the same type. If so, give a warning - let existsSimilarAttrib = sigAttribs |> List.exists (attribsHaveSameTycon implAttrib) - - if existsSimilarAttrib then - let (Attrib(implTcref,_,_,_,_,_,implRange)) = implAttrib - warning(Error(FSComp.SR.tcAttribArgsDiffer(implTcref.DisplayName), implRange)) - check keptImplAttribsRev remainingImplAttribs sigAttribs - else - check (implAttrib :: keptImplAttribsRev) remainingImplAttribs sigAttribs - - let keptImplAttribs = check [] implAttribs sigAttribs - - fixup (sigAttribs @ keptImplAttribs) - true - - let rec checkTypars m (aenv: TypeEquivEnv) (implTypars:Typars) (sigTypars:Typars) = - if implTypars.Length <> sigTypars.Length then - errorR (Error(FSComp.SR.typrelSigImplNotCompatibleParamCountsDiffer(),m)) - false - else - let aenv = aenv.BindEquivTypars implTypars sigTypars - (implTypars,sigTypars) ||> List.forall2 (fun implTypar sigTypar -> - let m = sigTypar.Range - if implTypar.StaticReq <> sigTypar.StaticReq then - errorR (Error(FSComp.SR.typrelSigImplNotCompatibleCompileTimeRequirementsDiffer(), m)) - - // Adjust the actual type parameter name to look like the signature - implTypar.SetIdent (mkSynId implTypar.Range sigTypar.Id.idText) - - // Mark it as "not compiler generated", now that we've got a good name for it - implTypar.SetCompilerGenerated false - - // Check the constraints in the implementation are present in the signature - implTypar.Constraints |> List.forall (fun implTyparCx -> - match implTyparCx with - // defaults can be dropped in the signature - | TyparConstraint.DefaultsTo(_,_acty,_) -> true - | _ -> - if not (List.exists (typarConstraintsAEquiv g aenv implTyparCx) sigTypar.Constraints) - then (errorR(Error(FSComp.SR.typrelSigImplNotCompatibleConstraintsDiffer(sigTypar.Name, Layout.showL(NicePrint.layoutTyparConstraint denv (implTypar,implTyparCx))),m)); false) - else true) && - - // Check the constraints in the signature are present in the implementation - sigTypar.Constraints |> List.forall (fun sigTyparCx -> - match sigTyparCx with - // defaults can be present in the signature and not in the implementation because they are erased - | TyparConstraint.DefaultsTo(_,_acty,_) -> true - // 'comparison' and 'equality' constraints can be present in the signature and not in the implementation because they are erased - | TyparConstraint.SupportsComparison _ -> true - | TyparConstraint.SupportsEquality _ -> true - | _ -> - if not (List.exists (fun implTyparCx -> typarConstraintsAEquiv g aenv implTyparCx sigTyparCx) implTypar.Constraints) then - (errorR(Error(FSComp.SR.typrelSigImplNotCompatibleConstraintsDifferRemove(sigTypar.Name, Layout.showL(NicePrint.layoutTyparConstraint denv (sigTypar,sigTyparCx))),m)); false) - else - true) && - (not checkingSig || checkAttribs aenv implTypar.Attribs sigTypar.Attribs (fun attribs -> implTypar.Data.typar_attribs <- attribs))) - - and checkTypeDef (aenv: TypeEquivEnv) (implTycon:Tycon) (sigTycon:Tycon) = - let m = implTycon.Range - // Propagate defn location information from implementation to signature . - sigTycon.SetOtherRange (implTycon.Range, true) - implTycon.SetOtherRange (sigTycon.Range, false) - let err f = Error(f(implTycon.TypeOrMeasureKind.ToString()), m) - if implTycon.LogicalName <> sigTycon.LogicalName then (errorR (err (FSComp.SR.DefinitionsInSigAndImplNotCompatibleNamesDiffer)); false) else - if implTycon.CompiledName <> sigTycon.CompiledName then (errorR (err (FSComp.SR.DefinitionsInSigAndImplNotCompatibleNamesDiffer)); false) else - checkExnInfo (fun f -> ExnconstrNotContained(denv,implTycon,sigTycon,f)) aenv implTycon.ExceptionInfo sigTycon.ExceptionInfo && - let implTypars = implTycon.Typars m - let sigTypars = sigTycon.Typars m - if implTypars.Length <> sigTypars.Length then - errorR (err(FSComp.SR.DefinitionsInSigAndImplNotCompatibleParameterCountsDiffer)) - false - elif isLessAccessible implTycon.Accessibility sigTycon.Accessibility then - errorR(err(FSComp.SR.DefinitionsInSigAndImplNotCompatibleAccessibilityDiffer)) - false - else - let aenv = aenv.BindEquivTypars implTypars sigTypars - - let aintfs = implTycon.ImmediateInterfaceTypesOfFSharpTycon - let fintfs = sigTycon.ImmediateInterfaceTypesOfFSharpTycon - let aintfsUser = implTycon.TypeContents.tcaug_interfaces |> List.filter (fun (_,compgen,_) -> not compgen) |> List.map p13 - let flatten tys = - tys - |> List.collect (AllSuperTypesOfType g amap m AllowMultiIntfInstantiations.Yes) - |> ListSet.setify (typeEquiv g) - |> List.filter (isInterfaceTy g) - let aintfs = flatten aintfs - let aintfsUser = flatten aintfsUser - let fintfs = flatten fintfs - - let unimpl = ListSet.subtract (fun fity aity -> typeAEquiv g aenv aity fity) fintfs aintfs - (unimpl |> List.forall (fun ity -> errorR (err (fun x -> FSComp.SR.DefinitionsInSigAndImplNotCompatibleMissingInterface(x, NicePrint.minimalStringOfType denv ity))); false)) && - let hidden = ListSet.subtract (typeAEquiv g aenv) aintfsUser fintfs - hidden |> List.iter (fun ity -> (if implTycon.IsFSharpInterfaceTycon then error else warning) (InterfaceNotRevealed(denv,ity,implTycon.Range))) - - let aNull = IsUnionTypeWithNullAsTrueValue g implTycon - let fNull = IsUnionTypeWithNullAsTrueValue g sigTycon - if aNull && not fNull then - errorR(err(FSComp.SR.DefinitionsInSigAndImplNotCompatibleImplementationSaysNull)) - elif fNull && not aNull then - errorR(err(FSComp.SR.DefinitionsInSigAndImplNotCompatibleSignatureSaysNull)) - - let aNull2 = TypeNullIsExtraValue g m (generalizedTyconRef (mkLocalTyconRef implTycon)) - let fNull2 = TypeNullIsExtraValue g m (generalizedTyconRef (mkLocalTyconRef implTycon)) - if aNull2 && not fNull2 then - errorR(err(FSComp.SR.DefinitionsInSigAndImplNotCompatibleImplementationSaysNull2)) - elif fNull2 && not aNull2 then - errorR(err(FSComp.SR.DefinitionsInSigAndImplNotCompatibleSignatureSaysNull2)) - - let aSealed = isSealedTy g (generalizedTyconRef (mkLocalTyconRef implTycon)) - let fSealed = isSealedTy g (generalizedTyconRef (mkLocalTyconRef sigTycon)) - if aSealed && not fSealed then - errorR(err(FSComp.SR.DefinitionsInSigAndImplNotCompatibleImplementationSealed)) - if not aSealed && fSealed then - errorR(err(FSComp.SR.DefinitionsInSigAndImplNotCompatibleImplementationIsNotSealed)) - - let aPartial = isAbstractTycon implTycon - let fPartial = isAbstractTycon sigTycon - if aPartial && not fPartial then - errorR(err(FSComp.SR.DefinitionsInSigAndImplNotCompatibleImplementationIsAbstract)) - - if not aPartial && fPartial then - errorR(err(FSComp.SR.DefinitionsInSigAndImplNotCompatibleSignatureIsAbstract)) - - if not (typeAEquiv g aenv (superOfTycon g implTycon) (superOfTycon g sigTycon)) then - errorR (err(FSComp.SR.DefinitionsInSigAndImplNotCompatibleTypesHaveDifferentBaseTypes)) - - checkTypars m aenv implTypars sigTypars && - checkTypeRepr err aenv implTycon.TypeReprInfo sigTycon.TypeReprInfo && - checkTypeAbbrev err aenv implTycon.TypeOrMeasureKind sigTycon.TypeOrMeasureKind implTycon.TypeAbbrev sigTycon.TypeAbbrev && - checkAttribs aenv implTycon.Attribs sigTycon.Attribs (fun attribs -> implTycon.Data.entity_attribs <- attribs) && - checkModuleOrNamespaceContents implTycon.Range aenv (mkLocalEntityRef implTycon) sigTycon.ModuleOrNamespaceType - - and checkValInfo aenv err (implVal : Val) (sigVal : Val) = - let id = implVal.Id - match implVal.ValReprInfo, sigVal.ValReprInfo with - | _,None -> true - | None, Some _ -> err(FSComp.SR.ValueNotContainedMutabilityArityNotInferred) - | Some (ValReprInfo (implTyparNames,implArgInfos,implRetInfo) as implValInfo), Some (ValReprInfo (sigTyparNames,sigArgInfos,sigRetInfo) as sigValInfo) -> - let ntps = implTyparNames.Length - let mtps = sigTyparNames.Length - if ntps <> mtps then - err(fun(x, y, z) -> FSComp.SR.ValueNotContainedMutabilityGenericParametersDiffer(x, y, z, string mtps, string ntps)) - elif implValInfo.KindsOfTypars <> sigValInfo.KindsOfTypars then - err(FSComp.SR.ValueNotContainedMutabilityGenericParametersAreDifferentKinds) - elif not (sigArgInfos.Length <= implArgInfos.Length && List.forall2 (fun x y -> List.length x <= List.length y) sigArgInfos (fst (List.chop sigArgInfos.Length implArgInfos))) then - err(fun(x, y, z) -> FSComp.SR.ValueNotContainedMutabilityAritiesDiffer(x, y, z, id.idText, string sigArgInfos.Length, id.idText, id.idText)) - else - let implArgInfos = implArgInfos |> List.take sigArgInfos.Length - let implArgInfos = (implArgInfos, sigArgInfos) ||> List.map2 (fun l1 l2 -> l1 |> List.take l2.Length) - // Propagate some information signature to implementation. - - // Check the attributes on each argument, and update the ValReprInfo for - // the value to reflect the information in the signature. - // This ensures that the compiled form of the value matches the signature rather than - // the implementation. This also propagates argument names from signature to implementation - let res = - (implArgInfos,sigArgInfos) ||> List.forall2 (List.forall2 (fun implArgInfo sigArgInfo -> - checkAttribs aenv implArgInfo.Attribs sigArgInfo.Attribs (fun attribs -> - implArgInfo.Name <- sigArgInfo.Name - implArgInfo.Attribs <- attribs))) && - - checkAttribs aenv implRetInfo.Attribs sigRetInfo.Attribs (fun attribs -> - implRetInfo.Name <- sigRetInfo.Name - implRetInfo.Attribs <- attribs) - - implVal.SetValReprInfo (Some (ValReprInfo (sigTyparNames,implArgInfos,implRetInfo))) - res - - and checkVal implModRef (aenv:TypeEquivEnv) (implVal:Val) (sigVal:Val) = - - // Propagate defn location information from implementation to signature . - sigVal.SetOtherRange (implVal.Range, true) - implVal.SetOtherRange (sigVal.Range, false) - - let mk_err denv f = ValueNotContained(denv,implModRef,implVal,sigVal,f) - let err denv f = errorR(mk_err denv f); false - let m = implVal.Range - if implVal.IsMutable <> sigVal.IsMutable then (err denv FSComp.SR.ValueNotContainedMutabilityAttributesDiffer) - elif implVal.LogicalName <> sigVal.LogicalName then (err denv FSComp.SR.ValueNotContainedMutabilityNamesDiffer) - elif implVal.CompiledName <> sigVal.CompiledName then (err denv FSComp.SR.ValueNotContainedMutabilityCompiledNamesDiffer) - elif implVal.DisplayName <> sigVal.DisplayName then (err denv FSComp.SR.ValueNotContainedMutabilityDisplayNamesDiffer) - elif isLessAccessible implVal.Accessibility sigVal.Accessibility then (err denv FSComp.SR.ValueNotContainedMutabilityAccessibilityMore) - elif implVal.MustInline <> sigVal.MustInline then (err denv FSComp.SR.ValueNotContainedMutabilityInlineFlagsDiffer) - elif implVal.LiteralValue <> sigVal.LiteralValue then (err denv FSComp.SR.ValueNotContainedMutabilityLiteralConstantValuesDiffer) - elif implVal.IsTypeFunction <> sigVal.IsTypeFunction then (err denv FSComp.SR.ValueNotContainedMutabilityOneIsTypeFunction) - else - let implTypars,atau = implVal.TypeScheme - let sigTypars,ftau = sigVal.TypeScheme - if implTypars.Length <> sigTypars.Length then (err {denv with showTyparBinding=true} FSComp.SR.ValueNotContainedMutabilityParameterCountsDiffer) else - let aenv = aenv.BindEquivTypars implTypars sigTypars - checkTypars m aenv implTypars sigTypars && - if not (typeAEquiv g aenv atau ftau) then err denv (FSComp.SR.ValueNotContainedMutabilityTypesDiffer) - elif not (checkValInfo aenv (err denv) implVal sigVal) then false - elif not (implVal.IsExtensionMember = sigVal.IsExtensionMember) then err denv (FSComp.SR.ValueNotContainedMutabilityExtensionsDiffer) - elif not (checkMemberDatasConform (err denv) (implVal.Attribs, implVal,implVal.MemberInfo) (sigVal.Attribs,sigVal,sigVal.MemberInfo)) then false - else checkAttribs aenv implVal.Attribs sigVal.Attribs (fun attribs -> implVal.Data.val_attribs <- attribs) - - - and checkExnInfo err aenv implTypeRepr sigTypeRepr = - match implTypeRepr,sigTypeRepr with - | TExnAsmRepr _, TExnFresh _ -> - (errorR (err FSComp.SR.ExceptionDefsNotCompatibleHiddenBySignature); false) - | TExnAsmRepr tcr1, TExnAsmRepr tcr2 -> - if tcr1 <> tcr2 then (errorR (err FSComp.SR.ExceptionDefsNotCompatibleDotNetRepresentationsDiffer); false) else true - | TExnAbbrevRepr _, TExnFresh _ -> - (errorR (err FSComp.SR.ExceptionDefsNotCompatibleAbbreviationHiddenBySignature); false) - | TExnAbbrevRepr ecr1, TExnAbbrevRepr ecr2 -> - if not (tcrefAEquiv g aenv ecr1 ecr2) then - (errorR (err FSComp.SR.ExceptionDefsNotCompatibleSignaturesDiffer); false) - else true - | TExnFresh r1, TExnFresh r2-> checkRecordFieldsForExn g denv err aenv r1 r2 - | TExnNone,TExnNone -> true - | _ -> - (errorR (err FSComp.SR.ExceptionDefsNotCompatibleExceptionDeclarationsDiffer); false) - - and checkUnionCase aenv implUnionCase sigUnionCase = - let err f = errorR(ConstrNotContained(denv,implUnionCase,sigUnionCase,f));false - sigUnionCase.OtherRangeOpt <- Some (implUnionCase.Range, true) - implUnionCase.OtherRangeOpt <- Some (sigUnionCase.Range, false) - if implUnionCase.Id.idText <> sigUnionCase.Id.idText then err FSComp.SR.ModuleContainsConstructorButNamesDiffer - elif implUnionCase.RecdFields.Length <> sigUnionCase.RecdFields.Length then err FSComp.SR.ModuleContainsConstructorButDataFieldsDiffer - elif not (List.forall2 (checkField aenv) implUnionCase.RecdFields sigUnionCase.RecdFields) then err FSComp.SR.ModuleContainsConstructorButTypesOfFieldsDiffer - elif isLessAccessible implUnionCase.Accessibility sigUnionCase.Accessibility then err FSComp.SR.ModuleContainsConstructorButAccessibilityDiffers - else checkAttribs aenv implUnionCase.Attribs sigUnionCase.Attribs (fun attribs -> implUnionCase.Attribs <- attribs) - - and checkField aenv implField sigField = - let err f = errorR(FieldNotContained(denv,implField,sigField,f)); false - sigField.rfield_other_range <- Some (implField.Range, true) - implField.rfield_other_range <- Some (sigField.Range, false) - if implField.rfield_id.idText <> sigField.rfield_id.idText then err FSComp.SR.FieldNotContainedNamesDiffer - elif isLessAccessible implField.Accessibility sigField.Accessibility then err FSComp.SR.FieldNotContainedAccessibilitiesDiffer - elif implField.IsStatic <> sigField.IsStatic then err FSComp.SR.FieldNotContainedStaticsDiffer - elif implField.IsMutable <> sigField.IsMutable then err FSComp.SR.FieldNotContainedMutablesDiffer - elif implField.LiteralValue <> sigField.LiteralValue then err FSComp.SR.FieldNotContainedLiteralsDiffer - elif not (typeAEquiv g aenv implField.FormalType sigField.FormalType) then err FSComp.SR.FieldNotContainedTypesDiffer - else - checkAttribs aenv implField.FieldAttribs sigField.FieldAttribs (fun attribs -> implField.rfield_fattribs <- attribs) && - checkAttribs aenv implField.PropertyAttribs sigField.PropertyAttribs (fun attribs -> implField.rfield_pattribs <- attribs) - - and checkMemberDatasConform err (_implAttrs,implVal,implMemberInfo) (_sigAttrs, sigVal,sigMemberInfo) = - match implMemberInfo,sigMemberInfo with - | None,None -> true - | Some implMembInfo, Some sigMembInfo -> - if not (implVal.CompiledName = sigVal.CompiledName) then - err(FSComp.SR.ValueNotContainedMutabilityDotNetNamesDiffer) - elif not (implMembInfo.MemberFlags.IsInstance = sigMembInfo.MemberFlags.IsInstance) then - err(FSComp.SR.ValueNotContainedMutabilityStaticsDiffer) - elif false then - err(FSComp.SR.ValueNotContainedMutabilityVirtualsDiffer) - elif not (implMembInfo.MemberFlags.IsDispatchSlot = sigMembInfo.MemberFlags.IsDispatchSlot) then - err(FSComp.SR.ValueNotContainedMutabilityAbstractsDiffer) - // The final check is an implication: - // classes have non-final CompareTo/Hash methods - // abstract have non-final CompareTo/Hash methods - // records have final CompareTo/Hash methods - // unions have final CompareTo/Hash methods - // This is an example where it is OK for the signature to say 'non-final' when the implementation says 'final' - elif not implMembInfo.MemberFlags.IsFinal && sigMembInfo.MemberFlags.IsFinal then - err(FSComp.SR.ValueNotContainedMutabilityFinalsDiffer) - elif not (implMembInfo.MemberFlags.IsOverrideOrExplicitImpl = sigMembInfo.MemberFlags.IsOverrideOrExplicitImpl) then - err(FSComp.SR.ValueNotContainedMutabilityOverridesDiffer) - elif not (implMembInfo.MemberFlags.MemberKind = sigMembInfo.MemberFlags.MemberKind) then - err(FSComp.SR.ValueNotContainedMutabilityOneIsConstructor) - else - let finstance = ValSpecIsCompiledAsInstance g sigVal - let ainstance = ValSpecIsCompiledAsInstance g implVal - if finstance && not ainstance then - err(FSComp.SR.ValueNotContainedMutabilityStaticButInstance) - elif not finstance && ainstance then - err(FSComp.SR.ValueNotContainedMutabilityInstanceButStatic) - else true - - | _ -> false - - // ------------------------------------------------------------------------------- - // WARNING!!!! - // checkRecordFields and checkRecordFieldsForExn are the EXACT SAME FUNCTION. - // The only difference is the signature for err - this is because err is a function - // that reports errors, and checkRecordFields is called with a different - // sig for err then checkRecordFieldsForExn. - // ------------------------------------------------------------------------------- - - and checkRecordFields _g _amap _denv err aenv (implFields:TyconRecdFields) (sigFields:TyconRecdFields) = - let implFields = implFields.TrueFieldsAsList - let sigFields = sigFields.TrueFieldsAsList - let m1 = implFields |> NameMap.ofKeyedList (fun rfld -> rfld.Name) - let m2 = sigFields |> NameMap.ofKeyedList (fun rfld -> rfld.Name) - NameMap.suball2 (fun s _ -> errorR(err (fun x -> FSComp.SR.DefinitionsInSigAndImplNotCompatibleFieldRequiredButNotSpecified(x, s))); false) (checkField aenv) m1 m2 && - NameMap.suball2 (fun s _ -> errorR(err (fun x -> FSComp.SR.DefinitionsInSigAndImplNotCompatibleFieldWasPresent(x, s))); false) (fun x y -> checkField aenv y x) m2 m1 && - // This check is required because constructors etc. are externally visible - // and thus compiled representations do pick up dependencies on the field order - (if List.forall2 (checkField aenv) implFields sigFields - then true - else (errorR(err (FSComp.SR.DefinitionsInSigAndImplNotCompatibleFieldOrderDiffer)); false)) - - and checkRecordFieldsForExn _g _denv err aenv (implFields:TyconRecdFields) (sigFields:TyconRecdFields) = - let implFields = implFields.TrueFieldsAsList - let sigFields = sigFields.TrueFieldsAsList - let m1 = implFields |> NameMap.ofKeyedList (fun rfld -> rfld.Name) - let m2 = sigFields |> NameMap.ofKeyedList (fun rfld -> rfld.Name) - NameMap.suball2 (fun s _ -> errorR(err (fun (x, y) -> FSComp.SR.ExceptionDefsNotCompatibleFieldInSigButNotImpl(s, x, y))); false) (checkField aenv) m1 m2 && - NameMap.suball2 (fun s _ -> errorR(err (fun (x, y) -> FSComp.SR.ExceptionDefsNotCompatibleFieldInImplButNotSig(s, x, y))); false) (fun x y -> checkField aenv y x) m2 m1 && - // This check is required because constructors etc. are externally visible - // and thus compiled representations do pick up dependencies on the field order - (if List.forall2 (checkField aenv) implFields sigFields - then true - else (errorR(err (FSComp.SR.ExceptionDefsNotCompatibleFieldOrderDiffers)); false)) - - and checkVirtualSlots _g denv err _aenv implAbstractSlots sigAbstractSlots = - let m1 = NameMap.ofKeyedList (fun (v:ValRef) -> v.DisplayName) implAbstractSlots - let m2 = NameMap.ofKeyedList (fun (v:ValRef) -> v.DisplayName) sigAbstractSlots - (m1,m2) ||> NameMap.suball2 (fun _s vref -> errorR(err (fun x -> FSComp.SR.DefinitionsInSigAndImplNotCompatibleAbstractMemberMissingInImpl(x, NicePrint.stringValOrMember denv vref.Deref))); false) (fun _x _y -> true) && - (m2,m1) ||> NameMap.suball2 (fun _s vref -> errorR(err (fun x -> FSComp.SR.DefinitionsInSigAndImplNotCompatibleAbstractMemberMissingInSig(x, NicePrint.stringValOrMember denv vref.Deref))); false) (fun _x _y -> true) - - and checkClassFields isStruct _g _amap _denv err aenv (implFields:TyconRecdFields) (sigFields:TyconRecdFields) = - let implFields = implFields.TrueFieldsAsList - let sigFields = sigFields.TrueFieldsAsList - let m1 = implFields |> NameMap.ofKeyedList (fun rfld -> rfld.Name) - let m2 = sigFields |> NameMap.ofKeyedList (fun rfld -> rfld.Name) - NameMap.suball2 (fun s _ -> errorR(err (fun x -> FSComp.SR.DefinitionsInSigAndImplNotCompatibleFieldRequiredButNotSpecified(x, s))); false) (checkField aenv) m1 m2 && - (if isStruct then - NameMap.suball2 (fun s _ -> warning(err (fun x -> FSComp.SR.DefinitionsInSigAndImplNotCompatibleFieldIsInImplButNotSig(x, s))); true) (fun x y -> checkField aenv y x) m2 m1 - else - true) - - - and checkTypeRepr err aenv implTypeRepr sigTypeRepr = - let reportNiceError k s1 s2 = - let aset = NameSet.ofList s1 - let fset = NameSet.ofList s2 - match Zset.elements (Zset.diff aset fset) with - | [] -> - match Zset.elements (Zset.diff fset aset) with - | [] -> (errorR (err (fun x -> FSComp.SR.DefinitionsInSigAndImplNotCompatibleNumbersDiffer(x, k))); false) - | l -> (errorR (err (fun x -> FSComp.SR.DefinitionsInSigAndImplNotCompatibleSignatureDefinesButImplDoesNot(x, k, String.concat ";" l))); false) - | l -> (errorR (err (fun x -> FSComp.SR.DefinitionsInSigAndImplNotCompatibleImplDefinesButSignatureDoesNot(x, k, String.concat ";" l))); false) - - match implTypeRepr,sigTypeRepr with - | (TRecdRepr _ - | TFiniteUnionRepr _ - | TILObjModelRepr _ -#if EXTENSIONTYPING - | TProvidedTypeExtensionPoint _ - | TProvidedNamespaceExtensionPoint _ -#endif - ), TNoRepr -> true - | (TFsObjModelRepr r), TNoRepr -> - match r.fsobjmodel_kind with - | TTyconStruct | TTyconEnum -> - (errorR (err FSComp.SR.DefinitionsInSigAndImplNotCompatibleImplDefinesStruct); false) - | _ -> - true - | (TAsmRepr _), TNoRepr -> - (errorR (err FSComp.SR.DefinitionsInSigAndImplNotCompatibleDotNetTypeRepresentationIsHidden); false) - | (TMeasureableRepr _), TNoRepr -> - (errorR (err FSComp.SR.DefinitionsInSigAndImplNotCompatibleTypeIsHidden); false) - | (TFiniteUnionRepr r1), (TFiniteUnionRepr r2) -> - let ucases1 = r1.UnionCasesAsList - let ucases2 = r2.UnionCasesAsList - if ucases1.Length <> ucases2.Length then - let names (l: UnionCase list) = l |> List.map (fun c -> c.Id.idText) - reportNiceError "union case" (names ucases1) (names ucases2) - else List.forall2 (checkUnionCase aenv) ucases1 ucases2 - | (TRecdRepr implFields), (TRecdRepr sigFields) -> - checkRecordFields g amap denv err aenv implFields sigFields - | (TFsObjModelRepr r1), (TFsObjModelRepr r2) -> - if not (match r1.fsobjmodel_kind,r2.fsobjmodel_kind with - | TTyconClass,TTyconClass -> true - | TTyconInterface,TTyconInterface -> true - | TTyconStruct,TTyconStruct -> true - | TTyconEnum, TTyconEnum -> true - | TTyconDelegate (TSlotSig(_,typ1,ctps1,mtps1,ps1, rty1)), - TTyconDelegate (TSlotSig(_,typ2,ctps2,mtps2,ps2, rty2)) -> - (typeAEquiv g aenv typ1 typ2) && - (ctps1.Length = ctps2.Length) && - (let aenv = aenv.BindEquivTypars ctps1 ctps2 - (typarsAEquiv g aenv ctps1 ctps2) && - (mtps1.Length = mtps2.Length) && - (let aenv = aenv.BindEquivTypars mtps1 mtps2 - (typarsAEquiv g aenv mtps1 mtps2) && - ((ps1,ps2) ||> List.lengthsEqAndForall2 (List.lengthsEqAndForall2 (fun p1 p2 -> typeAEquiv g aenv p1.Type p2.Type))) && - (returnTypesAEquiv g aenv rty1 rty2))) - | _,_ -> false) then - (errorR (err FSComp.SR.DefinitionsInSigAndImplNotCompatibleTypeIsDifferentKind); false) - else - let isStruct = (match r1.fsobjmodel_kind with TTyconStruct -> true | _ -> false) - checkClassFields isStruct g amap denv err aenv r1.fsobjmodel_rfields r2.fsobjmodel_rfields && - checkVirtualSlots g denv err aenv r1.fsobjmodel_vslots r2.fsobjmodel_vslots - | (TAsmRepr tcr1), (TAsmRepr tcr2) -> - if tcr1 <> tcr2 then (errorR (err FSComp.SR.DefinitionsInSigAndImplNotCompatibleILDiffer); false) else true - | (TMeasureableRepr ty1), (TMeasureableRepr ty2) -> - if typeAEquiv g aenv ty1 ty2 then true else (errorR (err FSComp.SR.DefinitionsInSigAndImplNotCompatibleRepresentationsDiffer); false) - | TNoRepr, TNoRepr -> true -#if EXTENSIONTYPING - | TProvidedTypeExtensionPoint info1 , TProvidedTypeExtensionPoint info2 -> - Tainted.EqTainted info1.ProvidedType.TypeProvider info2.ProvidedType.TypeProvider && ProvidedType.TaintedEquals(info1.ProvidedType,info2.ProvidedType) - | TProvidedNamespaceExtensionPoint _, TProvidedNamespaceExtensionPoint _ -> - System.Diagnostics.Debug.Assert(false, "unreachable: TProvidedNamespaceExtensionPoint only on namespaces, not types" ) - true -#endif - | TNoRepr, _ -> (errorR (err FSComp.SR.DefinitionsInSigAndImplNotCompatibleRepresentationsDiffer); false) - | _, _ -> (errorR (err FSComp.SR.DefinitionsInSigAndImplNotCompatibleRepresentationsDiffer); false) - - and checkTypeAbbrev err aenv kind1 kind2 implTypeAbbrev sigTypeAbbrev = - if kind1 <> kind2 then (errorR (err (fun x -> FSComp.SR.DefinitionsInSigAndImplNotCompatibleSignatureDeclaresDiffer(x, kind2.ToString(), kind1.ToString()))); false) - else - match implTypeAbbrev,sigTypeAbbrev with - | Some ty1, Some ty2 -> - if not (typeAEquiv g aenv ty1 ty2) then - let s1, s2, _ = NicePrint.minimalStringsOfTwoTypes denv ty1 ty2 - errorR (err (fun x -> FSComp.SR.DefinitionsInSigAndImplNotCompatibleAbbreviationsDiffer(x, s1, s2))) - false - else - true - | None,None -> true - | Some _, None -> (errorR (err (FSComp.SR.DefinitionsInSigAndImplNotCompatibleAbbreviationHiddenBySig)); false) - | None, Some _ -> (errorR (err FSComp.SR.DefinitionsInSigAndImplNotCompatibleSigHasAbbreviation); false) - - and checkModuleOrNamespaceContents m aenv (implModRef:ModuleOrNamespaceRef) (signModType:ModuleOrNamespaceType) = - let implModType = implModRef.ModuleOrNamespaceType - (if implModType.ModuleOrNamespaceKind <> signModType.ModuleOrNamespaceKind then errorR(Error(FSComp.SR.typrelModuleNamespaceAttributesDifferInSigAndImpl(),m))) - - - (implModType.TypesByMangledName , signModType.TypesByMangledName) - ||> NameMap.suball2 - (fun s _fx -> errorR(RequiredButNotSpecified(denv,implModRef,"type",(fun os -> Printf.bprintf os "%s" s),m)); false) - (checkTypeDef aenv) && - - - (implModType.ModulesAndNamespacesByDemangledName, signModType.ModulesAndNamespacesByDemangledName ) - ||> NameMap.suball2 - (fun s fx -> errorR(RequiredButNotSpecified(denv,implModRef,(if fx.IsModule then "module" else "namespace"),(fun os -> Printf.bprintf os "%s" s),m)); false) - (fun x1 x2 -> checkModuleOrNamespace aenv (mkLocalModRef x1) x2) && - - let sigValHadNoMatchingImplementation (fx:Val) (_closeActualVal: Val option) = - errorR(RequiredButNotSpecified(denv,implModRef,"value",(fun os -> - (* In the case of missing members show the full required enclosing type and signature *) - if fx.IsMember then - NicePrint.outputQualifiedValOrMember denv os fx - else - Printf.bprintf os "%s" fx.DisplayName),m)) - - let valuesPartiallyMatch (av:Val) (fv:Val) = - (av.LinkagePartialKey.MemberParentMangledName = fv.LinkagePartialKey.MemberParentMangledName) && - (av.LinkagePartialKey.LogicalName = fv.LinkagePartialKey.LogicalName) && - (av.LinkagePartialKey.TotalArgCount = fv.LinkagePartialKey.TotalArgCount) - - (implModType.AllValsAndMembersByLogicalNameUncached, signModType.AllValsAndMembersByLogicalNameUncached) - ||> NameMap.suball2 - (fun _s (fxs:Val list) -> sigValHadNoMatchingImplementation fxs.Head None; false) - (fun avs fvs -> - match avs,fvs with - | [],_ | _,[] -> failwith "unreachable" - | [av],[fv] -> - if valuesPartiallyMatch av fv then - checkVal implModRef aenv av fv - else - sigValHadNoMatchingImplementation fv None - false - | _ -> - // for each formal requirement, try to find a precisely matching actual requirement - let matchingPairs = - fvs |> List.choose (fun fv -> - match avs |> List.tryFind (fun av -> - let res = valLinkageAEquiv g aenv av fv - //if res then printfn "%s" (bufs (fun buf -> Printf.bprintf buf "YES MATCH: fv '%a', av '%a'" (NicePrint.outputQualifiedValOrMember denv) fv (NicePrint.outputQualifiedValOrMember denv) av)) - //else printfn "%s" (bufs (fun buf -> Printf.bprintf buf "NO MATCH: fv '%a', av '%a'" (NicePrint.outputQualifiedValOrMember denv) fv (NicePrint.outputQualifiedValOrMember denv) av)) - res) with - | None -> None - | Some av -> Some(fv,av)) - - // Check the ones with matching linkage - let allPairsOk = matchingPairs |> List.map (fun (fv,av) -> checkVal implModRef aenv av fv) |> List.forall id - let someNotOk = matchingPairs.Length < fvs.Length - // Report an error for those that don't. Try pairing up by enclosing-type/name - if someNotOk then - let noMatches,partialMatchingPairs = - fvs |> List.splitChoose (fun fv -> - match avs |> List.tryFind (fun av -> valuesPartiallyMatch av fv) with - | None -> Choice1Of2 fv - | Some av -> Choice2Of2(fv,av)) - for (fv,av) in partialMatchingPairs do - checkVal implModRef aenv av fv |> ignore - for fv in noMatches do - sigValHadNoMatchingImplementation fv None - allPairsOk && not someNotOk) - - - and checkModuleOrNamespace aenv implModRef sigModRef = - // Propagate defn location information from implementation to signature . - sigModRef.SetOtherRange (implModRef.Range, true) - implModRef.Deref.SetOtherRange (sigModRef.Range, false) - checkModuleOrNamespaceContents implModRef.Range aenv implModRef sigModRef.ModuleOrNamespaceType && - checkAttribs aenv implModRef.Attribs sigModRef.Attribs implModRef.Deref.SetAttribs - - member __.CheckSignature aenv (implModRef:ModuleOrNamespaceRef) (signModType:ModuleOrNamespaceType) = - checkModuleOrNamespaceContents implModRef.Range aenv implModRef signModType - - member __.CheckTypars m aenv (implTypars: Typars) (signTypars: Typars) = - checkTypars m aenv implTypars signTypars - - - /// Check the names add up between a signature and its implementation. We check this first. - let rec CheckNamesOfModuleOrNamespaceContents denv (implModRef:ModuleOrNamespaceRef) (signModType:ModuleOrNamespaceType) = - let m = implModRef.Range - let implModType = implModRef.ModuleOrNamespaceType - NameMap.suball2 - (fun s _fx -> errorR(RequiredButNotSpecified(denv,implModRef,"type",(fun os -> Printf.bprintf os "%s" s),m)); false) - (fun _ _ -> true) - implModType.TypesByMangledName - signModType.TypesByMangledName && - - (implModType.ModulesAndNamespacesByDemangledName, signModType.ModulesAndNamespacesByDemangledName ) - ||> NameMap.suball2 - (fun s fx -> errorR(RequiredButNotSpecified(denv,implModRef,(if fx.IsModule then "module" else "namespace"),(fun os -> Printf.bprintf os "%s" s),m)); false) - (fun x1 (x2:ModuleOrNamespace) -> CheckNamesOfModuleOrNamespace denv (mkLocalModRef x1) x2.ModuleOrNamespaceType) && - - (implModType.AllValsAndMembersByLogicalNameUncached , signModType.AllValsAndMembersByLogicalNameUncached) - ||> NameMap.suball2 - (fun _s (fxs:Val list) -> - let fx = fxs.Head - errorR(RequiredButNotSpecified(denv,implModRef,"value",(fun os -> - // In the case of missing members show the full required enclosing type and signature - if isSome fx.MemberInfo then - NicePrint.outputQualifiedValOrMember denv os fx - else - Printf.bprintf os "%s" fx.DisplayName),m)); false) - (fun _ _ -> true) - - - and CheckNamesOfModuleOrNamespace denv (implModRef:ModuleOrNamespaceRef) signModType = - CheckNamesOfModuleOrNamespaceContents denv implModRef signModType - -end - -//------------------------------------------------------------------------- -// Completeness of classes -//------------------------------------------------------------------------- - -type OverrideCanImplement = - | CanImplementAnyInterfaceSlot - | CanImplementAnyClassHierarchySlot - | CanImplementAnySlot - | CanImplementNoSlots - -/// The overall information about a method implementation in a class or object expression -type OverrideInfo = - | Override of OverrideCanImplement * TyconRef * Ident * (Typars * TyparInst) * TType list list * TType option * bool * bool - member x.CanImplement = let (Override(a,_,_,_,_,_,_,_)) = x in a - member x.BoundingTyconRef = let (Override(_,ty,_,_,_,_,_,_)) = x in ty - member x.LogicalName = let (Override(_,_,id,_,_,_,_,_)) = x in id.idText - member x.Range = let (Override(_,_,id,_,_,_,_,_)) = x in id.idRange - member x.IsFakeEventProperty = let (Override(_,_,_,_,_,_,b,_)) = x in b - member x.ArgTypes = let (Override(_,_,_,_,b,_,_,_)) = x in b - member x.ReturnType = let (Override(_,_,_,_,_,b,_,_)) = x in b - member x.IsCompilerGenerated = let (Override(_,_,_,_,_,_,_,b)) = x in b - -// If the bool is true then the slot is optional, i.e. is an interface slot -// which does not _have_ to be implemented, because an inherited implementation -// is available. -type RequiredSlot = RequiredSlot of MethInfo * (* isOptional: *) bool - -type SlotImplSet = SlotImplSet of RequiredSlot list * NameMultiMap * OverrideInfo list * PropInfo list - -exception TypeIsImplicitlyAbstract of range -exception OverrideDoesntOverride of DisplayEnv * OverrideInfo * MethInfo option * TcGlobals * Import.ImportMap * range - -module DispatchSlotChecking = - - /// Print the signature of an override to a buffer as part of an error message - let PrintOverrideToBuffer denv os (Override(_,_,id,(mtps,memberToParentInst),argTys,retTy,_,_)) = - let denv = { denv with showTyparBinding = true } - let retTy = (retTy |> GetFSharpViewOfReturnType denv.g) - let argInfos = - match argTys with - | [] -> [[(denv.g.unit_ty,ValReprInfo.unnamedTopArg1)]] - | _ -> argTys |> List.mapSquared (fun ty -> (ty, ValReprInfo.unnamedTopArg1)) - Layout.bufferL os (NicePrint.layoutMemberSig denv (memberToParentInst,id.idText,mtps, argInfos, retTy)) - - /// Print the signature of a MethInfo to a buffer as part of an error message - let PrintMethInfoSigToBuffer g amap m denv os minfo = - let denv = { denv with showTyparBinding = true } - let (CompiledSig(argTys,retTy,fmtps,ttpinst)) = CompiledSigOfMeth g amap m minfo - let retTy = (retTy |> GetFSharpViewOfReturnType g) - let argInfos = argTys |> List.mapSquared (fun ty -> (ty, ValReprInfo.unnamedTopArg1)) - let nm = minfo.LogicalName - Layout.bufferL os (NicePrint.layoutMemberSig denv (ttpinst,nm,fmtps, argInfos, retTy)) - - /// Format the signature of an override as a string as part of an error message - let FormatOverride denv d = bufs (fun buf -> PrintOverrideToBuffer denv buf d) - - /// Format the signature of a MethInfo as a string as part of an error message - let FormatMethInfoSig g amap m denv d = bufs (fun buf -> PrintMethInfoSigToBuffer g amap m denv buf d) - - /// Get the override info for an existing (inherited) method being used to implement a dispatch slot. - let GetInheritedMemberOverrideInfo g amap m parentType (minfo:MethInfo) = - let nm = minfo.LogicalName - let (CompiledSig (argTys,retTy,fmtps,ttpinst)) = CompiledSigOfMeth g amap m minfo - - let isFakeEventProperty = minfo.IsFSharpEventPropertyMethod - Override(parentType,tcrefOfAppTy g minfo.EnclosingType,mkSynId m nm, (fmtps,ttpinst),argTys,retTy,isFakeEventProperty,false) - - /// Get the override info for a value being used to implement a dispatch slot. - let GetTypeMemberOverrideInfo g reqdTy (overrideBy:ValRef) = - let _,argInfos,retTy,_ = GetTypeOfMemberInMemberForm g overrideBy - let nm = overrideBy.LogicalName - - let argTys = argInfos |> List.mapSquared fst - - let memberMethodTypars,memberToParentInst,argTys,retTy = - match PartitionValRefTypars g overrideBy with - | Some(_,_,memberMethodTypars,memberToParentInst,_tinst) -> - let argTys = argTys |> List.mapSquared (instType memberToParentInst) - let retTy = retTy |> Option.map (instType memberToParentInst) - memberMethodTypars, memberToParentInst,argTys, retTy - | None -> - error(Error(FSComp.SR.typrelMethodIsOverconstrained(),overrideBy.Range)) - let implKind = - if ValRefIsExplicitImpl g overrideBy then - - let belongsToReqdTy = - match overrideBy.MemberInfo.Value.ImplementedSlotSigs with - | [] -> false - | ss :: _ -> isInterfaceTy g ss.ImplementedType && typeEquiv g reqdTy ss.ImplementedType - if belongsToReqdTy then - CanImplementAnyInterfaceSlot - else - CanImplementNoSlots - else if overrideBy.IsDispatchSlotMember then - CanImplementNoSlots - // abstract slots can only implement interface slots - //CanImplementAnyInterfaceSlot <<----- Change to this to enable implicit interface implementation - - else - CanImplementAnyClassHierarchySlot - //CanImplementAnySlot <<----- Change to this to enable implicit interface implementation - - let isFakeEventProperty = overrideBy.IsFSharpEventProperty(g) - Override(implKind,overrideBy.MemberApparentParent, mkSynId overrideBy.Range nm, (memberMethodTypars,memberToParentInst),argTys,retTy,isFakeEventProperty, overrideBy.IsCompilerGenerated) - - /// Get the override information for an object expression method being used to implement dispatch slots - let GetObjectExprOverrideInfo g amap (implty, id:Ident, memberFlags, ty, arityInfo, bindingAttribs, rhsExpr) = - // Dissect the type - let tps, argInfos, retTy, _ = GetMemberTypeInMemberForm g memberFlags arityInfo ty id.idRange - let argTys = argInfos |> List.mapSquared fst - // Dissect the implementation - let _, ctorThisValOpt, baseValOpt, vsl, rhsExpr,_ = destTopLambda g amap arityInfo (rhsExpr,ty) - assert ctorThisValOpt.IsNone - - // Drop 'this' - match vsl with - | [thisv]::vs -> - // Check for empty variable list from a () arg - let vs = if vs.Length = 1 && argInfos.IsEmpty then [] else vs - let implKind = - if isInterfaceTy g implty then - CanImplementAnyInterfaceSlot - else - CanImplementAnyClassHierarchySlot - //CanImplementAnySlot <<----- Change to this to enable implicit interface implementation - let isFakeEventProperty = CompileAsEvent g bindingAttribs - let overrideByInfo = Override(implKind, tcrefOfAppTy g implty, id, (tps,[]), argTys, retTy, isFakeEventProperty, false) - overrideByInfo, (baseValOpt, thisv, vs, bindingAttribs, rhsExpr) - | _ -> - error(InternalError("Unexpected shape for object expression override",id.idRange)) - - /// Check if an override matches a dispatch slot by name - let IsNameMatch (dispatchSlot:MethInfo) (overrideBy: OverrideInfo) = - (overrideBy.LogicalName = dispatchSlot.LogicalName) - - /// Check if an override matches a dispatch slot by name - let IsImplMatch g (dispatchSlot:MethInfo) (overrideBy: OverrideInfo) = - // If the override is listed as only relevant to one type, and we're matching it against an abstract slot of an interface type, - // then check that interface type is the right type. - (match overrideBy.CanImplement with - | CanImplementNoSlots -> false - | CanImplementAnySlot -> true - | CanImplementAnyClassHierarchySlot -> not (isInterfaceTy g dispatchSlot.EnclosingType) - //| CanImplementSpecificInterfaceSlot parentTy -> isInterfaceTy g dispatchSlot.EnclosingType && typeEquiv g parentTy dispatchSlot.EnclosingType - | CanImplementAnyInterfaceSlot -> isInterfaceTy g dispatchSlot.EnclosingType) - - /// Check if the kinds of type parameters match between a dispatch slot and an override. - let IsTyparKindMatch g amap m (dispatchSlot:MethInfo) (Override(_,_,_,(mtps,_),_,_,_,_)) = - let (CompiledSig(_,_,fvmtps,_)) = CompiledSigOfMeth g amap m dispatchSlot - List.lengthsEqAndForall2 (fun (tp1:Typar) (tp2:Typar) -> tp1.Kind = tp2.Kind) mtps fvmtps - - /// Check if an override is a partial match for the requirements for a dispatch slot - let IsPartialMatch g amap m (dispatchSlot:MethInfo) (Override(_,_,_,(mtps,_),argTys,_retTy,_,_) as overrideBy) = - IsNameMatch dispatchSlot overrideBy && - let (CompiledSig (vargtys,_,fvmtps,_)) = CompiledSigOfMeth g amap m dispatchSlot - mtps.Length = fvmtps.Length && - IsTyparKindMatch g amap m dispatchSlot overrideBy && - argTys.Length = vargtys.Length && - IsImplMatch g dispatchSlot overrideBy - - /// Compute the reverse of a type parameter renaming. - let ReverseTyparRenaming g tinst = - tinst |> List.map (fun (tp,ty) -> (destTyparTy g ty, mkTyparTy tp)) - - /// Compose two instantiations of type parameters. - let ComposeTyparInsts inst1 inst2 = - inst1 |> List.map (map2Of2 (instType inst2)) - - /// Check if an override exactly matches the requirements for a dispatch slot - let IsExactMatch g amap m dispatchSlot (Override(_,_,_,(mtps,mtpinst),argTys,retTy,_,_) as overrideBy) = - IsPartialMatch g amap m dispatchSlot overrideBy && - let (CompiledSig (vargtys,vrty,fvmtps,ttpinst)) = CompiledSigOfMeth g amap m dispatchSlot - - // Compare the types. CompiledSigOfMeth, GetObjectExprOverrideInfo and GetTypeMemberOverrideInfo have already - // applied all relevant substitutions except the renamings from fvtmps <-> mtps - - let aenv = TypeEquivEnv.FromEquivTypars fvmtps mtps - - List.forall2 (List.lengthsEqAndForall2 (typeAEquiv g aenv)) vargtys argTys && - returnTypesAEquiv g aenv vrty retTy && - - // Comparing the method typars and their constraints is much trickier since the substitutions have not been applied - // to the constraints of these babies. This is partly because constraints are directly attached to typars so it's - // difficult to apply substitutions to them unless we separate them off at some point, which we don't as yet. - // - // Given C - // D - // dispatchSlot : C.M(...) - // overrideBy: parent: D value: ! (...) - // - // where X[dtps] indicates that X may involve free type variables dtps - // - // we have - // ttpinst maps ctps --> ctys[dtps] - // mtpinst maps ttps --> dtps - // - // compare fvtmps[ctps] and mtps[ttps] by - // fvtmps[ctps] @ ttpinst -- gives fvtmps[dtps] - // fvtmps[dtps] @ rev(mtpinst) -- gives fvtmps[ttps] - // - // Now fvtmps[ttps] and mtpinst[ttps] are comparable, i.e. have constraints w.r.t. the same set of type variables - // - // i.e. Compose the substitutions ttpinst and rev(mtpinst) - - let ttpinst = - // check we can reverse - in some error recovery situations we can't - if mtpinst |> List.exists (snd >> isTyparTy g >> not) then ttpinst - else ComposeTyparInsts ttpinst (ReverseTyparRenaming g mtpinst) - - // Compare under the composed substitutions - let aenv = TypeEquivEnv.FromTyparInst ttpinst - - typarsAEquiv g aenv fvmtps mtps - - /// Check if an override implements a dispatch slot - let OverrideImplementsDispatchSlot g amap m dispatchSlot availPriorOverride = - IsExactMatch g amap m dispatchSlot availPriorOverride && - // The override has to actually be in some subtype of the dispatch slot - ExistsHeadTypeInEntireHierarchy g amap m (generalizedTyconRef availPriorOverride.BoundingTyconRef) (tcrefOfAppTy g dispatchSlot.EnclosingType) - - /// Check if a dispatch slot is already implemented - let DispatchSlotIsAlreadyImplemented g amap m availPriorOverridesKeyed (dispatchSlot: MethInfo) = - availPriorOverridesKeyed - |> NameMultiMap.find dispatchSlot.LogicalName - |> List.exists (OverrideImplementsDispatchSlot g amap m dispatchSlot) - - - /// Check all dispatch slots are implemented by some override. - let CheckDispatchSlotsAreImplemented (denv,g,amap,m, - nenv,sink:TcResultsSink, - isOverallTyAbstract, - reqdTy, - dispatchSlots:RequiredSlot list, - availPriorOverrides:OverrideInfo list, - overrides:OverrideInfo list) = - - let isReqdTyInterface = isInterfaceTy g reqdTy - let showMissingMethodsAndRaiseErrors = (isReqdTyInterface || not isOverallTyAbstract) - let res = ref true - let fail exn = (res := false ; if showMissingMethodsAndRaiseErrors then errorR exn) - - // Index the availPriorOverrides and overrides by name - let availPriorOverridesKeyed = availPriorOverrides |> NameMultiMap.initBy (fun ov -> ov.LogicalName) - let overridesKeyed = overrides |> NameMultiMap.initBy (fun ov -> ov.LogicalName) - - dispatchSlots |> List.iter (fun (RequiredSlot(dispatchSlot,isOptional)) -> - - match NameMultiMap.find dispatchSlot.LogicalName overridesKeyed - |> List.filter (OverrideImplementsDispatchSlot g amap m dispatchSlot) with - | [ovd] -> - if not ovd.IsCompilerGenerated then - let item = Item.MethodGroup(ovd.LogicalName,[dispatchSlot],None) - CallNameResolutionSink sink (ovd.Range,nenv,item,item,ItemOccurence.Implemented,denv,AccessorDomain.AccessibleFromSomewhere) - sink |> ignore - () - | [] -> - if not isOptional && - // Check that no available prior override implements this dispatch slot - not (DispatchSlotIsAlreadyImplemented g amap m availPriorOverridesKeyed dispatchSlot) then - // error reporting path - let (CompiledSig (vargtys,_vrty,fvmtps,_)) = CompiledSigOfMeth g amap m dispatchSlot - let noimpl() = if isReqdTyInterface then fail(Error(FSComp.SR.typrelNoImplementationGivenWithSuggestion(NicePrint.stringOfMethInfo amap m denv dispatchSlot), m)) - else fail(Error(FSComp.SR.typrelNoImplementationGiven(NicePrint.stringOfMethInfo amap m denv dispatchSlot), m)) - match overrides |> List.filter (IsPartialMatch g amap m dispatchSlot) with - | [] -> - match overrides |> List.filter (fun overrideBy -> IsNameMatch dispatchSlot overrideBy && - IsImplMatch g dispatchSlot overrideBy) with - | [] -> - noimpl() - | [ Override(_,_,_,(mtps,_),argTys,_,_,_) as overrideBy ] -> - let error_msg = - if argTys.Length <> vargtys.Length then FSComp.SR.typrelMemberDoesNotHaveCorrectNumberOfArguments(FormatOverride denv overrideBy, FormatMethInfoSig g amap m denv dispatchSlot) - elif mtps.Length <> fvmtps.Length then FSComp.SR.typrelMemberDoesNotHaveCorrectNumberOfTypeParameters(FormatOverride denv overrideBy, FormatMethInfoSig g amap m denv dispatchSlot) - elif not (IsTyparKindMatch g amap m dispatchSlot overrideBy) then FSComp.SR.typrelMemberDoesNotHaveCorrectKindsOfGenericParameters(FormatOverride denv overrideBy, FormatMethInfoSig g amap m denv dispatchSlot) - else FSComp.SR.typrelMemberCannotImplement(FormatOverride denv overrideBy, NicePrint.stringOfMethInfo amap m denv dispatchSlot, FormatMethInfoSig g amap m denv dispatchSlot) - fail(Error(error_msg, overrideBy.Range)) - | overrideBy :: _ -> - errorR(Error(FSComp.SR.typrelOverloadNotFound(FormatMethInfoSig g amap m denv dispatchSlot, FormatMethInfoSig g amap m denv dispatchSlot),overrideBy.Range)) - - | [ overrideBy ] -> - - match dispatchSlots |> List.filter (fun (RequiredSlot(dispatchSlot,_)) -> OverrideImplementsDispatchSlot g amap m dispatchSlot overrideBy) with - | [] -> - // Error will be reported below in CheckOverridesAreAllUsedOnce - () - | _ -> - noimpl() - - | _ -> - fail(Error(FSComp.SR.typrelOverrideWasAmbiguous(FormatMethInfoSig g amap m denv dispatchSlot),m)) - | _ -> fail(Error(FSComp.SR.typrelMoreThenOneOverride(FormatMethInfoSig g amap m denv dispatchSlot),m))) - !res - - /// Check all implementations implement some dispatch slot. - let CheckOverridesAreAllUsedOnce(denv, g, amap, isObjExpr, reqdTy, - dispatchSlotsKeyed: NameMultiMap, - availPriorOverrides: OverrideInfo list, - overrides: OverrideInfo list) = - let availPriorOverridesKeyed = availPriorOverrides |> NameMultiMap.initBy (fun ov -> ov.LogicalName) - for overrideBy in overrides do - if not overrideBy.IsFakeEventProperty then - let m = overrideBy.Range - let relevantVirts = NameMultiMap.find overrideBy.LogicalName dispatchSlotsKeyed - let relevantVirts = relevantVirts |> List.map (fun (RequiredSlot(dispatchSlot,_)) -> dispatchSlot) - - match relevantVirts |> List.filter (fun dispatchSlot -> OverrideImplementsDispatchSlot g amap m dispatchSlot overrideBy) with - | [] -> - // This is all error reporting - match relevantVirts |> List.filter (fun dispatchSlot -> IsPartialMatch g amap m dispatchSlot overrideBy) with - | [dispatchSlot] -> - errorR(OverrideDoesntOverride(denv,overrideBy,Some dispatchSlot,g,amap,m)) - | _ -> - match relevantVirts |> List.filter (fun dispatchSlot -> IsNameMatch dispatchSlot overrideBy) with - | [dispatchSlot] -> - errorR(OverrideDoesntOverride(denv, overrideBy, Some dispatchSlot, g, amap, m)) - | _ -> - errorR(OverrideDoesntOverride(denv,overrideBy,None,g,amap,m)) - - - | [dispatchSlot] -> - if dispatchSlot.IsFinal && (isObjExpr || not (typeEquiv g reqdTy dispatchSlot.EnclosingType)) then - errorR(Error(FSComp.SR.typrelMethodIsSealed(NicePrint.stringOfMethInfo amap m denv dispatchSlot),m)) - | dispatchSlots -> - match dispatchSlots |> List.filter (fun dispatchSlot -> - isInterfaceTy g dispatchSlot.EnclosingType || - not (DispatchSlotIsAlreadyImplemented g amap m availPriorOverridesKeyed dispatchSlot)) with - | h1 :: h2 :: _ -> - errorR(Error(FSComp.SR.typrelOverrideImplementsMoreThenOneSlot((FormatOverride denv overrideBy), (NicePrint.stringOfMethInfo amap m denv h1), (NicePrint.stringOfMethInfo amap m denv h2)),m)) - | _ -> - // dispatch slots are ordered from the derived classes to base - // so we can check the topmost dispatch slot if it is final - match dispatchSlots with - | meth::_ when meth.IsFinal -> errorR(Error(FSComp.SR.tcCannotOverrideSealedMethod((sprintf "%s::%s" (meth.EnclosingType.ToString()) (meth.LogicalName))), m)) - | _ -> () - - - - /// Get the slots of a type that can or must be implemented. This depends - /// partly on the full set of interface types that are being implemented - /// simultaneously, e.g. - /// { new C with interface I2 = ... interface I3 = ... } - /// allReqdTys = {C;I2;I3} - /// - /// allReqdTys can include one class/record/union type. - let GetSlotImplSets (infoReader:InfoReader) denv isObjExpr allReqdTys = - - let g = infoReader.g - let amap = infoReader.amap - - let availImpliedInterfaces : TType list = - [ for (reqdTy,m) in allReqdTys do - if not (isInterfaceTy g reqdTy) then - let baseTyOpt = if isObjExpr then Some reqdTy else GetSuperTypeOfType g amap m reqdTy - match baseTyOpt with - | None -> () - | Some baseTy -> yield! AllInterfacesOfType g amap m AllowMultiIntfInstantiations.Yes baseTy ] - - // For each implemented type, get a list containing the transitive closure of - // interface types implied by the type. This includes the implemented type itself if the implemented type - // is an interface type. - let intfSets = - allReqdTys |> List.mapi (fun i (reqdTy,m) -> - let interfaces = AllInterfacesOfType g amap m AllowMultiIntfInstantiations.Yes reqdTy - let impliedTys = (if isInterfaceTy g reqdTy then interfaces else reqdTy :: interfaces) - (i, reqdTy, impliedTys,m)) - - // For each implemented type, reduce its list of implied interfaces by subtracting out those implied - // by another implemented interface type. - // - // REVIEW: Note complexity O(ity*jty) - let reqdTyInfos = - intfSets |> List.map (fun (i,reqdTy,impliedTys,m) -> - let reduced = - (impliedTys,intfSets) ||> List.fold (fun acc (j,jty,impliedTys2,m) -> - if i <> j && TypeFeasiblySubsumesType 0 g amap m jty CanCoerce reqdTy - then ListSet.subtract (TypesFeasiblyEquiv 0 g amap m) acc impliedTys2 - else acc ) - (i, reqdTy, m, reduced)) - - // Check that, for each implemented type, at least one implemented type is implied. This is enough to capture - // duplicates. - for (_i, reqdTy, m, impliedTys) in reqdTyInfos do - if isInterfaceTy g reqdTy && isNil impliedTys then - errorR(Error(FSComp.SR.typrelDuplicateInterface(),m)) - - // Check that no interface type is implied twice - // - // Note complexity O(reqdTy*reqdTy) - for (i, _reqdTy, reqdTyRange, impliedTys) in reqdTyInfos do - for (j,_,_,impliedTys2) in reqdTyInfos do - if i > j then - let overlap = ListSet.intersect (TypesFeasiblyEquiv 0 g amap reqdTyRange) impliedTys impliedTys2 - overlap |> List.iter (fun overlappingTy -> - if nonNil(GetImmediateIntrinsicMethInfosOfType (None,AccessibleFromSomewhere) g amap reqdTyRange overlappingTy |> List.filter (fun minfo -> minfo.IsVirtual)) then - errorR(Error(FSComp.SR.typrelNeedExplicitImplementation(NicePrint.minimalStringOfType denv (List.head overlap)),reqdTyRange))) - - // Get the SlotImplSet for each implemented type - // This contains the list of required members and the list of available members - [ for (_,reqdTy,reqdTyRange,impliedTys) in reqdTyInfos do - - // Build a set of the implied interface types, for quicker lookup, by nominal type - let isImpliedInterfaceTable = - impliedTys - |> List.filter (isInterfaceTy g) - |> List.map (fun ty -> tcrefOfAppTy g ty, ()) - |> TyconRefMap.OfList - - // Is a member an abstract slot of one of the implied interface types? - let isImpliedInterfaceType ty = - isImpliedInterfaceTable.ContainsKey (tcrefOfAppTy g ty) && - impliedTys |> List.exists (TypesFeasiblyEquiv 0 g amap reqdTyRange ty) - - //let isSlotImpl (minfo:MethInfo) = - // not minfo.IsAbstract && minfo.IsVirtual - - // Compute the abstract slots that require implementations - let dispatchSlots = - [ if isInterfaceTy g reqdTy then - for impliedTy in impliedTys do - // Check if the interface has an inherited implementation - // If so, you do not have to implement all the methods - each - // specific method is "optionally" implemented. - let isOptional = - ListSet.contains (typeEquiv g) impliedTy availImpliedInterfaces - for reqdSlot in GetImmediateIntrinsicMethInfosOfType (None,AccessibleFromSomewhere) g amap reqdTyRange impliedTy do - yield RequiredSlot(reqdSlot, isOptional) - else - - // In the normal case, the requirements for a class are precisely all the abstract slots up the whole hierarchy. - // So here we get and yield all of those. - for minfo in reqdTy |> GetIntrinsicMethInfosOfType infoReader (None,AccessibleFromSomewhere,AllowMultiIntfInstantiations.Yes) IgnoreOverrides reqdTyRange do - if minfo.IsDispatchSlot then - yield RequiredSlot(minfo,(*isOptional=*)false) ] - - - // Compute the methods that are available to implement abstract slots from the base class - // - // This is used in CheckDispatchSlotsAreImplemented when we think a dispatch slot may not - // have been implemented. - let availPriorOverrides : OverrideInfo list = - if isInterfaceTy g reqdTy then - [] - else - let reqdTy = - let baseTyOpt = if isObjExpr then Some reqdTy else GetSuperTypeOfType g amap reqdTyRange reqdTy - match baseTyOpt with - | None -> reqdTy - | Some baseTy -> baseTy - [ // Get any class hierarchy methods on this type - // - // NOTE: What we have below is an over-approximation that will get too many methods - // and not always correctly relate them to the slots they implement. For example, - // we may get an override from a base class and believe it implements a fresh, new abstract - // slot in a subclass. - for minfos in infoReader.GetRawIntrinsicMethodSetsOfType(None,AccessibleFromSomewhere,AllowMultiIntfInstantiations.Yes,reqdTyRange,reqdTy) do - for minfo in minfos do - if not minfo.IsAbstract then - yield GetInheritedMemberOverrideInfo g amap reqdTyRange CanImplementAnyClassHierarchySlot minfo ] - - // We also collect up the properties. This is used for abstract slot inference when overriding properties - let isRelevantRequiredProperty (x:PropInfo) = - (x.IsVirtualProperty && not (isInterfaceTy g reqdTy)) || - isImpliedInterfaceType x.EnclosingType - - let reqdProperties = - GetIntrinsicPropInfosOfType infoReader (None,AccessibleFromSomewhere,AllowMultiIntfInstantiations.Yes) IgnoreOverrides reqdTyRange reqdTy - |> List.filter isRelevantRequiredProperty - - let dispatchSlotsKeyed = dispatchSlots |> NameMultiMap.initBy (fun (RequiredSlot(v,_)) -> v.LogicalName) - yield SlotImplSet(dispatchSlots, dispatchSlotsKeyed, availPriorOverrides, reqdProperties) ] - - - /// Check that a type definition implements all its required interfaces after processing all declarations - /// within a file. - let CheckImplementationRelationAtEndOfInferenceScope (infoReader :InfoReader,denv,nenv,sink,tycon:Tycon,isImplementation) = - - let g = infoReader.g - let amap = infoReader.amap - - let tcaug = tycon.TypeContents - let interfaces = tycon.ImmediateInterfacesOfFSharpTycon |> List.map (fun (ity,_compgen,m) -> (ity,m)) - - let overallTy = generalizedTyconRef (mkLocalTyconRef tycon) - - let allReqdTys = (overallTy,tycon.Range) :: interfaces - - // Get all the members that are immediately part of this type - // Include the auto-generated members - let allImmediateMembers = tycon.MembersOfFSharpTyconSorted @ tycon.AllGeneratedValues - - // Get all the members we have to implement, organized by each type we explicitly implement - let slotImplSets = GetSlotImplSets infoReader denv false allReqdTys - - let allImpls = List.zip allReqdTys slotImplSets - - // Find the methods relevant to implementing the abstract slots listed under the reqdType being checked. - let allImmediateMembersThatMightImplementDispatchSlots = - allImmediateMembers |> List.filter (fun overrideBy -> - overrideBy.IsInstanceMember && // exclude static - overrideBy.IsVirtualMember && // exclude non virtual (e.g. keep override/default). [4469] - not overrideBy.IsDispatchSlotMember) - - let mustOverrideSomething reqdTy (overrideBy:ValRef) = - let memberInfo = overrideBy.MemberInfo.Value - not (overrideBy.IsFSharpEventProperty(g)) && - memberInfo.MemberFlags.IsOverrideOrExplicitImpl && - - match memberInfo.ImplementedSlotSigs with - | [] -> - // Are we looking at the implementation of the class hierarchy? If so include all the override members - not (isInterfaceTy g reqdTy) - | ss -> - ss |> List.forall (fun ss -> - let ty = ss.ImplementedType - if isInterfaceTy g ty then - // Is this a method impl listed under the reqdTy? - typeEquiv g ty reqdTy - else - not (isInterfaceTy g reqdTy) ) - - - // We check all the abstracts related to the class hierarchy and then check each interface implementation - for ((reqdTy,m),slotImplSet) in allImpls do - let (SlotImplSet(dispatchSlots, dispatchSlotsKeyed, availPriorOverrides,_)) = slotImplSet - try - - // Now extract the information about each overriding method relevant to this SlotImplSet - let allImmediateMembersThatMightImplementDispatchSlots = - allImmediateMembersThatMightImplementDispatchSlots - |> List.map (fun overrideBy -> overrideBy,GetTypeMemberOverrideInfo g reqdTy overrideBy) - - // Now check the implementation - // We don't give missing method errors for abstract classes - - if isImplementation && not (isInterfaceTy g overallTy) then - let overrides = allImmediateMembersThatMightImplementDispatchSlots |> List.map snd - let allCorrect = CheckDispatchSlotsAreImplemented (denv,g,amap,m,nenv,sink,tcaug.tcaug_abstract,reqdTy,dispatchSlots,availPriorOverrides,overrides) - - // Tell the user to mark the thing abstract if it was missing implementations - if not allCorrect && not tcaug.tcaug_abstract && not (isInterfaceTy g reqdTy) then - errorR(TypeIsImplicitlyAbstract(m)) - - let overridesToCheck = - allImmediateMembersThatMightImplementDispatchSlots - |> List.filter (fst >> mustOverrideSomething reqdTy) - |> List.map snd - - CheckOverridesAreAllUsedOnce (denv, g, amap, false, reqdTy, dispatchSlotsKeyed, availPriorOverrides, overridesToCheck) - - with e -> errorRecovery e m - - // Now record the full slotsigs of the abstract members implemented by each override. - // This is used to generate IL MethodImpls in the code generator. - allImmediateMembersThatMightImplementDispatchSlots |> List.iter (fun overrideBy -> - - let isFakeEventProperty = overrideBy.IsFSharpEventProperty(g) - let overriden = - if isFakeEventProperty then - let slotsigs = overrideBy.MemberInfo.Value.ImplementedSlotSigs - slotsigs |> List.map (ReparentSlotSigToUseMethodTypars g overrideBy.Range overrideBy) - else - [ for ((reqdTy,m),(SlotImplSet(_dispatchSlots,dispatchSlotsKeyed,_,_))) in allImpls do - let overrideByInfo = GetTypeMemberOverrideInfo g reqdTy overrideBy - let overridenForThisSlotImplSet = - [ for (RequiredSlot(dispatchSlot,_)) in NameMultiMap.find overrideByInfo.LogicalName dispatchSlotsKeyed do - if OverrideImplementsDispatchSlot g amap m dispatchSlot overrideByInfo then - if tyconRefEq g overrideByInfo.BoundingTyconRef (tcrefOfAppTy g dispatchSlot.EnclosingType) then - match dispatchSlot.ArbitraryValRef with - | Some virtMember -> - if virtMember.MemberInfo.Value.IsImplemented then errorR(Error(FSComp.SR.tcDefaultImplementationAlreadyExists(),overrideByInfo.Range)) - virtMember.MemberInfo.Value.IsImplemented <- true - | None -> () // not an F# slot - - // Get the slotsig of the overridden method - let slotsig = dispatchSlot.GetSlotSig(amap, m) - - // The slotsig from the overridden method is in terms of the type parameters on the parent type of the overriding method, - // Modify map the slotsig so it is in terms of the type parameters for the overriding method - let slotsig = ReparentSlotSigToUseMethodTypars g m overrideBy slotsig - - // Record the slotsig via mutation - yield slotsig ] - //if mustOverrideSomething reqdTy overrideBy then - // assert nonNil overridenForThisSlotImplSet - yield! overridenForThisSlotImplSet ] - - overrideBy.MemberInfo.Value.ImplementedSlotSigs <- overriden) - - -//------------------------------------------------------------------------- -// Sets of methods involved in overload resolution and trait constraint -// satisfaction. -//------------------------------------------------------------------------- - -/// In the following, 'T gets instantiated to: -/// 1. the expression being supplied for an argument -/// 2. "unit", when simply checking for the existence of an overload that satisfies -/// a signature, or when finding the corresponding witness. -/// Note the parametricity helps ensure that overload resolution doesn't depend on the -/// expression on the callside (though it is in some circumstances allowed -/// to depend on some type information inferred syntactically from that -/// expression, e.g. a lambda expression may be converted to a delegate as -/// an adhoc conversion. -/// -/// The bool indicates if named using a '?' -type CallerArg<'T> = - /// CallerArg(ty, range, isOpt, exprInfo) - | CallerArg of TType * range * bool * 'T - member x.Type = (let (CallerArg(ty,_,_,_)) = x in ty) - member x.Range = (let (CallerArg(_,m,_,_)) = x in m) - member x.IsOptional = (let (CallerArg(_,_,isOpt,_)) = x in isOpt) - member x.Expr = (let (CallerArg(_,_,_,expr)) = x in expr) - -/// Represents the information about an argument in the method being called -type CalledArg = - { Position: (int * int) - IsParamArray : bool - OptArgInfo : OptionalArgInfo - CallerInfoInfo : CallerInfoInfo - IsOutArg: bool - ReflArgInfo: ReflectedArgInfo - NameOpt: Ident option - CalledArgumentType : TType } - -let CalledArg(pos,isParamArray,optArgInfo,callerInfoInfo,isOutArg,nameOpt,reflArgInfo,calledArgTy) = - { Position=pos - IsParamArray=isParamArray - OptArgInfo =optArgInfo - CallerInfoInfo = callerInfoInfo - IsOutArg=isOutArg - ReflArgInfo=reflArgInfo - NameOpt=nameOpt - CalledArgumentType = calledArgTy } - -/// Represents a match between a caller argument and a called argument, arising from either -/// a named argument or an unnamed argument. -type AssignedCalledArg<'T> = - { /// The identifier for a named argument, if any - NamedArgIdOpt : Ident option - /// The called argument in the method - CalledArg: CalledArg - /// The argument on the caller side - CallerArg: CallerArg<'T> } - member x.Position = x.CalledArg.Position - -/// Represents the possibilities for a named-setter argument (a property, field , or a record field setter) -type AssignedItemSetterTarget = - | AssignedPropSetter of PropInfo * MethInfo * TypeInst (* the MethInfo is a non-indexer setter property *) - | AssignedILFieldSetter of ILFieldInfo - | AssignedRecdFieldSetter of RecdFieldInfo - -/// Represents the resolution of a caller argument as a named-setter argument -type AssignedItemSetter<'T> = AssignedItemSetter of Ident * AssignedItemSetterTarget * CallerArg<'T> - -type CallerNamedArg<'T> = - | CallerNamedArg of Ident * CallerArg<'T> - member x.Ident = (let (CallerNamedArg(id,_)) = x in id) - member x.Name = x.Ident.idText - member x.CallerArg = (let (CallerNamedArg(_,a)) = x in a) - -//------------------------------------------------------------------------- -// Callsite conversions -//------------------------------------------------------------------------- - -// F# supports three adhoc conversions at method callsites (note C# supports more, though ones -// such as implicit conversions interact badly with type inference). -// -// 1. The use of "(fun x y -> ...)" when a delegate it expected. This is not part of -// the ":>" coercion relationship or inference constraint problem as -// such, but is a special rule applied only to method arguments. -// -// The function AdjustCalledArgType detects this case based on types and needs to know that the type being applied -// is a function type. -// -// 2. The use of "(fun x y -> ...)" when Expression it expected. This is similar to above. -// -// 3. Two ways to pass a value where a byref is expected. The first (default) -// is to use a reference cell, and the interior address is taken automatically -// The second is an explicit use of the "address-of" operator "&e". Here we detect the second case, -// and record the presence of the sytnax "&e" in the pre-inferred actual type for the method argument. -// The function AdjustCalledArgType detects this and refuses to apply the default byref-to-ref transformation. -// -// The function AdjustCalledArgType also adjusts for optional arguments. -let AdjustCalledArgType (infoReader:InfoReader) isConstraint (calledArg: CalledArg) (callerArg: CallerArg<_>) = - let g = infoReader.g - // #424218 - when overload resolution is part of constraint solving - do not perform type-directed conversions - let calledArgTy = calledArg.CalledArgumentType - let callerArgTy = callerArg.Type - let m = callerArg.Range - if isConstraint then calledArgTy else - // If the called method argument is a byref type, then the caller may provide a byref or ref - if isByrefTy g calledArgTy then - if isByrefTy g callerArgTy then - calledArgTy - else - mkRefCellTy g (destByrefTy g calledArgTy) - else - // If the called method argument is a delegate type, then the caller may provide a function - let calledArgTy = - let adjustDelegateTy calledTy = - let (SigOfFunctionForDelegate(_,delArgTys,_,fty)) = GetSigOfFunctionForDelegate infoReader calledTy m AccessibleFromSomeFSharpCode - let delArgTys = (if isNil delArgTys then [g.unit_ty] else delArgTys) - if (fst (stripFunTy g callerArgTy)).Length = delArgTys.Length - then fty - else calledArgTy - - if isDelegateTy g calledArgTy && isFunTy g callerArgTy then - adjustDelegateTy calledArgTy - - elif isLinqExpressionTy g calledArgTy && isFunTy g callerArgTy then - let origArgTy = calledArgTy - let calledArgTy = destLinqExpressionTy g calledArgTy - if isDelegateTy g calledArgTy then - adjustDelegateTy calledArgTy - else - // BUG 435170: called arg is Expr<'t> where 't is not delegate - such conversion is not legal -> return original type - origArgTy - - elif calledArg.ReflArgInfo.AutoQuote && isQuotedExprTy g calledArgTy && not (isQuotedExprTy g callerArgTy) then - destQuotedExprTy g calledArgTy - - else calledArgTy - - // Adjust the called argument type to take into account whether the caller's argument is M(?arg=Some(3)) or M(arg=1) - // If the called method argument is optional with type Option, then the caller may provide a T, unless their argument is propogating-optional (i.e. isOptCallerArg) - let calledArgTy = - match calledArg.OptArgInfo with - | NotOptional -> calledArgTy - | CalleeSide when not callerArg.IsOptional && isOptionTy g calledArgTy -> destOptionTy g calledArgTy - | CalleeSide | CallerSide _ -> calledArgTy - calledArgTy - - -//------------------------------------------------------------------------- -// CalledMeth -//------------------------------------------------------------------------- - -type CalledMethArgSet<'T> = - { /// The called arguments corresponding to "unnamed" arguments - UnnamedCalledArgs : CalledArg list - /// Any unnamed caller arguments not otherwise assigned - UnnamedCallerArgs : CallerArg<'T> list - /// The called "ParamArray" argument, if any - ParamArrayCalledArgOpt : CalledArg option - /// Any unnamed caller arguments assigned to a "param array" argument - ParamArrayCallerArgs : CallerArg<'T> list - /// Named args - AssignedNamedArgs: AssignedCalledArg<'T> list } - member x.NumUnnamedCallerArgs = x.UnnamedCallerArgs.Length - member x.NumAssignedNamedArgs = x.AssignedNamedArgs.Length - member x.NumUnnamedCalledArgs = x.UnnamedCalledArgs.Length - - -let MakeCalledArgs amap m (minfo:MethInfo) minst = - // Mark up the arguments with their position, so we can sort them back into order later - let paramDatas = minfo.GetParamDatas(amap, m, minst) - paramDatas |> List.mapiSquared (fun i j (ParamData(isParamArrayArg,isOutArg,optArgInfo,callerInfoFlags,nmOpt,reflArgInfo,typeOfCalledArg)) -> - { Position=(i,j) - IsParamArray=isParamArrayArg - OptArgInfo=optArgInfo - CallerInfoInfo=callerInfoFlags - IsOutArg=isOutArg - ReflArgInfo=reflArgInfo - NameOpt=nmOpt - CalledArgumentType=typeOfCalledArg }) - -/// Represents the syntactic matching between a caller of a method and the called method. -/// -/// The constructor takes all the information about the caller and called side of a method, match up named arguments, property setters etc., -/// and returns a CalledMeth object for further analysis. -type CalledMeth<'T> - (infoReader:InfoReader, - nameEnv: NameResolutionEnv option, - isCheckingAttributeCall, - freshenMethInfo,// a function to help generate fresh type variables the property setters methods in generic classes - m, - ad, // the access domain of the place where the call is taking place - minfo:MethInfo, // the method we're attempting to call - calledTyArgs, // the 'called type arguments', i.e. the fresh generic instantiation of the method we're attempting to call - callerTyArgs: TType list, // the 'caller type arguments', i.e. user-given generic instantiation of the method we're attempting to call - pinfoOpt: PropInfo option, // the property related to the method we're attempting to call, if any - callerObjArgTys: TType list, // the types of the actual object argument, if any - curriedCallerArgs: (CallerArg<'T> list * CallerNamedArg<'T> list) list, // the data about any arguments supplied by the caller - allowParamArgs:bool, // do we allow the use of a param args method in its "expanded" form? - allowOutAndOptArgs: bool, // do we allow the use of the transformation that converts out arguments as tuple returns? - tyargsOpt : TType option) // method parameters - = - let g = infoReader.g - let methodRetTy = minfo.GetFSharpReturnTy(infoReader.amap, m, calledTyArgs) - - let fullCurriedCalledArgs = MakeCalledArgs infoReader.amap m minfo calledTyArgs - do assert (fullCurriedCalledArgs.Length = fullCurriedCalledArgs.Length) - - let argSetInfos = - (curriedCallerArgs, fullCurriedCalledArgs) ||> List.map2 (fun (unnamedCallerArgs,namedCallerArgs) fullCalledArgs -> - // Find the arguments not given by name - let unnamedCalledArgs = - fullCalledArgs |> List.filter (fun calledArg -> - match calledArg.NameOpt with - | Some nm -> namedCallerArgs |> List.forall (fun (CallerNamedArg(nm2,_e)) -> nm.idText <> nm2.idText) - | None -> true) - - // See if any of them are 'out' arguments being returned as part of a return tuple - let unnamedCalledArgs, unnamedCalledOptArgs, unnamedCalledOutArgs = - let nUnnamedCallerArgs = unnamedCallerArgs.Length - if allowOutAndOptArgs && nUnnamedCallerArgs < unnamedCalledArgs.Length then - let unnamedCalledArgsTrimmed,unnamedCalledOptOrOutArgs = List.chop nUnnamedCallerArgs unnamedCalledArgs - - // Check if all optional/out arguments are byref-out args - if unnamedCalledOptOrOutArgs |> List.forall (fun x -> x.IsOutArg && isByrefTy g x.CalledArgumentType) then - unnamedCalledArgsTrimmed,[],unnamedCalledOptOrOutArgs - // Check if all optional/out arguments are optional args - elif unnamedCalledOptOrOutArgs |> List.forall (fun x -> x.OptArgInfo.IsOptional) then - unnamedCalledArgsTrimmed,unnamedCalledOptOrOutArgs,[] - // Otherwise drop them on the floor - else - unnamedCalledArgs,[],[] - else - unnamedCalledArgs,[],[] - - let (unnamedCallerArgs,paramArrayCallerArgs),unnamedCalledArgs,paramArrayCalledArgOpt = - let minArgs = unnamedCalledArgs.Length - 1 - let supportsParamArgs = - allowParamArgs && - minArgs >= 0 && - unnamedCalledArgs |> List.last |> (fun calledArg -> calledArg.IsParamArray && isArray1DTy g calledArg.CalledArgumentType) - - if supportsParamArgs && unnamedCallerArgs.Length >= minArgs then - let a,b = List.frontAndBack unnamedCalledArgs - List.chop minArgs unnamedCallerArgs, a, Some(b) - else - (unnamedCallerArgs, []),unnamedCalledArgs, None - - let assignedNamedArgs = - fullCalledArgs |> List.choose (fun calledArg -> - match calledArg.NameOpt with - | Some nm -> - namedCallerArgs |> List.tryPick (fun (CallerNamedArg(nm2,callerArg)) -> - if nm.idText = nm2.idText then Some { NamedArgIdOpt = Some nm2; CallerArg=callerArg; CalledArg=calledArg } - else None) - | _ -> None) - - let unassignedNamedItem = - namedCallerArgs |> List.filter (fun (CallerNamedArg(nm,_e)) -> - fullCalledArgs |> List.forall (fun calledArg -> - match calledArg.NameOpt with - | Some nm2 -> nm.idText <> nm2.idText - | None -> true)) - - let attributeAssignedNamedItems,unassignedNamedItem = - if isCheckingAttributeCall then - // the assignment of names to properties is substantially for attribute specifications - // permits bindings of names to non-mutable fields and properties, so we do that using the old - // reliable code for this later on. - unassignedNamedItem,[] - else - [],unassignedNamedItem - - let assignedNamedProps,unassignedNamedItem = - let returnedObjTy = if minfo.IsConstructor then minfo.EnclosingType else methodRetTy - unassignedNamedItem |> List.splitChoose (fun (CallerNamedArg(id,e) as arg) -> - let nm = id.idText - let pinfos = GetIntrinsicPropInfoSetsOfType infoReader (Some(nm),ad,AllowMultiIntfInstantiations.Yes) IgnoreOverrides id.idRange returnedObjTy - let pinfos = pinfos |> ExcludeHiddenOfPropInfos g infoReader.amap m - match pinfos with - | [pinfo] when pinfo.HasSetter && not pinfo.IsIndexer -> - let pminfo = pinfo.SetterMethod - let pminst = freshenMethInfo m pminfo - Choice1Of2(AssignedItemSetter(id,AssignedPropSetter(pinfo,pminfo, pminst), e)) - | _ -> - let epinfos = - match nameEnv with - | Some(ne) -> ExtensionPropInfosOfTypeInScope infoReader ne (Some(nm), ad) m returnedObjTy - | _ -> [] - match epinfos with - | [pinfo] when pinfo.HasSetter && not pinfo.IsIndexer -> - let pminfo = pinfo.SetterMethod - let pminst = match minfo with - | MethInfo.FSMeth(_,TType.TType_app(_,types),_,_) -> types - | _ -> freshenMethInfo m pminfo - - let pminst = match tyargsOpt with - | Some(TType.TType_app(_, types)) -> types - | _ -> pminst - Choice1Of2(AssignedItemSetter(id,AssignedPropSetter(pinfo,pminfo, pminst), e)) - | _ -> - match infoReader.GetILFieldInfosOfType(Some(nm),ad,m,returnedObjTy) with - | finfo :: _ -> - Choice1Of2(AssignedItemSetter(id,AssignedILFieldSetter(finfo), e)) - | _ -> - match infoReader.TryFindRecdOrClassFieldInfoOfType(nm,m,returnedObjTy) with - | Some rfinfo -> - Choice1Of2(AssignedItemSetter(id,AssignedRecdFieldSetter(rfinfo), e)) - | None -> - Choice2Of2(arg)) - - let names = namedCallerArgs |> List.map (fun (CallerNamedArg(nm,_)) -> nm.idText) - - if (List.noRepeats String.order names).Length <> namedCallerArgs.Length then - errorR(Error(FSComp.SR.typrelNamedArgumentHasBeenAssignedMoreThenOnce(),m)) - - let argSet = { UnnamedCalledArgs=unnamedCalledArgs; UnnamedCallerArgs=unnamedCallerArgs; ParamArrayCalledArgOpt=paramArrayCalledArgOpt; ParamArrayCallerArgs=paramArrayCallerArgs; AssignedNamedArgs=assignedNamedArgs } - - (argSet,assignedNamedProps,unassignedNamedItem,attributeAssignedNamedItems,unnamedCalledOptArgs,unnamedCalledOutArgs)) - - let argSets = argSetInfos |> List.map (fun (x,_,_,_,_,_) -> x) - let assignedNamedProps = argSetInfos |> List.collect (fun (_,x,_,_,_,_) -> x) - let unassignedNamedItems = argSetInfos |> List.collect (fun (_,_,x,_,_,_) -> x) - let attributeAssignedNamedItems = argSetInfos |> List.collect (fun (_,_,_,x,_,_) -> x) - let unnamedCalledOptArgs = argSetInfos |> List.collect (fun (_,_,_,_,x,_) -> x) - let unnamedCalledOutArgs = argSetInfos |> List.collect (fun (_,_,_,_,_,x) -> x) - - member x.infoReader = infoReader - member x.amap = infoReader.amap - - /// the method we're attempting to call - member x.Method=minfo - /// the instantiation of the method we're attempting to call - member x.CalledTyArgs=calledTyArgs - /// the formal instantiation of the method we're attempting to call - member x.CallerTyArgs=callerTyArgs - /// The types of the actual object arguments, if any - member x.CallerObjArgTys=callerObjArgTys - /// The argument analysis for each set of curried arguments - member x.ArgSets=argSets - /// return type - member x.ReturnType=methodRetTy - /// named setters - member x.AssignedItemSetters=assignedNamedProps - /// the property related to the method we're attempting to call, if any - member x.AssociatedPropertyInfo=pinfoOpt - /// unassigned args - member x.UnassignedNamedArgs=unassignedNamedItems - /// args assigned to specify values for attribute fields and properties (these are not necessarily "property sets") - member x.AttributeAssignedNamedArgs=attributeAssignedNamedItems - /// unnamed called optional args: pass defaults for these - member x.UnnamedCalledOptArgs=unnamedCalledOptArgs - /// unnamed called out args: return these as part of the return tuple - member x.UnnamedCalledOutArgs=unnamedCalledOutArgs - - static member GetMethod (x:CalledMeth<'T>) = x.Method - - member x.NumArgSets = x.ArgSets.Length - - member x.HasOptArgs = nonNil x.UnnamedCalledOptArgs - member x.HasOutArgs = nonNil x.UnnamedCalledOutArgs - member x.UsesParamArrayConversion = x.ArgSets |> List.exists (fun argSet -> argSet.ParamArrayCalledArgOpt.IsSome) - member x.ParamArrayCalledArgOpt = x.ArgSets |> List.tryPick (fun argSet -> argSet.ParamArrayCalledArgOpt) - member x.ParamArrayCallerArgs = x.ArgSets |> List.tryPick (fun argSet -> if isSome argSet.ParamArrayCalledArgOpt then Some argSet.ParamArrayCallerArgs else None ) - member x.ParamArrayElementType = - assert (x.UsesParamArrayConversion) - x.ParamArrayCalledArgOpt.Value.CalledArgumentType |> destArrayTy x.amap.g - member x.NumAssignedProps = x.AssignedItemSetters.Length - member x.CalledObjArgTys(m) = x.Method.GetObjArgTypes(x.amap, m, x.CalledTyArgs) - member x.NumCalledTyArgs = x.CalledTyArgs.Length - member x.NumCallerTyArgs = x.CallerTyArgs.Length - - member x.AssignsAllNamedArgs = isNil x.UnassignedNamedArgs - - member x.HasCorrectArity = - (x.NumCalledTyArgs = x.NumCallerTyArgs) && - x.ArgSets |> List.forall (fun argSet -> argSet.NumUnnamedCalledArgs = argSet.NumUnnamedCallerArgs) - - member x.HasCorrectGenericArity = - (x.NumCalledTyArgs = x.NumCallerTyArgs) - - member x.IsAccessible(m,ad) = - IsMethInfoAccessible x.amap m ad x.Method - - member x.HasCorrectObjArgs(m) = - x.CalledObjArgTys(m).Length = x.CallerObjArgTys.Length - - member x.IsCandidate(m,ad) = - x.IsAccessible(m,ad) && - x.HasCorrectArity && - x.HasCorrectObjArgs(m) && - x.AssignsAllNamedArgs - - member x.AssignedUnnamedArgs = - // We use Seq.map2 to tolerate there being mismatched caller/called args - x.ArgSets |> List.map (fun argSet -> - (argSet.UnnamedCalledArgs, argSet.UnnamedCallerArgs) ||> Seq.map2 (fun calledArg callerArg -> - { NamedArgIdOpt=None; CalledArg=calledArg; CallerArg=callerArg }) |> Seq.toList) - - member x.AssignedNamedArgs = - x.ArgSets |> List.map (fun argSet -> argSet.AssignedNamedArgs) - - member x.AllUnnamedCalledArgs = x.ArgSets |> List.collect (fun x -> x.UnnamedCalledArgs) - member x.TotalNumUnnamedCalledArgs = x.ArgSets |> List.sumBy (fun x -> x.NumUnnamedCalledArgs) - member x.TotalNumUnnamedCallerArgs = x.ArgSets |> List.sumBy (fun x -> x.NumUnnamedCallerArgs) - member x.TotalNumAssignedNamedArgs = x.ArgSets |> List.sumBy (fun x -> x.NumAssignedNamedArgs) - -let NamesOfCalledArgs (calledArgs: CalledArg list) = - calledArgs |> List.choose (fun x -> x.NameOpt) - -//------------------------------------------------------------------------- -// Helpers dealing with propagating type information in method overload resolution -//------------------------------------------------------------------------- - -type ArgumentAnalysis = - | NoInfo - | ArgDoesNotMatch - | CallerLambdaHasArgTypes of TType list - | CalledArgMatchesType of TType - -let InferLambdaArgsForLambdaPropagation origRhsExpr = - let rec loop e = - match e with - | SynExpr.Lambda(_,_,_,rest,_) -> 1 + loop rest - | SynExpr.MatchLambda _ -> 1 - | _ -> 0 - loop origRhsExpr - -let ExamineArgumentForLambdaPropagation (infoReader:InfoReader) (arg: AssignedCalledArg) = - let g = infoReader.g - // Find the explicit lambda arguments of the caller. Ignore parentheses. - let argExpr = match arg.CallerArg.Expr with SynExpr.Paren(x,_,_,_) -> x | x -> x - let countOfCallerLambdaArg = InferLambdaArgsForLambdaPropagation argExpr - // Adjust for Expression<_>, Func<_,_>, ... - let adjustedCalledArgTy = AdjustCalledArgType infoReader false arg.CalledArg arg.CallerArg - if countOfCallerLambdaArg > 0 then - // Decompose the explicit function type of the target - let calledLambdaArgTys,_calledLambdaRetTy = Tastops.stripFunTy g adjustedCalledArgTy - if calledLambdaArgTys.Length >= countOfCallerLambdaArg then - // success - CallerLambdaHasArgTypes calledLambdaArgTys - elif isDelegateTy g (if isLinqExpressionTy g adjustedCalledArgTy then destLinqExpressionTy g adjustedCalledArgTy else adjustedCalledArgTy) then - ArgDoesNotMatch // delegate arity mismatch - else - NoInfo // not a function type on the called side - no information - else CalledArgMatchesType(adjustedCalledArgTy) // not a lambda on the caller side - push information from caller to called - -let ExamineMethodForLambdaPropagation(x:CalledMeth) = - let unnamedInfo = x.AssignedUnnamedArgs |> List.mapSquared (ExamineArgumentForLambdaPropagation x.infoReader) - let namedInfo = x.AssignedNamedArgs |> List.mapSquared (fun arg -> (arg.NamedArgIdOpt.Value, ExamineArgumentForLambdaPropagation x.infoReader arg)) - if unnamedInfo |> List.existsSquared (function CallerLambdaHasArgTypes _ -> true | _ -> false) || - namedInfo |> List.existsSquared (function (_,CallerLambdaHasArgTypes _) -> true | _ -> false) then - Some (unnamedInfo, namedInfo) - else - None - - - -//------------------------------------------------------------------------- -// "Type Completion" inference and a few other checks at the end of the inference scope -//------------------------------------------------------------------------- - - -/// "Type Completion" inference and a few other checks at the end of the inference scope -let FinalTypeDefinitionChecksAtEndOfInferenceScope (infoReader:InfoReader, nenv, sink, isImplementation, denv) (tycon:Tycon) = - - let g = infoReader.g - let amap = infoReader.amap - - let tcaug = tycon.TypeContents - tcaug.tcaug_closed <- true - - // Note you only have to explicitly implement 'System.IComparable' to customize structural comparison AND equality on F# types - if isImplementation && -#if EXTENSIONTYPING - not tycon.IsProvidedGeneratedTycon && -#endif - isNone tycon.GeneratedCompareToValues && - tycon.HasInterface g g.mk_IComparable_ty && - not (tycon.HasOverride g "Equals" [g.obj_ty]) && - not tycon.IsFSharpInterfaceTycon - then - (* Warn when we're doing this for class types *) - if AugmentWithHashCompare.TyconIsCandidateForAugmentationWithEquals g tycon then - warning(Error(FSComp.SR.typrelTypeImplementsIComparableShouldOverrideObjectEquals(tycon.DisplayName),tycon.Range)) - else - warning(Error(FSComp.SR.typrelTypeImplementsIComparableDefaultObjectEqualsProvided(tycon.DisplayName),tycon.Range)) - - AugmentWithHashCompare.CheckAugmentationAttribs isImplementation g amap tycon - // Check some conditions about generic comparison and hashing. We can only check this condition after we've done the augmentation - if isImplementation -#if EXTENSIONTYPING - && not tycon.IsProvidedGeneratedTycon -#endif - then - let tcaug = tycon.TypeContents - let m = tycon.Range - let hasExplicitObjectGetHashCode = tycon.HasOverride g "GetHashCode" [] - let hasExplicitObjectEqualsOverride = tycon.HasOverride g "Equals" [g.obj_ty] - - if (isSome tycon.GeneratedHashAndEqualsWithComparerValues) && - (hasExplicitObjectGetHashCode || hasExplicitObjectEqualsOverride) then - errorR(Error(FSComp.SR.typrelExplicitImplementationOfGetHashCodeOrEquals(tycon.DisplayName),m)) - - if not hasExplicitObjectEqualsOverride && hasExplicitObjectGetHashCode then - warning(Error(FSComp.SR.typrelExplicitImplementationOfGetHashCode(tycon.DisplayName),m)) - - if hasExplicitObjectEqualsOverride && not hasExplicitObjectGetHashCode then - warning(Error(FSComp.SR.typrelExplicitImplementationOfEquals(tycon.DisplayName),m)) - - - // remember these values to ensure we don't generate these methods during codegen - tcaug.SetHasObjectGetHashCode hasExplicitObjectGetHashCode - - if not tycon.IsHiddenReprTycon - && not tycon.IsTypeAbbrev - && not tycon.IsMeasureableReprTycon - && not tycon.IsAsmReprTycon - && not tycon.IsFSharpInterfaceTycon - && not tycon.IsFSharpDelegateTycon then - - DispatchSlotChecking.CheckImplementationRelationAtEndOfInferenceScope (infoReader,denv,nenv,sink,tycon,isImplementation) - -//------------------------------------------------------------------------- -// Additional helpers for type checking and constraint solving -//------------------------------------------------------------------------- - /// "Single Feasible Type" inference /// Look for the unique supertype of ty2 for which ty2 :> ty1 might feasibly hold let FindUniqueFeasibleSupertype g amap m ty1 ty2 = @@ -2019,661 +295,3 @@ let FindUniqueFeasibleSupertype g amap m ty1 ty2 = supertypes |> List.tryFind (TypeFeasiblySubsumesType 0 g amap m ty1 NoCoerce) - -/// Get the methods relevant to determining if a uniquely-identified-override exists based on the syntactic information -/// at the member signature prior to type inference. This is used to pre-assign type information if it does -let GetAbstractMethInfosForSynMethodDecl(infoReader:InfoReader,ad,memberName:Ident,bindm,typToSearchForAbstractMembers,valSynData) = - let minfos = - match typToSearchForAbstractMembers with - | _,Some(SlotImplSet(_, dispatchSlotsKeyed,_,_)) -> - NameMultiMap.find memberName.idText dispatchSlotsKeyed |> List.map (fun (RequiredSlot(dispatchSlot,_)) -> dispatchSlot) - | ty, None -> - GetIntrinsicMethInfosOfType infoReader (Some(memberName.idText), ad, AllowMultiIntfInstantiations.Yes) IgnoreOverrides bindm ty - let dispatchSlots = minfos |> List.filter (fun minfo -> minfo.IsDispatchSlot) - let topValSynArities = SynInfo.AritiesOfArgs valSynData - let topValSynArities = if topValSynArities.Length > 0 then topValSynArities.Tail else topValSynArities - let dispatchSlotsArityMatch = dispatchSlots |> List.filter (fun minfo -> minfo.NumArgs = topValSynArities) - dispatchSlots,dispatchSlotsArityMatch - -/// Get the properties relevant to determining if a uniquely-identified-override exists based on the syntactic information -/// at the member signature prior to type inference. This is used to pre-assign type information if it does -let GetAbstractPropInfosForSynPropertyDecl(infoReader:InfoReader,ad,memberName:Ident,bindm,typToSearchForAbstractMembers,_k,_valSynData) = - let pinfos = - match typToSearchForAbstractMembers with - | _,Some(SlotImplSet(_,_,_,reqdProps)) -> - reqdProps |> List.filter (fun pinfo -> pinfo.PropertyName = memberName.idText) - | ty, None -> - GetIntrinsicPropInfosOfType infoReader (Some(memberName.idText), ad, AllowMultiIntfInstantiations.Yes) IgnoreOverrides bindm ty - - let dispatchSlots = pinfos |> List.filter (fun pinfo -> pinfo.IsVirtualProperty) - dispatchSlots - -//------------------------------------------------------------------------- -// Additional helpers for building method calls and doing TAST generation -//------------------------------------------------------------------------- - -/// Is this a 'base' call (in the sense of C#) -let IsBaseCall objArgs = - match objArgs with - | [Expr.Val(v,_,_)] when v.BaseOrThisInfo = BaseVal -> true - | _ -> false - -/// Compute whether we insert a 'coerce' on the 'this' pointer for an object model call -/// For example, when calling an interface method on a struct, or a method on a constrained -/// variable type. -let ComputeConstrainedCallInfo g amap m (objArgs,minfo:MethInfo) = - match objArgs with - | [objArgExpr] when not minfo.IsExtensionMember -> - let methObjTy = minfo.EnclosingType - let objArgTy = tyOfExpr g objArgExpr - if TypeDefinitelySubsumesTypeNoCoercion 0 g amap m methObjTy objArgTy - // Constrained calls to class types can only ever be needed for the three class types that - // are base types of value types - || (isClassTy g methObjTy && - (not (typeEquiv g methObjTy g.system_Object_typ || - typeEquiv g methObjTy g.system_Value_typ || - typeEquiv g methObjTy g.system_Enum_typ))) then - None - else - // The object argument is a value type or variable type and the target method is an interface or System.Object - // type. A .NET 2.0 generic constrained call is required - Some objArgTy - | _ -> - None - - -/// Adjust the 'this' pointer before making a call -/// Take the address of a struct, and coerce to an interface/base/constraint type if necessary -let TakeObjAddrForMethodCall g amap (minfo:MethInfo) isMutable m objArgs f = - let ccallInfo = ComputeConstrainedCallInfo g amap m (objArgs,minfo) - let mustTakeAddress = - (minfo.IsStruct && not minfo.IsExtensionMember) // don't take the address of a struct when passing to an extension member - || - (match ccallInfo with - | Some _ -> true - | None -> false) - let wrap,objArgs = - match objArgs with - | [objArgExpr] -> - let objArgTy = tyOfExpr g objArgExpr - let wrap,objArgExpr' = mkExprAddrOfExpr g mustTakeAddress (isSome ccallInfo) isMutable objArgExpr None m - - // Extension members and calls to class constraints may need a coercion for their object argument - let objArgExpr' = - if isNone ccallInfo && // minfo.IsExtensionMember && minfo.IsStruct && - not (TypeDefinitelySubsumesTypeNoCoercion 0 g amap m minfo.EnclosingType objArgTy) then - mkCoerceExpr(objArgExpr',minfo.EnclosingType,m,objArgTy) - else - objArgExpr' - - wrap,[objArgExpr'] - - | _ -> - (fun x -> x), objArgs - let e,ety = f ccallInfo objArgs - wrap e,ety - -//------------------------------------------------------------------------- -// Build method calls. -//------------------------------------------------------------------------- - -#if EXTENSIONTYPING -// This imports a provided method, and checks if it is a known compiler intrinsic like "1 + 2" -let TryImportProvidedMethodBaseAsLibraryIntrinsic (amap:Import.ImportMap, m:range, mbase: Tainted) = - let methodName = mbase.PUntaint((fun x -> x.Name),m) - let declaringType = Import.ImportProvidedType amap m (mbase.PApply((fun x -> x.DeclaringType),m)) - if isAppTy amap.g declaringType then - let declaringEntity = tcrefOfAppTy amap.g declaringType - if not declaringEntity.IsLocalRef && ccuEq declaringEntity.nlr.Ccu amap.g.fslibCcu then - match amap.g.knownIntrinsics.TryGetValue ((declaringEntity.LogicalName, methodName)) with - | true,vref -> Some vref - | _ -> - match amap.g.knownFSharpCoreModules.TryGetValue(declaringEntity.LogicalName) with - | true,modRef -> - match modRef.ModuleOrNamespaceType.AllValsByLogicalName |> Seq.tryPick (fun (KeyValue(_,v)) -> if v.CompiledName = methodName then Some v else None) with - | Some v -> Some (mkNestedValRef modRef v) - | None -> None - | _ -> None - else - None - else - None -#endif - - -/// Build an expression that calls a given method info. -/// This is called after overload resolution, and also to call other -/// methods such as 'setters' for properties. -// tcVal: used to convert an F# value into an expression. See tc.fs. -// isProp: is it a property get? -// minst: the instantiation to apply for a generic method -// objArgs: the 'this' argument, if any -// args: the arguments, if any -let BuildMethodCall tcVal g amap isMutable m isProp minfo valUseFlags minst objArgs args = - - let direct = IsBaseCall objArgs - - TakeObjAddrForMethodCall g amap minfo isMutable m objArgs (fun ccallInfo objArgs -> - let allArgs = (objArgs @ args) - let valUseFlags = - if (direct && (match valUseFlags with NormalValUse -> true | _ -> false)) then - VSlotDirectCall - else - match ccallInfo with - | Some ty -> - // printfn "possible constrained call to '%s' at %A" minfo.LogicalName m - PossibleConstrainedCall ty - | None -> - valUseFlags - - match minfo with -#if EXTENSIONTYPING - // By this time this is an erased method info, e.g. one returned from an expression - // REVIEW: copied from tastops, which doesn't allow protected methods - | ProvidedMeth (amap,providedMeth,_,_) -> - // TODO: there is a fair bit of duplication here with mk_il_minfo_call. We should be able to merge these - - /// Build an expression node that is a call to a extension method in a generated assembly - let enclTy = minfo.EnclosingType - // prohibit calls to methods that are declared in specific array types (Get,Set,Address) - // these calls are provided by the runtime and should not be called from the user code - if isArrayTy g enclTy then - let tpe = TypeProviderError(FSComp.SR.tcRuntimeSuppliedMethodCannotBeUsedInUserCode(minfo.DisplayName), providedMeth.TypeProviderDesignation, m) - error (tpe) - let valu = isStructTy g enclTy - let isCtor = minfo.IsConstructor - if minfo.IsClassConstructor then - error (InternalError (minfo.LogicalName ^": cannot call a class constructor",m)) - let useCallvirt = not valu && not direct && minfo.IsVirtual - let isProtected = minfo.IsProtectedAccessiblity - let exprTy = if isCtor then enclTy else minfo.GetFSharpReturnTy(amap, m, minst) - match TryImportProvidedMethodBaseAsLibraryIntrinsic (amap, m, providedMeth) with - | Some fsValRef -> - //reraise() calls are converted to TOp.Reraise in the type checker. So if a provided expression includes a reraise call - // we must put it in that form here. - if valRefEq amap.g fsValRef amap.g.reraise_vref then - mkReraise m exprTy, exprTy - else - let vexp, vexpty = tcVal fsValRef valUseFlags (minfo.DeclaringTypeInst @ minst) m - BuildFSharpMethodApp g m fsValRef vexp vexpty allArgs - | None -> - let ilMethRef = Import.ImportProvidedMethodBaseAsILMethodRef amap m providedMeth - let isNewObj = isCtor && (match valUseFlags with NormalValUse -> true | _ -> false) - let actualTypeInst = - if isTupleTy g enclTy then argsOfAppTy g (mkCompiledTupleTy g (destTupleTy g enclTy)) // provided expressions can include method calls that get properties of tuple types - elif isFunTy g enclTy then [ domainOfFunTy g enclTy; rangeOfFunTy g enclTy ] // provided expressions can call Invoke - else minfo.DeclaringTypeInst - let actualMethInst = minst - let retTy = (if not isCtor && (ilMethRef.ReturnType = ILType.Void) then [] else [exprTy]) - let noTailCall = false - let expr = Expr.Op(TOp.ILCall(useCallvirt,isProtected,valu,isNewObj,valUseFlags,isProp,noTailCall,ilMethRef,actualTypeInst,actualMethInst, retTy),[],allArgs,m) - expr,exprTy - -#endif - - // Build a call to a .NET method - | ILMeth(_,ilMethInfo,_) -> - BuildILMethInfoCall g amap m isProp ilMethInfo valUseFlags minst direct allArgs - - // Build a call to an F# method - | FSMeth(_, _, vref, _) -> - - // Go see if this is a use of a recursive definition... Note we know the value instantiation - // we want to use so we pass that in order not to create a new one. - let vexp, vexpty = tcVal vref valUseFlags (minfo.DeclaringTypeInst @ minst) m - BuildFSharpMethodApp g m vref vexp vexpty allArgs - - // Build a 'call' to a struct default constructor - | DefaultStructCtor (g,typ) -> - if not (TypeHasDefaultValue g m typ) then - errorR(Error(FSComp.SR.tcDefaultStructConstructorCall(),m)) - mkDefault (m,typ), typ) - -//------------------------------------------------------------------------- -// Build delegate constructions (lambdas/functions to delegates) -//------------------------------------------------------------------------- - -/// Implements the elaborated form of adhoc conversions from functions to delegates at member callsites -let BuildNewDelegateExpr (eventInfoOpt:EventInfo option, g, amap, delegateTy, invokeMethInfo:MethInfo, delArgTys, f, fty, m) = - let slotsig = invokeMethInfo.GetSlotSig(amap, m) - let delArgVals,expr = - let topValInfo = ValReprInfo([],List.replicate (List.length delArgTys) ValReprInfo.unnamedTopArg, ValReprInfo.unnamedRetVal) - - // Try to pull apart an explicit lambda and use it directly - // Don't do this in the case where we're adjusting the arguments of a function used to build a .NET-compatible event handler - let lambdaContents = - if isSome eventInfoOpt then - None - else - tryDestTopLambda g amap topValInfo (f, fty) - match lambdaContents with - | None -> - - if List.exists (isByrefTy g) delArgTys then - error(Error(FSComp.SR.tcFunctionRequiresExplicitLambda(List.length delArgTys),m)) - - let delArgVals = delArgTys |> List.map (fun argty -> fst (mkCompGenLocal m "delegateArg" argty)) - let expr = - let args = - match eventInfoOpt with - | Some einfo -> - match delArgVals with - | [] -> error(nonStandardEventError einfo.EventName m) - | h :: _ when not (isObjTy g h.Type) -> error(nonStandardEventError einfo.EventName m) - | h :: t -> [exprForVal m h; mkTupledVars g m t] - | None -> - if isNil delArgTys then [mkUnit g m] else List.map (exprForVal m) delArgVals - mkApps g ((f,fty),[],args,m) - delArgVals,expr - - | Some _ -> - if isNil delArgTys then [], mkApps g ((f,fty),[],[mkUnit g m],m) - else - let _,_,_,vsl,body,_ = IteratedAdjustArityOfLambda g amap topValInfo f - List.concat vsl, body - - let meth = TObjExprMethod(slotsig, [], [], [delArgVals], expr, m) - mkObjExpr(delegateTy,None,BuildObjCtorCall g m,[meth],[],m) - -let CoerceFromFSharpFuncToDelegate g amap infoReader ad callerArgTy m callerArgExpr delegateTy = - let (SigOfFunctionForDelegate(invokeMethInfo,delArgTys,_,_)) = GetSigOfFunctionForDelegate infoReader delegateTy m ad - BuildNewDelegateExpr (None, g, amap, delegateTy, invokeMethInfo, delArgTys, callerArgExpr, callerArgTy, m) - - -//------------------------------------------------------------------------- -// Import provided expressions -//------------------------------------------------------------------------- - - -#if EXTENSIONTYPING -// This file is not a great place for this functionality to sit, it's here because of BuildMethodCall -module ProvidedMethodCalls = - - let private convertConstExpr g amap m (constant : Tainted) = - let (obj,objTy) = constant.PApply2(id,m) - let ty = Import.ImportProvidedType amap m objTy - let normTy = normalizeEnumTy g ty - obj.PUntaint((fun v -> - let fail() = raise <| TypeProviderError(FSComp.SR.etUnsupportedConstantType(v.GetType().ToString()), constant.TypeProviderDesignation, m) - try - match v with - | null -> mkNull m ty - | _ when typeEquiv g normTy g.bool_ty -> Expr.Const(Const.Bool(v :?> bool), m, ty) - | _ when typeEquiv g normTy g.sbyte_ty -> Expr.Const(Const.SByte(v :?> sbyte), m, ty) - | _ when typeEquiv g normTy g.byte_ty -> Expr.Const(Const.Byte(v :?> byte), m, ty) - | _ when typeEquiv g normTy g.int16_ty -> Expr.Const(Const.Int16(v :?> int16), m, ty) - | _ when typeEquiv g normTy g.uint16_ty -> Expr.Const(Const.UInt16(v :?> uint16), m, ty) - | _ when typeEquiv g normTy g.int32_ty -> Expr.Const(Const.Int32(v :?> int32), m, ty) - | _ when typeEquiv g normTy g.uint32_ty -> Expr.Const(Const.UInt32(v :?> uint32), m, ty) - | _ when typeEquiv g normTy g.int64_ty -> Expr.Const(Const.Int64(v :?> int64), m, ty) - | _ when typeEquiv g normTy g.uint64_ty -> Expr.Const(Const.UInt64(v :?> uint64), m, ty) - | _ when typeEquiv g normTy g.nativeint_ty -> Expr.Const(Const.IntPtr(v :?> int64), m, ty) - | _ when typeEquiv g normTy g.unativeint_ty -> Expr.Const(Const.UIntPtr(v :?> uint64), m, ty) - | _ when typeEquiv g normTy g.float32_ty -> Expr.Const(Const.Single(v :?> float32), m, ty) - | _ when typeEquiv g normTy g.float_ty -> Expr.Const(Const.Double(v :?> float), m, ty) - | _ when typeEquiv g normTy g.char_ty -> Expr.Const(Const.Char(v :?> char), m, ty) - | _ when typeEquiv g normTy g.string_ty -> Expr.Const(Const.String(v :?> string), m, ty) - | _ when typeEquiv g normTy g.decimal_ty -> Expr.Const(Const.Decimal(v :?> decimal), m, ty) - | _ when typeEquiv g normTy g.unit_ty -> Expr.Const(Const.Unit, m, ty) - | _ -> fail() - with _ -> - fail() - ), range=m) - - /// Erasure over System.Type. - /// - /// This is a reimplementation of the logic of provided-type erasure, working entirely over (tainted, provided) System.Type - /// values. This is used when preparing ParameterInfo objects to give to the provider in GetInvokerExpression. - /// These ParameterInfo have erased ParameterType - giving the provider an erased type makes it considerably easier - /// to implement a correct GetInvokerExpression. - /// - /// Ideally we would implement this operation by converting to an F# TType using ImportSystemType, and then erasing, and then converting - /// back to System.Type. However, there is currently no way to get from an arbitrary F# TType (even the TType for - /// System.Object) to a System.Type to give to the type provider. - let eraseSystemType (amap,m,inputType) = - let rec loop (st:Tainted) = - if st.PUntaint((fun st -> st.IsGenericParameter),m) then st - elif st.PUntaint((fun st -> st.IsArray),m) then - let et = st.PApply((fun st -> st.GetElementType()),m) - let rank = st.PUntaint((fun st -> st.GetArrayRank()),m) - (loop et).PApply((fun st -> ProvidedType.CreateNoContext(if rank = 1 then st.RawSystemType.MakeArrayType() else st.RawSystemType.MakeArrayType(rank))),m) - elif st.PUntaint((fun st -> st.IsByRef),m) then - let et = st.PApply((fun st -> st.GetElementType()),m) - (loop et).PApply((fun st -> ProvidedType.CreateNoContext(st.RawSystemType.MakeByRefType())),m) - elif st.PUntaint((fun st -> st.IsPointer),m) then - let et = st.PApply((fun st -> st.GetElementType()),m) - (loop et).PApply((fun st -> ProvidedType.CreateNoContext(st.RawSystemType.MakePointerType())),m) - else - let isGeneric = st.PUntaint((fun st -> st.IsGenericType),m) - let headType = if isGeneric then st.PApply((fun st -> st.GetGenericTypeDefinition()),m) else st - // We import in order to use IsProvidedErasedTycon, to make sure we at least don't reinvent that - let headTypeAsFSharpType = Import.ImportProvidedNamedType amap m headType - if headTypeAsFSharpType.IsProvidedErasedTycon then - let baseType = - st.PApply((fun st -> - match st.BaseType with - | null -> ProvidedType.CreateNoContext(typeof) // it might be an interface - | st -> st),m) - loop baseType - else - if isGeneric then - let genericArgs = st.PApplyArray((fun st -> st.GetGenericArguments()),"GetGenericArguments",m) - let typars = headTypeAsFSharpType.Typars(m) - // Drop the generic arguments that don't correspond to type arguments, i.e. are units-of-measure - let genericArgs = - [| for (genericArg,tp) in Seq.zip genericArgs typars do - if tp.Kind = TyparKind.Type then - yield genericArg |] - - if genericArgs.Length = 0 then - headType - else - let erasedArgTys = genericArgs |> Array.map loop - headType.PApply((fun st -> - let erasedArgTys = erasedArgTys |> Array.map (fun a -> a.PUntaintNoFailure (fun x -> x.RawSystemType)) - ProvidedType.CreateNoContext(st.RawSystemType.MakeGenericType erasedArgTys)),m) - else - st - loop inputType - - let convertProvidedExpressionToExprAndWitness tcVal (thisArg:Expr option, - allArgs:Exprs, - paramVars:Tainted[], - g,amap,mut,isProp,isSuperInit,m, - expr:Tainted) = - let varConv = - [ for (v,e) in Seq.zip (paramVars |> Seq.map (fun x -> x.PUntaint(id,m))) (Option.toList thisArg @ allArgs) do - yield (v,(None,e)) ] - |> Dictionary.ofList - - let rec exprToExprAndWitness top (ea:Tainted) = - let fail() = error(Error(FSComp.SR.etUnsupportedProvidedExpression(ea.PUntaint((fun etree -> etree.UnderlyingExpressionString), m)),m)) - match ea with - | Tainted.Null -> error(Error(FSComp.SR.etNullProvidedExpression(ea.TypeProviderDesignation),m)) - | _ -> - match ea.PApplyOption((function ProvidedTypeAsExpr x -> Some x | _ -> None), m) with - | Some info -> - let (expr,targetTy) = info.PApply2(id,m) - let srcExpr = exprToExpr expr - let targetTy = Import.ImportProvidedType amap m (targetTy.PApply(id,m)) - let sourceTy = Import.ImportProvidedType amap m (expr.PApply((fun e -> e.Type),m)) - let te = mkCoerceIfNeeded g targetTy sourceTy srcExpr - None, (te, tyOfExpr g te) - | None -> - match ea.PApplyOption((function ProvidedTypeTestExpr x -> Some x | _ -> None), m) with - | Some info -> - let (expr,targetTy) = info.PApply2(id,m) - let srcExpr = exprToExpr expr - let targetTy = Import.ImportProvidedType amap m (targetTy.PApply(id,m)) - let te = mkCallTypeTest g m targetTy srcExpr - None, (te, tyOfExpr g te) - | None -> - match ea.PApplyOption((function ProvidedIfThenElseExpr x -> Some x | _ -> None), m) with - | Some info -> - let test,thenBranch,elseBranch = info.PApply3(id,m) - let testExpr = exprToExpr test - let ifTrueExpr = exprToExpr thenBranch - let ifFalseExpr = exprToExpr elseBranch - let te = mkCond NoSequencePointAtStickyBinding SuppressSequencePointAtTarget m (tyOfExpr g ifTrueExpr) testExpr ifTrueExpr ifFalseExpr - None, (te, tyOfExpr g te) - | None -> - match ea.PApplyOption((function ProvidedVarExpr x -> Some x | _ -> None), m) with - | Some info -> - let _,vTe = varToExpr info - None, (vTe, tyOfExpr g vTe) - | None -> - match ea.PApplyOption((function ProvidedConstantExpr x -> Some x | _ -> None), m) with - | Some info -> - let ce = convertConstExpr g amap m info - None, (ce, tyOfExpr g ce) - | None -> - match ea.PApplyOption((function ProvidedNewTupleExpr x -> Some x | _ -> None), m) with - | Some info -> - let elems = info.PApplyArray(id, "GetInvokerExpresson",m) - let elemsT = elems |> Array.map exprToExpr |> Array.toList - let exprT = mkTupledNoTypes g m elemsT - None, (exprT, tyOfExpr g exprT) - | None -> - match ea.PApplyOption((function ProvidedNewArrayExpr x -> Some x | _ -> None), m) with - | Some info -> - let ty,elems = info.PApply2(id,m) - let tyT = Import.ImportProvidedType amap m ty - let elems = elems.PApplyArray(id, "GetInvokerExpresson",m) - let elemsT = elems |> Array.map exprToExpr |> Array.toList - let exprT = Expr.Op(TOp.Array, [tyT],elemsT,m) - None, (exprT, tyOfExpr g exprT) - | None -> - match ea.PApplyOption((function ProvidedTupleGetExpr x -> Some x | _ -> None), m) with - | Some info -> - let inp,n = info.PApply2(id, m) - let inpT = inp |> exprToExpr - // if type of expression is erased type then we need convert it to the underlying base type - let typeOfExpr = - let t = tyOfExpr g inpT - stripTyEqnsWrtErasure EraseMeasures g t - let tysT = tryDestTupleTy g typeOfExpr - let exprT = mkTupleFieldGet (inpT, tysT, n.PUntaint(id,m), m) - None, (exprT, tyOfExpr g exprT) - | None -> - match ea.PApplyOption((function ProvidedLambdaExpr x -> Some x | _ -> None), m) with - | Some info -> - let v,b = info.PApply2(id, m) - let vT = addVar v - let bT = exprToExpr b - removeVar v - let exprT = mkLambda m vT (bT, tyOfExpr g bT) - None, (exprT, tyOfExpr g exprT) - | None -> - match ea.PApplyOption((function ProvidedLetExpr x -> Some x | _ -> None), m) with - | Some info -> - let v,e,b = info.PApply3(id, m) - let eT = exprToExpr e - let vT = addVar v - let bT = exprToExpr b - removeVar v - let exprT = mkCompGenLet m vT eT bT - None, (exprT, tyOfExpr g exprT) - | None -> - match ea.PApplyOption((function ProvidedVarSetExpr x -> Some x | _ -> None), m) with - | Some info -> - let v,e = info.PApply2(id, m) - let eT = exprToExpr e - let vTopt,_ = varToExpr v - match vTopt with - | None -> - fail() - | Some vT -> - let exprT = mkValSet m (mkLocalValRef vT) eT - None, (exprT, tyOfExpr g exprT) - | None -> - match ea.PApplyOption((function ProvidedWhileLoopExpr x -> Some x | _ -> None), m) with - | Some info -> - let guardExpr,bodyExpr = info.PApply2(id, m) - let guardExprT = exprToExpr guardExpr - let bodyExprT = exprToExpr bodyExpr - let exprT = mkWhile g (SequencePointInfoForWhileLoop.NoSequencePointAtWhileLoop,SpecialWhileLoopMarker.NoSpecialWhileLoopMarker, guardExprT, bodyExprT, m) - None, (exprT, tyOfExpr g exprT) - | None -> - match ea.PApplyOption((function ProvidedForIntegerRangeLoopExpr x -> Some x | _ -> None), m) with - | Some info -> - let v,e1,e2,e3 = info.PApply4(id, m) - let e1T = exprToExpr e1 - let e2T = exprToExpr e2 - let vT = addVar v - let e3T = exprToExpr e3 - removeVar v - let exprT = mkFastForLoop g (SequencePointInfoForForLoop.NoSequencePointAtForLoop,m,vT,e1T,true,e2T,e3T) - None, (exprT, tyOfExpr g exprT) - | None -> - match ea.PApplyOption((function ProvidedNewDelegateExpr x -> Some x | _ -> None), m) with - | Some info -> - let delegateTy,boundVars,delegateBodyExpr = info.PApply3(id, m) - let delegateTyT = Import.ImportProvidedType amap m delegateTy - let vs = boundVars.PApplyArray(id, "GetInvokerExpresson",m) |> Array.toList - let vsT = List.map addVar vs - let delegateBodyExprT = exprToExpr delegateBodyExpr - List.iter removeVar vs - let lambdaExpr = mkLambdas m [] vsT (delegateBodyExprT, tyOfExpr g delegateBodyExprT) - let lambdaExprTy = tyOfExpr g lambdaExpr - let infoReader = InfoReader(g, amap) - let exprT = CoerceFromFSharpFuncToDelegate g amap infoReader AccessorDomain.AccessibleFromSomewhere lambdaExprTy m lambdaExpr delegateTyT - None, (exprT, tyOfExpr g exprT) - | None -> -#if PROVIDED_ADDRESS_OF - match ea.PApplyOption((function ProvidedAddressOfExpr x -> Some x | _ -> None), m) with - | Some e -> - let eT = exprToExpr e - let wrap,ce = mkExprAddrOfExpr g true false DefinitelyMutates eT None m - let ce = wrap ce - None, (ce, tyOfExpr g ce) - | None -> -#endif - match ea.PApplyOption((function ProvidedDefaultExpr x -> Some x | _ -> None), m) with - | Some pty -> - let ty = Import.ImportProvidedType amap m pty - let ce = mkDefault (m, ty) - None, (ce, tyOfExpr g ce) - | None -> - match ea.PApplyOption((function ProvidedCallExpr c -> Some c | _ -> None), m) with - | Some info -> - methodCallToExpr top ea info - | None -> - match ea.PApplyOption((function ProvidedSequentialExpr c -> Some c | _ -> None), m) with - | Some info -> - let e1,e2 = info.PApply2(id, m) - let e1T = exprToExpr e1 - let e2T = exprToExpr e2 - let ce = mkCompGenSequential m e1T e2T - None, (ce, tyOfExpr g ce) - | None -> - match ea.PApplyOption((function ProvidedTryFinallyExpr c -> Some c | _ -> None), m) with - | Some info -> - let e1,e2 = info.PApply2(id, m) - let e1T = exprToExpr e1 - let e2T = exprToExpr e2 - let ce = mkTryFinally g (e1T,e2T,m,tyOfExpr g e1T,SequencePointInfoForTry.NoSequencePointAtTry,SequencePointInfoForFinally.NoSequencePointAtFinally) - None, (ce, tyOfExpr g ce) - | None -> - match ea.PApplyOption((function ProvidedTryWithExpr c -> Some c | _ -> None), m) with - | Some info -> - let bT = exprToExpr (info.PApply((fun (x,_,_,_,_) -> x), m)) - let v1 = info.PApply((fun (_,x,_,_,_) -> x), m) - let v1T = addVar v1 - let e1T = exprToExpr (info.PApply((fun (_,_,x,_,_) -> x), m)) - removeVar v1 - let v2 = info.PApply((fun (_,_,_,x,_) -> x), m) - let v2T = addVar v2 - let e2T = exprToExpr (info.PApply((fun (_,_,_,_,x) -> x), m)) - removeVar v2 - let ce = mkTryWith g (bT,v1T,e1T,v2T,e2T,m,tyOfExpr g bT,SequencePointInfoForTry.NoSequencePointAtTry,SequencePointInfoForWith.NoSequencePointAtWith) - None, (ce, tyOfExpr g ce) - | None -> - match ea.PApplyOption((function ProvidedNewObjectExpr c -> Some c | _ -> None), m) with - | Some info -> - None, ctorCallToExpr info - | None -> - fail() - - - and ctorCallToExpr (ne:Tainted<_>) = - let (ctor,args) = ne.PApply2(id,m) - let targetMethInfo = ProvidedMeth(amap,ctor.PApply((fun ne -> upcast ne),m),None,m) - let objArgs = [] - let arguments = [ for ea in args.PApplyArray(id, "GetInvokerExpresson", m) -> exprToExpr ea ] - let callExpr = BuildMethodCall tcVal g amap Mutates.PossiblyMutates m false targetMethInfo isSuperInit [] objArgs arguments - callExpr - - and addVar (v:Tainted) = - let nm = v.PUntaint ((fun v -> v.Name),m) - let mut = v.PUntaint ((fun v -> v.IsMutable),m) - let vRaw = v.PUntaint (id,m) - let tyT = Import.ImportProvidedType amap m (v.PApply ((fun v -> v.Type),m)) - let vT,vTe = if mut then mkMutableCompGenLocal m nm tyT else mkCompGenLocal m nm tyT - varConv.[vRaw] <- (Some vT,vTe) - vT - - and removeVar (v:Tainted) = - let vRaw = v.PUntaint (id,m) - varConv.Remove vRaw |> ignore - - and methodCallToExpr top _origExpr (mce:Tainted<_>) = - let (objOpt,meth,args) = mce.PApply3(id,m) - let targetMethInfo = ProvidedMeth(amap,meth.PApply((fun mce -> upcast mce), m),None,m) - let objArgs = - match objOpt.PApplyOption(id, m) with - | None -> [] - | Some objExpr -> [exprToExpr objExpr] - - let arguments = [ for ea in args.PApplyArray(id, "GetInvokerExpresson", m) -> exprToExpr ea ] - let genericArguments = - if meth.PUntaint((fun m -> m.IsGenericMethod), m) then - meth.PApplyArray((fun m -> m.GetGenericArguments()), "GetGenericArguments", m) - else - [| |] - let replacementGenericArguments = genericArguments |> Array.map (fun t->Import.ImportProvidedType amap m t) |> List.ofArray - - let mut = if top then mut else PossiblyMutates - let isSuperInit = if top then isSuperInit else ValUseFlag.NormalValUse - let isProp = if top then isProp else false - let callExpr = BuildMethodCall tcVal g amap mut m isProp targetMethInfo isSuperInit replacementGenericArguments objArgs arguments - Some meth, callExpr - - and varToExpr (pe:Tainted) = - // sub in the appropriate argument - // REVIEW: "thisArg" pointer should be first, if present - let vRaw = pe.PUntaint(id,m) - if not (varConv.ContainsKey vRaw) then - let typeProviderDesignation = ExtensionTyping.DisplayNameOfTypeProvider (pe.TypeProvider, m) - error(NumberedError(FSComp.SR.etIncorrectParameterExpression(typeProviderDesignation,vRaw.Name), m)) - varConv.[vRaw] - - and exprToExpr expr = - let _, (resExpr, _) = exprToExprAndWitness false expr - resExpr - - exprToExprAndWitness true expr - - - // fill in parameter holes in the expression - let TranslateInvokerExpressionForProvidedMethodCall tcVal (g, amap, mut, isProp, isSuperInit, mi:Tainted, objArgs, allArgs, m) = - let parameters = - mi.PApplyArray((fun mi -> mi.GetParameters()), "GetParameters", m) - let paramTys = - parameters - |> Array.map (fun p -> p.PApply((fun st -> st.ParameterType),m)) - let erasedParamTys = - paramTys - |> Array.map (fun pty -> eraseSystemType (amap,m,pty)) - let paramVars = - erasedParamTys - |> Array.mapi (fun i erasedParamTy -> erasedParamTy.PApply((fun ty -> ProvidedVar.Fresh("arg" + i.ToString(),ty)),m)) - - - // encode "this" as the first ParameterExpression, if applicable - let thisArg, paramVars = - match objArgs with - | [objArg] -> - let erasedThisTy = eraseSystemType (amap,m,mi.PApply((fun mi -> mi.DeclaringType),m)) - let thisVar = erasedThisTy.PApply((fun ty -> ProvidedVar.Fresh("this", ty)), m) - Some objArg , Array.append [| thisVar |] paramVars - | [] -> None , paramVars - | _ -> failwith "multiple objArgs?" - - let ea = mi.PApplyWithProvider((fun (methodInfo,provider) -> ExtensionTyping.GetInvokerExpression(provider, methodInfo, [| for p in paramVars -> p.PUntaintNoFailure id |])), m) - - convertProvidedExpressionToExprAndWitness tcVal (thisArg,allArgs,paramVars,g,amap,mut,isProp,isSuperInit,m,ea) - - - let BuildInvokerExpressionForProvidedMethodCall tcVal (g, amap, mi:Tainted, objArgs, mut, isProp, isSuperInit, allArgs, m) = - try - let methInfoOpt, (expr, retTy) = TranslateInvokerExpressionForProvidedMethodCall tcVal (g, amap, mut, isProp, isSuperInit, mi, objArgs, allArgs, m) - - let exprty = GetCompiledReturnTyOfProvidedMethodInfo amap m mi |> GetFSharpViewOfReturnType g - let expr = mkCoerceIfNeeded g exprty retTy expr - methInfoOpt, expr, exprty - with - | :? TypeProviderError as tpe -> - let typeName = mi.PUntaint((fun mb -> mb.DeclaringType.FullName), m) - let methName = mi.PUntaint((fun mb -> mb.Name), m) - raise( tpe.WithContext(typeName, methName) ) // loses original stack trace -#endif diff --git a/src/fsharp/fsc.fs b/src/fsharp/fsc.fs index 8eb1ffcf6af..7f3ab96e115 100644 --- a/src/fsharp/fsc.fs +++ b/src/fsharp/fsc.fs @@ -13,16 +13,18 @@ module internal Microsoft.FSharp.Compiler.Driver open System +open System.Collections.Generic open System.Diagnostics open System.Globalization open System.IO -open System.Threading open System.Reflection -open System.Collections.Generic open System.Runtime.CompilerServices open System.Text +open System.Threading + open Internal.Utilities open Internal.Utilities.Collections + open Microsoft.FSharp.Compiler open Microsoft.FSharp.Compiler.AbstractIL open Microsoft.FSharp.Compiler.AbstractIL.IL @@ -35,22 +37,23 @@ open Microsoft.FSharp.Compiler.AbstractIL.IL #else open Microsoft.FSharp.Compiler.IlxGen #endif + +open Microsoft.FSharp.Compiler.AccessibilityLogic +open Microsoft.FSharp.Compiler.AttributeChecking open Microsoft.FSharp.Compiler.Ast +open Microsoft.FSharp.Compiler.CompileOps +open Microsoft.FSharp.Compiler.CompileOptions open Microsoft.FSharp.Compiler.ErrorLogger +open Microsoft.FSharp.Compiler.Infos +open Microsoft.FSharp.Compiler.Lib +open Microsoft.FSharp.Compiler.DiagnosticMessage +open Microsoft.FSharp.Compiler.Optimizer open Microsoft.FSharp.Compiler.Range +open Microsoft.FSharp.Compiler.InfoReader open Microsoft.FSharp.Compiler.TypeChecker -open Microsoft.FSharp.Compiler.Infos -open Microsoft.FSharp.Compiler.Infos.AccessibilityLogic -open Microsoft.FSharp.Compiler.Infos.AttributeChecking open Microsoft.FSharp.Compiler.Tast open Microsoft.FSharp.Compiler.Tastops -open Microsoft.FSharp.Compiler.Optimizer open Microsoft.FSharp.Compiler.TcGlobals -open Microsoft.FSharp.Compiler.CompileOps -open Microsoft.FSharp.Compiler.Lib -open Microsoft.FSharp.Compiler.CompileOptions -open Microsoft.FSharp.Compiler.DiagnosticMessage -open Microsoft.FSharp.Core #if EXTENSIONTYPING open Microsoft.FSharp.Compiler.ExtensionTyping diff --git a/src/fsharp/fsi/fsi.fs b/src/fsharp/fsi/fsi.fs index 69caf49bccf..93e567a7a14 100644 --- a/src/fsharp/fsi/fsi.fs +++ b/src/fsharp/fsi/fsi.fs @@ -25,8 +25,8 @@ open System.Reflection #if !FX_NO_WINFORMS open System.Windows.Forms #endif -open Microsoft.FSharp.Compiler open Microsoft.FSharp.Compiler.AbstractIL +open Microsoft.FSharp.Compiler.AbstractIL.Diagnostics open Microsoft.FSharp.Compiler.AbstractIL.IL open Microsoft.FSharp.Compiler.AbstractIL.Internal open Microsoft.FSharp.Compiler.AbstractIL.Internal.Library @@ -34,24 +34,26 @@ open Microsoft.FSharp.Compiler.AbstractIL.Extensions.ILX open Microsoft.FSharp.Compiler.AbstractIL.ILRuntimeWriter open Microsoft.FSharp.Compiler.Interactive.Settings open Microsoft.FSharp.Compiler.Interactive.RuntimeHelpers -open Microsoft.FSharp.Compiler.Lib + +open Microsoft.FSharp.Compiler +open Microsoft.FSharp.Compiler.AccessibilityLogic +open Microsoft.FSharp.Compiler.Ast open Microsoft.FSharp.Compiler.CompileOptions -open Microsoft.FSharp.Compiler.AbstractIL.Diagnostics -open Microsoft.FSharp.Compiler.AbstractIL.IL +open Microsoft.FSharp.Compiler.CompileOps +open Microsoft.FSharp.Compiler.ErrorLogger +open Microsoft.FSharp.Compiler.Infos +open Microsoft.FSharp.Compiler.InfoReader open Microsoft.FSharp.Compiler.IlxGen +open Microsoft.FSharp.Compiler.Lexhelp +open Microsoft.FSharp.Compiler.Layout +open Microsoft.FSharp.Compiler.Lib +open Microsoft.FSharp.Compiler.Optimizer +open Microsoft.FSharp.Compiler.PostTypeCheckSemanticChecks open Microsoft.FSharp.Compiler.Range -open Microsoft.FSharp.Compiler.Ast -open Microsoft.FSharp.Compiler.ErrorLogger open Microsoft.FSharp.Compiler.TypeChecker open Microsoft.FSharp.Compiler.Tast -open Microsoft.FSharp.Compiler.Infos open Microsoft.FSharp.Compiler.Tastops -open Microsoft.FSharp.Compiler.Optimizer open Microsoft.FSharp.Compiler.TcGlobals -open Microsoft.FSharp.Compiler.CompileOps -open Microsoft.FSharp.Compiler.Lexhelp -open Microsoft.FSharp.Compiler.Layout -open Microsoft.FSharp.Compiler.PostTypeCheckSemanticChecks open Internal.Utilities.Collections open Internal.Utilities.StructuredFormat @@ -766,7 +768,7 @@ let internal WithImplicitHome (tcConfigB, dir) f = /// A single instance of this object is created per interactive session. type internal FsiDynamicCompiler (timeReporter : FsiTimeReporter, - tcConfigB, + tcConfigB: TcConfigBuilder, tcLockObject : obj, errorLogger: ErrorLoggerThatStopsOnFirstError, outWriter: TextWriter, @@ -795,7 +797,7 @@ type internal FsiDynamicCompiler let infoReader = InfoReader(tcGlobals,tcImports.GetImportMap()) /// Add attributes - let CreateModuleFragment (tcConfigB, assemblyName, codegenResults) = + let CreateModuleFragment (tcConfigB: TcConfigBuilder, assemblyName, codegenResults) = if !progress then fprintfn fsiConsoleOutput.Out "Creating main module..."; let mainModule = mkILSimpleModule assemblyName (GetGeneratedILModuleName tcConfigB.target assemblyName) (tcConfigB.target = Dll) tcConfigB.subsystemVersion tcConfigB.useHighEntropyVA (mkILTypeDefs codegenResults.ilTypeDefs) None None 0x0 (mkILExportedTypes []) "" { mainModule @@ -1131,10 +1133,10 @@ type internal FsiIntellisenseProvider(tcGlobals, tcImports: TcImports) = let tcState = istate.tcState (* folded through now? *) let amap = tcImports.GetImportMap() - let infoReader = new Infos.InfoReader(tcGlobals,amap) + let infoReader = new InfoReader(tcGlobals,amap) let ncenv = new NameResolution.NameResolver(tcGlobals,amap,infoReader,NameResolution.FakeInstantiationGenerator) // Note: for the accessor domain we should use (AccessRightsOfEnv tcState.TcEnvFromImpls) - let ad = Infos.AccessibleFromSomeFSharpCode + let ad = AccessibleFromSomeFSharpCode let nItems = NameResolution.ResolvePartialLongIdent ncenv tcState.TcEnvFromImpls.NameEnv (ConstraintSolver.IsApplicableMethApprox tcGlobals amap rangeStdin) rangeStdin ad lid false let names = nItems |> List.map (fun d -> d.DisplayName) let names = names |> List.filter (fun (name:string) -> name.StartsWith(stem,StringComparison.Ordinal)) diff --git a/src/fsharp/infos.fs b/src/fsharp/infos.fs index 7d37ad064cb..c34c19ee382 100755 --- a/src/fsharp/infos.fs +++ b/src/fsharp/infos.fs @@ -8,11 +8,11 @@ module internal Microsoft.FSharp.Compiler.Infos open Internal.Utilities open Microsoft.FSharp.Compiler.AbstractIL +open Microsoft.FSharp.Compiler.AbstractIL.Diagnostics open Microsoft.FSharp.Compiler.AbstractIL.IL open Microsoft.FSharp.Compiler.AbstractIL.Internal open Microsoft.FSharp.Compiler.AbstractIL.Internal.Library open Microsoft.FSharp.Compiler -open Microsoft.FSharp.Compiler.AbstractIL.Diagnostics open Microsoft.FSharp.Compiler.Range open Microsoft.FSharp.Compiler.Ast open Microsoft.FSharp.Compiler.ErrorLogger @@ -20,7 +20,6 @@ open Microsoft.FSharp.Compiler.Tast open Microsoft.FSharp.Compiler.Tastops open Microsoft.FSharp.Compiler.Tastops.DebugPrint open Microsoft.FSharp.Compiler.TcGlobals -open Microsoft.FSharp.Compiler.AbstractIL.IL open Microsoft.FSharp.Compiler.Lib open Microsoft.FSharp.Core.Printf @@ -30,7 +29,7 @@ open Microsoft.FSharp.Core.CompilerServices #endif #if FX_RESHAPED_REFLECTION - open Microsoft.FSharp.Core.ReflectionAdapters +open Microsoft.FSharp.Core.ReflectionAdapters #endif //------------------------------------------------------------------------- @@ -38,10 +37,10 @@ open Microsoft.FSharp.Core.CompilerServices //------------------------------------------------------------------------- /// Import an IL type as an F# type. importInst gives the context for interpreting type variables. -let ImportType scoref amap m importInst ilty = +let ImportILType scoref amap m importInst ilty = ilty |> rescopeILType scoref |> Import.ImportILType amap m importInst -let CanImportType scoref amap m ilty = +let CanImportILType scoref amap m ilty = ilty |> rescopeILType scoref |> Import.CanImportILType amap m //------------------------------------------------------------------------- @@ -75,7 +74,7 @@ let GetSuperTypeOfType g amap m typ = let _,tinst = destAppTy g typ match tdef.Extends with | None -> None - | Some ilty -> Some (ImportType scoref amap m tinst ilty) + | Some ilty -> Some (ImportILType scoref amap m tinst ilty) | FSharpOrArrayOrByrefOrTupleOrExnTypeMetadata -> @@ -126,7 +125,7 @@ let rec GetImmediateInterfacesOfType skipUnref g amap m typ = #endif | ILTypeMetadata (scoref,tdef) -> - // ImportType may fail for an interface if the assembly load set is incomplete and the interface + // ImportILType may fail for an interface if the assembly load set is incomplete and the interface // comes from another assembly. In this case we simply skip the interface: // if we don't skip it, then compilation will just fail here, and if type checking // succeeds with fewer non-dereferencable interfaces reported then it would have @@ -134,8 +133,8 @@ let rec GetImmediateInterfacesOfType skipUnref g amap m typ = // doesn't apply: e.g. for mscorlib interfaces like IComparable, but we can always // assume those are present. [ for ity in tdef.Implements |> ILList.toList do - if skipUnref = SkipUnrefInterfaces.No || CanImportType scoref amap m ity then - yield ImportType scoref amap m tinst ity ] + if skipUnref = SkipUnrefInterfaces.No || CanImportILType scoref amap m ity then + yield ImportILType scoref amap m tinst ity ] | FSharpOrArrayOrByrefOrTupleOrExnTypeMetadata -> tcref.ImmediateInterfaceTypesOfFSharpTycon |> List.map (instType (mkInstForAppTy g typ)) @@ -277,8 +276,8 @@ let ExistsHeadTypeInEntireHierarchy g amap m typeToSearchFrom tcrefToLookFor = /// Read an Abstract IL type from metadata and convert to an F# type. -let ImportTypeFromMetadata amap m scoref tinst minst ilty = - ImportType scoref amap m (tinst@minst) ilty +let ImportILTypeFromMetadata amap m scoref tinst minst ilty = + ImportILType scoref amap m (tinst@minst) ilty /// Get the return type of an IL method, taking into account instantiations for type and method generic parameters, and @@ -286,7 +285,7 @@ let ImportTypeFromMetadata amap m scoref tinst minst ilty = let ImportReturnTypeFromMetaData amap m ty scoref tinst minst = match ty with | ILType.Void -> None - | retTy -> Some (ImportTypeFromMetadata amap m scoref tinst minst retTy) + | retTy -> Some (ImportILTypeFromMetadata amap m scoref tinst minst retTy) /// Copy constraints. If the constraint comes from a type parameter associated /// with a type constructor then we are simply renaming type variables. If it comes @@ -512,7 +511,7 @@ type OptionalArgInfo = else MissingValue else DefaultValue - CallerSide (analyze (ImportTypeFromMetadata amap m ilScope ilTypeInst [] ilParam.Type)) + CallerSide (analyze (ImportILTypeFromMetadata amap m ilScope ilTypeInst [] ilParam.Type)) | Some v -> CallerSide (Constant v) else @@ -762,17 +761,17 @@ type ILMethInfo = /// Get the argument types of the the IL method. If this is an C#-style extension method /// then drop the object argument. member x.GetParamTypes(amap,m,minst) = - x.ParamMetadata |> List.map (fun p -> ImportTypeFromMetadata amap m x.MetadataScope x.DeclaringTypeInst minst p.Type) + x.ParamMetadata |> List.map (fun p -> ImportILTypeFromMetadata amap m x.MetadataScope x.DeclaringTypeInst minst p.Type) /// Get all the argument types of the IL method. Include the object argument even if this is /// an C#-style extension method. member x.GetRawArgTypes(amap,m,minst) = - x.RawMetadata.Parameters |> ILList.toList |> List.map (fun p -> ImportTypeFromMetadata amap m x.MetadataScope x.DeclaringTypeInst minst p.Type) + x.RawMetadata.Parameters |> ILList.toList |> List.map (fun p -> ImportILTypeFromMetadata amap m x.MetadataScope x.DeclaringTypeInst minst p.Type) /// Get info about the arguments of the IL method. If this is an C#-style extension method then /// drop the object argument. member x.GetParamNamesAndTypes(amap,m,minst) = - x.ParamMetadata |> List.map (fun p -> ParamNameAndType(Option.map (mkSynId m) p.Name, ImportTypeFromMetadata amap m x.MetadataScope x.DeclaringTypeInst minst p.Type) ) + x.ParamMetadata |> List.map (fun p -> ParamNameAndType(Option.map (mkSynId m) p.Name, ImportILTypeFromMetadata amap m x.MetadataScope x.DeclaringTypeInst minst p.Type) ) /// Get a reference to the method (dropping all generic instantiations), as an Abstract IL ILMethodRef. member x.ILMethodRef = @@ -792,7 +791,7 @@ type ILMethInfo = // All C#-style extension methods are instance. We have to re-read the 'obj' type w.r.t. the // method instantiation. if x.IsILExtensionMethod then - [ImportTypeFromMetadata amap m x.MetadataScope x.DeclaringTypeInst minst x.RawMetadata.Parameters.Head.Type] + [ImportILTypeFromMetadata amap m x.MetadataScope x.DeclaringTypeInst minst x.RawMetadata.Parameters.Head.Type] else if x.IsInstance then [ x.ApparentEnclosingType ] else @@ -1399,7 +1398,7 @@ type MethInfo = let formalRetTy = ImportReturnTypeFromMetaData amap m ilminfo.RawMetadata.Return.Type ftinfo.ILScopeRef ftinfo.TypeInst formalMethTyparTys let formalParams = [ [ for p in ilminfo.RawMetadata.Parameters do - let paramType = ImportTypeFromMetadata amap m ftinfo.ILScopeRef ftinfo.TypeInst formalMethTyparTys p.Type + let paramType = ImportILTypeFromMetadata amap m ftinfo.ILScopeRef ftinfo.TypeInst formalMethTyparTys p.Type yield TSlotParam(p.Name, paramType, p.IsIn, p.IsOut, p.IsOptional, []) ] ] formalRetTy, formalParams #if EXTENSIONTYPING @@ -1577,7 +1576,7 @@ type ILFieldInfo = /// Get the type of the field as an F# type member x.FieldType(amap,m) = match x with - | ILFieldInfo (tinfo,fdef) -> ImportTypeFromMetadata amap m tinfo.ILScopeRef tinfo.TypeInst [] fdef.Type + | ILFieldInfo (tinfo,fdef) -> ImportILTypeFromMetadata amap m tinfo.ILScopeRef tinfo.TypeInst [] fdef.Type #if EXTENSIONTYPING | ProvidedField(amap,fi,m) -> Import.ImportProvidedType amap m (fi.PApply((fun fi -> fi.FieldType),m)) #endif @@ -1705,17 +1704,17 @@ type ILPropInfo = /// Get the names and types of the indexer arguments associated with the IL property. member x.GetParamNamesAndTypes(amap,m) = let (ILPropInfo (tinfo,pdef)) = x - pdef.Args |> ILList.toList |> List.map (fun ty -> ParamNameAndType(None, ImportTypeFromMetadata amap m tinfo.ILScopeRef tinfo.TypeInst [] ty) ) + pdef.Args |> ILList.toList |> List.map (fun ty -> ParamNameAndType(None, ImportILTypeFromMetadata amap m tinfo.ILScopeRef tinfo.TypeInst [] ty) ) /// Get the types of the indexer arguments associated with the IL property. member x.GetParamTypes(amap,m) = let (ILPropInfo (tinfo,pdef)) = x - pdef.Args |> ILList.toList |> List.map (fun ty -> ImportTypeFromMetadata amap m tinfo.ILScopeRef tinfo.TypeInst [] ty) + pdef.Args |> ILList.toList |> List.map (fun ty -> ImportILTypeFromMetadata amap m tinfo.ILScopeRef tinfo.TypeInst [] ty) /// Get the return type of the IL property. member x.GetPropertyType (amap,m) = let (ILPropInfo (tinfo,pdef)) = x - ImportTypeFromMetadata amap m tinfo.ILScopeRef tinfo.TypeInst [] pdef.Type + ImportILTypeFromMetadata amap m tinfo.ILScopeRef tinfo.TypeInst [] pdef.Type override x.ToString() = x.ILTypeInfo.ToString() + "::" + x.PropertyName @@ -2214,7 +2213,7 @@ type EventInfo = // Get the delegate type associated with an IL event, taking into account the instantiation of the // declaring type. if isNone edef.Type then error (nonStandardEventError x.EventName m) - ImportTypeFromMetadata amap m tinfo.ILScopeRef tinfo.TypeInst [] edef.Type.Value + ImportILTypeFromMetadata amap m tinfo.ILScopeRef tinfo.TypeInst [] edef.Type.Value | FSEvent(g,p,_,_) -> FindDelegateTypeOfPropertyEvent g amap x.EventName m (p.GetPropertyType(amap,m)) @@ -2308,1613 +2307,3 @@ let PropInfosEquivByNameAndSig erasureFlag g amap m (pinfo:PropInfo) (pinfo2:Pro typeEquivAux erasureFlag g retTy retTy2 -//------------------------------------------------------------------------- -// Basic accessibility logic -//------------------------------------------------------------------------- - -/// Represents the 'keys' a particular piece of code can use to access other constructs?. -[] -type AccessorDomain = - /// AccessibleFrom(cpaths, tyconRefOpt) - /// - /// cpaths: indicates we have the keys to access any members private to the given paths - /// tyconRefOpt: indicates we have the keys to access any protected members of the super types of 'TyconRef' - | AccessibleFrom of CompilationPath list * TyconRef option - - /// An AccessorDomain which returns public items - | AccessibleFromEverywhere - - /// An AccessorDomain which returns everything but .NET private/internal items. - /// This is used - /// - when solving member trait constraints, which are solved independently of accessibility - /// - for failure paths in error reporting, e.g. to produce an error that an F# item is not accessible - /// - an adhoc use in service.fs to look up a delegate signature - | AccessibleFromSomeFSharpCode - - /// An AccessorDomain which returns all items - | AccessibleFromSomewhere - - // Hashing and comparison is used for the memoization tables keyed by an accessor domain. - // It is dependent on a TcGlobals because of the TyconRef in the data structure - static member CustomGetHashCode(ad:AccessorDomain) = - match ad with - | AccessibleFrom _ -> 1 - | AccessibleFromEverywhere -> 2 - | AccessibleFromSomeFSharpCode -> 3 - | AccessibleFromSomewhere -> 4 - static member CustomEquals(g:TcGlobals, ad1:AccessorDomain, ad2:AccessorDomain) = - match ad1, ad2 with - | AccessibleFrom(cs1,tc1), AccessibleFrom(cs2,tc2) -> (cs1 = cs2) && (match tc1,tc2 with None,None -> true | Some tc1, Some tc2 -> tyconRefEq g tc1 tc2 | _ -> false) - | AccessibleFromEverywhere, AccessibleFromEverywhere -> true - | AccessibleFromSomeFSharpCode, AccessibleFromSomeFSharpCode -> true - | AccessibleFromSomewhere, AccessibleFromSomewhere -> true - | _ -> false - -module AccessibilityLogic = - - /// Indicates if an F# item is accessible - let IsAccessible ad taccess = - match ad with - | AccessibleFromEverywhere -> canAccessFromEverywhere taccess - | AccessibleFromSomeFSharpCode -> canAccessFromSomewhere taccess - | AccessibleFromSomewhere -> true - | AccessibleFrom (cpaths,_tcrefViewedFromOption) -> - List.exists (canAccessFrom taccess) cpaths - - /// Indicates if an IL member is accessible (ignoring its enclosing type) - let private IsILMemberAccessible g amap m (tcrefOfViewedItem : TyconRef) ad access = - match ad with - | AccessibleFromEverywhere -> - access = ILMemberAccess.Public - | AccessibleFromSomeFSharpCode -> - (access = ILMemberAccess.Public || - access = ILMemberAccess.Family || - access = ILMemberAccess.FamilyOrAssembly) - | AccessibleFrom (cpaths,tcrefViewedFromOption) -> - let accessibleByFamily = - ((access = ILMemberAccess.Family || - access = ILMemberAccess.FamilyOrAssembly) && - match tcrefViewedFromOption with - | None -> false - | Some tcrefViewedFrom -> - ExistsHeadTypeInEntireHierarchy g amap m (generalizedTyconRef tcrefViewedFrom) tcrefOfViewedItem) - let accessibleByInternalsVisibleTo = - (access = ILMemberAccess.Assembly && canAccessFromOneOf cpaths tcrefOfViewedItem.CompilationPath) - (access = ILMemberAccess.Public) || accessibleByFamily || accessibleByInternalsVisibleTo - | AccessibleFromSomewhere -> - true - - /// Indicates if tdef is accessible. If tdef.Access = ILTypeDefAccess.Nested then encTyconRefOpt s TyconRef of enclosing type - /// and visibility of tdef is obtained using member access rules - let private IsILTypeDefAccessible (amap : Import.ImportMap) m ad encTyconRefOpt (tdef: ILTypeDef) = - match tdef.Access with - | ILTypeDefAccess.Nested nestedAccess -> - match encTyconRefOpt with - | None -> assert false; true - | Some encTyconRef -> IsILMemberAccessible amap.g amap m encTyconRef ad nestedAccess - | _ -> - match ad with - | AccessibleFromSomewhere -> true - | AccessibleFromEverywhere - | AccessibleFromSomeFSharpCode - | AccessibleFrom _ -> tdef.Access = ILTypeDefAccess.Public - - /// Indicates if a TyconRef is visible through the AccessibleFrom(cpaths,_). - /// Note that InternalsVisibleTo extends those cpaths. - let private IsTyconAccessibleViaVisibleTo ad (tcrefOfViewedItem:TyconRef) = - match ad with - | AccessibleFromEverywhere - | AccessibleFromSomewhere - | AccessibleFromSomeFSharpCode -> false - | AccessibleFrom (cpaths,_tcrefViewedFromOption) -> - canAccessFromOneOf cpaths tcrefOfViewedItem.CompilationPath - - /// Indicates if given IL based TyconRef is accessible. If TyconRef is nested then we'll - /// walk though the list of enclosing types and test if all of them are accessible - let private IsILTypeInfoAccessible amap m ad (tcrefOfViewedItem : TyconRef) = - let scoref, enc, tdef = tcrefOfViewedItem.ILTyconInfo - let rec check parentTycon path = - let ilTypeDefAccessible = - match parentTycon with - | None -> - match path with - | [] -> assert false; true // in this case path should have at least one element - | [x] -> IsILTypeDefAccessible amap m ad None x // shortcut for non-nested types - | x::xs -> - // check if enclosing type x is accessible. - // if yes - create parent tycon for type 'x' and continue with the rest of the path - IsILTypeDefAccessible amap m ad None x && - ( - let parentILTyRef = mkRefForNestedILTypeDef scoref ([], x) - let parentTycon = Import.ImportILTypeRef amap m parentILTyRef - check (Some (parentTycon, [x])) xs - ) - | (Some (parentTycon, parentPath)) -> - match path with - | [] -> true // end of path is reached - success - | x::xs -> - // check if x is accessible from the parent tycon - // if yes - create parent tycon for type 'x' and continue with the rest of the path - IsILTypeDefAccessible amap m ad (Some parentTycon) x && - ( - let parentILTyRef = mkRefForNestedILTypeDef scoref (parentPath, x) - let parentTycon = Import.ImportILTypeRef amap m parentILTyRef - check (Some (parentTycon, parentPath @ [x])) xs - ) - ilTypeDefAccessible || IsTyconAccessibleViaVisibleTo ad tcrefOfViewedItem - - check None (enc @ [tdef]) - - /// Indicates if an IL member associated with the given ILType is accessible - let private IsILTypeAndMemberAccessible g amap m adType ad (ILTypeInfo(tcrefOfViewedItem, _, _, _)) access = - IsILTypeInfoAccessible amap m adType tcrefOfViewedItem && IsILMemberAccessible g amap m tcrefOfViewedItem ad access - - /// Indicates if an entity is accessible - let IsEntityAccessible amap m ad (tcref:TyconRef) = - if tcref.IsILTycon then - IsILTypeInfoAccessible amap m ad tcref - else - tcref.Accessibility |> IsAccessible ad - - /// Check that an entity is accessible - let CheckTyconAccessible amap m ad tcref = - let res = IsEntityAccessible amap m ad tcref - if not res then - errorR(Error(FSComp.SR.typeIsNotAccessible tcref.DisplayName,m)) - res - - /// Indicates if a type definition and its representation contents are accessible - let IsTyconReprAccessible amap m ad tcref = - IsEntityAccessible amap m ad tcref && - IsAccessible ad tcref.TypeReprAccessibility - - /// Check that a type definition and its representation contents are accessible - let CheckTyconReprAccessible amap m ad tcref = - CheckTyconAccessible amap m ad tcref && - (let res = IsAccessible ad tcref.TypeReprAccessibility - if not res then - errorR (Error (FSComp.SR.unionCasesAreNotAccessible tcref.DisplayName,m)) - res) - - /// Indicates if a type is accessible (both definition and instantiation) - let rec IsTypeAccessible g amap m ad ty = - not (isAppTy g ty) || - let tcref,tinst = destAppTy g ty - IsEntityAccessible amap m ad tcref && IsTypeInstAccessible g amap m ad tinst - - and IsTypeInstAccessible g amap m ad tinst = - match tinst with - | [] -> true - | _ -> List.forall (IsTypeAccessible g amap m ad) tinst - - /// Indicate if a provided member is accessible - let IsProvidedMemberAccessible (amap:Import.ImportMap) m ad ty access = - let g = amap.g - let isTyAccessible = IsTypeAccessible g amap m ad ty - if not isTyAccessible then false - else - not (isAppTy g ty) || - let tcrefOfViewedItem,_ = destAppTy g ty - IsILMemberAccessible g amap m tcrefOfViewedItem ad access - - /// Compute the accessibility of a provided member - let ComputeILAccess isPublic isFamily isFamilyOrAssembly isFamilyAndAssembly = - if isPublic then ILMemberAccess.Public - elif isFamily then ILMemberAccess.Family - elif isFamilyOrAssembly then ILMemberAccess.FamilyOrAssembly - elif isFamilyAndAssembly then ILMemberAccess.FamilyAndAssembly - else ILMemberAccess.Private - - /// IndiCompute the accessibility of a provided member - let IsILFieldInfoAccessible g amap m ad x = - match x with - | ILFieldInfo (tinfo,fd) -> IsILTypeAndMemberAccessible g amap m ad ad tinfo fd.Access -#if EXTENSIONTYPING - | ProvidedField (amap, tpfi, m) as pfi -> - let access = tpfi.PUntaint((fun fi -> ComputeILAccess fi.IsPublic fi.IsFamily fi.IsFamilyOrAssembly fi.IsFamilyAndAssembly), m) - IsProvidedMemberAccessible amap m ad pfi.EnclosingType access -#endif - - let GetILAccessOfILEventInfo (ILEventInfo (tinfo,edef)) = - (resolveILMethodRef tinfo.RawMetadata edef.AddMethod).Access - - let IsILEventInfoAccessible g amap m ad einfo = - let access = GetILAccessOfILEventInfo einfo - IsILTypeAndMemberAccessible g amap m ad ad einfo.ILTypeInfo access - - let private IsILMethInfoAccessible g amap m adType ad ilminfo = - match ilminfo with - | ILMethInfo (_,typ,None,mdef,_) -> IsILTypeAndMemberAccessible g amap m adType ad (ILTypeInfo.FromType g typ) mdef.Access - | ILMethInfo (_,_,Some declaringTyconRef,mdef,_) -> IsILMemberAccessible g amap m declaringTyconRef ad mdef.Access - - let GetILAccessOfILPropInfo (ILPropInfo(tinfo,pdef)) = - let tdef = tinfo.RawMetadata - let ilAccess = - match pdef.GetMethod with - | Some mref -> (resolveILMethodRef tdef mref).Access - | None -> - match pdef.SetMethod with - | None -> ILMemberAccess.Public - | Some mref -> (resolveILMethodRef tdef mref).Access - ilAccess - - let IsILPropInfoAccessible g amap m ad pinfo = - let ilAccess = GetILAccessOfILPropInfo pinfo - IsILTypeAndMemberAccessible g amap m ad ad pinfo.ILTypeInfo ilAccess - - let IsValAccessible ad (vref:ValRef) = - vref.Accessibility |> IsAccessible ad - - let CheckValAccessible m ad (vref:ValRef) = - if not (IsValAccessible ad vref) then - errorR (Error (FSComp.SR.valueIsNotAccessible vref.DisplayName,m)) - - let IsUnionCaseAccessible amap m ad (ucref:UnionCaseRef) = - IsTyconReprAccessible amap m ad ucref.TyconRef && - IsAccessible ad ucref.UnionCase.Accessibility - - let CheckUnionCaseAccessible amap m ad (ucref:UnionCaseRef) = - CheckTyconReprAccessible amap m ad ucref.TyconRef && - (let res = IsAccessible ad ucref.UnionCase.Accessibility - if not res then - errorR (Error (FSComp.SR.unionCaseIsNotAccessible ucref.CaseName,m)) - res) - - let IsRecdFieldAccessible amap m ad (rfref:RecdFieldRef) = - IsTyconReprAccessible amap m ad rfref.TyconRef && - IsAccessible ad rfref.RecdField.Accessibility - - let CheckRecdFieldAccessible amap m ad (rfref:RecdFieldRef) = - CheckTyconReprAccessible amap m ad rfref.TyconRef && - (let res = IsAccessible ad rfref.RecdField.Accessibility - if not res then - errorR (Error (FSComp.SR.fieldIsNotAccessible rfref.FieldName,m)) - res) - - let CheckRecdFieldInfoAccessible amap m ad (rfinfo:RecdFieldInfo) = - CheckRecdFieldAccessible amap m ad rfinfo.RecdFieldRef |> ignore - - let CheckILFieldInfoAccessible g amap m ad finfo = - if not (IsILFieldInfoAccessible g amap m ad finfo) then - errorR (Error (FSComp.SR.structOrClassFieldIsNotAccessible finfo.FieldName,m)) - - /// Uses a separate accessibility domains for containing type and method itself - /// This makes sense cases like - /// type A() = - /// type protected B() = - /// member this.Public() = () - /// member protected this.Protected() = () - /// type C() = - /// inherit A() - /// let x = A.B() - /// do x.Public() - /// when calling x.SomeMethod() we need to use 'adTyp' do verify that type of x is accessible from C - /// and 'ad' to determine accessibility of SomeMethod. - /// I.e when calling x.Public() and x.Protected() -in both cases first check should succeed and second - should fail in the latter one. - let IsTypeAndMethInfoAccessible amap m adTyp ad = function - | ILMeth (g,x,_) -> IsILMethInfoAccessible g amap m adTyp ad x - | FSMeth (_,_,vref,_) -> IsValAccessible ad vref - | DefaultStructCtor(g,typ) -> IsTypeAccessible g amap m ad typ -#if EXTENSIONTYPING - | ProvidedMeth(amap,tpmb,_,m) as etmi -> - let access = tpmb.PUntaint((fun mi -> ComputeILAccess mi.IsPublic mi.IsFamily mi.IsFamilyOrAssembly mi.IsFamilyAndAssembly), m) - IsProvidedMemberAccessible amap m ad etmi.EnclosingType access -#endif - let IsMethInfoAccessible amap m ad minfo = IsTypeAndMethInfoAccessible amap m ad ad minfo - - let IsPropInfoAccessible g amap m ad = function - | ILProp (_,x) -> IsILPropInfoAccessible g amap m ad x - | FSProp (_,_,Some vref,_) - | FSProp (_,_,_,Some vref) -> IsValAccessible ad vref -#if EXTENSIONTYPING - | ProvidedProp (amap, tppi, m) as pp-> - let access = - let a = tppi.PUntaint((fun ppi -> - let tryGetILAccessForProvidedMethodBase (mi : ProvidedMethodBase) = - match mi with - | null -> None - | mi -> Some(ComputeILAccess mi.IsPublic mi.IsFamily mi.IsFamilyOrAssembly mi.IsFamilyAndAssembly) - match tryGetILAccessForProvidedMethodBase(ppi.GetGetMethod()) with - | None -> tryGetILAccessForProvidedMethodBase(ppi.GetSetMethod()) - | x -> x), m) - defaultArg a ILMemberAccess.Public - IsProvidedMemberAccessible amap m ad pp.EnclosingType access -#endif - | _ -> false - - let IsFieldInfoAccessible ad (rfref:RecdFieldInfo) = - IsAccessible ad rfref.RecdField.Accessibility - -open AccessibilityLogic - - - -//------------------------------------------------------------------------- -// Check custom attributes -//------------------------------------------------------------------------- - -exception ObsoleteWarning of string * range -exception ObsoleteError of string * range - -let fail() = failwith "This custom attribute has an argument that can not yet be converted using this API" - -let rec evalILAttribElem e = - match e with - | ILAttribElem.String (Some x) -> box x - | ILAttribElem.String None -> null - | ILAttribElem.Bool x -> box x - | ILAttribElem.Char x -> box x - | ILAttribElem.SByte x -> box x - | ILAttribElem.Int16 x -> box x - | ILAttribElem.Int32 x -> box x - | ILAttribElem.Int64 x -> box x - | ILAttribElem.Byte x -> box x - | ILAttribElem.UInt16 x -> box x - | ILAttribElem.UInt32 x -> box x - | ILAttribElem.UInt64 x -> box x - | ILAttribElem.Single x -> box x - | ILAttribElem.Double x -> box x - | ILAttribElem.Null -> null - | ILAttribElem.Array (_, a) -> box [| for i in a -> evalILAttribElem i |] - // TODO: typeof<..> in attribute values - | ILAttribElem.Type (Some _t) -> fail() - | ILAttribElem.Type None -> null - | ILAttribElem.TypeRef (Some _t) -> fail() - | ILAttribElem.TypeRef None -> null - -let rec evalFSharpAttribArg g e = - match e with - | Expr.Const(c,_,_) -> - match c with - | Const.Bool b -> box b - | Const.SByte i -> box i - | Const.Int16 i -> box i - | Const.Int32 i -> box i - | Const.Int64 i -> box i - | Const.Byte i -> box i - | Const.UInt16 i -> box i - | Const.UInt32 i -> box i - | Const.UInt64 i -> box i - | Const.Single i -> box i - | Const.Double i -> box i - | Const.Char i -> box i - | Const.Zero -> null - | Const.String s -> box s - | _ -> fail() - | Expr.Op (TOp.Array,_,a,_) -> box [| for i in a -> evalFSharpAttribArg g i |] - | TypeOfExpr g ty -> box ty - // TODO: | TypeDefOfExpr g ty - | _ -> fail() - -type AttribInfo = - | FSAttribInfo of TcGlobals * Attrib - | ILAttribInfo of TcGlobals * Import.ImportMap * ILScopeRef * ILAttribute * range - - member x.TyconRef = - match x with - | FSAttribInfo(_g,Attrib(tcref,_,_,_,_,_,_)) -> tcref - | ILAttribInfo (g, amap, scoref, a, m) -> - let ty = ImportType scoref amap m [] a.Method.EnclosingType - tcrefOfAppTy g ty - - member x.ConstructorArguments = - match x with - | FSAttribInfo(g,Attrib(_,_,unnamedArgs,_,_,_,_)) -> - unnamedArgs - |> List.map (fun (AttribExpr(origExpr,evaluatedExpr)) -> - let ty = tyOfExpr g origExpr - let obj = evalFSharpAttribArg g evaluatedExpr - ty,obj) - | ILAttribInfo (g, amap, scoref, cattr, m) -> - let parms, _args = decodeILAttribData g.ilg cattr - [ for (argty,argval) in Seq.zip cattr.Method.FormalArgTypes parms -> - let ty = ImportType scoref amap m [] argty - let obj = evalILAttribElem argval - ty,obj ] - - member x.NamedArguments = - match x with - | FSAttribInfo(g,Attrib(_,_,_,namedArgs,_,_,_)) -> - namedArgs - |> List.map (fun (AttribNamedArg(nm,_,isField,AttribExpr(origExpr,evaluatedExpr))) -> - let ty = tyOfExpr g origExpr - let obj = evalFSharpAttribArg g evaluatedExpr - ty, nm, isField, obj) - | ILAttribInfo (g, amap, scoref, cattr, m) -> - let _parms, namedArgs = decodeILAttribData g.ilg cattr - [ for (nm, argty, isProp, argval) in namedArgs -> - let ty = ImportType scoref amap m [] argty - let obj = evalILAttribElem argval - let isField = not isProp - ty, nm, isField, obj ] - - -/// Check custom attributes. This is particularly messy because custom attributes come in in three different -/// formats. -module AttributeChecking = - - let AttribInfosOfIL g amap scoref m (attribs: ILAttributes) = - attribs.AsList |> List.map (fun a -> ILAttribInfo (g, amap, scoref, a, m)) - - let AttribInfosOfFS g attribs = - attribs |> List.map (fun a -> FSAttribInfo (g, a)) - - let GetAttribInfosOfEntity g amap m (tcref:TyconRef) = - match metadataOfTycon tcref.Deref with -#if EXTENSIONTYPING - // TODO: provided attributes - | ProvidedTypeMetadata _info -> [] - //let provAttribs = info.ProvidedType.PApply((fun a -> (a :> IProvidedCustomAttributeProvider)),m) - //match provAttribs.PUntaint((fun a -> a. .GetAttributeConstructorArgs(provAttribs.TypeProvider.PUntaintNoFailure(id), atref.FullName)),m) with - //| Some args -> f3 args - //| None -> None -#endif - | ILTypeMetadata (scoref,tdef) -> - tdef.CustomAttrs |> AttribInfosOfIL g amap scoref m - | FSharpOrArrayOrByrefOrTupleOrExnTypeMetadata -> - tcref.Attribs |> List.map (fun a -> FSAttribInfo (g, a)) - - - let GetAttribInfosOfMethod amap m minfo = - match minfo with - | ILMeth (g,ilminfo,_) -> ilminfo.RawMetadata.CustomAttrs |> AttribInfosOfIL g amap ilminfo.MetadataScope m - | FSMeth (g,_,vref,_) -> vref.Attribs |> AttribInfosOfFS g - | DefaultStructCtor _ -> [] -#if EXTENSIONTYPING - // TODO: provided attributes - | ProvidedMeth (_,_mi,_,_m) -> - [] - -#endif - - let GetAttribInfosOfProp amap m pinfo = - match pinfo with - | ILProp(g,ilpinfo) -> ilpinfo.RawMetadata.CustomAttrs |> AttribInfosOfIL g amap ilpinfo.ILTypeInfo.ILScopeRef m - | FSProp(g,_,Some vref,_) - | FSProp(g,_,_,Some vref) -> vref.Attribs |> AttribInfosOfFS g - | FSProp _ -> failwith "GetAttribInfosOfProp: unreachable" -#if EXTENSIONTYPING - // TODO: provided attributes - | ProvidedProp _ -> [] -#endif - - let GetAttribInfosOfEvent amap m einfo = - match einfo with - | ILEvent(g, x) -> x.RawMetadata.CustomAttrs |> AttribInfosOfIL g amap x.ILTypeInfo.ILScopeRef m - | FSEvent(_, pi, _vref1, _vref2) -> GetAttribInfosOfProp amap m pi -#if EXTENSIONTYPING - // TODO: provided attributes - | ProvidedEvent _ -> [] -#endif - - /// Analyze three cases for attributes declared on type definitions: IL-declared attributes, F#-declared attributes and - /// provided attributes. - // - // This is used for AttributeUsageAttribute, DefaultMemberAttribute and ConditionalAttribute (on attribute types) - let TryBindTyconRefAttribute g m (AttribInfo (atref,_) as args) (tcref:TyconRef) f1 f2 f3 = - ignore m; ignore f3 - match metadataOfTycon tcref.Deref with -#if EXTENSIONTYPING - | ProvidedTypeMetadata info -> - let provAttribs = info.ProvidedType.PApply((fun a -> (a :> IProvidedCustomAttributeProvider)),m) - match provAttribs.PUntaint((fun a -> a.GetAttributeConstructorArgs(provAttribs.TypeProvider.PUntaintNoFailure(id), atref.FullName)),m) with - | Some args -> f3 args - | None -> None -#endif - | ILTypeMetadata (_,tdef) -> - match TryDecodeILAttribute g atref tdef.CustomAttrs with - | Some attr -> f1 attr - | _ -> None - | FSharpOrArrayOrByrefOrTupleOrExnTypeMetadata -> - match TryFindFSharpAttribute g args tcref.Attribs with - | Some attr -> f2 attr - | _ -> None - - /// Analyze three cases for attributes declared on methods: IL-declared attributes, F#-declared attributes and - /// provided attributes. - let BindMethInfoAttributes m minfo f1 f2 f3 = - ignore m; ignore f3 - match minfo with - | ILMeth (_,x,_) -> f1 x.RawMetadata.CustomAttrs - | FSMeth (_,_,vref,_) -> f2 vref.Attribs - | DefaultStructCtor _ -> f2 [] -#if EXTENSIONTYPING - | ProvidedMeth (_,mi,_,_) -> f3 (mi.PApply((fun st -> (st :> IProvidedCustomAttributeProvider)),m)) -#endif - - /// Analyze three cases for attributes declared on methods: IL-declared attributes, F#-declared attributes and - /// provided attributes. - let TryBindMethInfoAttribute g m (AttribInfo(atref,_) as attribSpec) minfo f1 f2 f3 = -#if EXTENSIONTYPING -#else - // to prevent unused parameter warning - ignore f3 -#endif - BindMethInfoAttributes m minfo - (fun ilAttribs -> TryDecodeILAttribute g atref ilAttribs |> Option.bind f1) - (fun fsAttribs -> TryFindFSharpAttribute g attribSpec fsAttribs |> Option.bind f2) -#if EXTENSIONTYPING - (fun provAttribs -> - match provAttribs.PUntaint((fun a -> a.GetAttributeConstructorArgs(provAttribs.TypeProvider.PUntaintNoFailure(id), atref.FullName)),m) with - | Some args -> f3 args - | None -> None) -#else - (fun _provAttribs -> None) -#endif - - /// Try to find a specific attribute on a method, where the attribute accepts a string argument. - /// - /// This is just used for the 'ConditionalAttribute' attribute - let TryFindMethInfoStringAttribute g m attribSpec minfo = - TryBindMethInfoAttribute g m attribSpec minfo - (function ([ILAttribElem.String (Some msg) ],_) -> Some msg | _ -> None) - (function (Attrib(_,_,[ AttribStringArg msg ],_,_,_,_)) -> Some msg | _ -> None) - (function ([ Some ((:? string as msg) : obj) ],_) -> Some msg | _ -> None) - - /// Check if a method has a specific attribute. - let MethInfoHasAttribute g m attribSpec minfo = - TryBindMethInfoAttribute g m attribSpec minfo - (fun _ -> Some ()) - (fun _ -> Some ()) - (fun _ -> Some ()) - |> Option.isSome - - - - /// Check IL attributes for 'ObsoleteAttribute', returning errors and warnings as data - let private CheckILAttributes g cattrs m = - let (AttribInfo(tref,_)) = g.attrib_SystemObsolete - match TryDecodeILAttribute g tref cattrs with - | Some ([ILAttribElem.String (Some msg) ],_) -> - WarnD(ObsoleteWarning(msg,m)) - | Some ([ILAttribElem.String (Some msg); ILAttribElem.Bool isError ],_) -> - if isError then - ErrorD (ObsoleteError(msg,m)) - else - WarnD (ObsoleteWarning(msg,m)) - | Some ([ILAttribElem.String None ],_) -> - WarnD(ObsoleteWarning("",m)) - | Some _ -> - WarnD(ObsoleteWarning("",m)) - | None -> - CompleteD - - /// Check F# attributes for 'ObsoleteAttribute', 'CompilerMessageAttribute' and 'ExperimentalAttribute', - /// returning errors and warnings as data - let CheckFSharpAttributes g attribs m = - if isNil attribs then CompleteD - else - (match TryFindFSharpAttribute g g.attrib_SystemObsolete attribs with - | Some(Attrib(_,_,[ AttribStringArg s ],_,_,_,_)) -> - WarnD(ObsoleteWarning(s,m)) - | Some(Attrib(_,_,[ AttribStringArg s; AttribBoolArg(isError) ],_,_,_,_)) -> - if isError then - ErrorD (ObsoleteError(s,m)) - else - WarnD (ObsoleteWarning(s,m)) - | Some _ -> - WarnD(ObsoleteWarning("", m)) - | None -> - CompleteD - ) ++ (fun () -> - - match TryFindFSharpAttribute g g.attrib_CompilerMessageAttribute attribs with - | Some(Attrib(_,_,[ AttribStringArg s ; AttribInt32Arg n ],namedArgs,_,_,_)) -> - let msg = UserCompilerMessage(s,n,m) - let isError = - match namedArgs with - | ExtractAttribNamedArg "IsError" (AttribBoolArg v) -> v - | _ -> false - if isError then ErrorD msg else WarnD msg - - | _ -> - CompleteD - ) ++ (fun () -> - - match TryFindFSharpAttribute g g.attrib_ExperimentalAttribute attribs with - | Some(Attrib(_,_,[ AttribStringArg(s) ],_,_,_,_)) -> - WarnD(Experimental(s,m)) - | Some _ -> - WarnD(Experimental(FSComp.SR.experimentalConstruct (), m)) - | _ -> - CompleteD - ) ++ (fun () -> - - match TryFindFSharpAttribute g g.attrib_UnverifiableAttribute attribs with - | Some _ -> - WarnD(PossibleUnverifiableCode(m)) - | _ -> - CompleteD - ) - -#if EXTENSIONTYPING - /// Check a list of provided attributes for 'ObsoleteAttribute', returning errors and warnings as data - let private CheckProvidedAttributes g m (provAttribs: Tainted) = - let (AttribInfo(tref,_)) = g.attrib_SystemObsolete - match provAttribs.PUntaint((fun a -> a.GetAttributeConstructorArgs(provAttribs.TypeProvider.PUntaintNoFailure(id), tref.FullName)),m) with - | Some ([ Some (:? string as msg) ], _) -> WarnD(ObsoleteWarning(msg,m)) - | Some ([ Some (:? string as msg); Some (:?bool as isError) ], _) -> - if isError then - ErrorD (ObsoleteError(msg,m)) - else - WarnD (ObsoleteWarning(msg,m)) - | Some ([ None ], _) -> - WarnD(ObsoleteWarning("",m)) - | Some _ -> - WarnD(ObsoleteWarning("",m)) - | None -> - CompleteD -#endif - - /// Indicate if a list of IL attributes contains 'ObsoleteAttribute'. Used to suppress the item in intellisense. - let CheckILAttributesForUnseen g cattrs _m = - let (AttribInfo(tref,_)) = g.attrib_SystemObsolete - isSome (TryDecodeILAttribute g tref cattrs) - - /// Checks the attributes for CompilerMessageAttribute, which has an IsHidden argument that allows - /// items to be suppressed from intellisense. - let CheckFSharpAttributesForHidden g attribs = - nonNil attribs && - (match TryFindFSharpAttribute g g.attrib_CompilerMessageAttribute attribs with - | Some(Attrib(_,_,[AttribStringArg _; AttribInt32Arg messageNumber], - ExtractAttribNamedArg "IsHidden" (AttribBoolArg v),_,_,_)) -> - // Message number 62 is for "ML Compatibility". Items labelled with this are visible in intellisense - // when mlCompatibility is set. - v && not (messageNumber = 62 && g.mlCompatibility) - | _ -> false) - - /// Indicate if a list of F# attributes contains 'ObsoleteAttribute'. Used to suppress the item in intellisense. - let CheckFSharpAttributesForObsolete g attribs = - nonNil attribs && (HasFSharpAttribute g g.attrib_SystemObsolete attribs) - - /// Indicate if a list of F# attributes contains 'ObsoleteAttribute'. Used to suppress the item in intellisense. - /// Also check the attributes for CompilerMessageAttribute, which has an IsHidden argument that allows - /// items to be suppressed from intellisense. - let CheckFSharpAttributesForUnseen g attribs _m = - nonNil attribs && - (CheckFSharpAttributesForObsolete g attribs || - CheckFSharpAttributesForHidden g attribs) - -#if EXTENSIONTYPING - /// Indicate if a list of provided attributes contains 'ObsoleteAttribute'. Used to suppress the item in intellisense. - let CheckProvidedAttributesForUnseen (provAttribs: Tainted) m = - provAttribs.PUntaint((fun a -> a.GetAttributeConstructorArgs(provAttribs.TypeProvider.PUntaintNoFailure(id), typeof.FullName).IsSome),m) -#endif - - /// Check the attributes associated with a property, returning warnings and errors as data. - let CheckPropInfoAttributes pinfo m = - match pinfo with - | ILProp(g,ILPropInfo(_,pdef)) -> CheckILAttributes g pdef.CustomAttrs m - | FSProp(g,_,Some vref,_) - | FSProp(g,_,_,Some vref) -> CheckFSharpAttributes g vref.Attribs m - | FSProp _ -> failwith "CheckPropInfoAttributes: unreachable" -#if EXTENSIONTYPING - | ProvidedProp (amap,pi,m) -> - CheckProvidedAttributes amap.g m (pi.PApply((fun st -> (st :> IProvidedCustomAttributeProvider)),m)) - -#endif - - - /// Check the attributes associated with a IL field, returning warnings and errors as data. - let CheckILFieldAttributes g (finfo:ILFieldInfo) m = - match finfo with - | ILFieldInfo(_,pd) -> - CheckILAttributes g pd.CustomAttrs m |> CommitOperationResult -#if EXTENSIONTYPING - | ProvidedField (amap,fi,m) -> - CheckProvidedAttributes amap.g m (fi.PApply((fun st -> (st :> IProvidedCustomAttributeProvider)),m)) |> CommitOperationResult -#endif - - /// Check the attributes associated with a method, returning warnings and errors as data. - let CheckMethInfoAttributes g m tyargsOpt minfo = - let search = - BindMethInfoAttributes m minfo - (fun ilAttribs -> Some(CheckILAttributes g ilAttribs m)) - (fun fsAttribs -> - let res = - CheckFSharpAttributes g fsAttribs m ++ (fun () -> - if isNone tyargsOpt && HasFSharpAttribute g g.attrib_RequiresExplicitTypeArgumentsAttribute fsAttribs then - ErrorD(Error(FSComp.SR.tcFunctionRequiresExplicitTypeArguments(minfo.LogicalName),m)) - else - CompleteD) - Some res) -#if EXTENSIONTYPING - (fun provAttribs -> Some (CheckProvidedAttributes g m provAttribs)) -#else - (fun _provAttribs -> None) -#endif - match search with - | Some res -> res - | None -> CompleteD // no attribute = no errors - - /// Indicate if a method has 'Obsolete', 'CompilerMessageAttribute' or 'TypeProviderEditorHideMethodsAttribute'. - /// Used to suppress the item in intellisense. - let MethInfoIsUnseen g m typ minfo = - let isUnseenByObsoleteAttrib = - match BindMethInfoAttributes m minfo - (fun ilAttribs -> Some(CheckILAttributesForUnseen g ilAttribs m)) - (fun fsAttribs -> Some(CheckFSharpAttributesForUnseen g fsAttribs m)) -#if EXTENSIONTYPING - (fun provAttribs -> Some(CheckProvidedAttributesForUnseen provAttribs m)) -#else - (fun _provAttribs -> None) -#endif - with - | Some res -> res - | None -> false - - let isUnseenByHidingAttribute = -#if EXTENSIONTYPING - not (isObjTy g typ) && - isAppTy g typ && - isObjTy g minfo.EnclosingType && - let tcref = tcrefOfAppTy g typ - match tcref.TypeReprInfo with - | TProvidedTypeExtensionPoint info -> - info.ProvidedType.PUntaint((fun st -> (st :> IProvidedCustomAttributeProvider).GetHasTypeProviderEditorHideMethodsAttribute(info.ProvidedType.TypeProvider.PUntaintNoFailure(id))), m) - | _ -> - // This attribute check is done by name to ensure compilation doesn't take a dependency - // on Microsoft.FSharp.Core.CompilerServices.TypeProviderEditorHideMethodsAttribute. - // - // We are only interested in filtering out the method on System.Object, so it is sufficient - // just to look at the attributes on IL methods. - if tcref.IsILTycon then - tcref.ILTyconRawMetadata.CustomAttrs.AsList - |> List.exists (fun attr -> attr.Method.EnclosingType.TypeSpec.Name = typeof.FullName) - else - false -#else - typ |> ignore - false -#endif - isUnseenByObsoleteAttrib || isUnseenByHidingAttribute - - /// Indicate if a property has 'Obsolete' or 'CompilerMessageAttribute'. - /// Used to suppress the item in intellisense. - let PropInfoIsUnseen m pinfo = - match pinfo with - | ILProp (g,ILPropInfo(_,pdef)) -> CheckILAttributesForUnseen g pdef.CustomAttrs m - | FSProp (g,_,Some vref,_) - | FSProp (g,_,_,Some vref) -> CheckFSharpAttributesForUnseen g vref.Attribs m - | FSProp _ -> failwith "CheckPropInfoAttributes: unreachable" -#if EXTENSIONTYPING - | ProvidedProp (_amap,pi,m) -> - CheckProvidedAttributesForUnseen (pi.PApply((fun st -> (st :> IProvidedCustomAttributeProvider)),m)) m -#endif - - /// Check the attributes on an entity, returning errors and warnings as data. - let CheckEntityAttributes g (x:TyconRef) m = - if x.IsILTycon then - CheckILAttributes g x.ILTyconRawMetadata.CustomAttrs m - else - CheckFSharpAttributes g x.Attribs m - - /// Check the attributes on a union case, returning errors and warnings as data. - let CheckUnionCaseAttributes g (x:UnionCaseRef) m = - CheckEntityAttributes g x.TyconRef m ++ (fun () -> - CheckFSharpAttributes g x.Attribs m) - - /// Check the attributes on a record field, returning errors and warnings as data. - let CheckRecdFieldAttributes g (x:RecdFieldRef) m = - CheckEntityAttributes g x.TyconRef m ++ (fun () -> - CheckFSharpAttributes g x.PropertyAttribs m) - - /// Check the attributes on an F# value, returning errors and warnings as data. - let CheckValAttributes g (x:ValRef) m = - CheckFSharpAttributes g x.Attribs m - - /// Check the attributes on a record field, returning errors and warnings as data. - let CheckRecdFieldInfoAttributes g (x:RecdFieldInfo) m = - CheckRecdFieldAttributes g x.RecdFieldRef m - - -open AttributeChecking - -//------------------------------------------------------------------------- -// Build calls -//------------------------------------------------------------------------- - - -/// Build an expression node that is a call to a .NET method. -let BuildILMethInfoCall g amap m isProp (minfo:ILMethInfo) valUseFlags minst direct args = - let valu = isStructTy g minfo.ApparentEnclosingType - let ctor = minfo.IsConstructor - if minfo.IsClassConstructor then - error (InternalError (minfo.ILName+": cannot call a class constructor",m)) - let useCallvirt = - not valu && not direct && minfo.IsVirtual - let isProtected = minfo.IsProtectedAccessibility - let ilMethRef = minfo.ILMethodRef - let newobj = ctor && (match valUseFlags with NormalValUse -> true | _ -> false) - let exprTy = if ctor then minfo.ApparentEnclosingType else minfo.GetFSharpReturnTy(amap, m, minst) - let retTy = (if not ctor && (ilMethRef.ReturnType = ILType.Void) then [] else [exprTy]) - let isDllImport = minfo.IsDllImport g - Expr.Op(TOp.ILCall(useCallvirt,isProtected,valu,newobj,valUseFlags,isProp,isDllImport,ilMethRef,minfo.DeclaringTypeInst,minst,retTy),[],args,m), - exprTy - -/// Build a call to the System.Object constructor taking no arguments, -let BuildObjCtorCall g m = - let ilMethRef = (mkILCtorMethSpecForTy(g.ilg.typ_Object,[])).MethodRef - Expr.Op(TOp.ILCall(false,false,false,false,CtorValUsedAsSuperInit,false,true,ilMethRef,[],[],[g.obj_ty]),[],[],m) - - -/// Build a call to an F# method. -/// -/// Consume the arguments in chunks and build applications. This copes with various F# calling signatures -/// all of which ultimately become 'methods'. -/// -/// QUERY: this looks overly complex considering that we are doing a fundamentally simple -/// thing here. -let BuildFSharpMethodApp g m (vref: ValRef) vexp vexprty (args: Exprs) = - let arities = (arityOfVal vref.Deref).AritiesOfArgs - - let args3,(leftover,retTy) = - ((args,vexprty), arities) ||> List.mapFold (fun (args,fty) arity -> - match arity,args with - | (0|1),[] when typeEquiv g (domainOfFunTy g fty) g.unit_ty -> mkUnit g m, (args, rangeOfFunTy g fty) - | 0,(arg::argst)-> - warning(InternalError(sprintf "Unexpected zero arity, args = %s" (Layout.showL (Layout.sepListL (Layout.rightL ";") (List.map exprL args))),m)); - arg, (argst, rangeOfFunTy g fty) - | 1,(arg :: argst) -> arg, (argst, rangeOfFunTy g fty) - | 1,[] -> error(InternalError("expected additional arguments here",m)) - | _ -> - if args.Length < arity then error(InternalError("internal error in getting arguments, n = "+string arity+", #args = "+string args.Length,m)); - let tupargs,argst = List.chop arity args - let tuptys = tupargs |> List.map (tyOfExpr g) - (mkTupled g m tupargs tuptys), - (argst, rangeOfFunTy g fty) ) - if not leftover.IsEmpty then error(InternalError("Unexpected "+string(leftover.Length)+" remaining arguments in method application",m)) - mkApps g ((vexp,vexprty),[],args3,m), - retTy - -/// Build a call to an F# method. -let BuildFSharpMethodCall g m (typ,vref:ValRef) valUseFlags minst args = - let vexp = Expr.Val (vref,valUseFlags,m) - let vexpty = vref.Type - let tpsorig,tau = vref.TypeScheme - let vtinst = argsOfAppTy g typ @ minst - if tpsorig.Length <> vtinst.Length then error(InternalError("BuildFSharpMethodCall: unexpected List.length mismatch",m)) - let expr = mkTyAppExpr m (vexp,vexpty) vtinst - let exprty = instType (mkTyparInst tpsorig vtinst) tau - BuildFSharpMethodApp g m vref expr exprty args - - -/// Make a call to a method info. Used by the optimizer and code generator to build -/// calls to the type-directed solutions to member constraints. -let MakeMethInfoCall amap m minfo minst args = - let valUseFlags = NormalValUse // correct unless if we allow wild trait constraints like "T has a ctor and can be used as a parent class" - match minfo with - | ILMeth(g,ilminfo,_) -> - let direct = not minfo.IsVirtual - let isProp = false // not necessarily correct, but this is only used post-creflect where this flag is irrelevant - BuildILMethInfoCall g amap m isProp ilminfo valUseFlags minst direct args |> fst - | FSMeth(g,typ,vref,_) -> - BuildFSharpMethodCall g m (typ,vref) valUseFlags minst args |> fst - | DefaultStructCtor(_,typ) -> - mkDefault (m,typ) -#if EXTENSIONTYPING - | ProvidedMeth(amap,mi,_,m) -> - let isProp = false // not necessarily correct, but this is only used post-creflect where this flag is irrelevant - let ilMethodRef = Import.ImportProvidedMethodBaseAsILMethodRef amap m mi - let isConstructor = mi.PUntaint((fun c -> c.IsConstructor), m) - let valu = mi.PUntaint((fun c -> c.DeclaringType.IsValueType), m) - let actualTypeInst = [] // GENERIC TYPE PROVIDERS: for generics, we would have something here - let actualMethInst = [] // GENERIC TYPE PROVIDERS: for generics, we would have something here - let ilReturnTys = Option.toList (minfo.GetCompiledReturnTy(amap, m, [])) // GENERIC TYPE PROVIDERS: for generics, we would have more here - // REVIEW: Should we allow protected calls? - Expr.Op(TOp.ILCall(false,false, valu, isConstructor,valUseFlags,isProp,false,ilMethodRef,actualTypeInst,actualMethInst, ilReturnTys),[],args,m) - -#endif -//--------------------------------------------------------------------------- -// Helpers when selecting members -//--------------------------------------------------------------------------- - - -/// Use the given function to select some of the member values from the members of an F# type -let SelectImmediateMemberVals g optFilter f (tcref:TyconRef) = - let chooser (vref:ValRef) = - match vref.MemberInfo with - // The 'when' condition is a workaround for the fact that values providing - // override and interface implementations are published in inferred module types - // These cannot be selected directly via the "." notation. - // However, it certainly is useful to be able to publish these values, as we can in theory - // optimize code to make direct calls to these methods. - | Some membInfo when not (ValRefIsExplicitImpl g vref) -> - f membInfo vref - | _ -> - None - - match optFilter with - | None -> tcref.MembersOfFSharpTyconByName |> NameMultiMap.chooseRange chooser - | Some nm -> tcref.MembersOfFSharpTyconByName |> NameMultiMap.find nm |> List.choose chooser - -/// Check whether a name matches an optional filter -let checkFilter optFilter (nm:string) = match optFilter with None -> true | Some n2 -> nm = n2 - -/// Try to select an F# value when querying members, and if so return a MethInfo that wraps the F# value. -let TrySelectMemberVal g optFilter typ pri _membInfo (vref:ValRef) = - if checkFilter optFilter vref.LogicalName then - Some(FSMeth(g,typ,vref,pri)) - else - None - -/// Query the immediate methods of an F# type, not taking into account inherited methods. The optFilter -/// parameter is an optional name to restrict the set of properties returned. -let GetImmediateIntrinsicMethInfosOfType (optFilter,ad) g amap m typ = - let minfos = - - match metadataOfTy g typ with -#if EXTENSIONTYPING - | ProvidedTypeMetadata info -> - let st = info.ProvidedType - let meths = - match optFilter with - | Some name -> st.PApplyArray ((fun st -> st.GetMethods() |> Array.filter (fun mi -> mi.Name = name) ), "GetMethods", m) - | None -> st.PApplyArray ((fun st -> st.GetMethods()), "GetMethods", m) - [ for mi in meths -> ProvidedMeth(amap,mi.Coerce(m),None,m) ] -#endif - | ILTypeMetadata (_,tdef) -> - let mdefs = tdef.Methods - let mdefs = (match optFilter with None -> mdefs.AsList | Some nm -> mdefs.FindByName nm) - mdefs |> List.map (fun mdef -> MethInfo.CreateILMeth(amap, m, typ, mdef)) - | FSharpOrArrayOrByrefOrTupleOrExnTypeMetadata -> - if not (isAppTy g typ) then [] - else SelectImmediateMemberVals g optFilter (TrySelectMemberVal g optFilter typ None) (tcrefOfAppTy g typ) - let minfos = minfos |> List.filter (IsMethInfoAccessible amap m ad) - minfos - -/// A helper type to help collect properties. -/// -/// Join up getters and setters which are not associated in the F# data structure -type PropertyCollector(g,amap,m,typ,optFilter,ad) = - - let hashIdentity = - Microsoft.FSharp.Collections.HashIdentity.FromFunctions - (fun (pinfo:PropInfo) -> hash pinfo.PropertyName) - (fun pinfo1 pinfo2 -> - pinfo1.IsStatic = pinfo2.IsStatic && - PropInfosEquivByNameAndPartialSig EraseNone g amap m pinfo1 pinfo2 && - pinfo1.IsDefiniteFSharpOverride = pinfo2.IsDefiniteFSharpOverride ) - let props = new System.Collections.Generic.Dictionary(hashIdentity) - let add pinfo = - if props.ContainsKey(pinfo) then - match props.[pinfo], pinfo with - | FSProp (_,typ,Some vref1,_), FSProp (_,_,_,Some vref2) - | FSProp (_,typ,_,Some vref2), FSProp (_,_,Some vref1,_) -> - let pinfo = FSProp (g,typ,Some vref1,Some vref2) - props.[pinfo] <- pinfo - | _ -> - // This assert fires while editing bad code. We will give a warning later in check.fs - //assert ("unexpected case"= "") - () - else - props.[pinfo] <- pinfo - - member x.Collect(membInfo:ValMemberInfo,vref:ValRef) = - match membInfo.MemberFlags.MemberKind with - | MemberKind.PropertyGet -> - let pinfo = FSProp(g,typ,Some vref,None) - if checkFilter optFilter vref.PropertyName && IsPropInfoAccessible g amap m ad pinfo then - add pinfo - | MemberKind.PropertySet -> - let pinfo = FSProp(g,typ,None,Some vref) - if checkFilter optFilter vref.PropertyName && IsPropInfoAccessible g amap m ad pinfo then - add pinfo - | _ -> - () - - member x.Close() = [ for KeyValue(_,pinfo) in props -> pinfo ] - -/// Query the immediate properties of an F# type, not taking into account inherited properties. The optFilter -/// parameter is an optional name to restrict the set of properties returned. -let GetImmediateIntrinsicPropInfosOfType (optFilter,ad) g amap m typ = - let pinfos = - - match metadataOfTy g typ with -#if EXTENSIONTYPING - | ProvidedTypeMetadata info -> - let st = info.ProvidedType - let matchingProps = - match optFilter with - | Some name -> - match st.PApply((fun st -> st.GetProperty name), m) with - | Tainted.Null -> [||] - | pi -> [|pi|] - | None -> - st.PApplyArray((fun st -> st.GetProperties()), "GetProperties", m) - matchingProps - |> Seq.map(fun pi -> ProvidedProp(amap,pi,m)) - |> List.ofSeq -#endif - | ILTypeMetadata (_,tdef) -> - let tinfo = ILTypeInfo.FromType g typ - let pdefs = tdef.Properties - let pdefs = match optFilter with None -> pdefs.AsList | Some nm -> pdefs.LookupByName nm - pdefs |> List.map (fun pd -> ILProp(g,ILPropInfo(tinfo,pd))) - | FSharpOrArrayOrByrefOrTupleOrExnTypeMetadata -> - - if not (isAppTy g typ) then [] - else - let propCollector = new PropertyCollector(g,amap,m,typ,optFilter,ad) - SelectImmediateMemberVals g None - (fun membInfo vref -> propCollector.Collect(membInfo,vref); None) - (tcrefOfAppTy g typ) |> ignore - propCollector.Close() - - let pinfos = pinfos |> List.filter (IsPropInfoAccessible g amap m ad) - pinfos - - -//--------------------------------------------------------------------------- -// - -/// Sets of methods up the hierarchy, ignoring duplicates by name and sig. -/// Used to collect sets of virtual methods, protected methods, protected -/// properties etc. -type HierarchyItem = - | MethodItem of MethInfo list list - | PropertyItem of PropInfo list list - | RecdFieldItem of RecdFieldInfo - | EventItem of EventInfo list - | ILFieldItem of ILFieldInfo list - -/// An InfoReader is an object to help us read and cache infos. -/// We create one of these for each file we typecheck. -/// -/// REVIEW: We could consider sharing one InfoReader across an entire compilation -/// run or have one global one for each (g,amap) pair. -type InfoReader(g:TcGlobals, amap:Import.ImportMap) = - - /// Get the declared IL fields of a type, not including inherited fields - let GetImmediateIntrinsicILFieldsOfType (optFilter,ad) m typ = - let infos = - match metadataOfTy g typ with -#if EXTENSIONTYPING - | ProvidedTypeMetadata info -> - let st = info.ProvidedType - match optFilter with - | None -> - [ for fi in st.PApplyArray((fun st -> st.GetFields()), "GetFields" , m) -> ProvidedField(amap,fi,m) ] - | Some name -> - match st.PApply ((fun st -> st.GetField name), m) with - | Tainted.Null -> [] - | fi -> [ ProvidedField(amap,fi,m) ] -#endif - | ILTypeMetadata (_,tdef) -> - let tinfo = ILTypeInfo.FromType g typ - let fdefs = tdef.Fields - let fdefs = match optFilter with None -> fdefs.AsList | Some nm -> fdefs.LookupByName nm - fdefs |> List.map (fun pd -> ILFieldInfo(tinfo,pd)) - | FSharpOrArrayOrByrefOrTupleOrExnTypeMetadata -> - [] - let infos = infos |> List.filter (IsILFieldInfoAccessible g amap m ad) - infos - - /// Get the declared events of a type, not including inherited events - let ComputeImmediateIntrinsicEventsOfType (optFilter,ad) m typ = - let infos = - match metadataOfTy g typ with -#if EXTENSIONTYPING - | ProvidedTypeMetadata info -> - let st = info.ProvidedType - match optFilter with - | None -> - [ for ei in st.PApplyArray((fun st -> st.GetEvents()), "GetEvents" , m) -> ProvidedEvent(amap,ei,m) ] - | Some name -> - match st.PApply ((fun st -> st.GetEvent name), m) with - | Tainted.Null -> [] - | ei -> [ ProvidedEvent(amap,ei,m) ] -#endif - | ILTypeMetadata (_,tdef) -> - let tinfo = ILTypeInfo.FromType g typ - let edefs = tdef.Events - let edefs = match optFilter with None -> edefs.AsList | Some nm -> edefs.LookupByName nm - [ for edef in edefs do - let einfo = ILEventInfo(tinfo,edef) - if IsILEventInfoAccessible g amap m ad einfo then - yield ILEvent(g,einfo) ] - | FSharpOrArrayOrByrefOrTupleOrExnTypeMetadata -> - [] - infos - - /// Make a reference to a record or class field - let MakeRecdFieldInfo g typ (tcref:TyconRef) fspec = - RecdFieldInfo(argsOfAppTy g typ,tcref.MakeNestedRecdFieldRef fspec) - - /// Get the F#-declared record fields or class 'val' fields of a type - let GetImmediateIntrinsicRecdOrClassFieldsOfType (optFilter,_ad) _m typ = - match tryDestAppTy g typ with - | None -> [] - | Some tcref -> - // Note;secret fields are not allowed in lookups here, as we're only looking - // up user-visible fields in name resolution. - match optFilter with - | Some nm -> - match tcref.GetFieldByName nm with - | Some rfield when not rfield.IsCompilerGenerated -> [MakeRecdFieldInfo g typ tcref rfield] - | _ -> [] - | None -> - [ for fdef in tcref.AllFieldsArray do - if not fdef.IsCompilerGenerated then - yield MakeRecdFieldInfo g typ tcref fdef ] - - - /// The primitive reader for the method info sets up a hierarchy - let GetIntrinsicMethodSetsUncached ((optFilter,ad,allowMultiIntfInst),m,typ) = - FoldPrimaryHierarchyOfType (fun typ acc -> GetImmediateIntrinsicMethInfosOfType (optFilter,ad) g amap m typ :: acc) g amap m allowMultiIntfInst typ [] - - /// The primitive reader for the property info sets up a hierarchy - let GetIntrinsicPropertySetsUncached ((optFilter,ad,allowMultiIntfInst),m,typ) = - FoldPrimaryHierarchyOfType (fun typ acc -> GetImmediateIntrinsicPropInfosOfType (optFilter,ad) g amap m typ :: acc) g amap m allowMultiIntfInst typ [] - - let GetIntrinsicILFieldInfosUncached ((optFilter,ad),m,typ) = - FoldPrimaryHierarchyOfType (fun typ acc -> GetImmediateIntrinsicILFieldsOfType (optFilter,ad) m typ @ acc) g amap m AllowMultiIntfInstantiations.Yes typ [] - - let GetIntrinsicEventInfosUncached ((optFilter,ad),m,typ) = - FoldPrimaryHierarchyOfType (fun typ acc -> ComputeImmediateIntrinsicEventsOfType (optFilter,ad) m typ @ acc) g amap m AllowMultiIntfInstantiations.Yes typ [] - - let GetIntrinsicRecdOrClassFieldInfosUncached ((optFilter,ad),m,typ) = - FoldPrimaryHierarchyOfType (fun typ acc -> GetImmediateIntrinsicRecdOrClassFieldsOfType (optFilter,ad) m typ @ acc) g amap m AllowMultiIntfInstantiations.Yes typ [] - - let GetEntireTypeHierachyUncached (allowMultiIntfInst,m,typ) = - FoldEntireHierarchyOfType (fun typ acc -> typ :: acc) g amap m allowMultiIntfInst typ [] - - let GetPrimaryTypeHierachyUncached (allowMultiIntfInst,m,typ) = - FoldPrimaryHierarchyOfType (fun typ acc -> typ :: acc) g amap m allowMultiIntfInst typ [] - - /// The primitive reader for the named items up a hierarchy - let GetIntrinsicNamedItemsUncached ((nm,ad),m,typ) = - if nm = ".ctor" then None else // '.ctor' lookups only ever happen via constructor syntax - let optFilter = Some nm - FoldPrimaryHierarchyOfType (fun typ acc -> - let minfos = GetImmediateIntrinsicMethInfosOfType (optFilter,ad) g amap m typ - let pinfos = GetImmediateIntrinsicPropInfosOfType (optFilter,ad) g amap m typ - let finfos = GetImmediateIntrinsicILFieldsOfType (optFilter,ad) m typ - let einfos = ComputeImmediateIntrinsicEventsOfType (optFilter,ad) m typ - let rfinfos = GetImmediateIntrinsicRecdOrClassFieldsOfType (optFilter,ad) m typ - match acc with - | Some(MethodItem(inheritedMethSets)) when nonNil minfos -> Some(MethodItem (minfos::inheritedMethSets)) - | _ when nonNil minfos -> Some(MethodItem ([minfos])) - | Some(PropertyItem(inheritedPropSets)) when nonNil pinfos -> Some(PropertyItem(pinfos::inheritedPropSets)) - | _ when nonNil pinfos -> Some(PropertyItem([pinfos])) - | _ when nonNil finfos -> Some(ILFieldItem(finfos)) - | _ when nonNil einfos -> Some(EventItem(einfos)) - | _ when nonNil rfinfos -> - match rfinfos with - | [single] -> Some(RecdFieldItem(single)) - | _ -> failwith "Unexpected multiple fields with the same name" // Because an explicit name (i.e., nm) was supplied, there will be only one element at most. - | _ -> acc) - g amap m - AllowMultiIntfInstantiations.Yes - typ - None - - /// Make a cache for function 'f' keyed by type (plus some additional 'flags') that only - /// caches computations for monomorphic types. - - let MakeInfoCache f (flagsEq : System.Collections.Generic.IEqualityComparer<_>) = - new MemoizationTable<_,_> - (compute=f, - // Only cache closed, monomorphic types (closed = all members for the type - // have been processed). Generic type instantiations could be processed if we had - // a decent hash function for these. - canMemoize=(fun (_flags,(_:range),typ) -> - match stripTyEqns g typ with - | TType_app(tcref,[]) -> tcref.TypeContents.tcaug_closed - | _ -> false), - - keyComparer= - { new System.Collections.Generic.IEqualityComparer<_> with - member x.Equals((flags1,_,typ1),(flags2,_,typ2)) = - // Ignoring the ranges - that's OK. - flagsEq.Equals(flags1,flags2) && - match stripTyEqns g typ1, stripTyEqns g typ2 with - | TType_app(tcref1,[]),TType_app(tcref2,[]) -> tyconRefEq g tcref1 tcref2 - | _ -> false - member x.GetHashCode((flags,_,typ)) = - // Ignoring the ranges - that's OK. - flagsEq.GetHashCode flags + - (match stripTyEqns g typ with - | TType_app(tcref,[]) -> hash tcref.LogicalName - | _ -> 0) }) - - - let hashFlags0 = - { new System.Collections.Generic.IEqualityComparer<_> with - member x.GetHashCode((filter: string option, ad: AccessorDomain, _allowMultiIntfInst1)) = hash filter + AccessorDomain.CustomGetHashCode ad - member x.Equals((filter1, ad1, allowMultiIntfInst1), (filter2,ad2, allowMultiIntfInst2)) = - (filter1 = filter2) && AccessorDomain.CustomEquals(g,ad1,ad2) && allowMultiIntfInst1 = allowMultiIntfInst2 } - - let hashFlags1 = - { new System.Collections.Generic.IEqualityComparer<_> with - member x.GetHashCode((filter: string option,ad: AccessorDomain)) = hash filter + AccessorDomain.CustomGetHashCode ad - member x.Equals((filter1,ad1), (filter2,ad2)) = (filter1 = filter2) && AccessorDomain.CustomEquals(g,ad1,ad2) } - - let hashFlags2 = - { new System.Collections.Generic.IEqualityComparer<_> with - member x.GetHashCode((nm: string,ad: AccessorDomain)) = hash nm + AccessorDomain.CustomGetHashCode ad - member x.Equals((nm1,ad1), (nm2,ad2)) = (nm1 = nm2) && AccessorDomain.CustomEquals(g,ad1,ad2) } - - let methodInfoCache = MakeInfoCache GetIntrinsicMethodSetsUncached hashFlags0 - let propertyInfoCache = MakeInfoCache GetIntrinsicPropertySetsUncached hashFlags0 - let recdOrClassFieldInfoCache = MakeInfoCache GetIntrinsicRecdOrClassFieldInfosUncached hashFlags1 - let ilFieldInfoCache = MakeInfoCache GetIntrinsicILFieldInfosUncached hashFlags1 - let eventInfoCache = MakeInfoCache GetIntrinsicEventInfosUncached hashFlags1 - let namedItemsCache = MakeInfoCache GetIntrinsicNamedItemsUncached hashFlags2 - - let entireTypeHierarchyCache = MakeInfoCache GetEntireTypeHierachyUncached HashIdentity.Structural - let primaryTypeHierarchyCache = MakeInfoCache GetPrimaryTypeHierachyUncached HashIdentity.Structural - - member x.g = g - member x.amap = amap - - /// Read the raw method sets of a type, including inherited ones. Cache the result for monomorphic types - member x.GetRawIntrinsicMethodSetsOfType (optFilter,ad,allowMultiIntfInst,m,typ) = - methodInfoCache.Apply(((optFilter,ad,allowMultiIntfInst),m,typ)) - - /// Read the raw property sets of a type, including inherited ones. Cache the result for monomorphic types - member x.GetRawIntrinsicPropertySetsOfType (optFilter,ad,allowMultiIntfInst,m,typ) = - propertyInfoCache.Apply(((optFilter,ad,allowMultiIntfInst),m,typ)) - - /// Read the record or class fields of a type, including inherited ones. Cache the result for monomorphic types. - member x.GetRecordOrClassFieldsOfType (optFilter,ad,m,typ) = - recdOrClassFieldInfoCache.Apply(((optFilter,ad),m,typ)) - - /// Read the IL fields of a type, including inherited ones. Cache the result for monomorphic types. - member x.GetILFieldInfosOfType (optFilter,ad,m,typ) = - ilFieldInfoCache.Apply(((optFilter,ad),m,typ)) - - member x.GetImmediateIntrinsicEventsOfType (optFilter,ad,m,typ) = ComputeImmediateIntrinsicEventsOfType (optFilter,ad) m typ - - /// Read the events of a type, including inherited ones. Cache the result for monomorphic types. - member x.GetEventInfosOfType (optFilter,ad,m,typ) = - eventInfoCache.Apply(((optFilter,ad),m,typ)) - - /// Try and find a record or class field for a type. - member x.TryFindRecdOrClassFieldInfoOfType (nm,m,typ) = - match recdOrClassFieldInfoCache.Apply((Some nm,AccessibleFromSomewhere),m,typ) with - | [] -> None - | [single] -> Some single - | flds -> - // multiple fields with the same name can come from different classes, - // so filter them by the given type name - match tryDestAppTy g typ with - | None -> None - | Some tcref -> - match flds |> List.filter (fun rfinfo -> tyconRefEq g tcref rfinfo.TyconRef) with - | [] -> None - | [single] -> Some single - | _ -> failwith "unexpected multiple fields with same name" // Because it should have been already reported as duplicate fields - - /// Try and find an item with the given name in a type. - member x.TryFindNamedItemOfType (nm,ad,m,typ) = - namedItemsCache.Apply(((nm,ad),m,typ)) - - /// Get the super-types of a type, including interface types. - member x.GetEntireTypeHierachy (allowMultiIntfInst,m,typ) = - entireTypeHierarchyCache.Apply((allowMultiIntfInst,m,typ)) - - /// Get the super-types of a type, excluding interface types. - member x.GetPrimaryTypeHierachy (allowMultiIntfInst,m,typ) = - primaryTypeHierarchyCache.Apply((allowMultiIntfInst,m,typ)) - - -//------------------------------------------------------------------------- -// Constructor infos - - -/// Get the declared constructors of any F# type -let GetIntrinsicConstructorInfosOfType (infoReader:InfoReader) m ty = - let g = infoReader.g - let amap = infoReader.amap - if isAppTy g ty then - match metadataOfTy g ty with -#if EXTENSIONTYPING - | ProvidedTypeMetadata info -> - let st = info.ProvidedType - [ for ci in st.PApplyArray((fun st -> st.GetConstructors()), "GetConstructors", m) do - yield ProvidedMeth(amap,ci.Coerce(m),None,m) ] -#endif - | ILTypeMetadata _ -> - let tinfo = ILTypeInfo.FromType g ty - tinfo.RawMetadata.Methods.FindByName ".ctor" - |> List.filter (fun md -> match md.mdKind with MethodKind.Ctor -> true | _ -> false) - |> List.map (fun mdef -> MethInfo.CreateILMeth (amap, m, ty, mdef)) - - | FSharpOrArrayOrByrefOrTupleOrExnTypeMetadata -> - let tcref = tcrefOfAppTy g ty - tcref.MembersOfFSharpTyconByName - |> NameMultiMap.find ".ctor" - |> List.choose(fun vref -> - match vref.MemberInfo with - | Some membInfo when (membInfo.MemberFlags.MemberKind = MemberKind.Constructor) -> Some vref - | _ -> None) - |> List.map (fun x -> FSMeth(g,ty,x,None)) - else [] - -//------------------------------------------------------------------------- -// Collecting methods and properties taking into account hiding rules in the hierarchy - - -/// Indicates if we prefer overrides or abstract slots. -type FindMemberFlag = - /// Prefer items toward the top of the hierarchy, which we do if the items are virtual - /// but not when resolving base calls. - | IgnoreOverrides - /// Get overrides instead of abstract slots when measuring whether a class/interface implements all its required slots. - | PreferOverrides - -/// The input list is sorted from most-derived to least-derived type, so any System.Object methods -/// are at the end of the list. Return a filtered list where prior/subsequent members matching by name and -/// that are in the same equivalence class have been removed. We keep a name-indexed table to -/// be more efficient when we check to see if we've already seen a particular named method. -type private IndexedList<'T>(itemLists: 'T list list, itemsByName: NameMultiMap<'T>) = - - /// Get the item sets - member x.Items = itemLists - - /// Get the items with a particular name - member x.ItemsWithName(nm) = NameMultiMap.find nm itemsByName - - /// Add new items, extracting the names using the given function. - member x.AddItems(items,nmf) = IndexedList<'T>(items::itemLists,List.foldBack (fun x acc -> NameMultiMap.add (nmf x) x acc) items itemsByName ) - - /// Get an empty set of items - static member Empty = IndexedList<'T>([],NameMultiMap.empty) - - /// Filter a set of new items to add according to the content of the list. Only keep an item - /// if it passes 'keepTest' for all matching items already in the list. - member x.FilterNewItems keepTest nmf itemsToAdd = - // Have we already seen an item with the same name and that is in the same equivalence class? - // If so, ignore this one. Note we can check against the original incoming 'ilist' because we are assuming that - // none the elements of 'itemsToAdd' are equivalent. - itemsToAdd |> List.filter (fun item -> List.forall (keepTest item) (x.ItemsWithName(nmf item))) - -/// Add all the items to the IndexedList, preferring the ones in the super-types. This is used to hide methods -/// in super classes and/or hide overrides of methods in subclasses. -/// -/// Assume no items in 'items' are equivalent according to 'equivTest'. This is valid because each step in a -/// .NET class hierarchy introduces a consistent set of methods, none of which hide each other within the -/// given set. This is an important optimization because it means we don't have filter for equivalence between the -/// large overload sets introduced by methods like System.WriteLine. -/// -/// Assume items can be given names by 'nmf', where two items with different names are -/// not equivalent. - -let private FilterItemsInSubTypesBasedOnItemsInSuperTypes nmf keepTest itemLists = - let rec loop itemLists = - match itemLists with - | [] -> IndexedList.Empty - | items :: itemsInSuperTypes -> - let ilist = loop itemsInSuperTypes - let itemsToAdd = ilist.FilterNewItems keepTest nmf items - ilist.AddItems(itemsToAdd,nmf) - (loop itemLists).Items - -/// Add all the items to the IndexedList, preferring the ones in the sub-types. -let private FilterItemsInSuperTypesBasedOnItemsInSubTypes nmf keepTest itemLists = - let rec loop itemLists (indexedItemsInSubTypes:IndexedList<_>) = - match itemLists with - | [] -> List.rev indexedItemsInSubTypes.Items - | items :: itemsInSuperTypes -> - let itemsToAdd = items |> List.filter (fun item -> keepTest item (indexedItemsInSubTypes.ItemsWithName(nmf item))) - let ilist = indexedItemsInSubTypes.AddItems(itemsToAdd,nmf) - loop itemsInSuperTypes ilist - - loop itemLists IndexedList.Empty - -let private ExcludeItemsInSuperTypesBasedOnEquivTestWithItemsInSubTypes nmf equivTest itemLists = - FilterItemsInSuperTypesBasedOnItemsInSubTypes nmf (fun item1 items -> not (items |> List.exists (fun item2 -> equivTest item1 item2))) itemLists - -/// Filter the overrides of methods or properties, either keeping the overrides or keeping the dispatch slots. -let private FilterOverrides findFlag (isVirt:'a->bool,isNewSlot,isDefiniteOverride,isFinal,equivSigs,nmf:'a->string) items = - let equivVirts x y = isVirt x && isVirt y && equivSigs x y - - match findFlag with - | PreferOverrides -> - items - // For each F#-declared override, get rid of any equivalent abstract member in the same type - // This is because F# abstract members with default overrides give rise to two members with the - // same logical signature in the same type, e.g. - // type ClassType1() = - // abstract VirtualMethod1: string -> int - // default x.VirtualMethod1(s) = 3 - - |> List.map (fun items -> - let definiteOverrides = items |> List.filter isDefiniteOverride - items |> List.filter (fun item -> (isDefiniteOverride item || not (List.exists (equivVirts item) definiteOverrides)))) - - // only keep virtuals that are not signature-equivalent to virtuals in subtypes - |> ExcludeItemsInSuperTypesBasedOnEquivTestWithItemsInSubTypes nmf equivVirts - | IgnoreOverrides -> - let equivNewSlots x y = isNewSlot x && isNewSlot y && equivSigs x y - items - // Remove any F#-declared overrides. THese may occur in the same type as the abstract member (unlike with .NET metadata) - // Include any 'newslot' declared methods. - |> List.map (List.filter (fun x -> not (isDefiniteOverride x))) - - // Remove any virtuals that are signature-equivalent to virtuals in subtypes, except for newslots - // That is, keep if it's - /// (a) not virtual - // (b) is a new slot or - // (c) not equivalent - // We keep virtual finals around for error detection later on - |> FilterItemsInSubTypesBasedOnItemsInSuperTypes nmf (fun newItem priorItem -> - (isVirt newItem && isFinal newItem) || not (isVirt newItem) || isNewSlot newItem || not (equivVirts newItem priorItem) ) - - // Remove any abstract slots in supertypes that are (a) hidden by another newslot and (b) implemented - // We leave unimplemented ones around to give errors, e.g. for - // [] - // type PA() = - // abstract M : int -> unit - // - // [] - // type PB<'a>() = - // inherit PA() - // abstract M : 'a -> unit - // - // [] - // type PC() = - // inherit PB() - // // Here, PA.M and PB.M have the same signature, so PA.M is unimplementable. - // // REVIEW: in future we may give a friendly error at this point - // - // type PD() = - // inherit PC() - // override this.M(x:int) = () - - |> FilterItemsInSuperTypesBasedOnItemsInSubTypes nmf (fun item1 superTypeItems -> - not (isNewSlot item1 && - superTypeItems |> List.exists (equivNewSlots item1) && - superTypeItems |> List.exists (fun item2 -> isDefiniteOverride item1 && equivVirts item1 item2))) - - -/// Filter the overrides of methods, either keeping the overrides or keeping the dispatch slots. -let private FilterOverridesOfMethInfos findFlag g amap m minfos = - FilterOverrides findFlag ((fun (minfo:MethInfo) -> minfo.IsVirtual),(fun minfo -> minfo.IsNewSlot),(fun minfo -> minfo.IsDefiniteFSharpOverride),(fun minfo -> minfo.IsFinal),MethInfosEquivByNameAndSig EraseNone true g amap m,(fun minfo -> minfo.LogicalName)) minfos - -/// Filter the overrides of properties, either keeping the overrides or keeping the dispatch slots. -let private FilterOverridesOfPropInfos findFlag g amap m props = - FilterOverrides findFlag ((fun (pinfo:PropInfo) -> pinfo.IsVirtualProperty),(fun pinfo -> pinfo.IsNewSlot),(fun pinfo -> pinfo.IsDefiniteFSharpOverride),(fun _ -> false),PropInfosEquivByNameAndSig EraseNone g amap m, (fun pinfo -> pinfo.PropertyName)) props - -/// Exclude methods from super types which have the same signature as a method in a more specific type. -let ExcludeHiddenOfMethInfos g amap m (minfos:MethInfo list list) = - minfos - |> ExcludeItemsInSuperTypesBasedOnEquivTestWithItemsInSubTypes - (fun minfo -> minfo.LogicalName) - (fun m1 m2 -> - // only hide those truly from super classes - not (tyconRefEq g (tcrefOfAppTy g m1.EnclosingType) (tcrefOfAppTy g m2.EnclosingType)) && - MethInfosEquivByNameAndPartialSig EraseNone true g amap m m1 m2) - - |> List.concat - -/// Exclude properties from super types which have the same name as a property in a more specific type. -let ExcludeHiddenOfPropInfos g amap m pinfos = - pinfos - |> ExcludeItemsInSuperTypesBasedOnEquivTestWithItemsInSubTypes (fun (pinfo:PropInfo) -> pinfo.PropertyName) (PropInfosEquivByNameAndPartialSig EraseNone g amap m) - |> List.concat - -/// Get the sets of intrinsic methods in the hierarchy (not including extension methods) -let GetIntrinsicMethInfoSetsOfType (infoReader:InfoReader) (optFilter,ad,allowMultiIntfInst) findFlag m typ = - infoReader.GetRawIntrinsicMethodSetsOfType(optFilter,ad,allowMultiIntfInst,m,typ) - |> FilterOverridesOfMethInfos findFlag infoReader.g infoReader.amap m - -/// Get the sets intrinsic properties in the hierarchy (not including extension properties) -let GetIntrinsicPropInfoSetsOfType (infoReader:InfoReader) (optFilter,ad,allowMultiIntfInst) findFlag m typ = - infoReader.GetRawIntrinsicPropertySetsOfType(optFilter,ad,allowMultiIntfInst,m,typ) - |> FilterOverridesOfPropInfos findFlag infoReader.g infoReader.amap m - -/// Get the flattened list of intrinsic methods in the hierarchy -let GetIntrinsicMethInfosOfType infoReader (optFilter,ad,allowMultiIntfInst) findFlag m typ = - GetIntrinsicMethInfoSetsOfType infoReader (optFilter,ad,allowMultiIntfInst) findFlag m typ |> List.concat - -/// Get the flattened list of intrinsic properties in the hierarchy -let GetIntrinsicPropInfosOfType infoReader (optFilter,ad,allowMultiIntfInst) findFlag m typ = - GetIntrinsicPropInfoSetsOfType infoReader (optFilter,ad,allowMultiIntfInst) findFlag m typ |> List.concat - -/// Perform type-directed name resolution of a particular named member in an F# type -let TryFindIntrinsicNamedItemOfType (infoReader:InfoReader) (nm,ad) findFlag m typ = - match infoReader.TryFindNamedItemOfType(nm, ad, m, typ) with - | Some item -> - match item with - | PropertyItem psets -> Some(PropertyItem (psets |> FilterOverridesOfPropInfos findFlag infoReader.g infoReader.amap m)) - | MethodItem msets -> Some(MethodItem (msets |> FilterOverridesOfMethInfos findFlag infoReader.g infoReader.amap m)) - | _ -> Some(item) - | None -> None - -/// Try to detect the existence of a method on a type. -/// Used for -/// -- getting the GetEnumerator, get_Current, MoveNext methods for enumerable types -/// -- getting the Dispose method when resolving the 'use' construct -/// -- getting the various methods used to desugar the computation expression syntax -let TryFindIntrinsicMethInfo infoReader m ad nm ty = - GetIntrinsicMethInfosOfType infoReader (Some nm,ad,AllowMultiIntfInstantiations.Yes) IgnoreOverrides m ty - -/// Try to find a particular named property on a type. Only used to ensure that local 'let' definitions and property names -/// are distinct, a somewhat adhoc check in tc.fs. -let TryFindPropInfo infoReader m ad nm ty = - GetIntrinsicPropInfosOfType infoReader (Some nm,ad,AllowMultiIntfInstantiations.Yes) IgnoreOverrides m ty - -//------------------------------------------------------------------------- -// Helpers related to delegates and events -//------------------------------------------------------------------------- - -/// The Invoke MethInfo, the function argument types, the function return type -/// and the overall F# function type for the function type associated with a .NET delegate type -[] -type SigOfFunctionForDelegate = SigOfFunctionForDelegate of MethInfo * TType list * TType * TType - -/// Given a delegate type work out the minfo, argument types, return type -/// and F# function type by looking at the Invoke signature of the delegate. -let GetSigOfFunctionForDelegate (infoReader:InfoReader) delty m ad = - let g = infoReader.g - let amap = infoReader.amap - let invokeMethInfo = - match GetIntrinsicMethInfosOfType infoReader (Some "Invoke",ad,AllowMultiIntfInstantiations.Yes) IgnoreOverrides m delty with - | [h] -> h - | [] -> error(Error(FSComp.SR.noInvokeMethodsFound (),m)) - | h :: _ -> warning(InternalError(FSComp.SR.moreThanOneInvokeMethodFound (),m)); h - - let minst = [] // a delegate's Invoke method is never generic - let compiledViewOfDelArgTys = - match invokeMethInfo.GetParamTypes(amap, m, minst) with - | [args] -> args - | _ -> error(Error(FSComp.SR.delegatesNotAllowedToHaveCurriedSignatures (),m)) - let fsharpViewOfDelArgTys = - match compiledViewOfDelArgTys with - | [] -> [g.unit_ty] - | _ -> compiledViewOfDelArgTys - let delRetTy = invokeMethInfo.GetFSharpReturnTy(amap, m, minst) - CheckMethInfoAttributes g m None invokeMethInfo |> CommitOperationResult - let fty = mkIteratedFunTy fsharpViewOfDelArgTys delRetTy - SigOfFunctionForDelegate(invokeMethInfo,compiledViewOfDelArgTys,delRetTy,fty) - -/// Try and interpret a delegate type as a "standard" .NET delegate type associated with an event, with a "sender" parameter. -let TryDestStandardDelegateTyp (infoReader:InfoReader) m ad delTy = - let g = infoReader.g - let (SigOfFunctionForDelegate(_,compiledViewOfDelArgTys,delRetTy,_)) = GetSigOfFunctionForDelegate infoReader delTy m ad - match compiledViewOfDelArgTys with - | senderTy :: argTys when (isObjTy g senderTy) && not (List.exists (isByrefTy g) argTys) -> Some(mkTupledTy g argTys,delRetTy) - | _ -> None - - -/// Indicates if an event info is associated with a delegate type that is a "standard" .NET delegate type -/// with a sender parameter. -// -/// In the F# design, we take advantage of the following idiom to simplify away the bogus "object" parameter of the -/// of the "Add" methods associated with events. If you want to access it you -/// can use AddHandler instead. - -/// The .NET Framework guidelines indicate that the delegate type used for -/// an event should take two parameters, an "object source" parameter -/// indicating the source of the event, and an "e" parameter that -/// encapsulates any additional information about the event. The type of -/// the "e" parameter should derive from the EventArgs class. For events -/// that do not use any additional information, the .NET Framework has -/// already defined an appropriate delegate type: EventHandler. -/// (from http://msdn.microsoft.com/library/default.asp?url=/library/en-us/csref/html/vcwlkEventsTutorial.asp) -let IsStandardEventInfo (infoReader:InfoReader) m ad (einfo:EventInfo) = - let dty = einfo.GetDelegateType(infoReader.amap,m) - match TryDestStandardDelegateTyp infoReader m ad dty with - | Some _ -> true - | None -> false - -/// Get the (perhaps tupled) argument type accepted by an event -let ArgsTypOfEventInfo (infoReader:InfoReader) m ad (einfo:EventInfo) = - let amap = infoReader.amap - let dty = einfo.GetDelegateType(amap,m) - match TryDestStandardDelegateTyp infoReader m ad dty with - | Some(argtys,_) -> argtys - | None -> error(nonStandardEventError einfo.EventName m) - -/// Get the type of the event when looked at as if it is a property -/// Used when displaying the property in Intellisense -let PropTypOfEventInfo (infoReader:InfoReader) m ad (einfo:EventInfo) = - let g = infoReader.g - let amap = infoReader.amap - let delTy = einfo.GetDelegateType(amap,m) - let argsTy = ArgsTypOfEventInfo infoReader m ad einfo - mkIEventType g delTy argsTy - - diff --git a/src/fsharp/vs/ServiceDeclarations.fs b/src/fsharp/vs/ServiceDeclarations.fs index 5c4d52645f7..13eff5bcb83 100644 --- a/src/fsharp/vs/ServiceDeclarations.fs +++ b/src/fsharp/vs/ServiceDeclarations.fs @@ -8,25 +8,29 @@ namespace Microsoft.FSharp.Compiler.SourceCodeServices open System +open System.Collections.Generic open System.IO open System.Text -open System.Collections.Generic + open Microsoft.FSharp.Core.Printf open Microsoft.FSharp.Compiler open Microsoft.FSharp.Compiler.AbstractIL.IL open Microsoft.FSharp.Compiler.AbstractIL.Internal.Library open Microsoft.FSharp.Compiler.AbstractIL.Diagnostics -open Microsoft.FSharp.Compiler.PrettyNaming -open Microsoft.FSharp.Compiler.TcGlobals -open Microsoft.FSharp.Compiler.Range + +open Microsoft.FSharp.Compiler.AccessibilityLogic open Microsoft.FSharp.Compiler.Ast open Microsoft.FSharp.Compiler.ErrorLogger +open Microsoft.FSharp.Compiler.Layout +open Microsoft.FSharp.Compiler.Lib +open Microsoft.FSharp.Compiler.PrettyNaming +open Microsoft.FSharp.Compiler.Range open Microsoft.FSharp.Compiler.Tast open Microsoft.FSharp.Compiler.Tastops -open Microsoft.FSharp.Compiler.Lib -open Microsoft.FSharp.Compiler.Layout +open Microsoft.FSharp.Compiler.TcGlobals open Microsoft.FSharp.Compiler.Infos open Microsoft.FSharp.Compiler.NameResolution +open Microsoft.FSharp.Compiler.InfoReader open Microsoft.FSharp.Compiler.SourceCodeServices.ItemDescriptionIcons module EnvMisc2 = diff --git a/src/fsharp/vs/ServiceDeclarations.fsi b/src/fsharp/vs/ServiceDeclarations.fsi index 31a72e6742e..1961d37411f 100755 --- a/src/fsharp/vs/ServiceDeclarations.fsi +++ b/src/fsharp/vs/ServiceDeclarations.fsi @@ -12,6 +12,7 @@ open Microsoft.FSharp.Compiler.Range open Microsoft.FSharp.Compiler.TcGlobals open Microsoft.FSharp.Compiler.Infos open Microsoft.FSharp.Compiler.NameResolution +open Microsoft.FSharp.Compiler.InfoReader open Microsoft.FSharp.Compiler.Tast open Microsoft.FSharp.Compiler.Tastops diff --git a/src/fsharp/vs/Symbols.fs b/src/fsharp/vs/Symbols.fs index eaa0c25dd72..195a1dc3217 100644 --- a/src/fsharp/vs/Symbols.fs +++ b/src/fsharp/vs/Symbols.fs @@ -9,6 +9,9 @@ open Microsoft.FSharp.Compiler open Microsoft.FSharp.Compiler.AbstractIL.Internal.Library open Microsoft.FSharp.Compiler.AbstractIL.IL open Microsoft.FSharp.Compiler.Infos +open Microsoft.FSharp.Compiler.AttributeChecking +open Microsoft.FSharp.Compiler.AccessibilityLogic +open Microsoft.FSharp.Compiler.InfoReader open Microsoft.FSharp.Compiler.Range open Microsoft.FSharp.Compiler.Ast open Microsoft.FSharp.Compiler.CompileOps @@ -502,7 +505,7 @@ and FSharpEntity(cenv:cenv, entity:EntityRef) = member __.Attributes = if isUnresolved() then makeReadOnlyCollection[] else - AttributeChecking.GetAttribInfosOfEntity cenv.g cenv.amap range0 entity + GetAttribInfosOfEntity cenv.g cenv.amap range0 entity |> List.map (fun a -> FSharpAttribute(cenv, a)) |> makeReadOnlyCollection @@ -799,7 +802,7 @@ and FSharpAccessibility(a:Accessibility, ?isProtected) = override x.ToString() = stringOfAccess a -and [] FSharpAccessibilityRights(thisCcu: CcuThunk, ad:Infos.AccessorDomain) = +and [] FSharpAccessibilityRights(thisCcu: CcuThunk, ad:AccessorDomain) = member internal __.ThisCcu = thisCcu member internal __.Contents = ad @@ -1621,11 +1624,11 @@ and FSharpMemberOrFunctionOrValue(cenv, d:FSharpMemberOrValData, item) = let m = range0 match d with | E einfo -> - AttributeChecking.GetAttribInfosOfEvent cenv.amap m einfo |> List.map (fun a -> FSharpAttribute(cenv, a)) + GetAttribInfosOfEvent cenv.amap m einfo |> List.map (fun a -> FSharpAttribute(cenv, a)) | P pinfo -> - AttributeChecking.GetAttribInfosOfProp cenv.amap m pinfo |> List.map (fun a -> FSharpAttribute(cenv, a)) + GetAttribInfosOfProp cenv.amap m pinfo |> List.map (fun a -> FSharpAttribute(cenv, a)) | M minfo -> - AttributeChecking.GetAttribInfosOfMethod cenv.amap m minfo |> List.map (fun a -> FSharpAttribute(cenv, a)) + GetAttribInfosOfMethod cenv.amap m minfo |> List.map (fun a -> FSharpAttribute(cenv, a)) | V v -> v.Attribs |> List.map (fun a -> FSharpAttribute(cenv, AttribInfo.FSAttribInfo(cenv.g, a))) |> makeReadOnlyCollection diff --git a/src/fsharp/vs/Symbols.fsi b/src/fsharp/vs/Symbols.fsi index 6e9f9400448..86b13d3df24 100644 --- a/src/fsharp/vs/Symbols.fsi +++ b/src/fsharp/vs/Symbols.fsi @@ -13,10 +13,11 @@ namespace Microsoft.FSharp.Compiler.SourceCodeServices open System.Collections.Generic open Microsoft.FSharp.Compiler -open Microsoft.FSharp.Compiler.TcGlobals -open Microsoft.FSharp.Compiler.Tast -open Microsoft.FSharp.Compiler.Range +open Microsoft.FSharp.Compiler.AccessibilityLogic open Microsoft.FSharp.Compiler.CompileOps +open Microsoft.FSharp.Compiler.Range +open Microsoft.FSharp.Compiler.Tast +open Microsoft.FSharp.Compiler.TcGlobals module internal Impl = type internal cenv = @@ -420,8 +421,8 @@ and [] internal FSharpField = /// Represents the rights of a compilation to access symbols and [] internal FSharpAccessibilityRights = - internal new : CcuThunk * Infos.AccessorDomain -> FSharpAccessibilityRights - member internal Contents : Infos.AccessorDomain + internal new : CcuThunk * AccessorDomain -> FSharpAccessibilityRights + member internal Contents : AccessorDomain /// Indicates the accessibility of a symbol, as seen by the F# language and [] internal FSharpAccessibility = diff --git a/src/fsharp/vs/service.fs b/src/fsharp/vs/service.fs index e96d691a20c..90f0c9d827c 100644 --- a/src/fsharp/vs/service.fs +++ b/src/fsharp/vs/service.fs @@ -15,32 +15,36 @@ open System.Collections.Generic open Microsoft.FSharp.Core.Printf open Microsoft.FSharp.Compiler open Microsoft.FSharp.Compiler.AbstractIL +open Microsoft.FSharp.Compiler.AbstractIL.IL +open Microsoft.FSharp.Compiler.AbstractIL.Diagnostics open Microsoft.FSharp.Compiler.AbstractIL.Internal open Microsoft.FSharp.Compiler.AbstractIL.Internal.Library + +open Microsoft.FSharp.Compiler.AccessibilityLogic +open Microsoft.FSharp.Compiler.Ast +open Microsoft.FSharp.Compiler.CompileOps +open Microsoft.FSharp.Compiler.ErrorLogger +open Microsoft.FSharp.Compiler.Lib open Microsoft.FSharp.Compiler.MSBuildResolver -open Microsoft.FSharp.Compiler.AbstractIL.Diagnostics open Microsoft.FSharp.Compiler.PrettyNaming - -open Microsoft.FSharp.Compiler.TcGlobals open Microsoft.FSharp.Compiler.Parser open Microsoft.FSharp.Compiler.Range -open Microsoft.FSharp.Compiler.Ast -open Microsoft.FSharp.Compiler.ErrorLogger open Microsoft.FSharp.Compiler.Lexhelp -open Microsoft.FSharp.Compiler.CompileOps +open Microsoft.FSharp.Compiler.Layout open Microsoft.FSharp.Compiler.Tast open Microsoft.FSharp.Compiler.Tastops open Microsoft.FSharp.Compiler.Tastops.DebugPrint -open Microsoft.FSharp.Compiler.Lib -open Microsoft.FSharp.Compiler.AbstractIL.IL -open Microsoft.FSharp.Compiler.Layout -open Microsoft.FSharp.Compiler.TypeChecker +open Microsoft.FSharp.Compiler.TcGlobals open Microsoft.FSharp.Compiler.Infos +open Microsoft.FSharp.Compiler.InfoReader open Microsoft.FSharp.Compiler.NameResolution +open Microsoft.FSharp.Compiler.TypeChecker + open Internal.Utilities.Collections open Internal.Utilities.Debug open Internal.Utilities open Internal.Utilities.StructuredFormat + open Microsoft.FSharp.Compiler.SourceCodeServices.ItemDescriptionsImpl [] diff --git a/src/update.cmd b/src/update.cmd index ceb4462f4c9..366619821c2 100644 --- a/src/update.cmd +++ b/src/update.cmd @@ -8,15 +8,11 @@ setlocal if /i "%1" == "debug" goto :ok if /i "%1" == "release" goto :ok -if /i "%1" == "vsdebug" goto :ok -if /i "%1" == "vsrelease" goto :ok echo adding required strong name verification skipping, and NGening built binaries echo Usage: echo update.cmd debug [-ngen] echo update.cmd release [-ngen] -echo update.cmd vsdebug [-ngen] -echo update.cmd vsrelease [-ngen] exit /b 1 :ok diff --git a/tests/RunTests.cmd b/tests/RunTests.cmd index 140fbd34de3..1c634fad0e7 100644 --- a/tests/RunTests.cmd +++ b/tests/RunTests.cmd @@ -60,7 +60,7 @@ set HOSTED_COMPILER=1 rem path to fsc.exe which will be used by tests set FSCBINPATH=%~dp0..\%FLAVOR%\net40\bin -ECHO FSCBINPATH% +ECHO %FSCBINPATH% rem folder where test logs/results will be dropped set RESULTSDIR=%~dp0TestResults diff --git a/tests/fsharp/FSharp.Tests.fsproj b/tests/fsharp/FSharp.Tests.fsproj index cc09622d025..9fb41bcc3cf 100644 --- a/tests/fsharp/FSharp.Tests.fsproj +++ b/tests/fsharp/FSharp.Tests.fsproj @@ -67,6 +67,7 @@ + diff --git a/tests/fsharp/FSharpTestSuiteAsserts.fs b/tests/fsharp/FSharpTestSuiteAsserts.fs new file mode 100644 index 00000000000..f862421f6cd --- /dev/null +++ b/tests/fsharp/FSharpTestSuiteAsserts.fs @@ -0,0 +1,22 @@ +module FSharpTestSuiteAsserts + +open PlatformHelpers +open FSharpTestSuiteTypes + +let requireVSUltimate cfg = attempt { + do! match cfg.INSTALL_SKU with + | Some (Ultimate) -> Success + | x -> + // IF /I "%INSTALL_SKU%" NEQ "ULTIMATE" ( + // echo Test not supported except on Ultimate + NUnitConf.skip (sprintf "Test not supported except on Ultimate, was %A" x) + // exit /b 0 + // ) + } + +let requireENCulture () = attempt { + do! match System.Threading.Thread.CurrentThread.CurrentCulture.TwoLetterISOLanguageName with + | "en" -> Success + | c -> + NUnitConf.skip (sprintf "Test not supported except en Culture, was %s" c) + } diff --git a/tests/fsharp/core/.gitignore b/tests/fsharp/core/.gitignore index 34c12b24af2..71c2b74eda1 100644 --- a/tests/fsharp/core/.gitignore +++ b/tests/fsharp/core/.gitignore @@ -56,3 +56,11 @@ fsi-reload/load1.exe fsi-reload/load2.exe quotesInMultipleModules/module2-staticlink.exe + +load-script/out.stderr.txt +load-script/out.stdout.txt + +members/basics/tmptest.exe +members/basics/tmptest.fs +members/basics/tmptest.fsi +members/basics/tmptest1.exe diff --git a/tests/fsharp/core/control/test.fsx b/tests/fsharp/core/control/test.fsx index 0ef8971a32c..25da1fff98a 100644 --- a/tests/fsharp/core/control/test.fsx +++ b/tests/fsharp/core/control/test.fsx @@ -1844,6 +1844,8 @@ module CheckNoPumpingBecauseWeTrampolineSynchronousCode = Application.Exit() } |> Async.StartImmediate) + form.WindowState <- FormWindowState.Minimized + form.ShowInTaskbar <- false Application.Run form // Set the synchronization context back to its original value System.Threading.SynchronizationContext.SetSynchronizationContext(null); diff --git a/tests/fsharp/core/fsi-shadowcopy/test1.fsx b/tests/fsharp/core/fsi-shadowcopy/test1.fsx index 6b1f4c531ba..3e34e651775 100644 --- a/tests/fsharp/core/fsi-shadowcopy/test1.fsx +++ b/tests/fsharp/core/fsi-shadowcopy/test1.fsx @@ -5,7 +5,10 @@ open System;; open System.Diagnostics;; let compiled wait = - let c = Process.Start(Environment.GetEnvironmentVariable("FSC"), "Library1.fs --target:library") + let psi = ProcessStartInfo(Environment.GetEnvironmentVariable("FSC"), "Library1.fs --target:library") + psi.CreateNoWindow <- true + psi.UseShellExecute <- false + let c = Process.Start(psi) c.WaitForExit(wait) |> ignore if c.ExitCode = 0 then true else false;; diff --git a/tests/fsharp/core/fsi-shadowcopy/test2.fsx b/tests/fsharp/core/fsi-shadowcopy/test2.fsx index 1da068cbefd..34da503c636 100644 --- a/tests/fsharp/core/fsi-shadowcopy/test2.fsx +++ b/tests/fsharp/core/fsi-shadowcopy/test2.fsx @@ -5,7 +5,10 @@ open System;; open System.Diagnostics;; let compiled wait = - let c = Process.Start(Environment.GetEnvironmentVariable("FSC"), "Library1.fs --target:library") + let psi = ProcessStartInfo(Environment.GetEnvironmentVariable("FSC"), "Library1.fs --target:library") + psi.CreateNoWindow <- true + psi.UseShellExecute <- false + let c = Process.Start(psi) c.WaitForExit(wait) |> ignore if c.ExitCode = 0 then true else false;; diff --git a/tests/fsharp/core/tests_core.fs b/tests/fsharp/core/tests_core.fs index 502b941e219..c51f82cd296 100644 --- a/tests/fsharp/core/tests_core.fs +++ b/tests/fsharp/core/tests_core.fs @@ -7,20 +7,10 @@ open NUnit.Framework open NUnitConf open PlatformHelpers open FSharpTestSuiteTypes +open FSharpTestSuiteAsserts let testContext = FSharpTestSuite.testContext -let requireVSUltimate cfg = attempt { - do! match cfg.INSTALL_SKU with - | Some (Ultimate) -> Success - | x -> - // IF /I "%INSTALL_SKU%" NEQ "ULTIMATE" ( - // echo Test not supported except on Ultimate - NUnitConf.skip (sprintf "Test not supported except on Ultimate, was %A" x) - // exit /b 0 - // ) - } - module Access = [] let access p = check (attempt { @@ -667,7 +657,6 @@ module Printing = // if NOT EXIST z.output.test.200.bsl COPY z.output.test.200.txt z.output.test.200.bsl // %PRDIFF% z.output.test.200.txt z.output.test.200.bsl > z.output.test.200.diff [] - [] //not enough [] [] [] @@ -676,6 +665,8 @@ module Printing = let printing flag diffFileOut expectedFileOut diffFileErr expectedFileErr = check (attempt { let { Directory = dir; Config = cfg } = testContext () + do! requireENCulture () + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult let peverify = Commands.peverify exec cfg.PEVERIFY "/nologo" let copy from' = Commands.copy_y dir from' >> checkResult diff --git a/tests/fsharp/project.json b/tests/fsharp/project.json index 593a76fd005..afb8dcafab1 100644 --- a/tests/fsharp/project.json +++ b/tests/fsharp/project.json @@ -2,7 +2,7 @@ "dependencies": { "Microsoft.NETCore.Platforms": "1.0.1-rc2-23911", "NETStandard.Library": "1.5.0-rc2-23911", - "Microsoft.NETCore.Runtime.CoreCLR": "1.0.1-rc2-23911", + "Microsoft.NETCore.Runtime.CoreCLR": "1.0.2-rc2-23911", "Microsoft.NETCore.TestHost": "1.0.0-rc2-23911", "Microsoft.NETCore.ConsoleHost": "1.0.0-rc2-23911", "System.Collections.Immutable":"1.2.0-rc2-23911", @@ -18,7 +18,7 @@ "System.Security.Cryptography.Algorithms": "4.1.0-rc2-23911", "System.Security.Cryptography.Primitives": "4.0.0-rc2-23911", "System.Threading.Thread": "4.0.0-rc2-23911", - "System.Threading.ThreadPool": "4.0.10-rc2-23911", + "System.Threading.ThreadPool": "4.0.10-rc2-23911" }, "runtimes": { "win7-x86": { }, diff --git a/tests/fsharp/regression/656/run.bat b/tests/fsharp/regression/656/run.bat deleted file mode 100644 index 672c716c37d..00000000000 --- a/tests/fsharp/regression/656/run.bat +++ /dev/null @@ -1,33 +0,0 @@ -@if "%_echo%"=="" echo off - -setlocal -dir build.ok > NUL ) || ( - @echo 'build.ok' not found. - goto :ERROR -) - -call %~d0%~p0..\..\..\config.bat - - if exist test.ok (del /f /q test.ok) - %CLIX% pack%ILX_CONFIG%.exe - if NOT EXIST test.ok goto SetError - -:Ok -echo Ran fsharp %~f0 ok. -endlocal -exit /b 0 - -:Skip -echo Skipped %~f0 -endlocal -exit /b 0 - - -:Error -echo Test Script Failed (perhaps test did not emit test.ok signal file?) -endlocal -exit /b %ERRORLEVEL% - -:SetError -set NonexistentErrorLevel 2> nul -goto Error diff --git a/tests/fsharp/regression/tests_regression.fs b/tests/fsharp/regression/tests_regression.fs index d575128164c..a68cb384623 100644 --- a/tests/fsharp/regression/tests_regression.fs +++ b/tests/fsharp/regression/tests_regression.fs @@ -98,28 +98,11 @@ module ``656`` = do! peverify "pack.exe" } - let run cfg dir = attempt { - - let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult - let fileguard = (Commands.getfullpath dir) >> FileGuard.create - - // if exist test.ok (del /f /q test.ok) - use testOkFile = fileguard "test.ok" - - // %CLIX% pack.exe - do! exec ("."/"pack.exe") "" - - // if NOT EXIST test.ok goto SetError - do! testOkFile |> NUnitConf.checkGuardExists - } - [] let ``656`` () = check (attempt { let { Directory = dir; Config = cfg } = testContext () do! build cfg dir - - do! run cfg dir }) diff --git a/tests/fsharp/typeProviders/tests_typeProviders.fs b/tests/fsharp/typeProviders/tests_typeProviders.fs index 119f827a0df..40b4e2d6b81 100644 --- a/tests/fsharp/typeProviders/tests_typeProviders.fs +++ b/tests/fsharp/typeProviders/tests_typeProviders.fs @@ -7,20 +7,10 @@ open NUnit.Framework open FSharpTestSuiteTypes open NUnitConf open PlatformHelpers +open FSharpTestSuiteAsserts let testContext = FSharpTestSuite.testContext -let requireVSUltimate cfg = attempt { - do! match cfg.INSTALL_SKU with - | Some (Ultimate) -> Success - | x -> - // IF /I "%INSTALL_SKU%" NEQ "ULTIMATE" ( - // echo Test not supported except on Ultimate - NUnitConf.skip (sprintf "Test not supported except on Ultimate, was %A" x) - // exit /b 0 - // ) - } - module DiamondAssembly = let build cfg dir = attempt { @@ -361,6 +351,8 @@ module NegTests = let negTests name = check (attempt { let { Directory = dir; Config = cfg } = testContext () + do! requireENCulture () + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult let fsc = Commands.fsc exec cfg.FSC let del = Commands.rm dir diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/TypeProviders/CallIntrinsics.il.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/TypeProviders/CallIntrinsics.il.netfx4.bsl similarity index 100% rename from tests/fsharpqa/Source/CodeGen/EmittedIL/TypeProviders/CallIntrinsics.il.bsl rename to tests/fsharpqa/Source/CodeGen/EmittedIL/TypeProviders/CallIntrinsics.il.netfx4.bsl diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/TypeProviders/env.lst b/tests/fsharpqa/Source/CodeGen/EmittedIL/TypeProviders/env.lst index 71cd4d55470..8cb36bef519 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/TypeProviders/env.lst +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/TypeProviders/env.lst @@ -1 +1 @@ -Expensive,NoCrossVer SOURCE=CallIntrinsics.fsx PRECMD="\$FSC_PIPE -a --nowarn:1204,40,1203,26 provider.fsx" SCFLAGS="-r:provider.dll -a -g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd CallIntrinsics.dll" # CallIntrinsics.fsx +Expensive,NoCrossVer SOURCE=CallIntrinsics.fsx PRECMD="\$FSC_PIPE -a --nowarn:1204,40,1203,26 provider.fsx" SCFLAGS="-r:provider.dll -a -g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd CallIntrinsics.dll NetFx40" # CallIntrinsics.fsx diff --git a/tests/fsharpqa/Source/test.lst b/tests/fsharpqa/Source/test.lst index e72df7c3c56..d9120a3e79c 100644 --- a/tests/fsharpqa/Source/test.lst +++ b/tests/fsharpqa/Source/test.lst @@ -27,7 +27,7 @@ CodeGen01,NoMT,CodeGen CodeGen\EmittedIL\SteppingMatch CodeGen01,NoMT,CodeGen CodeGen\EmittedIL\TailCalls CodeGen01,NoMT,CodeGen CodeGen\EmittedIL\TestFunctions CodeGen01,NoMT,CodeGen CodeGen\EmittedIL\Tuples -NoHostedCompiler,CodeGen01,NoMT CodeGen\EmittedIL\TypeProviders +NoHostedCompiler,CodeGen01,NoMT,EmittedIL_TypeProviders CodeGen\EmittedIL\TypeProviders CodeGen01,NoMT,CodeGen CodeGen\StringEncoding CodeGen01,NoMT,CodeGen CodeGen\Structure diff --git a/vsintegration/deployment/EnableOpenSource/EnableOpenSource.csproj b/vsintegration/deployment/EnableOpenSource/EnableOpenSource.csproj index b84850c4f94..f7e0b484202 100644 --- a/vsintegration/deployment/EnableOpenSource/EnableOpenSource.csproj +++ b/vsintegration/deployment/EnableOpenSource/EnableOpenSource.csproj @@ -50,14 +50,14 @@ False True - + Program $(DevEnvDir)devenv.exe /rootsuffix FSharp /log FSharp true - + Program $(DevEnvDir)devenv.exe /rootsuffix FSharp /log diff --git a/vsintegration/src/FSharp.ProjectSystem.FSharp/Project.fs b/vsintegration/src/FSharp.ProjectSystem.FSharp/Project.fs index baab1d9b51f..753edb01480 100644 --- a/vsintegration/src/FSharp.ProjectSystem.FSharp/Project.fs +++ b/vsintegration/src/FSharp.ProjectSystem.FSharp/Project.fs @@ -1353,7 +1353,7 @@ See also ...\SetupAuthoring\FSharp\Registry\FSProjSys_Registration.wxs, e.g. result // Fulfill HostObject contract with Fsc task, and enable 'capture' of compiler flags for the project. - member x.Compile(compile:System.Converter, flags:string[], sources:string[]) = + member x.Compile(compile:Func, flags:string[], sources:string[]) = // Note: This method may be called from non-UI thread! The Fsc task in FSharp.Build.dll invokes this method via reflection, and // the Fsc task is typically created by MSBuild on a background thread. So be careful. #if DEBUG @@ -1370,7 +1370,7 @@ See also ...\SetupAuthoring\FSharp\Registry\FSProjSys_Registration.wxs, e.g. // This is the first time, so set up interface for language service to talk to us projectSite.Open(x.CreateRunningProjectSite()) if actuallyBuild then - compile.Invoke(0) + compile.Invoke() else 0 @@ -1990,32 +1990,32 @@ See also ...\SetupAuthoring\FSharp\Registry\FSProjSys_Registration.wxs, e.g. | ApplicationDefinition = 4 | Page = 5 | Resource = 6 - + and public FSharpBuildActionPropertyDescriptor internal (prop : PropertyDescriptor) = inherit PropertyDescriptor(prop) - + override this.DisplayName = SR.BuildAction - + override this.ComponentType = typeof - + override this.PropertyType = typeof - + override this.IsReadOnly = false - + override this.GetEditor(editorBaseType : Type) = this.CreateInstance(editorBaseType) - + override this.Converter = null - + override this.CanResetValue(o : obj) = prop.CanResetValue(o) - + override this.GetValue (o : obj) = prop.GetValue(o) - + override this.SetValue (o : obj, value : obj) = prop.SetValue(o, value) - + override this.ResetValue (o : obj) = prop.ResetValue(o) - + override this.ShouldSerializeValue(o : obj) = prop.ShouldSerializeValue(o) and diff --git a/vsintegration/src/fsharp.common.props b/vsintegration/src/fsharp.common.props index 416175402a0..48c922d9577 100644 --- a/vsintegration/src/fsharp.common.props +++ b/vsintegration/src/fsharp.common.props @@ -14,11 +14,11 @@ ..\.. net40 - + $(FSharpSourcesRoot)\..\$(Configuration)\$(TargetFramework)\bin - + true full false diff --git a/vsintegration/tests/Salsa/salsa.fs b/vsintegration/tests/Salsa/salsa.fs index 1a50ad15b4d..4b7b87019ea 100644 --- a/vsintegration/tests/Salsa/salsa.fs +++ b/vsintegration/tests/Salsa/salsa.fs @@ -44,13 +44,13 @@ module internal Salsa = { new System.IDisposable with member this.Dispose() = actuallyBuild <- true } member th.Results = capturedFlags, capturedSources - member th.Compile(compile:System.Converter, flags:string[], sources:string[]) = + member th.Compile(compile:Func, flags:string[], sources:string[]) = use t = Trace.Call("MSBuild", "Compile", fun _ -> "Host compile invoke by Fsc task") Trace.PrintLine("MSBuild", fun _ -> sprintf "flags=%A" flags) capturedFlags <- flags capturedSources <- sources if actuallyBuild then - compile.Invoke(0) + compile.Invoke() else 0 interface ITaskHost diff --git a/vsintegration/tests/unittests/Tests.Build.fs b/vsintegration/tests/unittests/Tests.Build.fs index a6a1fd3713e..0c2d32b7df6 100644 --- a/vsintegration/tests/unittests/Tests.Build.fs +++ b/vsintegration/tests/unittests/Tests.Build.fs @@ -41,7 +41,7 @@ type MyLogger(f : string -> unit) = type FauxHostObject() = let mutable myFlags : string[] = null let mutable mySources : string[] = null - member x.Compile(compile:System.Converter, flags:string[], sources:string[]) = + member x.Compile(compile:Func, flags:string[], sources:string[]) = myFlags <- flags mySources <- sources 0 diff --git a/vsintegration/tests/unittests/Tests.ProjectSystem.MultiTargeting.fs b/vsintegration/tests/unittests/Tests.ProjectSystem.MultiTargeting.fs index 9cd81a48d70..0cd5d5815fc 100644 --- a/vsintegration/tests/unittests/Tests.ProjectSystem.MultiTargeting.fs +++ b/vsintegration/tests/unittests/Tests.ProjectSystem.MultiTargeting.fs @@ -30,8 +30,8 @@ type MultiTargeting() = let dirName = Path.GetDirectoryName(projFile) let libDirName = Directory.CreateDirectory(Path.Combine(dirName, "lib")).FullName let codeBase = (new Uri(Assembly.GetExecutingAssembly().EscapedCodeBase)).LocalPath |> Path.GetDirectoryName - let refLibPath = Path.Combine(libDirName, "FSharp.Core.Unittests.dll") - File.Copy(Path.Combine(codeBase, "FSharp.Core.Unittests.dll"), refLibPath) + let refLibPath = Path.Combine(libDirName, "VisualFSharp.Unittests.dll") + File.Copy(Path.Combine(codeBase, "VisualFSharp.Unittests.dll"), refLibPath) File.AppendAllText(projFile, TheTests.FsprojTextWithProjectReferencesAndOtherFlags([], [refLibPath], [], null, "", "v4.0")) refLibPath From 7a68444ebf912ca8a010f4e4a5c0aeadb4002bef Mon Sep 17 00:00:00 2001 From: "Avi.Avni" Date: Sun, 1 May 2016 00:10:31 +0300 Subject: [PATCH 032/129] fix merge --- src/fsharp/MethodCalls.fs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/fsharp/MethodCalls.fs b/src/fsharp/MethodCalls.fs index 43731c50ae2..14c41717483 100644 --- a/src/fsharp/MethodCalls.fs +++ b/src/fsharp/MethodCalls.fs @@ -62,15 +62,17 @@ type CalledArg = { Position: (int * int) IsParamArray : bool OptArgInfo : OptionalArgInfo + CallerInfoInfo : CallerInfoInfo IsOutArg: bool ReflArgInfo: ReflectedArgInfo NameOpt: Ident option CalledArgumentType : TType } -let CalledArg(pos,isParamArray,optArgInfo,isOutArg,nameOpt,reflArgInfo,calledArgTy) = +let CalledArg(pos,isParamArray,optArgInfo,callerInfoInfo,isOutArg,nameOpt,reflArgInfo,calledArgTy) = { Position=pos IsParamArray=isParamArray OptArgInfo =optArgInfo + CallerInfoInfo = callerInfoInfo IsOutArg=isOutArg ReflArgInfo=reflArgInfo NameOpt=nameOpt @@ -198,10 +200,11 @@ type CalledMethArgSet<'T> = let MakeCalledArgs amap m (minfo:MethInfo) minst = // Mark up the arguments with their position, so we can sort them back into order later let paramDatas = minfo.GetParamDatas(amap, m, minst) - paramDatas |> List.mapiSquared (fun i j (ParamData(isParamArrayArg,isOutArg,optArgInfo,nmOpt,reflArgInfo,typeOfCalledArg)) -> + paramDatas |> List.mapiSquared (fun i j (ParamData(isParamArrayArg,isOutArg,optArgInfo,callerInfoFlags,nmOpt,reflArgInfo,typeOfCalledArg)) -> { Position=(i,j) IsParamArray=isParamArrayArg OptArgInfo=optArgInfo + CallerInfoInfo = callerInfoFlags IsOutArg=isOutArg ReflArgInfo=reflArgInfo NameOpt=nmOpt From 7650c850d0cda9a16e94109f2c10aed271e4d434 Mon Sep 17 00:00:00 2001 From: "Avi.Avni" Date: Tue, 3 May 2016 20:42:14 +0300 Subject: [PATCH 033/129] fix caller member name and add warning when no caller member name --- src/fsharp/FSComp.txt | 1 + src/fsharp/TypeChecker.fs | 18 ++++++++++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/fsharp/FSComp.txt b/src/fsharp/FSComp.txt index 445fdcce777..4dda406d858 100644 --- a/src/fsharp/FSComp.txt +++ b/src/fsharp/FSComp.txt @@ -1294,3 +1294,4 @@ estApplyStaticArgumentsForMethodNotImplemented,"A type provider implemented GetS 3195,optsResponseFileNameInvalid,"Response file name '%s' is empty, contains invalid characters, has a drive specification without an absolute path, or is too long" 3196,fsharpCoreNotFoundToBeCopied,"Cannot find FSharp.Core.dll in compiler's directory" 3197,etMissingStaticArgumentsToMethod,"This provided method requires static parameters" +3198,tcNoCallerMemberName,"There is no caller member name" \ No newline at end of file diff --git a/src/fsharp/TypeChecker.fs b/src/fsharp/TypeChecker.fs index 2276413f89a..1addfb9d54e 100755 --- a/src/fsharp/TypeChecker.fs +++ b/src/fsharp/TypeChecker.fs @@ -9214,8 +9214,13 @@ and TcMethodApplication emptyPreBinder,Expr.Const(Const.Int32(mMethExpr.StartLine), mMethExpr, currCalledArgTy) | CallerFilePath when typeEquiv cenv.g currCalledArgTy cenv.g.string_ty -> emptyPreBinder,Expr.Const(Const.String(System.IO.Path.GetFullPath(mMethExpr.FileName)), mMethExpr, currCalledArgTy) - | CallerMemberName when typeEquiv cenv.g currCalledArgTy cenv.g.string_ty && env.eCallerMemberName.IsSome -> - emptyPreBinder,Expr.Const(Const.String(env.eCallerMemberName.Value), mMethExpr, currCalledArgTy) + | CallerMemberName when typeEquiv cenv.g currCalledArgTy cenv.g.string_ty -> + let name = match env.eCallerMemberName with + | Some(name) -> name + | None -> + warning(Error(FSComp.SR.tcNoCallerMemberName(), mMethExpr)) + System.String.Empty + emptyPreBinder,Expr.Const(Const.String(name), mMethExpr, currCalledArgTy) | _ -> emptyPreBinder,Expr.Const(TcFieldInit mMethExpr fieldInit,mMethExpr,currCalledArgTy) @@ -9254,8 +9259,13 @@ and TcMethodApplication | CallerFilePath when typeEquiv cenv.g calledNonOptTy cenv.g.string_ty -> let filePathExpr = Expr.Const(Const.String(System.IO.Path.GetFullPath(mMethExpr.FileName)), mMethExpr, calledNonOptTy) emptyPreBinder,mkUnionCaseExpr(mkSomeCase cenv.g,[calledNonOptTy],[filePathExpr],mMethExpr) - | CallerMemberName when typeEquiv cenv.g calledNonOptTy cenv.g.string_ty && env.eCallerMemberName.IsSome -> - let memberNameExpr = Expr.Const(Const.String(env.eCallerMemberName.Value), mMethExpr, calledNonOptTy) + | CallerMemberName when typeEquiv cenv.g calledNonOptTy cenv.g.string_ty -> + let name = match env.eCallerMemberName with + | Some(name) -> name + | None -> + warning(Error(FSComp.SR.tcNoCallerMemberName(), mMethExpr)) + System.String.Empty + let memberNameExpr = Expr.Const(Const.String(name), mMethExpr, calledNonOptTy) emptyPreBinder,mkUnionCaseExpr(mkSomeCase cenv.g,[calledNonOptTy],[memberNameExpr],mMethExpr) | _ -> emptyPreBinder,mkUnionCaseExpr(mkNoneCase cenv.g,[calledNonOptTy],[],mMethExpr) From 445123ec036f6513946340350602e711469cc033 Mon Sep 17 00:00:00 2001 From: "Avi.Avni" Date: Tue, 3 May 2016 20:42:50 +0300 Subject: [PATCH 034/129] add tests for caller member name --- .../Imported/CallerInfo/CSharpLib.cs | 9 ++++- .../Imported/CallerInfo/CallerFilePath.fs | 6 +-- .../Imported/CallerInfo/CallerLineNumber.fs | 6 +-- .../Imported/CallerInfo/CallerMemberName.fs | 37 +++++++++++++++++++ .../Imported/CallerInfo/ViaInteractive.fsx | 2 +- .../Imported/CallerInfo/env.lst | 1 + 6 files changed, 52 insertions(+), 9 deletions(-) create mode 100644 tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerMemberName.fs diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CSharpLib.cs b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CSharpLib.cs index 44750e38379..627c9b30181 100644 --- a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CSharpLib.cs +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CSharpLib.cs @@ -15,10 +15,15 @@ public static string FilePath([CallerFilePath] string filePath = "dummy1") { return filePath; } + + public static string MemberName([CallerMemberName] string memberName = "dummy1") + { + return memberName; + } - public static Tuple AllInfo(int normalArg, [CallerFilePath] string filePath = "dummy2", [CallerLineNumber] int line = 778) + public static Tuple AllInfo(int normalArg, [CallerFilePath] string filePath = "dummy2", [CallerLineNumber] int line = 778, [CallerMemberName] string memberName = "dummy3") { - return new Tuple(filePath, line); + return new Tuple(filePath, line, memberName); } } diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerFilePath.fs b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerFilePath.fs index 1353ac55783..a807e51b4b5 100644 --- a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerFilePath.fs +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerFilePath.fs @@ -49,17 +49,17 @@ module Program = | x -> failwithf "Unexpected: %A" x match CallerInfoTest.AllInfo(21) with - | (path, _) when matchesPath "Conformance\\SpecialAttributesAndTypes\\Imported\\CallerInfo\\CallerFilePath.fs" path -> () + | (path, _, _) when matchesPath "Conformance\\SpecialAttributesAndTypes\\Imported\\CallerInfo\\CallerFilePath.fs" path -> () | x -> failwithf "Unexpected C# result with multiple parameter types: %A" x # 345 "qwerty1" match CallerInfoTest.AllInfo(123) with - | (path, _) when matchesPath "Conformance\\SpecialAttributesAndTypes\\Imported\\CallerInfo\\qwerty1" path -> () + | (path, _, _) when matchesPath "Conformance\\SpecialAttributesAndTypes\\Imported\\CallerInfo\\qwerty1" path -> () | x -> failwithf "Unexpected C# result with multiple parameter types: %A" x # 456 "qwerty2" match CallerInfoTest.AllInfo(123) with - | (path, _) when matchesPath "Conformance\\SpecialAttributesAndTypes\\Imported\\CallerInfo\\qwerty2" path -> () + | (path, _, _) when matchesPath "Conformance\\SpecialAttributesAndTypes\\Imported\\CallerInfo\\qwerty2" path -> () | x -> failwithf "Unexpected C# result with multiple parameter types: %A" x 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerLineNumber.fs b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerLineNumber.fs index 665af31c99e..4692802480b 100644 --- a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerLineNumber.fs +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerLineNumber.fs @@ -23,7 +23,7 @@ module Program = failwith "Unexpected C# CallerLineNumber" match CallerInfoTest.AllInfo(21) with - | (_, 25) -> () + | (_, 25, _) -> () | x -> failwithf "Unexpected C# result with multiple parameter types: %A" x if (typeof.GetCustomAttributes(typeof, false).[0] :?> MyCallerInfoAttribute).LineNumber <> 5 then @@ -39,11 +39,11 @@ module Program = # 345 "qwerty" match CallerInfoTest.AllInfo(123) with - | (_, 345) -> () + | (_, 345, _) -> () | x -> failwithf "Unexpected C# result with multiple parameter types: %A" x # 456 "qwerty" match CallerInfoTest.AllInfo(123) with - | (_, 456) -> () + | (_, 456, _) -> () | x -> failwithf "Unexpected C# result with multiple parameter types: %A" x 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerMemberName.fs b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerMemberName.fs new file mode 100644 index 00000000000..5854c470412 --- /dev/null +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerMemberName.fs @@ -0,0 +1,37 @@ +namespace Test + +open System.Runtime.CompilerServices +open CSharpLib + +type MyTy() = + static member GetCallerMemberName([] ?memberName : string) = + memberName + +module Program = + [] + let main (_:string[]) = + if MyTy.GetCallerMemberName() <> Some("main") then + failwith "Unexpected F# CallerMemberName" + + if MyTy.GetCallerMemberName("foo") <> Some("foo") then + failwith "Unexpected F# CallerMemberName" + + if CallerInfoTest.MemberName() <> "main" then + failwith "Unexpected C# CallerMemberName" + + if CallerInfoTest.MemberName("foo") <> "foo" then + failwith "Unexpected C# CallerMemberName" + + match CallerInfoTest.AllInfo(21) with + | (_, _, "main") -> () + | x -> failwithf "Unexpected C# result with multiple parameter types: %A" x + + let getCallerLineNumber = CallerInfoTest.MemberName + + if () |> CallerInfoTest.MemberName <> "main" then + failwith "Unexpected C# CallerLineNumber" + + if getCallerLineNumber () <> "getCallerLineNumber" then + failwith "Unexpected C# CallerLineNumber" + + 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/ViaInteractive.fsx b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/ViaInteractive.fsx index 4e8821372b9..2357128cabf 100644 --- a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/ViaInteractive.fsx +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/ViaInteractive.fsx @@ -24,7 +24,7 @@ if MyTy.GetCallerLineNumber() <> Some(23) then failwith "Unexpected F# CallerLineNumber" match CallerInfoTest.AllInfo(21) with -| (path, 26) when matchesPath checkPath path -> () +| (path, 26, "") when matchesPath checkPath path -> () | x -> failwithf "Unexpected C# result with multiple parameter types: %A" x #q \ No newline at end of file diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/env.lst b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/env.lst index db596ffae40..72380e030b9 100644 --- a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/env.lst +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/env.lst @@ -1,5 +1,6 @@ SOURCE=CallerLineNumber.fs SCFLAGS="-r CSharpLib.dll --test:ErrorRanges" PRECMD="\$CSC_PIPE /t:library CSharpLib.cs" # CallerLineNumber.fs SOURCE=CallerFilePath.fs SCFLAGS="-r CSharpLib.dll --test:ErrorRanges" PRECMD="\$CSC_PIPE /t:library CSharpLib.cs" # CallerFilePath.fs + SOURCE=CallerMemberName.fs SCFLAGS="-r CSharpLib.dll --test:ErrorRanges" PRECMD="\$CSC_PIPE /t:library CSharpLib.cs" # CallerMemberName.fs SOURCE=E_CallerLineNumber.fs SCFLAGS="--test:ErrorRanges" # E_CallerLineNumber.fs SOURCE=E_CallerFilePath.fs SCFLAGS="--test:ErrorRanges" # E_CallerFilePath.fs SOURCE=E_MultipleAttrs.fs SCFLAGS="--test:ErrorRanges" # E_MultipleAttrs.fs From 119d5678426b9c4eb6976b4fa009fdb966437bfd Mon Sep 17 00:00:00 2001 From: Lincoln Atkinson Date: Sat, 7 May 2016 21:07:24 -0700 Subject: [PATCH 035/129] Updates and fixes to CallerMemberName --- src/fsharp/TypeChecker.fs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/fsharp/TypeChecker.fs b/src/fsharp/TypeChecker.fs index 544a649c16e..b2960457a39 100755 --- a/src/fsharp/TypeChecker.fs +++ b/src/fsharp/TypeChecker.fs @@ -9626,10 +9626,15 @@ and TcNormalizedBinding declKind (cenv:cenv) env tpenv overallTy safeThisValOpt match bind with | NormalizedBinding(vis,bkind,isInline,isMutable,attrs,doc,_,valSynData,pat,NormalizedBindingRhs(spatsL,rtyOpt,rhsExpr),mBinding,spBind) -> - let name = match pat with - | SynPat.Named(_,name,_,_,_) -> Some(name.idText) - | _ -> None - let envinner = {envinner with eCallerMemberName = name } + let callerName = + match declKind, bkind, pat with + | ExpressionBinding, _, _ -> envinner.eCallerMemberName + | _, _, SynPat.Named(_,name,_,_,_) -> Some(name.idText) + | ClassLetBinding, DoBinding, _ -> Some(".ctor") + | ModuleOrMemberBinding, StandaloneExpression, _ -> Some(".cctor") + | _, _, _ -> envinner.eCallerMemberName + + let envinner = {envinner with eCallerMemberName = callerName } let (SynValData(memberFlagsOpt,valSynInfo,_)) = valSynData From 7938a7d7990c4ce1febc569d5dbe853c49f531a3 Mon Sep 17 00:00:00 2001 From: Lincoln Atkinson Date: Sat, 7 May 2016 21:47:09 -0700 Subject: [PATCH 036/129] Remove warning for scenarios where there is no calling member --- src/fsharp/FSComp.txt | 3 +-- src/fsharp/TypeChecker.fs | 43 ++++++++++++++++----------------------- 2 files changed, 18 insertions(+), 28 deletions(-) diff --git a/src/fsharp/FSComp.txt b/src/fsharp/FSComp.txt index 172022d9379..c0fa84e4877 100644 --- a/src/fsharp/FSComp.txt +++ b/src/fsharp/FSComp.txt @@ -1293,5 +1293,4 @@ estApplyStaticArgumentsForMethodNotImplemented,"A type provider implemented GetS 3194,optsResponseFileNotFound,"Response file '%s' not found in '%s'" 3195,optsResponseFileNameInvalid,"Response file name '%s' is empty, contains invalid characters, has a drive specification without an absolute path, or is too long" 3196,fsharpCoreNotFoundToBeCopied,"Cannot find FSharp.Core.dll in compiler's directory" -3197,etMissingStaticArgumentsToMethod,"This provided method requires static parameters" -3198,tcNoCallerMemberName,"There is no caller member name" \ No newline at end of file +3197,etMissingStaticArgumentsToMethod,"This provided method requires static parameters" \ No newline at end of file diff --git a/src/fsharp/TypeChecker.fs b/src/fsharp/TypeChecker.fs index b2960457a39..997236d893e 100755 --- a/src/fsharp/TypeChecker.fs +++ b/src/fsharp/TypeChecker.fs @@ -9207,18 +9207,13 @@ and TcMethodApplication | ByrefTy cenv.g inst -> build inst (PassByRef(inst, currDfltVal)) | _ -> - match calledArg.CallerInfoInfo with - | CallerLineNumber when typeEquiv cenv.g currCalledArgTy cenv.g.int_ty -> + match calledArg.CallerInfoInfo, env.eCallerMemberName with + | CallerLineNumber, _ when typeEquiv cenv.g currCalledArgTy cenv.g.int_ty -> emptyPreBinder,Expr.Const(Const.Int32(mMethExpr.StartLine), mMethExpr, currCalledArgTy) - | CallerFilePath when typeEquiv cenv.g currCalledArgTy cenv.g.string_ty -> + | CallerFilePath, _ when typeEquiv cenv.g currCalledArgTy cenv.g.string_ty -> emptyPreBinder,Expr.Const(Const.String(System.IO.Path.GetFullPath(mMethExpr.FileName)), mMethExpr, currCalledArgTy) - | CallerMemberName when typeEquiv cenv.g currCalledArgTy cenv.g.string_ty -> - let name = match env.eCallerMemberName with - | Some(name) -> name - | None -> - warning(Error(FSComp.SR.tcNoCallerMemberName(), mMethExpr)) - System.String.Empty - emptyPreBinder,Expr.Const(Const.String(name), mMethExpr, currCalledArgTy) + | CallerMemberName, Some(callerName) when (typeEquiv cenv.g currCalledArgTy cenv.g.string_ty) -> + emptyPreBinder,Expr.Const(Const.String(callerName), mMethExpr, currCalledArgTy) | _ -> emptyPreBinder,Expr.Const(TcFieldInit mMethExpr fieldInit,mMethExpr,currCalledArgTy) @@ -9250,22 +9245,18 @@ and TcMethodApplication else calledArgTy // should be unreachable - match calledArg.CallerInfoInfo with - | CallerLineNumber when typeEquiv cenv.g calledNonOptTy cenv.g.int_ty -> - let lineExpr = Expr.Const(Const.Int32(mMethExpr.StartLine), mMethExpr, calledNonOptTy) - emptyPreBinder,mkUnionCaseExpr(mkSomeCase cenv.g,[calledNonOptTy],[lineExpr],mMethExpr) - | CallerFilePath when typeEquiv cenv.g calledNonOptTy cenv.g.string_ty -> - let filePathExpr = Expr.Const(Const.String(System.IO.Path.GetFullPath(mMethExpr.FileName)), mMethExpr, calledNonOptTy) - emptyPreBinder,mkUnionCaseExpr(mkSomeCase cenv.g,[calledNonOptTy],[filePathExpr],mMethExpr) - | CallerMemberName when typeEquiv cenv.g calledNonOptTy cenv.g.string_ty -> - let name = match env.eCallerMemberName with - | Some(name) -> name - | None -> - warning(Error(FSComp.SR.tcNoCallerMemberName(), mMethExpr)) - System.String.Empty - let memberNameExpr = Expr.Const(Const.String(name), mMethExpr, calledNonOptTy) - emptyPreBinder,mkUnionCaseExpr(mkSomeCase cenv.g,[calledNonOptTy],[memberNameExpr],mMethExpr) - | _ -> emptyPreBinder,mkUnionCaseExpr(mkNoneCase cenv.g,[calledNonOptTy],[],mMethExpr) + match calledArg.CallerInfoInfo, env.eCallerMemberName with + | CallerLineNumber, _ when typeEquiv cenv.g calledNonOptTy cenv.g.int_ty -> + let lineExpr = Expr.Const(Const.Int32(mMethExpr.StartLine), mMethExpr, calledNonOptTy) + emptyPreBinder,mkUnionCaseExpr(mkSomeCase cenv.g,[calledNonOptTy],[lineExpr],mMethExpr) + | CallerFilePath, _ when typeEquiv cenv.g calledNonOptTy cenv.g.string_ty -> + let filePathExpr = Expr.Const(Const.String(System.IO.Path.GetFullPath(mMethExpr.FileName)), mMethExpr, calledNonOptTy) + emptyPreBinder,mkUnionCaseExpr(mkSomeCase cenv.g,[calledNonOptTy],[filePathExpr],mMethExpr) + | CallerMemberName, Some(callerName) when typeEquiv cenv.g calledNonOptTy cenv.g.string_ty -> + let memberNameExpr = Expr.Const(Const.String(callerName), mMethExpr, calledNonOptTy) + emptyPreBinder,mkUnionCaseExpr(mkSomeCase cenv.g,[calledNonOptTy],[memberNameExpr],mMethExpr) + | _ -> + emptyPreBinder,mkUnionCaseExpr(mkNoneCase cenv.g,[calledNonOptTy],[],mMethExpr) // Combine the variable allocators (if any) let wrapper = (wrapper >> wrapper2) From f6ddde6cd6e1b2b5a5ff02b1227b2d80de9738e1 Mon Sep 17 00:00:00 2001 From: Lincoln Atkinson Date: Sat, 7 May 2016 22:07:27 -0700 Subject: [PATCH 037/129] Adjust tests --- .../Imported/CallerInfo/CallerMemberName.fs | 6 +++--- .../Imported/CallerInfo/ViaInteractive.fsx | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerMemberName.fs b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerMemberName.fs index 5854c470412..28eb7f208b6 100644 --- a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerMemberName.fs +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerMemberName.fs @@ -29,9 +29,9 @@ module Program = let getCallerLineNumber = CallerInfoTest.MemberName if () |> CallerInfoTest.MemberName <> "main" then - failwith "Unexpected C# CallerLineNumber" + failwith "Unexpected C# CallerMemberName" - if getCallerLineNumber () <> "getCallerLineNumber" then - failwith "Unexpected C# CallerLineNumber" + if getCallerLineNumber () <> "main" then + failwith "Unexpected C# CallerMemberName" 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/ViaInteractive.fsx b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/ViaInteractive.fsx index 2357128cabf..8a9e9928e4e 100644 --- a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/ViaInteractive.fsx +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/ViaInteractive.fsx @@ -24,7 +24,7 @@ if MyTy.GetCallerLineNumber() <> Some(23) then failwith "Unexpected F# CallerLineNumber" match CallerInfoTest.AllInfo(21) with -| (path, 26, "") when matchesPath checkPath path -> () +| (path, 26, ".cctor") when matchesPath checkPath path -> () | x -> failwithf "Unexpected C# result with multiple parameter types: %A" x #q \ No newline at end of file From 4ad54917eaf88e51e982d81775b62e6c7cec307d Mon Sep 17 00:00:00 2001 From: "Avi.Avni" Date: Wed, 11 May 2016 18:01:29 +0300 Subject: [PATCH 038/129] fix CallerMemberName for properties add some tests --- src/fsharp/TypeChecker.fs | 16 ++++++++++++---- .../Imported/CallerInfo/CallerMemberName.fs | 13 ++++++++++++- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/fsharp/TypeChecker.fs b/src/fsharp/TypeChecker.fs index 997236d893e..4047c365fb9 100755 --- a/src/fsharp/TypeChecker.fs +++ b/src/fsharp/TypeChecker.fs @@ -9617,18 +9617,26 @@ and TcNormalizedBinding declKind (cenv:cenv) env tpenv overallTy safeThisValOpt match bind with | NormalizedBinding(vis,bkind,isInline,isMutable,attrs,doc,_,valSynData,pat,NormalizedBindingRhs(spatsL,rtyOpt,rhsExpr),mBinding,spBind) -> - let callerName = + let (SynValData(memberFlagsOpt,valSynInfo,_)) = valSynData + + let callerName = match declKind, bkind, pat with | ExpressionBinding, _, _ -> envinner.eCallerMemberName - | _, _, SynPat.Named(_,name,_,_,_) -> Some(name.idText) + | _, _, SynPat.Named(_,name,_,_,_) -> + match memberFlagsOpt with + | Some(memberFlags) -> + match memberFlags.MemberKind with + | MemberKind.PropertyGet | MemberKind.PropertySet | MemberKind.PropertyGetSet -> Some(name.idText.Substring(4)) + | MemberKind.ClassConstructor -> Some(".ctor") + | MemberKind.Constructor -> Some(".ctor") + | _ -> Some(name.idText) + | _ -> Some(name.idText) | ClassLetBinding, DoBinding, _ -> Some(".ctor") | ModuleOrMemberBinding, StandaloneExpression, _ -> Some(".cctor") | _, _, _ -> envinner.eCallerMemberName let envinner = {envinner with eCallerMemberName = callerName } - let (SynValData(memberFlagsOpt,valSynInfo,_)) = valSynData - let attrTgt = DeclKind.AllowedAttribTargets memberFlagsOpt declKind // Check the attributes of the binding, parameters or return value diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerMemberName.fs b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerMemberName.fs index 28eb7f208b6..dc3b9cbb019 100644 --- a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerMemberName.fs +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerMemberName.fs @@ -3,9 +3,14 @@ namespace Test open System.Runtime.CompilerServices open CSharpLib -type MyTy() = +type MyTy() = static member GetCallerMemberName([] ?memberName : string) = memberName + + static member GetCallerMemberNameProperty + with get () = MyTy.GetCallerMemberName() + + member val GetCallerMemberNameProperty1 = MyTy.GetCallerMemberName() with get, set module Program = [] @@ -15,7 +20,13 @@ module Program = if MyTy.GetCallerMemberName("foo") <> Some("foo") then failwith "Unexpected F# CallerMemberName" + + if MyTy.GetCallerMemberNameProperty <> Some("GetCallerMemberNameProperty") then + failwith "Unexpected F# CallerMemberName" + if MyTy().GetCallerMemberNameProperty1 <> Some("GetCallerMemberNameProperty1") then + failwith "Unexpected F# CallerMemberName" + if CallerInfoTest.MemberName() <> "main" then failwith "Unexpected C# CallerMemberName" From fde322923ae9505b40c39b7b17ecab38d1e0bb6f Mon Sep 17 00:00:00 2001 From: Lincoln Atkinson Date: Thu, 12 May 2016 01:23:28 -0700 Subject: [PATCH 039/129] Expand CallerMemberName tests --- .../Imported/CallerInfo/CSharpLib.cs | 10 ++ .../Imported/CallerInfo/CallerMemberName.fs | 146 +++++++++++++++--- 2 files changed, 134 insertions(+), 22 deletions(-) diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CSharpLib.cs b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CSharpLib.cs index 627c9b30181..352115961c3 100644 --- a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CSharpLib.cs +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CSharpLib.cs @@ -36,4 +36,14 @@ public MyCallerInfoAttribute([CallerLineNumber] int lineNumber = -1) LineNumber = lineNumber; } } + + public class MyCallerMemberNameAttribute : Attribute + { + public string MemberName { get; set; } + + public MyCallerMemberNameAttribute([CallerMemberName] string member = "dflt") + { + MemberName = member; + } + } } \ No newline at end of file diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerMemberName.fs b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerMemberName.fs index dc3b9cbb019..ee73b3f795e 100644 --- a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerMemberName.fs +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerMemberName.fs @@ -1,48 +1,150 @@ namespace Test open System.Runtime.CompilerServices +open System.Reflection open CSharpLib -type MyTy() = +[] +do + () + +[] +type MyTy() = + let functionVal = MyTy.GetCallerMemberName + let typeLetValue = MyTy.GetCallerMemberName() + let typeLetFunc (i:int) = i, MyTy.GetCallerMemberName() + let typeLetFuncNested () = + let nestedFunc () = MyTy.GetCallerMemberName() + nestedFunc () + do + MyTy.Check(MyTy.GetCallerMemberName(), Some(".ctor"), "primary ctor") + + new(i : int) = + MyTy.Check(MyTy.GetCallerMemberName(), Some(".ctor"), ".NET ctor") + MyTy() + + member __.Item + with get(i:int) = MyTy.GetCallerMemberName() + and set(i:int) (v:string option) = + MyTy.Check(MyTy.GetCallerMemberName(), Some("Item"), "index setter") + + member __.CheckMembers() = + MyTy.Check(MyTy.GetCallerMemberName(), Some("CheckMembers"), ".NET method") + MyTy.Check(typeLetValue, Some("typeLetValue"), "type let value") + MyTy.Check(typeLetFunc 2 |> snd, Some("typeLetFunc"), "type let func") + MyTy.Check((typeLetFuncNested ()) , Some("typeLetFuncNested"), "type let func nested") + MyTy.Check(__.GetCallerMemberNameProperty1, Some("GetCallerMemberNameProperty1@"), "auto property getter") + MyTy.Check(MyTy.GetCallerMemberNameProperty, Some("GetCallerMemberNameProperty"), "property getter") + MyTy.GetCallerMemberNameProperty <- Some("test") + MyTy.Check(__.[10], Some("Item"), "indexer getter") + __.[10] <- Some("test") + + let result = + [1..10] + |> List.map (fun i -> MyTy.GetCallerMemberName()) + |> List.head + MyTy.Check(result, Some("CheckMembers"), "lambda") + MyTy.Check(functionVal (), Some("functionVal"), "functionVal") + () + static member GetCallerMemberName([] ?memberName : string) = memberName + + static member Check(actual : string option, expected : string option, message) = + printfn "%A" actual + if actual <> expected then + failwith message static member GetCallerMemberNameProperty with get () = MyTy.GetCallerMemberName() + and set (v : string option) = + MyTy.Check(MyTy.GetCallerMemberName(), Some("GetCallerMemberNameProperty"), "property setter") member val GetCallerMemberNameProperty1 = MyTy.GetCallerMemberName() with get, set +[] +type MyStruct = + val A : int + new(a : int) = + { A = a } + then + MyTy.Check(MyTy.GetCallerMemberName(), Some(".ctor"), "struct ctor") + +[] +type Extensions = + [] + static member DotNetExtensionMeth(instance : System.DateTime) = + MyTy.GetCallerMemberName() + module Program = + type System.String with + member __.StringExtensionMeth() = + MyTy.Check(MyTy.GetCallerMemberName(),Some("StringExtensionMeth"), "extension method") + 1 + member __.StringExtensionProp = + MyTy.Check(MyTy.GetCallerMemberName(), Some("StringExtensionProp"), "extension property") + 2 + + let callerInfoAsFunc = MyTy.GetCallerMemberName + let rebindFunc = callerInfoAsFunc + let moduleLetVal = MyTy.GetCallerMemberName() + let moduleFunc (i : int) = i, MyTy.GetCallerMemberName() + let moduleFuncNested i = + let nestedFunc j = + (j + 1),MyTy.GetCallerMemberName() + nestedFunc i + let ``backtick value name`` = MyTy.GetCallerMemberName() + let (+++) a b = + (a+b, MyTy.GetCallerMemberName()) + + MyTy.Check(MyTy.GetCallerMemberName(), Some(".cctor"), "module cctor") + [] let main (_:string[]) = - if MyTy.GetCallerMemberName() <> Some("main") then - failwith "Unexpected F# CallerMemberName" + MyTy.Check(MyTy.GetCallerMemberName(), Some("main"), "main") - if MyTy.GetCallerMemberName("foo") <> Some("foo") then - failwith "Unexpected F# CallerMemberName" - - if MyTy.GetCallerMemberNameProperty <> Some("GetCallerMemberNameProperty") then - failwith "Unexpected F# CallerMemberName" - - if MyTy().GetCallerMemberNameProperty1 <> Some("GetCallerMemberNameProperty1") then - failwith "Unexpected F# CallerMemberName" - - if CallerInfoTest.MemberName() <> "main" then - failwith "Unexpected C# CallerMemberName" - - if CallerInfoTest.MemberName("foo") <> "foo" then - failwith "Unexpected C# CallerMemberName" + MyTy.Check(MyTy.GetCallerMemberName("foo"), Some("foo"), "passed value") + + MyTy.Check(moduleLetVal, Some("moduleLetVal"), "module let value") + + MyTy.Check(``backtick value name``, Some("backtick value name"), "backtick identifier") + + MyTy.Check(moduleFunc 3 |> snd, Some("moduleFunc"), "module func") + + MyTy.Check(moduleFuncNested 10 |> snd, Some("moduleFuncNested"), "module func nested") + + let inst = MyTy() + inst.CheckMembers() + let inst2 = MyTy(2) + inst2.CheckMembers() + + let v = CallerInfoTest.MemberName() + MyTy.Check(Some(v), Some("main"), "C# main") + + MyTy.Check(Some(CallerInfoTest.MemberName("foo")), Some("foo"), "C# passed value") match CallerInfoTest.AllInfo(21) with | (_, _, "main") -> () | x -> failwithf "Unexpected C# result with multiple parameter types: %A" x - let getCallerLineNumber = CallerInfoTest.MemberName + MyTy.Check(() |> callerInfoAsFunc, Some("callerInfoAsFunc"), "method as function value 1") + MyTy.Check(() |> rebindFunc, Some("callerInfoAsFunc"), "method as function value 2") + + let typeAttr = typeof.GetCustomAttributes(typeof, false).[0] :?> MyCallerMemberNameAttribute + MyTy.Check(Some(typeAttr.MemberName), Some("dflt"), "attribute on type") + + let asmAttr = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof, false).[0] :?> MyCallerMemberNameAttribute + MyTy.Check(Some(asmAttr.MemberName), Some("dflt"), "attribute on asm") + + let s = "123" + let s1 = s.StringExtensionMeth() + let s2 = s.StringExtensionProp + + let dt = System.DateTime.Now + MyTy.Check(dt.DotNetExtensionMeth(), Some("DotNetExtensionMeth"), ".NET extension method") - if () |> CallerInfoTest.MemberName <> "main" then - failwith "Unexpected C# CallerMemberName" + let strct = MyStruct(10) - if getCallerLineNumber () <> "main" then - failwith "Unexpected C# CallerMemberName" + MyTy.Check(1 +++ 2 |> snd, Some("op_PlusPlusPlus"), "operator") 0 \ No newline at end of file From 8927df42d48e8b7d01bb23cb98ba125ebafe426a Mon Sep 17 00:00:00 2001 From: "Avi.Avni" Date: Thu, 12 May 2016 12:31:26 +0300 Subject: [PATCH 040/129] fix build --- src/fsharp/vs/Symbols.fs | 4 ++-- src/fsharp/vs/service.fs | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/fsharp/vs/Symbols.fs b/src/fsharp/vs/Symbols.fs index 195a1dc3217..ec3317ddfd1 100644 --- a/src/fsharp/vs/Symbols.fs +++ b/src/fsharp/vs/Symbols.fs @@ -1531,7 +1531,7 @@ and FSharpMemberOrFunctionOrValue(cenv, d:FSharpMemberOrValData, item) = match d with | P p -> - [ [ for (ParamData(isParamArrayArg,isOutArg,optArgInfo,nmOpt,_reflArgInfo,pty)) in p.GetParamDatas(cenv.amap,range0) do + [ [ for (ParamData(isParamArrayArg,isOutArg,optArgInfo,_callerInfoInfo,nmOpt,_reflArgInfo,pty)) in p.GetParamDatas(cenv.amap,range0) do // INCOMPLETENESS: Attribs is empty here, so we can't look at attributes for // either .NET or F# parameters let argInfo : ArgReprInfo = { Name=nmOpt; Attribs= [] } @@ -1543,7 +1543,7 @@ and FSharpMemberOrFunctionOrValue(cenv, d:FSharpMemberOrValData, item) = | M m -> [ for argtys in m.GetParamDatas(cenv.amap,range0,m.FormalMethodInst) do yield - [ for (ParamData(isParamArrayArg,isOutArg,optArgInfo,nmOpt,_reflArgInfo,pty)) in argtys do + [ for (ParamData(isParamArrayArg,isOutArg,optArgInfo,_callerInfoInfo,nmOpt,_reflArgInfo,pty)) in argtys do // INCOMPLETENESS: Attribs is empty here, so we can't look at attributes for // either .NET or F# parameters let argInfo : ArgReprInfo = { Name=nmOpt; Attribs= [] } diff --git a/src/fsharp/vs/service.fs b/src/fsharp/vs/service.fs index 90f0c9d827c..653d23671d6 100644 --- a/src/fsharp/vs/service.fs +++ b/src/fsharp/vs/service.fs @@ -88,13 +88,13 @@ module internal Params = let ParamOfUnionCaseField g denv isGenerated (i : int) f = let initial = ParamOfRecdField g denv f - let display = if isGenerated i f then initial.Display else NicePrint.stringOfParamData denv (ParamData(false, false, NotOptional, Some f.rfield_id, ReflectedArgInfo.None, f.rfield_type)) + let display = if isGenerated i f then initial.Display else NicePrint.stringOfParamData denv (ParamData(false, false, NotOptional, NoCallerInfo, Some f.rfield_id, ReflectedArgInfo.None, f.rfield_type)) FSharpMethodGroupItemParameter( name=initial.ParameterName, canonicalTypeTextForSorting=initial.CanonicalTypeTextForSorting, display=display) - let ParamOfParamData g denv (ParamData(_isParamArrayArg, _isOutArg, _optArgInfo, nmOpt, _reflArgInfo, pty) as paramData) = + let ParamOfParamData g denv (ParamData(_isParamArrayArg, _isOutArg, _optArgInfo, _callerInfoInfo, nmOpt, _reflArgInfo, pty) as paramData) = FSharpMethodGroupItemParameter( name = (match nmOpt with None -> "" | Some pn -> pn.idText), canonicalTypeTextForSorting = printCanonicalizedTypeName g denv pty, @@ -104,7 +104,7 @@ module internal Params = let ParamsOfParamDatas g denv (paramDatas:ParamData list) rty = let paramNames,paramPrefixes,paramTypes = paramDatas - |> List.map (fun (ParamData(isParamArrayArg, _isOutArg, optArgInfo, nmOpt, _reflArgInfo, pty)) -> + |> List.map (fun (ParamData(isParamArrayArg, _isOutArg, optArgInfo, _callerInfoInfo, nmOpt, _reflArgInfo, pty)) -> let isOptArg = optArgInfo.IsOptional match nmOpt, isOptArg, tryDestOptionTy denv.g pty with // Layout an optional argument @@ -251,7 +251,7 @@ module internal Params = let paramDatas = argInfo |> List.map ParamNameAndType.FromArgInfo - |> List.map (fun (ParamNameAndType(nmOpt, pty)) -> ParamData(false, false, NotOptional, nmOpt, ReflectedArgInfo.None, pty)) + |> List.map (fun (ParamNameAndType(nmOpt, pty)) -> ParamData(false, false, NotOptional, NoCallerInfo, nmOpt, ReflectedArgInfo.None, pty)) ParamsOfParamDatas g denv paramDatas returnTy | Item.UnionCase(ucr,_) -> match ucr.UnionCase.RecdFields with @@ -281,7 +281,7 @@ module internal Params = | None -> let argNamesAndTys = ItemDescriptionsImpl.ParamNameAndTypesOfUnaryCustomOperation g minfo let _, argTys, _ = PrettyTypes.PrettifyTypesN g (argNamesAndTys |> List.map (fun (ParamNameAndType(_,ty)) -> ty)) - let paramDatas = (argNamesAndTys, argTys) ||> List.map2 (fun (ParamNameAndType(nmOpt, _)) argTy -> ParamData(false, false, NotOptional, nmOpt, ReflectedArgInfo.None,argTy)) + let paramDatas = (argNamesAndTys, argTys) ||> List.map2 (fun (ParamNameAndType(nmOpt, _)) argTy -> ParamData(false, false, NotOptional, NoCallerInfo, nmOpt, ReflectedArgInfo.None,argTy)) let rty = minfo.GetFSharpReturnTy(amap, m, minfo.FormalMethodInst) ParamsOfParamDatas g denv paramDatas rty | Some _ -> @@ -290,7 +290,7 @@ module internal Params = | Item.FakeInterfaceCtor _ -> [] | Item.DelegateCtor delty -> let (SigOfFunctionForDelegate(_, _, _, fty)) = GetSigOfFunctionForDelegate infoReader delty m AccessibleFromSomeFSharpCode - ParamsOfParamDatas g denv [ParamData(false, false, NotOptional, None, ReflectedArgInfo.None, fty)] delty + ParamsOfParamDatas g denv [ParamData(false, false, NotOptional, NoCallerInfo, None, ReflectedArgInfo.None, fty)] delty | _ -> [] @@ -653,7 +653,7 @@ type TypeCheckInfo methods |> List.collect (fun meth -> match meth.GetParamDatas(amap, m, meth.FormalMethodInst) with - | x::_ -> x |> List.choose(fun (ParamData(_isParamArray, _isOut, _optArgInfo, name, _, ty)) -> + | x::_ -> x |> List.choose(fun (ParamData(_isParamArray, _isOut, _optArgInfo, _callerInfoInfo, name, _, ty)) -> match name with | Some n -> Some (Item.ArgName(n, ty, Some (ArgumentContainer.Method meth))) | None -> None From e919a9832d23e917f27f091857932b990db3fb1a Mon Sep 17 00:00:00 2001 From: "Avi.Avni" Date: Thu, 12 May 2016 19:47:49 +0300 Subject: [PATCH 041/129] add negative tests --- .../Imported/CallerInfo/E_CallerMemberName.fs | 16 ++++++++++++++++ .../Imported/CallerInfo/env.lst | 1 + 2 files changed, 17 insertions(+) create mode 100644 tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/E_CallerMemberName.fs diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/E_CallerMemberName.fs b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/E_CallerMemberName.fs new file mode 100644 index 00000000000..30ef0c16e55 --- /dev/null +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/E_CallerMemberName.fs @@ -0,0 +1,16 @@ +//'CallerMemberName' must be applied to an argument of type 'string', but has been applied to an argument of type 'int' +//'CallerMemberName' can only be applied to optional arguments +//'CallerMemberName' can only be applied to optional arguments +namespace Test + +open System.Runtime.CompilerServices + +type MyTy() = + static member GetCallerMemberNamehNotString([] ?name : int) = + name + + static member GetCallerMemberNameNotOptional([] name : string) = + name + + static member GetCallerMemberNameNotOptional([] name : string option) = + name \ No newline at end of file diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/env.lst b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/env.lst index 72380e030b9..1dac02145a5 100644 --- a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/env.lst +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/env.lst @@ -3,6 +3,7 @@ SOURCE=CallerMemberName.fs SCFLAGS="-r CSharpLib.dll --test:ErrorRanges" PRECMD="\$CSC_PIPE /t:library CSharpLib.cs" # CallerMemberName.fs SOURCE=E_CallerLineNumber.fs SCFLAGS="--test:ErrorRanges" # E_CallerLineNumber.fs SOURCE=E_CallerFilePath.fs SCFLAGS="--test:ErrorRanges" # E_CallerFilePath.fs + SOURCE=E_CallerMemberName.fs SCFLAGS="--test:ErrorRanges" # E_CallerMemberName.fs SOURCE=E_MultipleAttrs.fs SCFLAGS="--test:ErrorRanges" # E_MultipleAttrs.fs SOURCE=ViaInteractive.fsx SCFLAGS="--test:ErrorRanges -r CSharpLib.dll" PRECMD="\$CSC_PIPE /t:library CSharpLib.cs" FSIMODE=EXEC COMPILE_ONLY=1 # ViaInteractive.fsx - exec SOURCE=ViaInteractive.fsx SCFLAGS="--test:ErrorRanges -r CSharpLib.dll" PRECMD="\$CSC_PIPE /t:library CSharpLib.cs" FSIMODE=PIPE COMPILE_ONLY=1 # ViaInteractive.fsx - pipe From 1ed22a816e37fcc2ed3b69f8143ad0ad1e81b4d8 Mon Sep 17 00:00:00 2001 From: "Avi.Avni" Date: Thu, 12 May 2016 20:01:09 +0300 Subject: [PATCH 042/129] update chkCurriedMethodsCantHaveOutParams error --- src/fsharp/FSComp.txt | 2 +- tests/fsharp/typecheck/sigs/neg23.bsl | 4 ++-- .../MemberDeclarations/E_byref_two_arguments_curried.fsx | 2 +- .../MemberDeclarations/E_optional_two_arguments_curried.fsx | 2 +- .../MemberDeclarations/E_out_two_arguments_curried.fsx | 2 +- .../MemberDeclarations/E_paramarray_two_arguments_curried.fsx | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/fsharp/FSComp.txt b/src/fsharp/FSComp.txt index c0fa84e4877..e9372cd7a37 100644 --- a/src/fsharp/FSComp.txt +++ b/src/fsharp/FSComp.txt @@ -256,7 +256,7 @@ chkUnionCaseDefaultAugmentation,"default augmentation of the union case" 438,chkDuplicateMethod,"Duplicate method. The method '%s' has the same name and signature as another method in this type." 438,chkDuplicateMethodWithSuffix,"Duplicate method. The method '%s' has the same name and signature as another method in this type once tuples, functions, units of measure and/or provided types are erased." 439,chkDuplicateMethodCurried,"The method '%s' has curried arguments but has the same name as another method in this type. Methods with curried arguments cannot be overloaded. Consider using a method taking tupled arguments." -440,chkCurriedMethodsCantHaveOutParams,"Methods with curried arguments cannot declare 'out', 'ParamArray', 'optional', 'ReflectedDefinition', 'byref', 'CallerLineNumber', or 'CallerFilePath' arguments" +440,chkCurriedMethodsCantHaveOutParams,"Methods with curried arguments cannot declare 'out', 'ParamArray', 'optional', 'ReflectedDefinition', 'byref', 'CallerLineNumber', 'CallerMemberName', or 'CallerFilePath' arguments" 441,chkDuplicateProperty,"Duplicate property. The property '%s' has the same name and signature as another property in this type." 441,chkDuplicatePropertyWithSuffix,"Duplicate property. The property '%s' has the same name and signature as another property in this type once tuples, functions, units of measure and/or provided types are erased." 442,chkDuplicateMethodInheritedType,"Duplicate method. The abstract method '%s' has the same name and signature as an abstract method in an inherited type." diff --git a/tests/fsharp/typecheck/sigs/neg23.bsl b/tests/fsharp/typecheck/sigs/neg23.bsl index f817caa2ef0..43ccae55657 100644 --- a/tests/fsharp/typecheck/sigs/neg23.bsl +++ b/tests/fsharp/typecheck/sigs/neg23.bsl @@ -27,9 +27,9 @@ neg23.fs(82,18,82,20): typecheck error FS0439: The method 'X0' has curried argum neg23.fs(85,18,85,21): typecheck error FS0439: The method 'X01' has curried arguments but has the same name as another method in this type. Methods with curried arguments cannot be overloaded. Consider using a method taking tupled arguments. -neg23.fs(88,18,88,21): typecheck error FS0440: Methods with curried arguments cannot declare 'out', 'ParamArray', 'optional', 'ReflectedDefinition', 'byref', 'CallerLineNumber', or 'CallerFilePath' arguments +neg23.fs(88,18,88,21): typecheck error FS0440: Methods with curried arguments cannot declare 'out', 'ParamArray', 'optional', 'ReflectedDefinition', 'byref', 'CallerLineNumber', 'CallerMemberName', or 'CallerFilePath' arguments -neg23.fs(90,18,90,21): typecheck error FS0440: Methods with curried arguments cannot declare 'out', 'ParamArray', 'optional', 'ReflectedDefinition', 'byref', 'CallerLineNumber', or 'CallerFilePath' arguments +neg23.fs(90,18,90,21): typecheck error FS0440: Methods with curried arguments cannot declare 'out', 'ParamArray', 'optional', 'ReflectedDefinition', 'byref', 'CallerLineNumber', 'CallerMemberName', or 'CallerFilePath' arguments neg23.fs(93,18,93,21): typecheck error FS0439: The method 'X04' has curried arguments but has the same name as another method in this type. Methods with curried arguments cannot be overloaded. Consider using a method taking tupled arguments. diff --git a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/ClassTypes/MemberDeclarations/E_byref_two_arguments_curried.fsx b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/ClassTypes/MemberDeclarations/E_byref_two_arguments_curried.fsx index 68bd6ad5b0b..e5ffef324c3 100644 --- a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/ClassTypes/MemberDeclarations/E_byref_two_arguments_curried.fsx +++ b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/ClassTypes/MemberDeclarations/E_byref_two_arguments_curried.fsx @@ -2,6 +2,6 @@ // Regression test for FSHARP1.0:5580 // disallow curried byref parameters // Out arguments - curried -//Methods with curried arguments cannot declare 'out', 'ParamArray', 'optional', 'ReflectedDefinition', 'byref', 'CallerLineNumber', or 'CallerFilePath' arguments +//Methods with curried arguments cannot declare 'out', 'ParamArray', 'optional', 'ReflectedDefinition', 'byref', 'CallerLineNumber', 'CallerMemberName', or 'CallerFilePath' arguments type Misc2() = static member M (foo : int byref) (bar : int byref) = foo <- 10 diff --git a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/ClassTypes/MemberDeclarations/E_optional_two_arguments_curried.fsx b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/ClassTypes/MemberDeclarations/E_optional_two_arguments_curried.fsx index f788556262b..3aa8c622948 100644 --- a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/ClassTypes/MemberDeclarations/E_optional_two_arguments_curried.fsx +++ b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/ClassTypes/MemberDeclarations/E_optional_two_arguments_curried.fsx @@ -2,6 +2,6 @@ // Regression test for FSHARP1.0:5580 // disallow curried byref parameters // optional arguments - curried -//Methods with curried arguments cannot declare 'out', 'ParamArray', 'optional', 'ReflectedDefinition', 'byref', 'CallerLineNumber', or 'CallerFilePath' arguments +//Methods with curried arguments cannot declare 'out', 'ParamArray', 'optional', 'ReflectedDefinition', 'byref', 'CallerLineNumber', 'CallerMemberName', or 'CallerFilePath' arguments type Misc0() = static member M (?foo : int) (?bar : int) = 10 diff --git a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/ClassTypes/MemberDeclarations/E_out_two_arguments_curried.fsx b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/ClassTypes/MemberDeclarations/E_out_two_arguments_curried.fsx index b7754e95dde..2f6cec8efca 100644 --- a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/ClassTypes/MemberDeclarations/E_out_two_arguments_curried.fsx +++ b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/ClassTypes/MemberDeclarations/E_out_two_arguments_curried.fsx @@ -2,6 +2,6 @@ // Regression test for FSHARP1.0:5580 // disallow curried byref parameters // Out arguments - curried -//Methods with curried arguments cannot declare 'out', 'ParamArray', 'optional', 'ReflectedDefinition', 'byref', 'CallerLineNumber', or 'CallerFilePath' arguments +//Methods with curried arguments cannot declare 'out', 'ParamArray', 'optional', 'ReflectedDefinition', 'byref', 'CallerLineNumber', 'CallerMemberName', or 'CallerFilePath' arguments type Misc2() = static member M ([] foo : int byref) ([] bar : int byref) = foo <- 10 diff --git a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/ClassTypes/MemberDeclarations/E_paramarray_two_arguments_curried.fsx b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/ClassTypes/MemberDeclarations/E_paramarray_two_arguments_curried.fsx index 5840eee3a07..fb611d7bb1d 100644 --- a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/ClassTypes/MemberDeclarations/E_paramarray_two_arguments_curried.fsx +++ b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/ClassTypes/MemberDeclarations/E_paramarray_two_arguments_curried.fsx @@ -2,6 +2,6 @@ // Regression test for FSHARP1.0:5580 // disallow curried byref parameters // ParamArray arguments - non curried -//Methods with curried arguments cannot declare 'out', 'ParamArray', 'optional', 'ReflectedDefinition', 'byref', 'CallerLineNumber', or 'CallerFilePath' arguments +//Methods with curried arguments cannot declare 'out', 'ParamArray', 'optional', 'ReflectedDefinition', 'byref', 'CallerLineNumber', 'CallerMemberName', or 'CallerFilePath' arguments type Misc0() = static member M ([] args : string[]) ([] argc : int) = args.Length + argc From 80975acae663fce2ecc7af0b2078306249d205d5 Mon Sep 17 00:00:00 2001 From: "Avi.Avni" Date: Thu, 12 May 2016 20:57:07 +0300 Subject: [PATCH 043/129] implement the CS7080 warning and add test --- src/fsharp/FSComp.txt | 3 ++- src/fsharp/infos.fs | 4 ++++ .../Imported/CallerInfo/E_CallerMemberName.fs | 4 ++-- .../Imported/CallerInfo/W_CallerMemberName.fs | 8 ++++++++ .../SpecialAttributesAndTypes/Imported/CallerInfo/env.lst | 1 + 5 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/W_CallerMemberName.fs diff --git a/src/fsharp/FSComp.txt b/src/fsharp/FSComp.txt index e9372cd7a37..27e79073c3b 100644 --- a/src/fsharp/FSComp.txt +++ b/src/fsharp/FSComp.txt @@ -1293,4 +1293,5 @@ estApplyStaticArgumentsForMethodNotImplemented,"A type provider implemented GetS 3194,optsResponseFileNotFound,"Response file '%s' not found in '%s'" 3195,optsResponseFileNameInvalid,"Response file name '%s' is empty, contains invalid characters, has a drive specification without an absolute path, or is too long" 3196,fsharpCoreNotFoundToBeCopied,"Cannot find FSharp.Core.dll in compiler's directory" -3197,etMissingStaticArgumentsToMethod,"This provided method requires static parameters" \ No newline at end of file +3197,etMissingStaticArgumentsToMethod,"This provided method requires static parameters" +3198,CallerMemberNameIsOverriden,"The CallerMemberNameAttribute applied to parameter '%s' will have no effect. It is overridden by the CallerFilePathAttribute." \ No newline at end of file diff --git a/src/fsharp/infos.fs b/src/fsharp/infos.fs index c34c19ee382..28fc006705b 100755 --- a/src/fsharp/infos.fs +++ b/src/fsharp/infos.fs @@ -1326,6 +1326,10 @@ type MethInfo = | true, false, false -> CallerLineNumber | false, true, false -> CallerFilePath | false, false, true -> CallerMemberName + | false, true, true -> match TryFindFSharpAttribute g g.attrib_CallerMemberNameAttribute argInfo.Attribs with + | Some(Attrib(_,_,_,_,_,_,callerMemberNameAttributeRange)) -> warning(Error(FSComp.SR.CallerMemberNameIsOverriden(argInfo.Name.Value.idText), callerMemberNameAttributeRange)) + CallerFilePath + | _ -> failwith "Impossible" | _, _, _ -> // if multiple caller info attributes are specified, pick the "wrong" one here // so that we get an error later diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/E_CallerMemberName.fs b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/E_CallerMemberName.fs index 30ef0c16e55..9749e1e1508 100644 --- a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/E_CallerMemberName.fs +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/E_CallerMemberName.fs @@ -1,4 +1,4 @@ -//'CallerMemberName' must be applied to an argument of type 'string', but has been applied to an argument of type 'int' +//'CallerMemberName' must be applied to an argument of type 'string', but has been applied to an argument of type 'int' //'CallerMemberName' can only be applied to optional arguments //'CallerMemberName' can only be applied to optional arguments namespace Test @@ -6,7 +6,7 @@ namespace Test open System.Runtime.CompilerServices type MyTy() = - static member GetCallerMemberNamehNotString([] ?name : int) = + static member GetCallerMemberNameNotString([] ?name : int) = name static member GetCallerMemberNameNotOptional([] name : string) = diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/W_CallerMemberName.fs b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/W_CallerMemberName.fs new file mode 100644 index 00000000000..49b9362c3e8 --- /dev/null +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/W_CallerMemberName.fs @@ -0,0 +1,8 @@ +//The CallerMemberNameAttribute applied to parameter 'name' will have no effect. It is overridden by the CallerFilePathAttribute. +namespace Test + +open System.Runtime.CompilerServices + +type MyTy() = + static member GetCallerMemberName([] ?name : string) = + name \ No newline at end of file diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/env.lst b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/env.lst index 1dac02145a5..46d8cb48635 100644 --- a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/env.lst +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/env.lst @@ -5,6 +5,7 @@ SOURCE=E_CallerFilePath.fs SCFLAGS="--test:ErrorRanges" # E_CallerFilePath.fs SOURCE=E_CallerMemberName.fs SCFLAGS="--test:ErrorRanges" # E_CallerMemberName.fs SOURCE=E_MultipleAttrs.fs SCFLAGS="--test:ErrorRanges" # E_MultipleAttrs.fs + SOURCE=W_CallerMemberName.fs SCFLAGS="--test:ErrorRanges" # W_CallerMemberName.fs SOURCE=ViaInteractive.fsx SCFLAGS="--test:ErrorRanges -r CSharpLib.dll" PRECMD="\$CSC_PIPE /t:library CSharpLib.cs" FSIMODE=EXEC COMPILE_ONLY=1 # ViaInteractive.fsx - exec SOURCE=ViaInteractive.fsx SCFLAGS="--test:ErrorRanges -r CSharpLib.dll" PRECMD="\$CSC_PIPE /t:library CSharpLib.cs" FSIMODE=PIPE COMPILE_ONLY=1 # ViaInteractive.fsx - pipe SOURCE=CallerInfoAndQuotiation.fs SCFLAGS="-r CSharpLib.dll --test:ErrorRanges" PRECMD="\$CSC_PIPE /t:library CSharpLib.cs" # CallerInfoAndQuotiation.fs From 4d2563e3dadf1e0c34b25e3d5e74a949fc6b5fb9 Mon Sep 17 00:00:00 2001 From: Taylor Wood Date: Wed, 1 Jun 2016 23:16:06 -0500 Subject: [PATCH 044/129] Expand unit-type-expected compiler warning --- src/fsharp/FSStrings.resx | 2 +- .../LetBindings/Basic/W_DoBindingsNotUnit01.fs | 2 +- .../Expressions/BindingExpressions/Binding/in01.fs | 2 +- .../Expressions/BindingExpressions/Binding/in02.fs | 2 +- .../Expressions/BindingExpressions/Binding/in03.fs | 2 +- .../Expressions/BindingExpressions/Binding/in04.fs | 2 +- .../Expressions/BindingExpressions/Binding/in05.fs | 2 +- .../ControlFlowExpressions/TryFinally/W-TryFinallyNotUnit.fs | 2 +- .../QueryExpressions/E_WhereRequiresParens01.fs | 2 +- .../PatternMatching/Named/E_ActivePatternUnconstrained01.fs | 2 +- tests/fsharpqa/Source/Diagnostics/General/W_Multiline02.fs | 2 +- tests/fsharpqa/Source/Diagnostics/NONTERM/quoteExpr01.fs | 2 +- tests/fsharpqa/Source/Diagnostics/async/MissingIgnore.fs | 2 +- .../Source/Diagnostics/async/MissingReturnBangForLoop01.fs | 2 +- .../Source/Diagnostics/async/MissingReturnBangForLoop02.fs | 2 +- .../Source/Diagnostics/async/MissingReturnBangForLoop03.fs | 2 +- .../Source/Diagnostics/async/MissingReturnBangForLoop04.fs | 2 +- tests/fsharpqa/Source/Misc/Parsing02.fs | 4 ++-- 18 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/fsharp/FSStrings.resx b/src/fsharp/FSStrings.resx index f95cf777b4a..f4c45a898f5 100644 --- a/src/fsharp/FSStrings.resx +++ b/src/fsharp/FSStrings.resx @@ -892,7 +892,7 @@ This expression is a function value, i.e. is missing arguments. Its type is {0}. - This expression should have type 'unit', but has type '{0}'. Use 'ignore' to discard the result of the expression, or 'let' to bind the result to a name. + This expression has a value of type '{0}' that is implicitly ignored. Use the 'ignore' function to discard this value explicitly, e.g. 'expr |> ignore', or bind it to a name to refer to it later, e.g. 'let result = expr'. This expression should have type 'unit', but has type '{0}'. If assigning to a property use the syntax 'obj.Prop <- expr'. diff --git a/tests/fsharpqa/Source/Conformance/DeclarationElements/LetBindings/Basic/W_DoBindingsNotUnit01.fs b/tests/fsharpqa/Source/Conformance/DeclarationElements/LetBindings/Basic/W_DoBindingsNotUnit01.fs index f527a126c76..f9ffa7970ce 100644 --- a/tests/fsharpqa/Source/Conformance/DeclarationElements/LetBindings/Basic/W_DoBindingsNotUnit01.fs +++ b/tests/fsharpqa/Source/Conformance/DeclarationElements/LetBindings/Basic/W_DoBindingsNotUnit01.fs @@ -2,7 +2,7 @@ #light // Verify warning when 'do-bindings' do not return unit. -//This expression should have type 'unit', but has type 'int' +//This expression has a value of type 'int' that is implicitly ignored let square x = x * x diff --git a/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in01.fs b/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in01.fs index 1f96f9e14f8..d4d1116810e 100644 --- a/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in01.fs +++ b/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in01.fs @@ -5,7 +5,7 @@ // Eventually, we will deprecated them - and the specs will be updated. // //The value or constructor 'a' is not defined$ -//This expression should have type 'unit', but has type 'bool'\. Use 'ignore' to discard the result of the expression, or 'let' to bind the result to a name\.$ +//This expression has a value of type 'bool' that is implicitly ignored\. Use the 'ignore' function to discard this value explicitly, e\.g\. 'expr \|> ignore', or bind it to a name to refer to it later, e\.g\. 'let result = expr'\.$ module A = let a = 3 in a + 1 |> ignore;; a > 4;; diff --git a/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in02.fs b/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in02.fs index d49ef5d5bff..9d1abe85d68 100644 --- a/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in02.fs +++ b/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in02.fs @@ -4,7 +4,7 @@ // I'm adding these cases to make sure we do not accidentally change the behavior from version to version // Eventually, we will deprecated them - and the specs will be updated. // -//This expression should have type 'unit', but has type 'bool'\. Use 'ignore' to discard the result of the expression, or 'let' to bind the result to a name\.$ +//This expression has a value of type 'bool' that is implicitly ignored\. Use the 'ignore' function to discard this value explicitly, e\.g\. 'expr \|> ignore', or bind it to a name to refer to it later, e\.g\. 'let result = expr'\.$ // module B = diff --git a/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in03.fs b/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in03.fs index 41759f95d54..f36c08169f8 100644 --- a/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in03.fs +++ b/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in03.fs @@ -4,7 +4,7 @@ // I'm adding these cases to make sure we do not accidentally change the behavior from version to version // Eventually, we will deprecated them - and the specs will be updated. // -//This expression should have type 'unit', but has type 'bool'\. Use 'ignore' to discard the result of the expression, or 'let' to bind the result to a name\.$ +//This expression has a value of type 'bool' that is implicitly ignored\. Use the 'ignore' function to discard this value explicitly, e\.g\. 'expr \|> ignore', or bind it to a name to refer to it later, e\.g\. 'let result = expr'\.$ // module C = let a = 3 diff --git a/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in04.fs b/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in04.fs index 5899d4bbbd2..a56dcd72f94 100644 --- a/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in04.fs +++ b/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in04.fs @@ -4,7 +4,7 @@ // I'm adding these cases to make sure we do not accidentally change the behavior from version to version // Eventually, we will deprecated them - and the specs will be updated. // -//This expression should have type 'unit', but has type 'bool'\. Use 'ignore' to discard the result of the expression, or 'let' to bind the result to a name\.$ +//This expression has a value of type 'bool' that is implicitly ignored\. Use the 'ignore' function to discard this value explicitly, e\.g\. 'expr \|> ignore', or bind it to a name to refer to it later, e\.g\. 'let result = expr'\.$ // module D = diff --git a/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in05.fs b/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in05.fs index 183ff1a0e89..a6cf5359f82 100644 --- a/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in05.fs +++ b/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in05.fs @@ -5,7 +5,7 @@ // Eventually, we will deprecated them - and the specs will be updated. //The type 'int' does not match the type 'unit'$ //Type mismatch\. Expecting a. ''a -> 'b' .but given a. ''a -> unit' .The type 'int' does not match the type 'unit'$ -//This expression should have type 'unit', but has type 'bool'\. Use 'ignore' to discard the result of the expression, or 'let' to bind the result to a name\.$ +//This expression has a value of type 'bool' that is implicitly ignored\. Use the 'ignore' function to discard this value explicitly, e\.g\. 'expr \|> ignore', or bind it to a name to refer to it later, e\.g\. 'let result = expr'\.$ module E = let a = 3 in a + 1 |> ignore diff --git a/tests/fsharpqa/Source/Conformance/Expressions/ControlFlowExpressions/TryFinally/W-TryFinallyNotUnit.fs b/tests/fsharpqa/Source/Conformance/Expressions/ControlFlowExpressions/TryFinally/W-TryFinallyNotUnit.fs index 516306e9269..dcfad64bdfb 100644 --- a/tests/fsharpqa/Source/Conformance/Expressions/ControlFlowExpressions/TryFinally/W-TryFinallyNotUnit.fs +++ b/tests/fsharpqa/Source/Conformance/Expressions/ControlFlowExpressions/TryFinally/W-TryFinallyNotUnit.fs @@ -2,7 +2,7 @@ #light // Verify warning if a finally block does not return 'unit' -//This expression should have type 'unit', but has type 'bool' +//This expression has a value of type 'bool' that is implicitly ignored let x : int = try diff --git a/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/QueryExpressions/E_WhereRequiresParens01.fs b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/QueryExpressions/E_WhereRequiresParens01.fs index d36c7227514..f69b652c4cd 100644 --- a/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/QueryExpressions/E_WhereRequiresParens01.fs +++ b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/QueryExpressions/E_WhereRequiresParens01.fs @@ -1,7 +1,7 @@ // #Conformance #DataExpressions #Query // Where expressions require parenthesis //'where' is not used correctly\. This is a custom operation in this query or computation expression\.$ -//This expression should have type 'unit', but has type 'bool'\. Use 'ignore' to discard the result of the expression, or 'let' to bind the result to a name\.$ +//This expression has a value of type 'bool' that is implicitly ignored\. Use the 'ignore' function to discard this value explicitly, e\.g\. 'expr \|> ignore', or bind it to a name to refer to it later, e\.g\. 'let result = expr'\.$ let query = query { for i in [1..10] do diff --git a/tests/fsharpqa/Source/Conformance/PatternMatching/Named/E_ActivePatternUnconstrained01.fs b/tests/fsharpqa/Source/Conformance/PatternMatching/Named/E_ActivePatternUnconstrained01.fs index 1f0a23ab75e..17ad18262e1 100644 --- a/tests/fsharpqa/Source/Conformance/PatternMatching/Named/E_ActivePatternUnconstrained01.fs +++ b/tests/fsharpqa/Source/Conformance/PatternMatching/Named/E_ActivePatternUnconstrained01.fs @@ -2,7 +2,7 @@ // Regression test for FSHARP1.0:5590 // This code used to compile, but fail peverification // Now, it just does not compile anymore telling the user to annotated it a bit. -//This expression should have type 'unit', but has type 'int'\. Use 'ignore' to discard the result of the expression, or 'let' to bind the result to a name\.$ +//This expression has a value of type 'int' that is implicitly ignored\. Use the 'ignore' function to discard this value explicitly, e\.g\. 'expr \|> ignore', or bind it to a name to refer to it later, e\.g\. 'let result = expr'\.$ //Active pattern '\|A1\|A2\|A3\|' has a result type containing type variables that are not determined by the input\. The common cause is a when a result case is not mentioned, e\.g\. 'let \(\|A\|B\|\) \(x:int\) = A x'\. This can be fixed with a type constraint, e\.g\. 'let \(\|A\|B\|\) \(x:int\) : Choice = A x'$ let (|A1|A2|A3|) (inp:int) : Choice = printfn "hello" diff --git a/tests/fsharpqa/Source/Diagnostics/General/W_Multiline02.fs b/tests/fsharpqa/Source/Diagnostics/General/W_Multiline02.fs index cac6c4ad929..f6d624f2cc5 100644 --- a/tests/fsharpqa/Source/Diagnostics/General/W_Multiline02.fs +++ b/tests/fsharpqa/Source/Diagnostics/General/W_Multiline02.fs @@ -1,7 +1,7 @@ // #Regression #Diagnostics // Regression test for FSHARP1.0:3596 // Make sure that error spans correctly across multiple lines -//This expression should have type 'unit' +//This expression has a value of type 'int' that is implicitly ignored #nowarn "988" let f g x = g x diff --git a/tests/fsharpqa/Source/Diagnostics/NONTERM/quoteExpr01.fs b/tests/fsharpqa/Source/Diagnostics/NONTERM/quoteExpr01.fs index c402ba1b347..a78898e77d7 100644 --- a/tests/fsharpqa/Source/Diagnostics/NONTERM/quoteExpr01.fs +++ b/tests/fsharpqa/Source/Diagnostics/NONTERM/quoteExpr01.fs @@ -1,5 +1,5 @@ // #Regression #Diagnostics // Regression test for FSHARP1.0:2391, FSHARP1.0:1479 -//This expression should have type 'unit', but has type 'seq.Quotations.Var.' +//This expression has a value of type 'seq.Quotations\.Var.' that is implicitly ignored #light "off" <@@ 1 @@>.GetFreeVars() diff --git a/tests/fsharpqa/Source/Diagnostics/async/MissingIgnore.fs b/tests/fsharpqa/Source/Diagnostics/async/MissingIgnore.fs index 9e3adbb5d47..cefbf104a47 100644 --- a/tests/fsharpqa/Source/Diagnostics/async/MissingIgnore.fs +++ b/tests/fsharpqa/Source/Diagnostics/async/MissingIgnore.fs @@ -1,5 +1,5 @@ // #Regression #Diagnostics #Async // Regression tests for FSHARP1.0:4394 -//This expression should have type 'unit', but has type 'int'\. Use 'ignore' to discard the result of the expression, or 'let' to bind the result to a name\.$ +//This expression has a value of type 'int' that is implicitly ignored\. Use the 'ignore' function to discard this value explicitly, e\.g\. 'expr \|> ignore', or bind it to a name to refer to it later, e\.g\. 'let result = expr'\.$ async { 1; return 2 } |> ignore diff --git a/tests/fsharpqa/Source/Diagnostics/async/MissingReturnBangForLoop01.fs b/tests/fsharpqa/Source/Diagnostics/async/MissingReturnBangForLoop01.fs index 888b8f9e104..2e53ebcc6d0 100644 --- a/tests/fsharpqa/Source/Diagnostics/async/MissingReturnBangForLoop01.fs +++ b/tests/fsharpqa/Source/Diagnostics/async/MissingReturnBangForLoop01.fs @@ -1,5 +1,5 @@ // #Regression #Diagnostics #Async // Regression tests for FSHARP1.0:4394 // common mistake: forgetting the return! For a loop -//This expression should have type 'unit', but has type 'Async<'a>'\. Use 'ignore' to discard the result of the expression, or 'let' to bind the result to a name\.$ +//This expression has a value of type 'Async<'a>' that is implicitly ignored\. Use the 'ignore' function to discard this value explicitly, e\.g\. 'expr \|> ignore', or bind it to a name to refer to it later, e\.g\. 'let result = expr'\.$ let rec loop() = async { let x = 1 in loop() } diff --git a/tests/fsharpqa/Source/Diagnostics/async/MissingReturnBangForLoop02.fs b/tests/fsharpqa/Source/Diagnostics/async/MissingReturnBangForLoop02.fs index af12902b2a6..f5ee4118eec 100644 --- a/tests/fsharpqa/Source/Diagnostics/async/MissingReturnBangForLoop02.fs +++ b/tests/fsharpqa/Source/Diagnostics/async/MissingReturnBangForLoop02.fs @@ -1,5 +1,5 @@ // #Regression #Diagnostics #Async // Regression tests for FSHARP1.0:4394 // common mistake: forgetting the return! For a loop -//This expression should have type 'unit', but has type 'Async<'a>'\. Use 'ignore' to discard the result of the expression, or 'let' to bind the result to a name\.$ +//This expression has a value of type 'Async<'a>' that is implicitly ignored\. Use the 'ignore' function to discard this value explicitly, e\.g\. 'expr \|> ignore', or bind it to a name to refer to it later, e\.g\. 'let result = expr'\.$ let rec loop() = async { loop() } diff --git a/tests/fsharpqa/Source/Diagnostics/async/MissingReturnBangForLoop03.fs b/tests/fsharpqa/Source/Diagnostics/async/MissingReturnBangForLoop03.fs index e612c237631..821a452ef65 100644 --- a/tests/fsharpqa/Source/Diagnostics/async/MissingReturnBangForLoop03.fs +++ b/tests/fsharpqa/Source/Diagnostics/async/MissingReturnBangForLoop03.fs @@ -1,6 +1,6 @@ // #Regression #Diagnostics #Async // Regression tests for FSHARP1.0:4394 // common mistake: forgetting the return! For a loop -//This expression should have type 'unit', but has type 'Async<'a>'\. Use 'ignore' to discard the result of the expression, or 'let' to bind the result to a name\.$ +//This expression has a value of type 'Async<'a>' that is implicitly ignored\. Use the 'ignore' function to discard this value explicitly, e\.g\. 'expr \|> ignore', or bind it to a name to refer to it later, e\.g\. 'let result = expr'\.$ //This expression was expected to have type. 'Async<'a>' .but here has type. 'unit' let rec loop2() = async.Delay(fun () -> loop2(); ()); diff --git a/tests/fsharpqa/Source/Diagnostics/async/MissingReturnBangForLoop04.fs b/tests/fsharpqa/Source/Diagnostics/async/MissingReturnBangForLoop04.fs index d12252d42c8..f433fb10b6b 100644 --- a/tests/fsharpqa/Source/Diagnostics/async/MissingReturnBangForLoop04.fs +++ b/tests/fsharpqa/Source/Diagnostics/async/MissingReturnBangForLoop04.fs @@ -1,7 +1,7 @@ // #Regression #Diagnostics #Async // Regression tests for FSHARP1.0:4394 // common mistake: forgetting the return! For a loop -//This expression should have type 'unit', but has type 'Async<'a>'\. Use 'ignore' to discard the result of the expression, or 'let' to bind the result to a name\.$ +//This expression has a value of type 'Async<'a>' that is implicitly ignored\. Use the 'ignore' function to discard this value explicitly, e\.g\. 'expr \|> ignore', or bind it to a name to refer to it later, e\.g\. 'let result = expr'\.$ //This expression was expected to have type. 'Async<'a>' .but here has type. 'unit' // Note: interestingly, this looks much better if a method call is not used let delay x = async.Delay x diff --git a/tests/fsharpqa/Source/Misc/Parsing02.fs b/tests/fsharpqa/Source/Misc/Parsing02.fs index d4db9a719bc..67f9859ebef 100644 --- a/tests/fsharpqa/Source/Misc/Parsing02.fs +++ b/tests/fsharpqa/Source/Misc/Parsing02.fs @@ -1,8 +1,8 @@ // #Regression #Misc // Verify warnings associated with top level expressions getting discarded -//This expression should have type 'unit', but has type '\( \^a -> unit\) \* int' -//This expression should have type 'unit', but has type '\('a \[\] -> unit \[\]\) \* string \[\]' +//This expression has a value of type '\( \^a -> unit\) \* int' that is implicitly ignored +//This expression has a value of type '\('a \[\] -> unit \[\]\) \* string \[\]' that is implicitly ignored // Note the comma between printf "%A", this results in a tuple expr which probabaly wasn't intended. let arr = [|"Foo"; "Bar"|] From 0cda1c37205ce0c0b6fd6e7f97bc5e0ef8e5e1fc Mon Sep 17 00:00:00 2001 From: "Avi.Avni" Date: Sat, 4 Jun 2016 23:45:54 +0300 Subject: [PATCH 045/129] fix test --- .../Imported/CallerInfo/W_CallerMemberName.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/W_CallerMemberName.fs b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/W_CallerMemberName.fs index 49b9362c3e8..2ee25fac1b0 100644 --- a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/W_CallerMemberName.fs +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/W_CallerMemberName.fs @@ -1,4 +1,4 @@ -//The CallerMemberNameAttribute applied to parameter 'name' will have no effect. It is overridden by the CallerFilePathAttribute. +//The CallerMemberNameAttribute applied to parameter 'name' will have no effect. It is overridden by the CallerFilePathAttribute. namespace Test open System.Runtime.CompilerServices From de846232f251c72206b6d6b1c8a4b981065b7eb9 Mon Sep 17 00:00:00 2001 From: Taylor Wood Date: Mon, 6 Jun 2016 18:09:20 -0500 Subject: [PATCH 046/129] Update unit-type-expected compiler warning --- src/fsharp/CompileOps.fs | 4 ++-- src/fsharp/FSStrings.resx | 2 +- .../LetBindings/Basic/W_DoBindingsNotUnit01.fs | 2 +- .../Expressions/BindingExpressions/Binding/in01.fs | 2 +- .../Expressions/BindingExpressions/Binding/in02.fs | 2 +- .../Expressions/BindingExpressions/Binding/in03.fs | 2 +- .../Expressions/BindingExpressions/Binding/in04.fs | 2 +- .../Expressions/BindingExpressions/Binding/in05.fs | 2 +- .../TryFinally/W-TryFinallyNotUnit.fs | 2 +- .../QueryExpressions/E_WhereRequiresParens01.fs | 2 +- .../PatternMatching/Named/E_ActivePatternUnconstrained01.fs | 2 +- tests/fsharpqa/Source/Diagnostics/General/W_Multiline02.fs | 2 +- tests/fsharpqa/Source/Diagnostics/NONTERM/quoteExpr01.fs | 2 +- tests/fsharpqa/Source/Diagnostics/async/MissingIgnore.fs | 2 +- .../Source/Diagnostics/async/MissingReturnBangForLoop01.fs | 2 +- .../Source/Diagnostics/async/MissingReturnBangForLoop02.fs | 2 +- .../Source/Diagnostics/async/MissingReturnBangForLoop03.fs | 2 +- .../Source/Diagnostics/async/MissingReturnBangForLoop04.fs | 2 +- tests/fsharpqa/Source/Misc/Parsing02.fs | 6 +++--- 19 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/fsharp/CompileOps.fs b/src/fsharp/CompileOps.fs index 4ff176e17ed..61da60bdfa5 100755 --- a/src/fsharp/CompileOps.fs +++ b/src/fsharp/CompileOps.fs @@ -531,7 +531,7 @@ let UseOfAddressOfOperatorE() = DeclareResourceString("UseOfAddressOfOperator"," let DefensiveCopyWarningE() = DeclareResourceString("DefensiveCopyWarning","%s") let DeprecatedThreadStaticBindingWarningE() = DeclareResourceString("DeprecatedThreadStaticBindingWarning","") let FunctionValueUnexpectedE() = DeclareResourceString("FunctionValueUnexpected","%s") -let UnitTypeExpected1E() = DeclareResourceString("UnitTypeExpected1","%s") +let UnitTypeExpected1E() = DeclareResourceString("UnitTypeExpected1","") let UnitTypeExpected2E() = DeclareResourceString("UnitTypeExpected2","%s") let RecursiveUseCheckedAtRuntimeE() = DeclareResourceString("RecursiveUseCheckedAtRuntime","") let LetRecUnsound1E() = DeclareResourceString("LetRecUnsound1","%s") @@ -1182,7 +1182,7 @@ let OutputPhasedErrorR (os:System.Text.StringBuilder) (err:PhasedError) = if perhapsProp then os.Append(UnitTypeExpected2E().Format (NicePrint.stringOfTy denv ty)) |> ignore else - os.Append(UnitTypeExpected1E().Format (NicePrint.stringOfTy denv ty)) |> ignore + os.Append(UnitTypeExpected1E().Format) |> ignore | RecursiveUseCheckedAtRuntime _ -> os.Append(RecursiveUseCheckedAtRuntimeE().Format) |> ignore | LetRecUnsound (_,[v],_) -> diff --git a/src/fsharp/FSStrings.resx b/src/fsharp/FSStrings.resx index f4c45a898f5..f028e00b6f8 100644 --- a/src/fsharp/FSStrings.resx +++ b/src/fsharp/FSStrings.resx @@ -892,7 +892,7 @@ This expression is a function value, i.e. is missing arguments. Its type is {0}. - This expression has a value of type '{0}' that is implicitly ignored. Use the 'ignore' function to discard this value explicitly, e.g. 'expr |> ignore', or bind it to a name to refer to it later, e.g. 'let result = expr'. + The result of this expression is implicitly ignored. Consider using 'ignore' to discard this value explicitly, e.g. 'expr |> ignore', or 'let' to bind the result to a name, e.g. 'let result = expr'. This expression should have type 'unit', but has type '{0}'. If assigning to a property use the syntax 'obj.Prop <- expr'. diff --git a/tests/fsharpqa/Source/Conformance/DeclarationElements/LetBindings/Basic/W_DoBindingsNotUnit01.fs b/tests/fsharpqa/Source/Conformance/DeclarationElements/LetBindings/Basic/W_DoBindingsNotUnit01.fs index f9ffa7970ce..e703b6ac2a4 100644 --- a/tests/fsharpqa/Source/Conformance/DeclarationElements/LetBindings/Basic/W_DoBindingsNotUnit01.fs +++ b/tests/fsharpqa/Source/Conformance/DeclarationElements/LetBindings/Basic/W_DoBindingsNotUnit01.fs @@ -2,7 +2,7 @@ #light // Verify warning when 'do-bindings' do not return unit. -//This expression has a value of type 'int' that is implicitly ignored +//The result of this expression is implicitly ignored let square x = x * x diff --git a/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in01.fs b/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in01.fs index d4d1116810e..72abc807372 100644 --- a/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in01.fs +++ b/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in01.fs @@ -5,7 +5,7 @@ // Eventually, we will deprecated them - and the specs will be updated. // //The value or constructor 'a' is not defined$ -//This expression has a value of type 'bool' that is implicitly ignored\. Use the 'ignore' function to discard this value explicitly, e\.g\. 'expr \|> ignore', or bind it to a name to refer to it later, e\.g\. 'let result = expr'\.$ +//The result of this expression is implicitly ignored\. Consider using 'ignore' to discard this value explicitly, e\.g\. 'expr \|> ignore', or 'let' to bind the result to a name, e\.g\. 'let result = expr'.$ module A = let a = 3 in a + 1 |> ignore;; a > 4;; diff --git a/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in02.fs b/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in02.fs index 9d1abe85d68..b3799eb1539 100644 --- a/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in02.fs +++ b/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in02.fs @@ -4,7 +4,7 @@ // I'm adding these cases to make sure we do not accidentally change the behavior from version to version // Eventually, we will deprecated them - and the specs will be updated. // -//This expression has a value of type 'bool' that is implicitly ignored\. Use the 'ignore' function to discard this value explicitly, e\.g\. 'expr \|> ignore', or bind it to a name to refer to it later, e\.g\. 'let result = expr'\.$ +//The result of this expression is implicitly ignored\. Consider using 'ignore' to discard this value explicitly, e\.g\. 'expr \|> ignore', or 'let' to bind the result to a name, e\.g\. 'let result = expr'.$ // module B = diff --git a/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in03.fs b/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in03.fs index f36c08169f8..e0af19fb87c 100644 --- a/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in03.fs +++ b/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in03.fs @@ -4,7 +4,7 @@ // I'm adding these cases to make sure we do not accidentally change the behavior from version to version // Eventually, we will deprecated them - and the specs will be updated. // -//This expression has a value of type 'bool' that is implicitly ignored\. Use the 'ignore' function to discard this value explicitly, e\.g\. 'expr \|> ignore', or bind it to a name to refer to it later, e\.g\. 'let result = expr'\.$ +//The result of this expression is implicitly ignored\. Consider using 'ignore' to discard this value explicitly, e\.g\. 'expr \|> ignore', or 'let' to bind the result to a name, e\.g\. 'let result = expr'.$ // module C = let a = 3 diff --git a/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in04.fs b/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in04.fs index a56dcd72f94..36e735c458e 100644 --- a/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in04.fs +++ b/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in04.fs @@ -4,7 +4,7 @@ // I'm adding these cases to make sure we do not accidentally change the behavior from version to version // Eventually, we will deprecated them - and the specs will be updated. // -//This expression has a value of type 'bool' that is implicitly ignored\. Use the 'ignore' function to discard this value explicitly, e\.g\. 'expr \|> ignore', or bind it to a name to refer to it later, e\.g\. 'let result = expr'\.$ +//The result of this expression is implicitly ignored\. Consider using 'ignore' to discard this value explicitly, e\.g\. 'expr \|> ignore', or 'let' to bind the result to a name, e\.g\. 'let result = expr'.$ // module D = diff --git a/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in05.fs b/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in05.fs index a6cf5359f82..68dad9c89db 100644 --- a/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in05.fs +++ b/tests/fsharpqa/Source/Conformance/Expressions/BindingExpressions/Binding/in05.fs @@ -5,7 +5,7 @@ // Eventually, we will deprecated them - and the specs will be updated. //The type 'int' does not match the type 'unit'$ //Type mismatch\. Expecting a. ''a -> 'b' .but given a. ''a -> unit' .The type 'int' does not match the type 'unit'$ -//This expression has a value of type 'bool' that is implicitly ignored\. Use the 'ignore' function to discard this value explicitly, e\.g\. 'expr \|> ignore', or bind it to a name to refer to it later, e\.g\. 'let result = expr'\.$ +//The result of this expression is implicitly ignored\. Consider using 'ignore' to discard this value explicitly, e\.g\. 'expr \|> ignore', or 'let' to bind the result to a name, e\.g\. 'let result = expr'.$ module E = let a = 3 in a + 1 |> ignore diff --git a/tests/fsharpqa/Source/Conformance/Expressions/ControlFlowExpressions/TryFinally/W-TryFinallyNotUnit.fs b/tests/fsharpqa/Source/Conformance/Expressions/ControlFlowExpressions/TryFinally/W-TryFinallyNotUnit.fs index dcfad64bdfb..bdb54bf3d7b 100644 --- a/tests/fsharpqa/Source/Conformance/Expressions/ControlFlowExpressions/TryFinally/W-TryFinallyNotUnit.fs +++ b/tests/fsharpqa/Source/Conformance/Expressions/ControlFlowExpressions/TryFinally/W-TryFinallyNotUnit.fs @@ -2,7 +2,7 @@ #light // Verify warning if a finally block does not return 'unit' -//This expression has a value of type 'bool' that is implicitly ignored +//The result of this expression is implicitly ignored let x : int = try diff --git a/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/QueryExpressions/E_WhereRequiresParens01.fs b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/QueryExpressions/E_WhereRequiresParens01.fs index f69b652c4cd..453173b9192 100644 --- a/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/QueryExpressions/E_WhereRequiresParens01.fs +++ b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/QueryExpressions/E_WhereRequiresParens01.fs @@ -1,7 +1,7 @@ // #Conformance #DataExpressions #Query // Where expressions require parenthesis //'where' is not used correctly\. This is a custom operation in this query or computation expression\.$ -//This expression has a value of type 'bool' that is implicitly ignored\. Use the 'ignore' function to discard this value explicitly, e\.g\. 'expr \|> ignore', or bind it to a name to refer to it later, e\.g\. 'let result = expr'\.$ +//The result of this expression is implicitly ignored\. Consider using 'ignore' to discard this value explicitly, e\.g\. 'expr \|> ignore', or 'let' to bind the result to a name, e\.g\. 'let result = expr'.$ let query = query { for i in [1..10] do diff --git a/tests/fsharpqa/Source/Conformance/PatternMatching/Named/E_ActivePatternUnconstrained01.fs b/tests/fsharpqa/Source/Conformance/PatternMatching/Named/E_ActivePatternUnconstrained01.fs index 17ad18262e1..b930cbaba00 100644 --- a/tests/fsharpqa/Source/Conformance/PatternMatching/Named/E_ActivePatternUnconstrained01.fs +++ b/tests/fsharpqa/Source/Conformance/PatternMatching/Named/E_ActivePatternUnconstrained01.fs @@ -2,7 +2,7 @@ // Regression test for FSHARP1.0:5590 // This code used to compile, but fail peverification // Now, it just does not compile anymore telling the user to annotated it a bit. -//This expression has a value of type 'int' that is implicitly ignored\. Use the 'ignore' function to discard this value explicitly, e\.g\. 'expr \|> ignore', or bind it to a name to refer to it later, e\.g\. 'let result = expr'\.$ +//The result of this expression is implicitly ignored\. Consider using 'ignore' to discard this value explicitly, e\.g\. 'expr \|> ignore', or 'let' to bind the result to a name, e\.g\. 'let result = expr'.$ //Active pattern '\|A1\|A2\|A3\|' has a result type containing type variables that are not determined by the input\. The common cause is a when a result case is not mentioned, e\.g\. 'let \(\|A\|B\|\) \(x:int\) = A x'\. This can be fixed with a type constraint, e\.g\. 'let \(\|A\|B\|\) \(x:int\) : Choice = A x'$ let (|A1|A2|A3|) (inp:int) : Choice = printfn "hello" diff --git a/tests/fsharpqa/Source/Diagnostics/General/W_Multiline02.fs b/tests/fsharpqa/Source/Diagnostics/General/W_Multiline02.fs index f6d624f2cc5..b68027a1693 100644 --- a/tests/fsharpqa/Source/Diagnostics/General/W_Multiline02.fs +++ b/tests/fsharpqa/Source/Diagnostics/General/W_Multiline02.fs @@ -1,7 +1,7 @@ // #Regression #Diagnostics // Regression test for FSHARP1.0:3596 // Make sure that error spans correctly across multiple lines -//This expression has a value of type 'int' that is implicitly ignored +//The result of this expression is implicitly ignored #nowarn "988" let f g x = g x diff --git a/tests/fsharpqa/Source/Diagnostics/NONTERM/quoteExpr01.fs b/tests/fsharpqa/Source/Diagnostics/NONTERM/quoteExpr01.fs index a78898e77d7..f6f6443df63 100644 --- a/tests/fsharpqa/Source/Diagnostics/NONTERM/quoteExpr01.fs +++ b/tests/fsharpqa/Source/Diagnostics/NONTERM/quoteExpr01.fs @@ -1,5 +1,5 @@ // #Regression #Diagnostics // Regression test for FSHARP1.0:2391, FSHARP1.0:1479 -//This expression has a value of type 'seq.Quotations\.Var.' that is implicitly ignored +//The result of this expression is implicitly ignored #light "off" <@@ 1 @@>.GetFreeVars() diff --git a/tests/fsharpqa/Source/Diagnostics/async/MissingIgnore.fs b/tests/fsharpqa/Source/Diagnostics/async/MissingIgnore.fs index cefbf104a47..3fe0919320d 100644 --- a/tests/fsharpqa/Source/Diagnostics/async/MissingIgnore.fs +++ b/tests/fsharpqa/Source/Diagnostics/async/MissingIgnore.fs @@ -1,5 +1,5 @@ // #Regression #Diagnostics #Async // Regression tests for FSHARP1.0:4394 -//This expression has a value of type 'int' that is implicitly ignored\. Use the 'ignore' function to discard this value explicitly, e\.g\. 'expr \|> ignore', or bind it to a name to refer to it later, e\.g\. 'let result = expr'\.$ +//The result of this expression is implicitly ignored\. Consider using 'ignore' to discard this value explicitly, e\.g\. 'expr \|> ignore', or 'let' to bind the result to a name, e\.g\. 'let result = expr'.$ async { 1; return 2 } |> ignore diff --git a/tests/fsharpqa/Source/Diagnostics/async/MissingReturnBangForLoop01.fs b/tests/fsharpqa/Source/Diagnostics/async/MissingReturnBangForLoop01.fs index 2e53ebcc6d0..4dd57691e8d 100644 --- a/tests/fsharpqa/Source/Diagnostics/async/MissingReturnBangForLoop01.fs +++ b/tests/fsharpqa/Source/Diagnostics/async/MissingReturnBangForLoop01.fs @@ -1,5 +1,5 @@ // #Regression #Diagnostics #Async // Regression tests for FSHARP1.0:4394 // common mistake: forgetting the return! For a loop -//This expression has a value of type 'Async<'a>' that is implicitly ignored\. Use the 'ignore' function to discard this value explicitly, e\.g\. 'expr \|> ignore', or bind it to a name to refer to it later, e\.g\. 'let result = expr'\.$ +//The result of this expression is implicitly ignored\. Consider using 'ignore' to discard this value explicitly, e\.g\. 'expr \|> ignore', or 'let' to bind the result to a name, e\.g\. 'let result = expr'.$ let rec loop() = async { let x = 1 in loop() } diff --git a/tests/fsharpqa/Source/Diagnostics/async/MissingReturnBangForLoop02.fs b/tests/fsharpqa/Source/Diagnostics/async/MissingReturnBangForLoop02.fs index f5ee4118eec..a9bb89c9dac 100644 --- a/tests/fsharpqa/Source/Diagnostics/async/MissingReturnBangForLoop02.fs +++ b/tests/fsharpqa/Source/Diagnostics/async/MissingReturnBangForLoop02.fs @@ -1,5 +1,5 @@ // #Regression #Diagnostics #Async // Regression tests for FSHARP1.0:4394 // common mistake: forgetting the return! For a loop -//This expression has a value of type 'Async<'a>' that is implicitly ignored\. Use the 'ignore' function to discard this value explicitly, e\.g\. 'expr \|> ignore', or bind it to a name to refer to it later, e\.g\. 'let result = expr'\.$ +//The result of this expression is implicitly ignored\. Consider using 'ignore' to discard this value explicitly, e\.g\. 'expr \|> ignore', or 'let' to bind the result to a name, e\.g\. 'let result = expr'.$ let rec loop() = async { loop() } diff --git a/tests/fsharpqa/Source/Diagnostics/async/MissingReturnBangForLoop03.fs b/tests/fsharpqa/Source/Diagnostics/async/MissingReturnBangForLoop03.fs index 821a452ef65..dfba108aac0 100644 --- a/tests/fsharpqa/Source/Diagnostics/async/MissingReturnBangForLoop03.fs +++ b/tests/fsharpqa/Source/Diagnostics/async/MissingReturnBangForLoop03.fs @@ -1,6 +1,6 @@ // #Regression #Diagnostics #Async // Regression tests for FSHARP1.0:4394 // common mistake: forgetting the return! For a loop -//This expression has a value of type 'Async<'a>' that is implicitly ignored\. Use the 'ignore' function to discard this value explicitly, e\.g\. 'expr \|> ignore', or bind it to a name to refer to it later, e\.g\. 'let result = expr'\.$ +//The result of this expression is implicitly ignored\. Consider using 'ignore' to discard this value explicitly, e\.g\. 'expr \|> ignore', or 'let' to bind the result to a name, e\.g\. 'let result = expr'.$ //This expression was expected to have type. 'Async<'a>' .but here has type. 'unit' let rec loop2() = async.Delay(fun () -> loop2(); ()); diff --git a/tests/fsharpqa/Source/Diagnostics/async/MissingReturnBangForLoop04.fs b/tests/fsharpqa/Source/Diagnostics/async/MissingReturnBangForLoop04.fs index f433fb10b6b..b86efb67132 100644 --- a/tests/fsharpqa/Source/Diagnostics/async/MissingReturnBangForLoop04.fs +++ b/tests/fsharpqa/Source/Diagnostics/async/MissingReturnBangForLoop04.fs @@ -1,7 +1,7 @@ // #Regression #Diagnostics #Async // Regression tests for FSHARP1.0:4394 // common mistake: forgetting the return! For a loop -//This expression has a value of type 'Async<'a>' that is implicitly ignored\. Use the 'ignore' function to discard this value explicitly, e\.g\. 'expr \|> ignore', or bind it to a name to refer to it later, e\.g\. 'let result = expr'\.$ +//The result of this expression is implicitly ignored\. Consider using 'ignore' to discard this value explicitly, e\.g\. 'expr \|> ignore', or 'let' to bind the result to a name, e\.g\. 'let result = expr'.$ //This expression was expected to have type. 'Async<'a>' .but here has type. 'unit' // Note: interestingly, this looks much better if a method call is not used let delay x = async.Delay x diff --git a/tests/fsharpqa/Source/Misc/Parsing02.fs b/tests/fsharpqa/Source/Misc/Parsing02.fs index 67f9859ebef..9a17369e870 100644 --- a/tests/fsharpqa/Source/Misc/Parsing02.fs +++ b/tests/fsharpqa/Source/Misc/Parsing02.fs @@ -1,10 +1,10 @@ // #Regression #Misc // Verify warnings associated with top level expressions getting discarded -//This expression has a value of type '\( \^a -> unit\) \* int' that is implicitly ignored -//This expression has a value of type '\('a \[\] -> unit \[\]\) \* string \[\]' that is implicitly ignored +//The result of this expression is implicitly ignored +//The result of this expression is implicitly ignored -// Note the comma between printf "%A", this results in a tuple expr which probabaly wasn't intended. +// Note the comma between printf "%A", this results in a tuple expr which probably wasn't intended. let arr = [|"Foo"; "Bar"|] printf "%d", arr.Length From 36005579efa22622d33ee85bcef89ba42668990f Mon Sep 17 00:00:00 2001 From: Taylor Wood Date: Tue, 7 Jun 2016 16:23:42 -0500 Subject: [PATCH 047/129] Add test case for unused result warning --- .../fsharpqa/Source/Warnings/WarnIfExpressionResultUnused.fs | 5 +++++ tests/fsharpqa/Source/Warnings/env.lst | 1 + 2 files changed, 6 insertions(+) create mode 100644 tests/fsharpqa/Source/Warnings/WarnIfExpressionResultUnused.fs diff --git a/tests/fsharpqa/Source/Warnings/WarnIfExpressionResultUnused.fs b/tests/fsharpqa/Source/Warnings/WarnIfExpressionResultUnused.fs new file mode 100644 index 00000000000..e43c60b38d9 --- /dev/null +++ b/tests/fsharpqa/Source/Warnings/WarnIfExpressionResultUnused.fs @@ -0,0 +1,5 @@ +// #Warnings +//The result of this expression is implicitly ignored\. Consider using 'ignore' to discard this value explicitly, e\.g\. 'expr \|> ignore', or 'let' to bind the result to a name, e\.g\. 'let result = expr'.$ + +1 + 2 +printfn "%d" 3 diff --git a/tests/fsharpqa/Source/Warnings/env.lst b/tests/fsharpqa/Source/Warnings/env.lst index 89651c646aa..4ccec603e9b 100644 --- a/tests/fsharpqa/Source/Warnings/env.lst +++ b/tests/fsharpqa/Source/Warnings/env.lst @@ -12,3 +12,4 @@ SOURCE=DowncastInsteadOfUpcast.fs # DowncastInsteadOfUpcast.fs SOURCE=RuntimeTypeTestInPattern.fs # RuntimeTypeTestInPattern.fs SOURCE=RuntimeTypeTestInPattern2.fs # RuntimeTypeTestInPattern2.fs + SOURCE=WarnIfExpressionResultUnused.fs # WarnIfExpressionResultUnused.fs From b276c96b5e3e6b0a682847e9e35c3e4fd2423ce7 Mon Sep 17 00:00:00 2001 From: "Avi.Avni" Date: Fri, 10 Jun 2016 16:16:25 +0300 Subject: [PATCH 048/129] add tests --- .../Imported/CallerInfo/CallerMemberName.fs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerMemberName.fs b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerMemberName.fs index ee73b3f795e..9814a5b045d 100644 --- a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerMemberName.fs +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerMemberName.fs @@ -16,6 +16,8 @@ type MyTy() = let typeLetFuncNested () = let nestedFunc () = MyTy.GetCallerMemberName() nestedFunc () + let anonymousLambda = (fun () -> MyTy.GetCallerMemberName()) () + let asyncVal = async { return MyTy.GetCallerMemberName() } |> Async.RunSynchronously do MyTy.Check(MyTy.GetCallerMemberName(), Some(".ctor"), "primary ctor") @@ -45,6 +47,8 @@ type MyTy() = |> List.head MyTy.Check(result, Some("CheckMembers"), "lambda") MyTy.Check(functionVal (), Some("functionVal"), "functionVal") + MyTy.Check(anonymousLambda, Some("anonymousLambda"), "anonymousLambda") + MyTy.Check(asyncVal, Some("asyncVal"), "asyncVal") () static member GetCallerMemberName([] ?memberName : string) = @@ -76,6 +80,13 @@ type Extensions = static member DotNetExtensionMeth(instance : System.DateTime) = MyTy.GetCallerMemberName() +type IMyInterface = + abstract member MyInterfaceMethod : unit -> string option + +[] +type MyAbstractTy() = + abstract MyAbstractMethod : unit -> string option + module Program = type System.String with member __.StringExtensionMeth() = @@ -147,4 +158,11 @@ module Program = MyTy.Check(1 +++ 2 |> snd, Some("op_PlusPlusPlus"), "operator") + let obj = { new IMyInterface with + member this.MyInterfaceMethod() = MyTy.GetCallerMemberName() } + MyTy.Check(obj.MyInterfaceMethod(), Some("MyInterfaceMethod"), "MyInterfaceMethod") + + let obj1 = { new MyAbstractTy() with member x.MyAbstractMethod() = MyTy.GetCallerMemberName() } + MyTy.Check(obj1.MyAbstractMethod(), Some("MyAbstractMethod"), "MyAbstractMethod") + 0 \ No newline at end of file From 87fc720610022412c07d265d345ceb60d427e6ad Mon Sep 17 00:00:00 2001 From: "Avi.Avni" Date: Mon, 13 Jun 2016 19:04:19 +0300 Subject: [PATCH 049/129] change tests from member of class to value of function --- .../Imported/CallerInfo/CallerMemberName.fs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerMemberName.fs b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerMemberName.fs index 9814a5b045d..59c8b98e3ed 100644 --- a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerMemberName.fs +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerMemberName.fs @@ -16,8 +16,6 @@ type MyTy() = let typeLetFuncNested () = let nestedFunc () = MyTy.GetCallerMemberName() nestedFunc () - let anonymousLambda = (fun () -> MyTy.GetCallerMemberName()) () - let asyncVal = async { return MyTy.GetCallerMemberName() } |> Async.RunSynchronously do MyTy.Check(MyTy.GetCallerMemberName(), Some(".ctor"), "primary ctor") @@ -47,8 +45,6 @@ type MyTy() = |> List.head MyTy.Check(result, Some("CheckMembers"), "lambda") MyTy.Check(functionVal (), Some("functionVal"), "functionVal") - MyTy.Check(anonymousLambda, Some("anonymousLambda"), "anonymousLambda") - MyTy.Check(asyncVal, Some("asyncVal"), "asyncVal") () static member GetCallerMemberName([] ?memberName : string) = @@ -165,4 +161,9 @@ module Program = let obj1 = { new MyAbstractTy() with member x.MyAbstractMethod() = MyTy.GetCallerMemberName() } MyTy.Check(obj1.MyAbstractMethod(), Some("MyAbstractMethod"), "MyAbstractMethod") + let asyncVal = async { return MyTy.GetCallerMemberName() } |> Async.RunSynchronously + MyTy.Check(asyncVal, Some("main"), "asyncVal") + + let anonymousLambda = fun () -> MyTy.GetCallerMemberName() + MyTy.Check(anonymousLambda(), Some("main"), "anonymousLambda") 0 \ No newline at end of file From d7064b21afb3f5d0087a14feef3d1a17cb3df57f Mon Sep 17 00:00:00 2001 From: "Avi.Avni" Date: Mon, 13 Jun 2016 19:19:37 +0300 Subject: [PATCH 050/129] add delegate test improve description --- .../Imported/CallerInfo/CallerMemberName.fs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerMemberName.fs b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerMemberName.fs index 59c8b98e3ed..c23e6a0f4ff 100644 --- a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerMemberName.fs +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerMemberName.fs @@ -1,5 +1,6 @@ namespace Test +open System open System.Runtime.CompilerServices open System.Reflection open CSharpLib @@ -156,14 +157,17 @@ module Program = let obj = { new IMyInterface with member this.MyInterfaceMethod() = MyTy.GetCallerMemberName() } - MyTy.Check(obj.MyInterfaceMethod(), Some("MyInterfaceMethod"), "MyInterfaceMethod") + MyTy.Check(obj.MyInterfaceMethod(), Some("MyInterfaceMethod"), "Object expression from interface") let obj1 = { new MyAbstractTy() with member x.MyAbstractMethod() = MyTy.GetCallerMemberName() } - MyTy.Check(obj1.MyAbstractMethod(), Some("MyAbstractMethod"), "MyAbstractMethod") + MyTy.Check(obj1.MyAbstractMethod(), Some("MyAbstractMethod"), "Object expression from abstract type") let asyncVal = async { return MyTy.GetCallerMemberName() } |> Async.RunSynchronously - MyTy.Check(asyncVal, Some("main"), "asyncVal") + MyTy.Check(asyncVal, Some("main"), "Async computation expression value") let anonymousLambda = fun () -> MyTy.GetCallerMemberName() - MyTy.Check(anonymousLambda(), Some("main"), "anonymousLambda") + MyTy.Check(anonymousLambda(), Some("main"), "Anonymous lambda") + + let delegateVal = new Func(fun () -> MyTy.GetCallerMemberName()) + MyTy.Check(delegateVal.Invoke(), Some("main"), "Delegate value") 0 \ No newline at end of file From 37bf5b0c30186ce2fc8a2eadf547c3d6ec6c6e36 Mon Sep 17 00:00:00 2001 From: "Avi.Avni" Date: Mon, 13 Jun 2016 20:20:19 +0300 Subject: [PATCH 051/129] add static do tests --- .../Imported/CallerInfo/CallerMemberName.fs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerMemberName.fs b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerMemberName.fs index c23e6a0f4ff..b9bb974c8bd 100644 --- a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerMemberName.fs +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerMemberName.fs @@ -19,6 +19,8 @@ type MyTy() = nestedFunc () do MyTy.Check(MyTy.GetCallerMemberName(), Some(".ctor"), "primary ctor") + static do + MyTy.Check(MyTy.GetCallerMemberName(), Some(".cctor"), "static ctor") new(i : int) = MyTy.Check(MyTy.GetCallerMemberName(), Some(".ctor"), ".NET ctor") From ba3fee7652c02512872e6e80f4d7c6b6767b15f8 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Wed, 15 Jun 2016 20:28:25 +0100 Subject: [PATCH 052/129] struct unions --- VisualFSharp.sln | 86 +---- src/absil/il.fs | 2 + src/absil/il.fsi | 2 + src/absil/ilprint.fs | 4 +- src/absil/ilwrite.fs | 2 +- src/absil/ilx.fs | 13 +- src/absil/ilx.fsi | 3 +- src/fsharp/AugmentWithHashCompare.fs | 294 ++++++++++-------- src/fsharp/ConstraintSolver.fs | 14 +- src/fsharp/FSComp.txt | 3 +- .../FSharp.Core/DiscrimantedUnionType.fs | 134 +++++++- src/fsharp/IlxGen.fs | 52 +++- src/fsharp/NameResolution.fs | 2 +- src/fsharp/Optimizer.fs | 4 +- src/fsharp/PatternMatchCompilation.fs | 39 ++- src/fsharp/PostInferenceChecks.fs | 25 +- src/fsharp/QuotationTranslator.fs | 3 + src/fsharp/TastOps.fs | 127 +++++--- src/fsharp/TastOps.fsi | 33 +- src/fsharp/TastPickle.fs | 4 + src/fsharp/TypeChecker.fs | 98 +++--- src/fsharp/infos.fs | 2 +- src/fsharp/tast.fs | 37 ++- src/ilx/EraseUnions.fs | 200 ++++++------ src/ilx/EraseUnions.fsi | 21 +- tests/fsharp/typecheck/sigs/neg95.bsl | 6 +- tests/fsharp/typecheck/sigs/neg95.fs | 6 + 27 files changed, 753 insertions(+), 463 deletions(-) diff --git a/VisualFSharp.sln b/VisualFSharp.sln index 6224d843be1..002dbd63f6b 100644 --- a/VisualFSharp.sln +++ b/VisualFSharp.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 -VisualStudioVersion = 14.0.25123.0 +VisualStudioVersion = 14.0.24720.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.Compiler", "src\fsharp\FSharp.Compiler\FSharp.Compiler.fsproj", "{2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}" EndProject @@ -120,7 +120,15 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XMLFile", "vsintegration\It EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VisualFSharpVsix", "vsintegration\VisualFSharpVsix\VisualFSharpVsix.csproj", "{E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{A83A9A70-8C33-4253-BF6F-3AADB509F21C}" + ProjectSection(SolutionItems) = preProject + Performance1.psess = Performance1.psess + EndProjectSection +EndProject Global + GlobalSection(Performance) = preSolution + HasPerformanceSessions = true + EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Debug|x86 = Debug|x86 @@ -130,54 +138,6 @@ Global Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.Debug|x86.ActiveCfg = Debug|Any CPU - {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.Debug|x86.Build.0 = Debug|Any CPU - {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.Proto|Any CPU.ActiveCfg = Proto|Any CPU - {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.Proto|Any CPU.Build.0 = Proto|Any CPU - {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.Proto|x86.ActiveCfg = Proto|Any CPU - {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.Proto|x86.Build.0 = Proto|Any CPU - {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.Release|Any CPU.Build.0 = Release|Any CPU - {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.Release|x86.ActiveCfg = Release|Any CPU - {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.Release|x86.Build.0 = Release|Any CPU - {493D19F9-35A4-4D0B-9B25-CA948823B709}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {493D19F9-35A4-4D0B-9B25-CA948823B709}.Debug|Any CPU.Build.0 = Debug|Any CPU - {493D19F9-35A4-4D0B-9B25-CA948823B709}.Debug|x86.ActiveCfg = Debug|Any CPU - {493D19F9-35A4-4D0B-9B25-CA948823B709}.Debug|x86.Build.0 = Debug|Any CPU - {493D19F9-35A4-4D0B-9B25-CA948823B709}.Proto|Any CPU.ActiveCfg = Proto|Any CPU - {493D19F9-35A4-4D0B-9B25-CA948823B709}.Proto|Any CPU.Build.0 = Proto|Any CPU - {493D19F9-35A4-4D0B-9B25-CA948823B709}.Proto|x86.ActiveCfg = Proto|Any CPU - {493D19F9-35A4-4D0B-9B25-CA948823B709}.Proto|x86.Build.0 = Proto|Any CPU - {493D19F9-35A4-4D0B-9B25-CA948823B709}.Release|Any CPU.ActiveCfg = Release|Any CPU - {493D19F9-35A4-4D0B-9B25-CA948823B709}.Release|Any CPU.Build.0 = Release|Any CPU - {493D19F9-35A4-4D0B-9B25-CA948823B709}.Release|x86.ActiveCfg = Release|Any CPU - {493D19F9-35A4-4D0B-9B25-CA948823B709}.Release|x86.Build.0 = Release|Any CPU - {530DF8CA-7996-407A-B533-D0C2873257AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {530DF8CA-7996-407A-B533-D0C2873257AF}.Debug|Any CPU.Build.0 = Debug|Any CPU - {530DF8CA-7996-407A-B533-D0C2873257AF}.Debug|x86.ActiveCfg = Debug|Any CPU - {530DF8CA-7996-407A-B533-D0C2873257AF}.Debug|x86.Build.0 = Debug|Any CPU - {530DF8CA-7996-407A-B533-D0C2873257AF}.Proto|Any CPU.ActiveCfg = Proto|Any CPU - {530DF8CA-7996-407A-B533-D0C2873257AF}.Proto|Any CPU.Build.0 = Proto|Any CPU - {530DF8CA-7996-407A-B533-D0C2873257AF}.Proto|x86.ActiveCfg = Proto|Any CPU - {530DF8CA-7996-407A-B533-D0C2873257AF}.Proto|x86.Build.0 = Proto|Any CPU - {530DF8CA-7996-407A-B533-D0C2873257AF}.Release|Any CPU.ActiveCfg = Release|Any CPU - {530DF8CA-7996-407A-B533-D0C2873257AF}.Release|Any CPU.Build.0 = Release|Any CPU - {530DF8CA-7996-407A-B533-D0C2873257AF}.Release|x86.ActiveCfg = Release|Any CPU - {530DF8CA-7996-407A-B533-D0C2873257AF}.Release|x86.Build.0 = Release|Any CPU - {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.Debug|Any CPU.Build.0 = Debug|Any CPU - {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.Debug|x86.ActiveCfg = Debug|Any CPU - {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.Debug|x86.Build.0 = Debug|Any CPU - {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.Proto|Any CPU.ActiveCfg = Proto|Any CPU - {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.Proto|Any CPU.Build.0 = Proto|Any CPU - {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.Proto|x86.ActiveCfg = Proto|Any CPU - {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.Proto|x86.Build.0 = Proto|Any CPU - {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.Release|Any CPU.ActiveCfg = Release|Any CPU - {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.Release|Any CPU.Build.0 = Release|Any CPU - {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.Release|x86.ActiveCfg = Release|Any CPU - {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.Release|x86.Build.0 = Release|Any CPU {2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}.Debug|Any CPU.Build.0 = Debug|Any CPU {2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -502,18 +462,6 @@ Global {C94C257C-3C0A-4858-B5D8-D746498D1F08}.Release|Any CPU.Build.0 = Release|Any CPU {C94C257C-3C0A-4858-B5D8-D746498D1F08}.Release|x86.ActiveCfg = Release|Any CPU {C94C257C-3C0A-4858-B5D8-D746498D1F08}.Release|x86.Build.0 = Release|Any CPU - {CB7D20C4-6506-406D-9144-5342C3595F03}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {CB7D20C4-6506-406D-9144-5342C3595F03}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CB7D20C4-6506-406D-9144-5342C3595F03}.Debug|x86.ActiveCfg = Debug|Any CPU - {CB7D20C4-6506-406D-9144-5342C3595F03}.Debug|x86.Build.0 = Debug|Any CPU - {CB7D20C4-6506-406D-9144-5342C3595F03}.Proto|Any CPU.ActiveCfg = Proto|Any CPU - {CB7D20C4-6506-406D-9144-5342C3595F03}.Proto|Any CPU.Build.0 = Proto|Any CPU - {CB7D20C4-6506-406D-9144-5342C3595F03}.Proto|x86.ActiveCfg = Proto|Any CPU - {CB7D20C4-6506-406D-9144-5342C3595F03}.Proto|x86.Build.0 = Proto|Any CPU - {CB7D20C4-6506-406D-9144-5342C3595F03}.Release|Any CPU.ActiveCfg = Release|Any CPU - {CB7D20C4-6506-406D-9144-5342C3595F03}.Release|Any CPU.Build.0 = Release|Any CPU - {CB7D20C4-6506-406D-9144-5342C3595F03}.Release|x86.ActiveCfg = Release|Any CPU - {CB7D20C4-6506-406D-9144-5342C3595F03}.Release|x86.Build.0 = Release|Any CPU {649FA588-F02E-457C-9FCF-87E46407481E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {649FA588-F02E-457C-9FCF-87E46407481E}.Debug|Any CPU.Build.0 = Debug|Any CPU {649FA588-F02E-457C-9FCF-87E46407481E}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -753,14 +701,6 @@ Global {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.Release|Any CPU.Build.0 = Release|Any CPU {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.Release|x86.ActiveCfg = Release|Any CPU {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.Release|x86.Build.0 = Release|Any CPU - {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.VSRelease|x86.Build.0 = VSRelease|Any CPU {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}.Debug|Any CPU.Build.0 = Debug|Any CPU {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -773,14 +713,6 @@ Global {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}.Release|Any CPU.Build.0 = Release|Any CPU {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}.Release|x86.ActiveCfg = Release|Any CPU {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}.Release|x86.Build.0 = Release|Any CPU - {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}.VSRelease|x86.Build.0 = VSRelease|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/absil/il.fs b/src/absil/il.fs index 8287cfb3aa1..5a0cdee0b60 100755 --- a/src/absil/il.fs +++ b/src/absil/il.fs @@ -2063,6 +2063,8 @@ let mkILFormalGenericArgs (gparams:ILGenericParameterDefs) = let mkILFormalBoxedTy tref gparams = mkILBoxedTy tref (mkILFormalGenericArgs gparams) +let mkILFormalNamedTy bx tref gparams = mkILNamedTy bx tref (mkILFormalGenericArgs gparams) + // -------------------------------------------------------------------- // Operations on class etc. defs. // -------------------------------------------------------------------- diff --git a/src/absil/il.fsi b/src/absil/il.fsi index 4a81afa084f..147f5baf987 100644 --- a/src/absil/il.fsi +++ b/src/absil/il.fsi @@ -1676,6 +1676,7 @@ val mkILTySpecRaw: ILTypeRef * ILGenericArgs -> ILTypeSpec /// Make types. val mkILTy: ILBoxity -> ILTypeSpec -> ILType val mkILNamedTy: ILBoxity -> ILTypeRef -> ILGenericArgsList -> ILType +val mkILNamedTyRaw: ILBoxity -> ILTypeRef -> ILGenericArgs -> ILType val mkILBoxedTy: ILTypeRef -> ILGenericArgsList -> ILType val mkILBoxedTyRaw: ILTypeRef -> ILGenericArgs -> ILType val mkILValueTy: ILTypeRef -> ILGenericArgsList -> ILType @@ -1727,6 +1728,7 @@ val mkILCallSig: ILCallingConv * ILType list * ILType -> ILCallingSignature /// Make generalized verions of possibly-generic types, /// e.g. Given the ILTypeDef for List, return the type "List". val mkILFormalBoxedTy: ILTypeRef -> ILGenericParameterDef list -> ILType +val mkILFormalNamedTy: ILBoxity -> ILTypeRef -> ILGenericParameterDef list -> ILType val mkILFormalTyparsRaw: ILTypes -> ILGenericParameterDefs val mkILFormalTypars: ILType list -> ILGenericParameterDefs diff --git a/src/absil/ilprint.fs b/src/absil/ilprint.fs index 819cfdb74ee..b8289f30b0f 100644 --- a/src/absil/ilprint.fs +++ b/src/absil/ilprint.fs @@ -439,12 +439,12 @@ let goutput_alternative_ref env os (alt: IlxUnionAlternative) = output_id os alt.Name; alt.FieldDefs |> Array.toList |> output_parens (output_seq "," (fun os fdef -> goutput_typ env os fdef.Type)) os -let goutput_curef env os (IlxUnionRef(tref,alts,_,_)) = +let goutput_curef env os (IlxUnionRef(_,tref,alts,_,_)) = output_string os " .classunion import "; goutput_tref env os tref; output_parens (output_seq "," (goutput_alternative_ref env)) os (Array.toList alts) -let goutput_cuspec env os (IlxUnionSpec(IlxUnionRef(tref,_,_,_),i)) = +let goutput_cuspec env os (IlxUnionSpec(IlxUnionRef(_,tref,_,_,_),i)) = output_string os "class /* classunion */ "; goutput_tref env os tref; goutput_gactuals env os i diff --git a/src/absil/ilwrite.fs b/src/absil/ilwrite.fs index ac8b23f5b14..282ab07d95a 100644 --- a/src/absil/ilwrite.fs +++ b/src/absil/ilwrite.fs @@ -1261,7 +1261,7 @@ let FindMethodDefIdx cenv mdkey = let (TdKey (tenc2,tname2)) = typeNameOfIdx mdkey2.TypeIdx dprintn ("A method in '"+(String.concat "." (tenc2@[tname2]))+"' had the right name but the wrong signature:") dprintn ("generic arity: "+string mdkey2.GenericArity) - dprintn (sprintf "mdkey2: %A" mdkey2)) + dprintn (sprintf "mdkey2: %+A" mdkey2)) raise MethodDefNotFound diff --git a/src/absil/ilx.fs b/src/absil/ilx.fs index efc5056aac6..d183fe0796b 100644 --- a/src/absil/ilx.fs +++ b/src/absil/ilx.fs @@ -45,16 +45,17 @@ type IlxUnionHasHelpers = | SpecialFSharpOptionHelpers type IlxUnionRef = - | IlxUnionRef of ILTypeRef * IlxUnionAlternative[] * bool * (* hasHelpers: *) IlxUnionHasHelpers + | IlxUnionRef of boxity: ILBoxity * ILTypeRef * IlxUnionAlternative[] * bool * (* hasHelpers: *) IlxUnionHasHelpers type IlxUnionSpec = | IlxUnionSpec of IlxUnionRef * ILGenericArgs - member x.EnclosingType = let (IlxUnionSpec(IlxUnionRef(tref,_,_,_),inst)) = x in mkILBoxedTyRaw tref inst - member x.TypeRef = let (IlxUnionSpec(IlxUnionRef(tref,_,_,_),_)) = x in tref + member x.EnclosingType = let (IlxUnionSpec(IlxUnionRef(bx,tref,_,_,_),inst)) = x in mkILNamedTy bx tref inst + member x.Boxity = let (IlxUnionSpec(IlxUnionRef(bx,_,_,_,_),_)) = x in bx + member x.TypeRef = let (IlxUnionSpec(IlxUnionRef(_,tref,_,_,_),_)) = x in tref member x.GenericArgs = let (IlxUnionSpec(_,inst)) = x in inst - member x.AlternativesArray = let (IlxUnionSpec(IlxUnionRef(_,alts,_,_),_)) = x in alts - member x.IsNullPermitted = let (IlxUnionSpec(IlxUnionRef(_,_,np,_),_)) = x in np - member x.HasHelpers = let (IlxUnionSpec(IlxUnionRef(_,_,_,b),_)) = x in b + member x.AlternativesArray = let (IlxUnionSpec(IlxUnionRef(_,_,alts,_,_),_)) = x in alts + member x.IsNullPermitted = let (IlxUnionSpec(IlxUnionRef(_,_,_,np,_),_)) = x in np + member x.HasHelpers = let (IlxUnionSpec(IlxUnionRef(_,_,_,_,b),_)) = x in b member x.Alternatives = Array.toList x.AlternativesArray member x.Alternative idx = x.AlternativesArray.[idx] member x.FieldDef idx fidx = x.Alternative(idx).FieldDef(fidx) diff --git a/src/absil/ilx.fsi b/src/absil/ilx.fsi index db96d9cdb4c..b7413fbf698 100644 --- a/src/absil/ilx.fsi +++ b/src/absil/ilx.fsi @@ -40,7 +40,7 @@ type IlxUnionHasHelpers = | SpecialFSharpOptionHelpers type IlxUnionRef = - | IlxUnionRef of ILTypeRef * IlxUnionAlternative[] * bool (* cudNullPermitted *) * IlxUnionHasHelpers (* cudHasHelpers *) + | IlxUnionRef of boxity: ILBoxity * ILTypeRef * IlxUnionAlternative[] * bool (* cudNullPermitted *) * IlxUnionHasHelpers (* cudHasHelpers *) type IlxUnionSpec = | IlxUnionSpec of IlxUnionRef * ILGenericArgs @@ -48,6 +48,7 @@ type IlxUnionSpec = member GenericArgs : ILGenericArgs member Alternatives : IlxUnionAlternative list member AlternativesArray : IlxUnionAlternative[] + member Boxity : ILBoxity member TypeRef : ILTypeRef member IsNullPermitted : bool member HasHelpers : IlxUnionHasHelpers diff --git a/src/fsharp/AugmentWithHashCompare.fs b/src/fsharp/AugmentWithHashCompare.fs index 3b4031007c1..842561c857b 100644 --- a/src/fsharp/AugmentWithHashCompare.fs +++ b/src/fsharp/AugmentWithHashCompare.fs @@ -110,29 +110,29 @@ let mkCombineHashGenerators g m exprs accv acce = // Build comparison functions for union, record and exception types. //------------------------------------------------------------------------- +let mkThatAddrLocal g m ty = mkCompGenLocal m "obj" (mkThisTy g ty) + let mkThisVarThatVar g m ty = let thisv,thise = mkThisVar g m ty - let thatv,thate = mkCompGenLocal m "obj" (mkThisTy g ty) - thisv,thatv,thise,thate + let thataddrv,thataddre = mkThatAddrLocal g m ty + thisv,thataddrv,thise,thataddre -let mkThatVarBind g m ty thatv expr = +let mkThatVarBind g m ty thataddrv expr = if isStructTy g ty then let thatv2,_ = mkMutableCompGenLocal m "obj" ty - thatv2,mkCompGenLet m thatv (mkValAddr m (mkLocalValRef thatv2)) expr - else thatv,expr + thatv2,mkCompGenLet m thataddrv (mkValAddr m (mkLocalValRef thatv2)) expr + else thataddrv,expr -let mkThatAddrLocal g m ty = - if isStructTy g ty then - mkMutableCompGenLocal m "objCast" (mkByrefTy g ty) - else - mkCompGenLocal m "objCast" ty - let mkBindThatAddr g m ty thataddrv thatv thate expr = if isStructTy g ty then mkCompGenLet m thataddrv (mkValAddr m (mkLocalValRef thatv)) expr else mkCompGenLet m thataddrv thate expr +let mkDerefThis g m (thisv: Val) thise = + if isByrefTy g thisv.Type then mkAddrGet m (mkLocalValRef thisv) + else thise + let mkCompareTestConjuncts g m exprs = match exprs with | [] -> mkZero g m @@ -186,7 +186,7 @@ let mkRecdCompare g tcref (tycon:Tycon) = let m = tycon.Range let fields = tycon.AllInstanceFieldsAsList let tinst,ty = mkMinimalTy g tcref - let thisv,thatv,thise,thate = mkThisVarThatVar g m ty + let thisv,thataddrv,thise,thataddre = mkThisVarThatVar g m ty let compe = mkILCallGetComparer g m let mkTest (fspec:RecdField) = let fty = fspec.FormalType @@ -195,12 +195,12 @@ let mkRecdCompare g tcref (tycon:Tycon) = mkCallGenericComparisonWithComparerOuter g m fty compe (mkRecdFieldGetViaExprAddr(thise, fref, tinst, m)) - (mkRecdFieldGetViaExprAddr(thate, fref, tinst, m)) + (mkRecdFieldGetViaExprAddr(thataddre, fref, tinst, m)) let expr = mkCompareTestConjuncts g m (List.map mkTest fields) - let expr = if tycon.IsStructOrEnumTycon then expr else mkBindNullComparison g m thise thate expr + let expr = if tycon.IsStructOrEnumTycon then expr else mkBindNullComparison g m thise thataddre expr - let thatv,expr = mkThatVarBind g m ty thatv expr + let thatv,expr = mkThatVarBind g m ty thataddrv expr thisv,thatv, expr @@ -222,7 +222,7 @@ let mkRecdCompareWithComparer g tcref (tycon:Tycon) (_thisv,thise) (_,thate) com (mkRecdFieldGetViaExprAddr(thataddre, fref, tinst, m)) let expr = mkCompareTestConjuncts g m (List.map mkTest fields) - let expr = if tycon.IsStructOrEnumTycon then expr else mkBindNullComparison g m thise thate expr + let expr = if tycon.IsStructOrEnumTycon then expr else mkBindNullComparison g m thise tce expr let expr = mkBindThatAddr g m ty thataddrv tcv tce expr // will be optimized away if not necessary @@ -235,19 +235,19 @@ let mkRecdEquality g tcref (tycon:Tycon) = let m = tycon.Range let fields = tycon.AllInstanceFieldsAsList let tinst,ty = mkMinimalTy g tcref - let thisv,thatv,thise,thate = mkThisVarThatVar g m ty + let thisv,thataddrv,thise,thataddre = mkThisVarThatVar g m ty let mkTest (fspec:RecdField) = let fty = fspec.FormalType let fref = tcref.MakeNestedRecdFieldRef fspec let m = fref.Range mkCallGenericEqualityEROuter g m fty (mkRecdFieldGetViaExprAddr(thise, fref, tinst, m)) - (mkRecdFieldGetViaExprAddr(thate, fref, tinst, m)) + (mkRecdFieldGetViaExprAddr(thataddre, fref, tinst, m)) let expr = mkEqualsTestConjuncts g m (List.map mkTest fields) - let expr = if tycon.IsStructOrEnumTycon then expr else mkBindThatNullEquals g m thise thate expr + let expr = if tycon.IsStructOrEnumTycon then expr else mkBindThatNullEquals g m thise thataddre expr - let thatv,expr = mkThatVarBind g m ty thatv expr + let thatv,expr = mkThatVarBind g m ty thataddrv expr thisv,thatv,expr /// Build the equality implementation for a record type when parameterized by a comparer @@ -288,12 +288,11 @@ let mkExnEquality g exnref (exnc:Tycon) = let expr = mkEqualsTestConjuncts g m (List.mapi mkTest (exnc.AllInstanceFieldsAsList)) let expr = let mbuilder = new MatchBuilder(NoSequencePointAtInvisibleBinding,m ) - let dtree = - TDSwitch(thate, - [ mkCase(Test.IsInst(g.exn_ty,mkAppTy exnref []), - mbuilder.AddResultTarget(expr,SuppressSequencePointAtTarget)) ], - Some(mbuilder.AddResultTarget(mkFalse g m,SuppressSequencePointAtTarget)), - m) + let cases = + [ mkCase(Test.IsInst(g.exn_ty,mkAppTy exnref []), + mbuilder.AddResultTarget(expr,SuppressSequencePointAtTarget)) ] + let dflt = Some(mbuilder.AddResultTarget(mkFalse g m,SuppressSequencePointAtTarget)) + let dtree = TDSwitch(thate,cases,dflt,m) mbuilder.Close(dtree,m,g.bool_ty) let expr = mkBindThatNullEquals g m thise thate expr @@ -313,12 +312,11 @@ let mkExnEqualityWithComparer g exnref (exnc:Tycon) (_thisv,thise) thatobje (tha let expr = mkEqualsTestConjuncts g m (List.mapi mkTest (exnc.AllInstanceFieldsAsList)) let expr = let mbuilder = new MatchBuilder(NoSequencePointAtInvisibleBinding,m ) - let dtree = - TDSwitch(thataddre, - [ mkCase(Test.IsInst(g.exn_ty,mkAppTy exnref []), - mbuilder.AddResultTarget(expr,SuppressSequencePointAtTarget)) ], - Some(mbuilder.AddResultTarget(mkFalse g m,SuppressSequencePointAtTarget)), - m) + let cases = + [ mkCase(Test.IsInst(g.exn_ty,mkAppTy exnref []), + mbuilder.AddResultTarget(expr,SuppressSequencePointAtTarget)) ] + let dflt = mbuilder.AddResultTarget(mkFalse g m,SuppressSequencePointAtTarget) + let dtree = TDSwitch(thate,cases,Some dflt,m) mbuilder.Close(dtree,m,g.bool_ty) let expr = mkBindThatAddr g m g.exn_ty thataddrv thatv thate expr let expr = mkIsInstConditional g m g.exn_ty thatobje thatv expr (mkFalse g m) @@ -330,8 +328,7 @@ let mkUnionCompare g tcref (tycon:Tycon) = let m = tycon.Range let ucases = tycon.UnionCasesAsList let tinst,ty = mkMinimalTy g tcref - let thisv,thise = mkCompGenLocal m "this" ty - let thatv,thate = mkCompGenLocal m "obj" ty + let thisv,thataddrv,thise,thataddre = mkThisVarThatVar g m ty let thistagv,thistage = mkCompGenLocal m "thisTag" g.int_ty let thattagv,thattage = mkCompGenLocal m "thatTag" g.int_ty let compe = mkILCallGetComparer g m @@ -341,30 +338,29 @@ let mkUnionCompare g tcref (tycon:Tycon) = let mkCase ucase = let cref = tcref.MakeNestedUnionCaseRef ucase let m = cref.Range - let thisucv,thisucve = mkCompGenLocal m "thisCast" (mkProvenUnionCaseTy cref tinst) - let thatucv,thatucve = mkCompGenLocal m "objCast" (mkProvenUnionCaseTy cref tinst) - let mkTest j (argty:RecdField) = - mkCallGenericComparisonWithComparerOuter g m argty.FormalType - compe - (mkUnionCaseFieldGetProven(thisucve, cref, tinst, j, m)) - (mkUnionCaseFieldGetProven(thatucve, cref, tinst, j, m)) let rfields = ucase.RecdFields if isNil rfields then None else - Some (mkCase(Test.UnionCase(cref,tinst), - mbuilder.AddResultTarget - (mkCompGenLet m thisucv (mkUnionCaseProof(thise,cref,tinst,m)) - (mkCompGenLet m thatucv (mkUnionCaseProof(thate,cref,tinst,m)) - (mkCompareTestConjuncts g m (List.mapi mkTest rfields))), - SuppressSequencePointAtTarget))) + let mkTest thise thataddre j (argty:RecdField) = + mkCallGenericComparisonWithComparerOuter g m argty.FormalType + compe + (mkUnionCaseFieldGetProvenViaExprAddr(thise, cref, tinst, j, m)) + (mkUnionCaseFieldGetProvenViaExprAddr(thataddre, cref, tinst, j, m)) + let test = + if cref.Tycon.IsStructOrEnumTycon then + mkCompareTestConjuncts g m (List.mapi (mkTest thise thataddre) rfields) + else + let thisucv,thisucve = mkCompGenLocal m "thisCast" (mkProvenUnionCaseTy cref tinst) + let thatucv,thatucve = mkCompGenLocal m "objCast" (mkProvenUnionCaseTy cref tinst) + mkCompGenLet m thisucv (mkUnionCaseProof (thise,cref,tinst,m)) + (mkCompGenLet m thatucv (mkUnionCaseProof (thataddre,cref,tinst,m)) + (mkCompareTestConjuncts g m (List.mapi (mkTest thisucve thatucve) rfields))) + Some (mkCase(Test.UnionCase(cref,tinst),mbuilder.AddResultTarget(test,SuppressSequencePointAtTarget))) let nullary,nonNullary = List.partition isNone (List.map mkCase ucases) if isNil nonNullary then mkZero g m else - let dtree = - TDSwitch(thise, - (nonNullary |> List.map (function (Some c) -> c | None -> failwith "mkUnionCompare")), - (if isNil nullary then None - else Some (mbuilder.AddResultTarget(mkZero g m,SuppressSequencePointAtTarget))), - m) + let cases = nonNullary |> List.map (function (Some c) -> c | None -> failwith "mkUnionCompare") + let dflt = if isNil nullary then None else Some (mbuilder.AddResultTarget(mkZero g m,SuppressSequencePointAtTarget)) + let dtree = TDSwitch(thise, cases, dflt,m) mbuilder.Close(dtree,m,g.int_ty) let expr = @@ -375,53 +371,56 @@ let mkUnionCompare g tcref (tycon:Tycon) = expr (mkAsmExpr ([ IL.AI_sub ],[], [thistage; thattage],[g.int_ty],m))in mkCompGenLet m thistagv - (mkUnionCaseTagGet (thise,tcref,tinst,m)) + (mkUnionCaseTagGetViaExprAddr (thise,tcref,tinst,m)) (mkCompGenLet m thattagv - (mkUnionCaseTagGet (thate,tcref,tinst,m)) + (mkUnionCaseTagGetViaExprAddr (thataddre,tcref,tinst,m)) tagsEqTested) - let expr = mkBindNullComparison g m thise thate expr - thisv,thatv, expr + let expr = if tycon.IsStructOrEnumTycon then expr else mkBindNullComparison g m thise thataddre expr + thisv,thataddrv, expr /// Build the comparison implementation for a union type when parameterized by a comparer -let mkUnionCompareWithComparer g tcref (tycon:Tycon) (_thisv,thise) (thatv,thate) compe = +let mkUnionCompareWithComparer g tcref (tycon:Tycon) (_thisv,thise) (_thatv,thate) compe = let m = tycon.Range let ucases = tycon.UnionCasesAsList let tinst,ty = mkMinimalTy g tcref let thistagv,thistage = mkCompGenLocal m "thisTag" g.int_ty let thattagv,thattage = mkCompGenLocal m "thatTag" g.int_ty let thataddrv,thataddre = mkThatAddrLocal g m ty + let tcv,tce = mkCompGenLocal m "objTemp" ty // let tcv = thate let expr = let mbuilder = new MatchBuilder(NoSequencePointAtInvisibleBinding,m ) let mkCase ucase = let cref = tcref.MakeNestedUnionCaseRef ucase let m = cref.Range - let thisucv,thisucve = mkCompGenLocal m "thisCastu" (mkProvenUnionCaseTy cref tinst) - let thatucv,thatucve = mkCompGenLocal m "thatCastu" (mkProvenUnionCaseTy cref tinst) - let mkTest j (argty:RecdField) = - mkCallGenericComparisonWithComparerOuter g m argty.FormalType - compe - (mkUnionCaseFieldGetProven(thisucve, cref, tinst, j, m)) - (mkUnionCaseFieldGetProven(thatucve, cref, tinst, j, m)) let rfields = ucase.RecdFields if isNil rfields then None else - Some (mkCase(Test.UnionCase(cref,tinst), - mbuilder.AddResultTarget - (mkCompGenLet m thisucv (mkUnionCaseProof(thise,cref,tinst,m)) - (mkCompGenLet m thatucv (mkUnionCaseProof(thataddre,cref,tinst,m)) - (mkCompareTestConjuncts g m (List.mapi mkTest rfields))), - SuppressSequencePointAtTarget))) + + let mkTest thise thataddre j (argty:RecdField) = + mkCallGenericComparisonWithComparerOuter g m argty.FormalType + compe + (mkUnionCaseFieldGetProvenViaExprAddr(thise, cref, tinst, j, m)) + (mkUnionCaseFieldGetProvenViaExprAddr(thataddre, cref, tinst, j, m)) + + let test = + if cref.Tycon.IsStructOrEnumTycon then + mkCompareTestConjuncts g m (List.mapi (mkTest thise thataddre) rfields) + else + let thisucv,thisucve = mkCompGenLocal m "thisCastu" (mkProvenUnionCaseTy cref tinst) + let thatucv,thatucve = mkCompGenLocal m "thatCastu" (mkProvenUnionCaseTy cref tinst) + mkCompGenLet m thisucv (mkUnionCaseProof (thise,cref,tinst,m)) + (mkCompGenLet m thatucv (mkUnionCaseProof (thataddre,cref,tinst,m)) + (mkCompareTestConjuncts g m (List.mapi (mkTest thisucve thatucve) rfields))) + + Some (mkCase(Test.UnionCase(cref,tinst),mbuilder.AddResultTarget(test,SuppressSequencePointAtTarget))) let nullary,nonNullary = List.partition isNone (List.map mkCase ucases) if isNil nonNullary then mkZero g m else - let dtree = - TDSwitch(thise, - (nonNullary |> List.map (function (Some c) -> c | None -> failwith "mkUnionCompare")), - (if isNil nullary then None - else Some (mbuilder.AddResultTarget(mkZero g m,SuppressSequencePointAtTarget))), - m) + let cases = nonNullary |> List.map (function (Some c) -> c | None -> failwith "mkUnionCompare") + let dflt = if isNil nullary then None else Some (mbuilder.AddResultTarget(mkZero g m,SuppressSequencePointAtTarget)) + let dtree = TDSwitch(thise, cases, dflt,m) mbuilder.Close(dtree,m,g.int_ty) let expr = @@ -432,13 +431,15 @@ let mkUnionCompareWithComparer g tcref (tycon:Tycon) (_thisv,thise) (thatv,thate expr (mkAsmExpr ([ IL.AI_sub ],[], [thistage; thattage],[g.int_ty],m))in mkCompGenLet m thistagv - (mkUnionCaseTagGet (thise,tcref,tinst,m)) + (mkUnionCaseTagGetViaExprAddr (thise,tcref,tinst,m)) (mkCompGenLet m thattagv - (mkUnionCaseTagGet (thataddre,tcref,tinst,m)) + (mkUnionCaseTagGetViaExprAddr (thataddre,tcref,tinst,m)) tagsEqTested) - let expr = mkBindNullComparison g m thise thate expr - let expr = mkBindThatAddr g m ty thataddrv thatv thate expr + let expr = if tycon.IsStructOrEnumTycon then expr else mkBindNullComparison g m thise tce expr + let expr = mkBindThatAddr g m ty thataddrv tcv tce expr + // will be optimized away if not necessary + let expr = mkCompGenLet m tcv thate expr expr @@ -447,8 +448,7 @@ let mkUnionEquality g tcref (tycon:Tycon) = let m = tycon.Range let ucases = tycon.UnionCasesAsList let tinst,ty = mkMinimalTy g tcref - let thisv,thise = mkCompGenLocal m "this" ty - let thatv,thate = mkCompGenLocal m "obj" ty + let thisv,thataddrv,thise,thataddre = mkThisVarThatVar g m ty let thistagv,thistage = mkCompGenLocal m "thisTag" g.int_ty let thattagv,thattage = mkCompGenLocal m "thatTag" g.int_ty @@ -457,27 +457,31 @@ let mkUnionEquality g tcref (tycon:Tycon) = let mkCase ucase = let cref = tcref.MakeNestedUnionCaseRef ucase let m = cref.Range - let thisucv,thisucve = mkCompGenLocal m "thisCast" (mkProvenUnionCaseTy cref tinst) - let thatucv,thatucve = mkCompGenLocal m "objCast" (mkProvenUnionCaseTy cref tinst) - let mkTest j (argty:RecdField) = - mkCallGenericEqualityEROuter g m argty.FormalType - (mkUnionCaseFieldGetProven(thisucve, cref, tinst, j, m)) - (mkUnionCaseFieldGetProven(thatucve, cref, tinst, j, m)) let rfields = ucase.RecdFields if isNil rfields then None else - Some (mkCase(Test.UnionCase(cref,tinst), - mbuilder.AddResultTarget - (mkCompGenLet m thisucv (mkUnionCaseProof(thise,cref,tinst,m)) - (mkCompGenLet m thatucv (mkUnionCaseProof(thate,cref,tinst,m)) - (mkEqualsTestConjuncts g m (List.mapi mkTest rfields))), - SuppressSequencePointAtTarget))) + + let mkTest thise thataddre j (argty:RecdField) = + mkCallGenericEqualityEROuter g m argty.FormalType + (mkUnionCaseFieldGetProvenViaExprAddr(thise, cref, tinst, j, m)) + (mkUnionCaseFieldGetProvenViaExprAddr(thataddre, cref, tinst, j, m)) + + let test = + if cref.Tycon.IsStructOrEnumTycon then + mkEqualsTestConjuncts g m (List.mapi (mkTest thise thataddre) rfields) + else + let thisucv,thisucve = mkCompGenLocal m "thisCast" (mkProvenUnionCaseTy cref tinst) + let thatucv,thatucve = mkCompGenLocal m "objCast" (mkProvenUnionCaseTy cref tinst) + mkCompGenLet m thisucv (mkUnionCaseProof (thise,cref,tinst,m)) + (mkCompGenLet m thatucv (mkUnionCaseProof (thataddre,cref,tinst,m)) + (mkEqualsTestConjuncts g m (List.mapi (mkTest thisucve thatucve) rfields))) + + Some (mkCase(Test.UnionCase(cref,tinst), mbuilder.AddResultTarget(test, SuppressSequencePointAtTarget))) let nullary,nonNullary = List.partition isNone (List.map mkCase ucases) if isNil nonNullary then mkTrue g m else - let dtree = - TDSwitch(thise,List.map (function (Some c) -> c | None -> failwith "mkUnionEquality") nonNullary, - (if isNil nullary then None else Some (mbuilder.AddResultTarget(mkTrue g m,SuppressSequencePointAtTarget))), - m) + let cases = List.map (function (Some c) -> c | None -> failwith "mkUnionEquality") nonNullary + let dflt = (if isNil nullary then None else Some (mbuilder.AddResultTarget(mkTrue g m,SuppressSequencePointAtTarget))) + let dtree = TDSwitch(thise, cases, dflt, m) mbuilder.Close(dtree,m,g.bool_ty) let expr = @@ -489,13 +493,14 @@ let mkUnionEquality g tcref (tycon:Tycon) = (mkFalse g m) mkCompGenLet m thistagv - (mkUnionCaseTagGet (thise,tcref,tinst,m)) + (mkUnionCaseTagGetViaExprAddr (thise,tcref,tinst,m)) (mkCompGenLet m thattagv - (mkUnionCaseTagGet (thate,tcref,tinst,m)) + (mkUnionCaseTagGetViaExprAddr (thataddre,tcref,tinst,m)) tagsEqTested) - let expr = mkBindThatNullEquals g m thise thate expr - thisv,thatv, expr + let thatv,expr = mkThatVarBind g m ty thataddrv expr + let expr = if tycon.IsStructOrEnumTycon then expr else mkBindThatNullEquals g m thise thataddre expr + thisv,thatv,expr /// Build the equality implementation for a union type when parameterized by a comparer @@ -512,28 +517,34 @@ let mkUnionEqualityWithComparer g tcref (tycon:Tycon) (_thisv,thise) thatobje (t let mkCase ucase = let cref = tcref.MakeNestedUnionCaseRef ucase let m = cref.Range - let thisucv,thisucve = mkCompGenLocal m "thisCastu" (mkProvenUnionCaseTy cref tinst) - let thatucv,thatucve = mkCompGenLocal m "thatCastu" (mkProvenUnionCaseTy cref tinst) - let mkTest j (argty:RecdField) = - mkCallGenericEqualityWithComparerOuter g m argty.FormalType - compe - (mkUnionCaseFieldGetProven(thisucve, cref, tinst, j, m)) - (mkUnionCaseFieldGetProven(thatucve, cref, tinst, j, m)) + let rfields = ucase.RecdFields if isNil rfields then None else - Some (mkCase(Test.UnionCase(cref,tinst), - mbuilder.AddResultTarget - (mkCompGenLet m thisucv (mkUnionCaseProof(thise,cref,tinst,m)) - (mkCompGenLet m thatucv (mkUnionCaseProof(thataddre,cref,tinst,m)) - (mkEqualsTestConjuncts g m (List.mapi mkTest rfields))), - SuppressSequencePointAtTarget))) + + let mkTest thise thataddre j (argty:RecdField) = + mkCallGenericEqualityWithComparerOuter g m argty.FormalType + compe + (mkUnionCaseFieldGetProvenViaExprAddr(thise, cref, tinst, j, m)) + (mkUnionCaseFieldGetProvenViaExprAddr(thataddre, cref, tinst, j, m)) + + let test = + if cref.Tycon.IsStructOrEnumTycon then + mkEqualsTestConjuncts g m (List.mapi (mkTest thise thataddre) rfields) + else + let thisucv,thisucve = mkCompGenLocal m "thisCastu" (mkProvenUnionCaseTy cref tinst) + let thatucv,thatucve = mkCompGenLocal m "thatCastu" (mkProvenUnionCaseTy cref tinst) + + mkCompGenLet m thisucv (mkUnionCaseProof (thise,cref,tinst,m)) + (mkCompGenLet m thatucv (mkUnionCaseProof (thataddre,cref,tinst,m)) + (mkEqualsTestConjuncts g m (List.mapi (mkTest thisucve thatucve) rfields))) + + Some (mkCase(Test.UnionCase(cref,tinst), mbuilder.AddResultTarget (test, SuppressSequencePointAtTarget))) let nullary,nonNullary = List.partition isNone (List.map mkCase ucases) if isNil nonNullary then mkTrue g m else - let dtree = - TDSwitch(thise,List.map (function (Some c) -> c | None -> failwith "mkUnionEquality") nonNullary, - (if isNil nullary then None else Some (mbuilder.AddResultTarget(mkTrue g m,SuppressSequencePointAtTarget))), - m) + let cases = List.map (function (Some c) -> c | None -> failwith "mkUnionEquality") nonNullary + let dflt = if isNil nullary then None else Some (mbuilder.AddResultTarget(mkTrue g m,SuppressSequencePointAtTarget)) + let dtree = TDSwitch(thise, cases, dflt, m) mbuilder.Close(dtree,m,g.bool_ty) let expr = @@ -545,9 +556,9 @@ let mkUnionEqualityWithComparer g tcref (tycon:Tycon) (_thisv,thise) thatobje (t (mkFalse g m) mkCompGenLet m thistagv - (mkUnionCaseTagGet (thise,tcref,tinst,m)) + (mkUnionCaseTagGetViaExprAddr (thise,tcref,tinst,m)) (mkCompGenLet m thattagv - (mkUnionCaseTagGet (thataddre,tcref,tinst,m)) + (mkUnionCaseTagGetViaExprAddr (thataddre,tcref,tinst,m)) tagsEqTested) let expr = mkBindThatAddr g m ty thataddrv thatv thate expr let expr = mkIsInstConditional g m ty thatobje thatv expr (mkFalse g m) @@ -605,25 +616,32 @@ let mkUnionHashWithComparer g tcref (tycon:Tycon) compe = let mbuilder = new MatchBuilder(NoSequencePointAtInvisibleBinding,m ) let accv,acce = mkMutableCompGenLocal m "i" g.int_ty let mkCase i ucase1 = - let c1ref = tcref.MakeNestedUnionCaseRef ucase1 - let ucv,ucve = mkCompGenLocal m "unionCase" (mkProvenUnionCaseTy c1ref tinst) - let m = c1ref.Range - let mkHash j (rfield:RecdField) = - let fty = rfield.FormalType - let e = mkUnionCaseFieldGetProven(ucve, c1ref, tinst, j, m) - mkCallGenericHashWithComparerOuter g m fty compe e - mkCase(Test.UnionCase(c1ref,tinst), - mbuilder.AddResultTarget - (mkCompGenLet m ucv - (mkUnionCaseProof(thise,c1ref,tinst,m)) + let c1ref = tcref.MakeNestedUnionCaseRef ucase1 + let m = c1ref.Range + let mkHash thise j (rfield:RecdField) = + let fty = rfield.FormalType + let e = mkUnionCaseFieldGetProvenViaExprAddr(thise, c1ref, tinst, j, m) + mkCallGenericHashWithComparerOuter g m fty compe e + + let test = + if tycon.IsStructOrEnumTycon then + mkCompGenSequential m + (mkValSet m (mkLocalValRef accv) (mkInt g m i)) + (mkCombineHashGenerators g m (List.mapi (mkHash thise) ucase1.RecdFields) (mkLocalValRef accv) acce) + else + let ucv,ucve = mkCompGenLocal m "unionCase" (mkProvenUnionCaseTy c1ref tinst) + mkCompGenLet m ucv + (mkUnionCaseProof (thise,c1ref,tinst,m)) (mkCompGenSequential m - (mkValSet m (mkLocalValRef accv) (mkInt g m i)) - (mkCombineHashGenerators g m (List.mapi mkHash ucase1.RecdFields) (mkLocalValRef accv) acce)), - SuppressSequencePointAtTarget)) - let dtree = TDSwitch(thise,List.mapi mkCase ucases, None,m) + (mkValSet m (mkLocalValRef accv) (mkInt g m i)) + (mkCombineHashGenerators g m (List.mapi (mkHash ucve) ucase1.RecdFields) (mkLocalValRef accv) acce)) + + mkCase(Test.UnionCase(c1ref,tinst),mbuilder.AddResultTarget(test,SuppressSequencePointAtTarget)) + + let dtree = TDSwitch(thise, List.mapi mkCase ucases, None,m) let stmt = mbuilder.Close(dtree,m,g.int_ty) let expr = mkCompGenLet m accv (mkZero g m) stmt - let expr = mkBindNullHash g m thise expr + let expr = if tycon.IsStructOrEnumTycon then expr else mkBindNullHash g m thise expr thisv,expr diff --git a/src/fsharp/ConstraintSolver.fs b/src/fsharp/ConstraintSolver.fs index fbab553659d..3800e29755b 100644 --- a/src/fsharp/ConstraintSolver.fs +++ b/src/fsharp/ConstraintSolver.fs @@ -2575,11 +2575,21 @@ let CodegenWitnessThatTypSupportsTraitConstraint tcVal g amap m (traitInfo:Trait | true, true, 1 -> Some (mkStaticRecdFieldSet (rfref, tinst, argExprs.[0], m)) | true, false, 2 -> - Some (mkRecdFieldSet g (argExprs.[0], rfref, tinst, argExprs.[1], m)) + // If we resolve to an instance field on a struct and we haven't yet taken + // the address of the object then go do that + if rfref.Tycon.IsStructOrEnumTycon && not (isByrefTy g (tyOfExpr g argExprs.[0])) then + let h = List.head argExprs + let wrap,h' = mkExprAddrOfExpr g true false DefinitelyMutates h None m + Some (wrap (mkRecdFieldSetViaExprAddr (h', rfref, tinst, argExprs.[1], m))) + else + Some (mkRecdFieldSetViaExprAddr (argExprs.[0], rfref, tinst, argExprs.[1], m)) | false, true, 0 -> Some (mkStaticRecdFieldGet (rfref, tinst, m)) | false, false, 1 -> - Some (mkRecdFieldGet g (argExprs.[0], rfref, tinst, m)) + if rfref.Tycon.IsStructOrEnumTycon && isByrefTy g (tyOfExpr g argExprs.[0]) then + Some (mkRecdFieldGetViaExprAddr (argExprs.[0], rfref, tinst, m)) + else + Some (mkRecdFieldGet g (argExprs.[0], rfref, tinst, m)) | _ -> None ResultD res | Choice3Of4 expr -> ResultD (Some (MakeApplicationAndBetaReduce g (expr, tyOfExpr g expr, [], argExprs, m))) diff --git a/src/fsharp/FSComp.txt b/src/fsharp/FSComp.txt index 28b15426e03..c52663bd402 100644 --- a/src/fsharp/FSComp.txt +++ b/src/fsharp/FSComp.txt @@ -1301,4 +1301,5 @@ estApplyStaticArgumentsForMethodNotImplemented,"A type provider implemented GetS 3196,fsharpCoreNotFoundToBeCopied,"Cannot find FSharp.Core.dll in compiler's directory" 3197,etMissingStaticArgumentsToMethod,"This provided method requires static parameters" 3198,considerUpcast,"The conversion from %s to %s is a compile-time safe upcast, not a downcast. Consider using 'upcast' instead of 'downcast'." -3198,considerUpcastOperator,"The conversion from %s to %s is a compile-time safe upcast, not a downcast. Consider using the :> (upcast) operator instead of the :?> (downcast) operator." \ No newline at end of file +3198,considerUpcastOperator,"The conversion from %s to %s is a compile-time safe upcast, not a downcast. Consider using the :> (upcast) operator instead of the :?> (downcast) operator." +3199,tcStructUnionMultiCase,"A union type which is a struct must have only one case." \ No newline at end of file diff --git a/src/fsharp/FSharp.Core.Unittests/FSharp.Core/DiscrimantedUnionType.fs b/src/fsharp/FSharp.Core.Unittests/FSharp.Core/DiscrimantedUnionType.fs index 42f038b67bc..52ea6fbf388 100644 --- a/src/fsharp/FSharp.Core.Unittests/FSharp.Core/DiscrimantedUnionType.fs +++ b/src/fsharp/FSharp.Core.Unittests/FSharp.Core/DiscrimantedUnionType.fs @@ -1,10 +1,25 @@ // Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -namespace FSharp.Core.Unittests.FSharp_Core.Microsoft_FSharp_Core +module FSharp.Core.Unittests.FSharp_Core.Microsoft_FSharp_Core.DiscriminatedUnionTypes open System open System.Numerics +open System.Reflection +open System.Runtime.InteropServices open FSharp.Core.Unittests.LibraryTestFx open NUnit.Framework +open FsCheck +open FsCheck.PropOperators + +#if FX_RESHAPED_REFLECTION +open FSharp.Reflection.FSharpReflectionExtensions + +[] +module PrimReflectionAdapters = + + type System.Type with + member this.IsValueType = this.GetTypeInfo().IsValueType +#endif + type EnumUnion = | A @@ -95,4 +110,119 @@ type UseUnionsWithData() = | _ -> Assert.Fail() match a2 with | Alpha x when x = 2 -> () - | _ -> Assert.Fail() \ No newline at end of file + | _ -> Assert.Fail() + +[] +type StructUnion = SU of C : int * D : int + +let private hasAttribute<'T,'Attr>() = + typeof<'T>.GetTypeInfo().GetCustomAttributes() |> Seq.exists (fun x -> x.GetType() = typeof<'Attr>) + + +let [] ``struct unions hold [] metadata`` () = + Assert.IsTrue (hasAttribute()) + + +let [] ``struct unions are comparable`` () = + Check.QuickThrowOnFailure <| + fun (i1:int) (i2:int) -> + i1 <> i2 ==> + let sr1 = SU (i1, i2) + let sr2 = SU (i1, i2) + let sr3 = SU (i2, i1) + (sr1 = sr2) |@ "sr1 = sr2" .&. + (sr1 <> sr3) |@ "sr1 <> sr3" .&. + (sr1.Equals sr2) |@ "sr1.Equals sr2" + + +let [] ``struct unions support pattern matching`` () = + Check.QuickThrowOnFailure <| + fun (i1:int) (i2:int) -> + let sr1 = SU(i1, i2) + (match sr1 with + | SU(c,d) when c = i1 && d = i2 -> true + | _ -> false) + |@ "with pattern match on struct union" .&. + (sr1 |> function + | SU(c,d) when c = i1 && d = i2 -> true + | _ -> false) + |@ "function pattern match on struct union" + + +let [] ``struct unions support let binds using `` () = + Check.QuickThrowOnFailure <| + fun (i1:int) (i2:int) -> + let sr1 = SU(i1,i2) + let (SU (c1,d2)) as sr2 = sr1 + (sr1 = sr2) |@ "sr1 = sr2" .&. + (c1 = i1 && d2 = i2) |@ "c1 = i1 && d2 = i2" + + +let [] ``struct unions support function argument bindings`` () = + Check.QuickThrowOnFailure <| + fun (i1:int) (i2:int) -> + let sr1 = SU(i1,i2) + let test sr1 (SU (c1,d2) as sr2) = + sr1 = sr2 && c1 = i1 && d2 = i2 + test sr1 sr1 + + + +[] +[] +type ComparisonStructUnion = + | SU2 of int * int + member x.C1 = (match x with SU2(a,b) -> a) + member x.C2 = (match x with SU2(a,b) -> b) + override self.Equals other = + match other with + | :? ComparisonStructUnion as o -> (self.C1 + self.C2) = (o.C1 + o.C2) + | _ -> false + + override self.GetHashCode() = hash self + interface IComparable with + member self.CompareTo other = + match other with + | :? ComparisonStructUnion as o -> compare (self.C1 + self.C2) (o.C1 + o.C2) + | _ -> invalidArg "other" "cannot compare values of different types" + + +[] +let ``struct unions support []`` () = + Check.QuickThrowOnFailure <| + fun (i1:int) (i2:int) -> + let sr1 = SU2(i1,i2) + let sr2 = SU2(i1,i2) + (sr1.Equals sr2) + + +[] +let ``struct unions support []`` () = + Check.QuickThrowOnFailure <| + fun (i1:int) (i2:int) (k1:int) (k2:int) -> + let sr1 = SU2(i1,i2) + let sr2 = SU2(k1,k2) + if sr1 > sr2 then compare sr1 sr2 = 1 + elif sr1 < sr2 then compare sr1 sr2 = -1 + elif sr1 = sr2 then compare sr1 sr2 = 0 + else false + + +[] +let ``struct unions hold [] [] metadata`` () = + Assert.IsTrue (hasAttribute()) + Assert.IsTrue (hasAttribute()) + + +[] +[] +type NoComparisonStructUnion = + | SU3 of int * int + + + +[] +let ``struct unions hold [] [] metadata`` () = + Assert.IsTrue (hasAttribute()) + Assert.IsTrue (hasAttribute()) + diff --git a/src/fsharp/IlxGen.fs b/src/fsharp/IlxGen.fs index e7f357eb825..55ee5241a28 100644 --- a/src/fsharp/IlxGen.fs +++ b/src/fsharp/IlxGen.fs @@ -473,7 +473,8 @@ and GenUnionRef amap m g (tcref: TyconRef) = altFields=GenUnionCaseRef amap m g tyenvinner i cspec.RecdFieldsArray }) let nullPermitted = IsUnionTypeWithNullAsTrueValue g tycon let hasHelpers = ComputeUnionHasHelpers g tcref - IlxUnionRef(tref,alternatives,nullPermitted,hasHelpers)) + let boxity = (if tcref.IsStructOrEnumTycon then ILBoxity.AsValue else ILBoxity.AsObject) + IlxUnionRef(boxity, tref,alternatives,nullPermitted,hasHelpers)) and ComputeUnionHasHelpers g (tcref : TyconRef) = if tyconRefEq g tcref g.unit_tcr_canon then NoHelpers @@ -1751,6 +1752,8 @@ let rec GenExpr cenv (cgbuf:CodeGenBuffer) eenv sp expr sequel = GenGetExnField cenv cgbuf eenv (e,ecref,n,m) sequel | TOp.UnionCaseFieldGet(ucref,n),[e],_ -> GenGetUnionCaseField cenv cgbuf eenv (e,ucref,tyargs,n,m) sequel + | TOp.UnionCaseFieldGetAddr(ucref,n),[e],_ -> + GenGetUnionCaseFieldAddr cenv cgbuf eenv (e,ucref,tyargs,n,m) sequel | TOp.UnionCaseTagGet ucref,[e],_ -> GenGetUnionCaseTag cenv cgbuf eenv (e,ucref,tyargs,m) sequel | TOp.UnionCaseProof ucref,[e],_ -> @@ -2181,12 +2184,13 @@ and GenUnionCaseProof cenv cgbuf eenv (e,ucref,tyargs,m) sequel = GenExpr cenv cgbuf eenv SPSuppress e Continue; let cuspec,idx = GenUnionCaseSpec cenv.amap m cenv.g eenv.tyenv ucref tyargs let fty = EraseUnions.GetILTypeForAlternative cuspec idx - EraseUnions.emitCastData cenv.g.ilg (UnionCodeGen cgbuf) (false,cuspec,idx) + let avoidHelpers = entityRefInThisAssembly cenv.g.compilingFslib ucref.TyconRef + EraseUnions.emitCastData cenv.g.ilg (UnionCodeGen cgbuf) (false,avoidHelpers,cuspec,idx) CG.EmitInstrs cgbuf (pop 1) (Push [fty]) [ ] // push/pop to match the line above GenSequel cenv eenv.cloc cgbuf sequel and GenGetUnionCaseField cenv cgbuf eenv (e,ucref,tyargs,n,m) sequel = - assert (isProvenUnionCaseTy (tyOfExpr cenv.g e)); + assert (ucref.Tycon.IsStructOrEnumTycon || isProvenUnionCaseTy (tyOfExpr cenv.g e)); GenExpr cenv cgbuf eenv SPSuppress e Continue; let cuspec,idx = GenUnionCaseSpec cenv.amap m cenv.g eenv.tyenv ucref tyargs @@ -2195,6 +2199,16 @@ and GenGetUnionCaseField cenv cgbuf eenv (e,ucref,tyargs,n,m) sequel = CG.EmitInstrs cgbuf (pop 1) (Push [fty]) (EraseUnions.mkLdData (avoidHelpers, cuspec, idx, n)); GenSequel cenv eenv.cloc cgbuf sequel +and GenGetUnionCaseFieldAddr cenv cgbuf eenv (e,ucref,tyargs,n,m) sequel = + assert (ucref.Tycon.IsStructOrEnumTycon || isProvenUnionCaseTy (tyOfExpr cenv.g e)); + + GenExpr cenv cgbuf eenv SPSuppress e Continue; + let cuspec,idx = GenUnionCaseSpec cenv.amap m cenv.g eenv.tyenv ucref tyargs + let fty = actualTypOfIlxUnionField cuspec idx n + let avoidHelpers = entityRefInThisAssembly cenv.g.compilingFslib ucref.TyconRef + CG.EmitInstrs cgbuf (pop 1) (Push [ILType.Byref fty]) (EraseUnions.mkLdDataAddr (avoidHelpers, cuspec, idx, n)); + GenSequel cenv eenv.cloc cgbuf sequel + and GenGetUnionCaseTag cenv cgbuf eenv (e,tcref,tyargs,m) sequel = GenExpr cenv cgbuf eenv SPSuppress e Continue; let cuspec = GenUnionSpec cenv.amap m cenv.g eenv.tyenv tcref tyargs @@ -2206,7 +2220,8 @@ and GenGetUnionCaseTag cenv cgbuf eenv (e,tcref,tyargs,m) sequel = and GenSetUnionCaseField cenv cgbuf eenv (e,ucref,tyargs,n,e2,m) sequel = GenExpr cenv cgbuf eenv SPSuppress e Continue; let cuspec,idx = GenUnionCaseSpec cenv.amap m cenv.g eenv.tyenv ucref tyargs - EraseUnions.emitCastData cenv.g.ilg (UnionCodeGen cgbuf) (false,cuspec,idx) + let avoidHelpers = entityRefInThisAssembly cenv.g.compilingFslib ucref.TyconRef + EraseUnions.emitCastData cenv.g.ilg (UnionCodeGen cgbuf) (false,avoidHelpers,cuspec,idx) CG.EmitInstrs cgbuf (pop 1) (Push [cuspec.EnclosingType]) [ ] // push/pop to match the line above GenExpr cenv cgbuf eenv SPSuppress e2 Continue; CG.EmitInstrs cgbuf (pop 2) Push0 (EraseUnions.mkStData (cuspec, idx, n)); @@ -4247,12 +4262,17 @@ and GenDecisionTreeSwitch cenv cgbuf inplabOpt stackAtTargets eenv e cases defau let failureTree = (match defaultTargetOpt with None -> cases.Tail.Head.CaseTree | Some d -> d) GenDecisionTreeTest cenv eenv.cloc cgbuf stackAtTargets e None eenv (if b then successTree else failureTree) (if b then failureTree else successTree) targets repeatSP targetInfos sequel - // optimize a single test for a type constructor to an "isdata" test - much + // // Remove a single test for a union case . Union case tests are always exa + //| [ TCase(Test.UnionCase _, successTree) ] when (defaultTargetOpt.IsNone) -> + // GenDecisionTreeAndTargetsInner cenv cgbuf inplabOpt stackAtTargets eenv successTree targets repeatSP targetInfos sequel + // //GenDecisionTree cenv eenv.cloc cgbuf stackAtTargets e (Some (pop 1, Push [cenv.g.ilg.typ_bool], Choice1Of2 (avoidHelpers, cuspec, idx))) eenv successTree failureTree targets repeatSP targetInfos sequel + + // Optimize a single test for a union case to an "isdata" test - much // more efficient code, and this case occurs in the generated equality testers where perf is important - | TCase(Test.UnionCase(c,tyargs), successTree) :: rest when List.length rest = (match defaultTargetOpt with None -> 1 | Some _ -> 0) -> + | TCase(Test.UnionCase(c,tyargs), successTree) :: rest when rest.Length = (match defaultTargetOpt with None -> 1 | Some _ -> 0) -> let failureTree = match defaultTargetOpt with - | None -> cases.Tail.Head.CaseTree + | None -> rest.Head.CaseTree | Some tg -> tg let cuspec = GenUnionSpec cenv.amap m cenv.g eenv.tyenv c.TyconRef tyargs let idx = c.Index @@ -6116,7 +6136,7 @@ and GenTypeDef cenv mgbuf lazyInitInfo eenv m (tycon:Tycon) = | TTyconInterface -> ILTypeDefKind.Interface | TTyconEnum -> ILTypeDefKind.Enum | TTyconDelegate _ -> ILTypeDefKind.Delegate - | TRecdRepr _ when tycon.IsStructRecordTycon -> ILTypeDefKind.ValueType + | TRecdRepr _ | TUnionRepr _ when tycon.IsStructOrEnumTycon -> ILTypeDefKind.ValueType | _ -> ILTypeDefKind.Class let requiresExtraField = @@ -6285,13 +6305,15 @@ and GenTypeDef cenv mgbuf lazyInitInfo eenv m (tycon:Tycon) = (true,emptyILLocals,2, nonBranchingInstrsToCode ([ // load the hardwired format string - I_ldstr "%+0.8A"; + yield I_ldstr "%+0.8A"; // make the printf format object - mkNormalNewobj newFormatMethSpec; + yield mkNormalNewobj newFormatMethSpec; // call sprintf - mkNormalCall sprintfMethSpec; + yield mkNormalCall sprintfMethSpec; // call the function returned by sprintf - mkLdarg0 ] @ + yield mkLdarg0 + if ilThisTy.Boxity = ILBoxity.AsValue then + yield mkNormalLdobj ilThisTy ] @ callInstrs), None)) yield ilMethodDef |> AddSpecialNameFlag |> AddNonUserCompilerGeneratedAttribs cenv.g @@ -6319,7 +6341,7 @@ and GenTypeDef cenv mgbuf lazyInitInfo eenv m (tycon:Tycon) = relevantFields |> List.map (fun (_,ilFieldName,_,_,_,ilPropType,_,fspec) -> (fspec.Name,ilFieldName,ilPropType)) - let isStructRecord = tycon.IsStructRecordTycon + let isStructRecord = tycon.IsStructRecordOrUnionTycon // No type spec if the record is a value type let spec = if isStructRecord then None else Some(cenv.g.ilg.tspec_Object) @@ -6506,7 +6528,7 @@ and GenTypeDef cenv mgbuf lazyInitInfo eenv m (tycon:Tycon) = InitSemantics=ILTypeInit.BeforeField; IsSealed=true; IsAbstract=false; - tdKind= ILTypeDefKind.Class + tdKind= (if tycon.IsStructOrEnumTycon then ILTypeDefKind.ValueType else ILTypeDefKind.Class) Fields = ilFields; Events= ilEvents; Properties = ilProperties; @@ -6518,7 +6540,7 @@ and GenTypeDef cenv mgbuf lazyInitInfo eenv m (tycon:Tycon) = NestedTypes=emptyILTypeDefs; Encoding= ILDefaultPInvokeEncoding.Auto; Implements= mkILTypes ilIntfTys; - Extends= Some cenv.g.ilg.typ_Object; + Extends= Some (if tycon.IsStructOrEnumTycon then cenv.g.ilg.typ_ValueType else cenv.g.ilg.typ_Object) SecurityDecls= emptyILSecurityDecls; HasSecurity=false } let tdef2 = EraseUnions.mkClassUnionDef cenv.g.ilg tref tdef cuinfo diff --git a/src/fsharp/NameResolution.fs b/src/fsharp/NameResolution.fs index 9ebd2bafafe..52345ff8c43 100755 --- a/src/fsharp/NameResolution.fs +++ b/src/fsharp/NameResolution.fs @@ -1656,7 +1656,7 @@ let private ResolveObjectConstructorPrim (ncenv:NameResolver) edenv resInfo m ad success (resInfo, Item.FakeInterfaceCtor typ) else let defaultStructCtorInfo = - if (isStructTy g typ && not(isRecdTy g typ) && not(ctorInfos |> List.exists (fun x -> x.IsNullary))) then + if (isStructTy g typ && not (isRecdTy g typ) && not (isUnionTy g typ) && not(ctorInfos |> List.exists (fun x -> x.IsNullary))) then [DefaultStructCtor(g,typ)] else [] if (isNil defaultStructCtorInfo && isNil ctorInfos) || not (isAppTy g typ) then diff --git a/src/fsharp/Optimizer.fs b/src/fsharp/Optimizer.fs index 0bb9b2dfe87..e3451d188f1 100644 --- a/src/fsharp/Optimizer.fs +++ b/src/fsharp/Optimizer.fs @@ -1320,7 +1320,8 @@ and OpHasEffect g op = | TOp.ExnFieldGet(ecref,n) -> isExnFieldMutable ecref n | TOp.RefAddrGet -> false | TOp.ValFieldGet rfref -> rfref.RecdField.IsMutable || (TryFindTyconRefBoolAttribute g Range.range0 g.attrib_AllowNullLiteralAttribute rfref.TyconRef = Some(true)) - | TOp.ValFieldGetAddr _rfref -> true (* check *) + | TOp.ValFieldGetAddr rfref -> rfref.RecdField.IsMutable (* data is immutable, so taking address is ok *) + | TOp.UnionCaseFieldGetAddr _ -> false (* data is immutable, so taking address is ok *) | TOp.LValueOp (LGetAddr,lv) -> lv.IsMutable | TOp.UnionCaseFieldSet _ | TOp.ExnFieldSet _ @@ -1928,6 +1929,7 @@ and OptimizeExprOpFallback cenv env (op,tyargs,args',m) arginfos valu = | TOp.Array | TOp.For _ | TOp.While _ | TOp.TryCatch _ | TOp.TryFinally _ | TOp.ILCall _ | TOp.TraitCall _ | TOp.LValueOp _ | TOp.ValFieldSet _ | TOp.UnionCaseFieldSet _ | TOp.RefAddrGet | TOp.Coerce | TOp.Reraise + | TOp.UnionCaseFieldGetAddr _ | TOp.ExnFieldSet _ -> 1,valu | TOp.Recd (ctorInfo,tcref) -> let finfos = tcref.AllInstanceFieldsAsList diff --git a/src/fsharp/PatternMatchCompilation.fs b/src/fsharp/PatternMatchCompilation.fs index 0dae5cdfbf2..22400641b79 100644 --- a/src/fsharp/PatternMatchCompilation.fs +++ b/src/fsharp/PatternMatchCompilation.fs @@ -375,7 +375,7 @@ let getDiscrimOfPattern g tpinst t = | TPat_array (args,ty,_m) -> Some(Test.ArrayLength (args.Length,ty)) | TPat_query ((pexp,resTys,apatVrefOpt,idx,apinfo),_,_m) -> - Some(Test.ActivePatternCase (pexp, instTypes tpinst resTys, apatVrefOpt,idx,apinfo)) + Some(Test.ActivePatternCase (pexp, instTypes tpinst resTys, apatVrefOpt, idx, apinfo)) | _ -> None let constOfDiscrim discrim = @@ -897,6 +897,21 @@ let CompilePatternBasic let appexp = mkIsInst tgty argexp matchm Some(vexp),Some(mkInvisibleBind v appexp) + // Any match on a struct union must take the address of its input + | EdgeDiscrim(_i',(Test.UnionCase (ucref, _)),_) :: _rest + when (isNil topgtvs && ucref.Tycon.IsStructRecordOrUnionTycon) -> + + let argexp = GetSubExprOfInput subexpr + let vOpt,addrexp = mkExprAddrOfExprAux g true false NeverMutates argexp None matchm + match vOpt with + | None -> None, None + | Some (v,e) -> + if topv.IsMemberOrModuleBinding then + AdjustValToTopVal v topv.ActualParent ValReprInfo.emptyValData; + Some addrexp, Some (mkInvisibleBind v e) + + + #if OPTIMIZE_LIST_MATCHING | [EdgeDiscrim(_, ListConsDiscrim g tinst,m); EdgeDiscrim(_, ListEmptyDiscrim g _, _)] | [EdgeDiscrim(_, ListEmptyDiscrim g _, _); EdgeDiscrim(_, ListConsDiscrim g tinst, m)] @@ -915,7 +930,7 @@ let CompilePatternBasic #endif // Active pattern matches: create a variable to hold the results of executing the active pattern. - | (EdgeDiscrim(_,(Test.ActivePatternCase(pexp,resTys,_resPreBindOpt,_,apinfo)),m) :: _) -> + | (EdgeDiscrim(_,(Test.ActivePatternCase(pexp,resTys,_,_,apinfo)),m) :: _) -> if debug then dprintf "Building result var for active pattern...\n"; if nonNil topgtvs then error(InternalError("Unexpected generalized type variables when compiling an active pattern",m)); @@ -957,13 +972,14 @@ let CompilePatternBasic #endif (isNil topgtvs && not topv.IsMemberOrModuleBinding && + not ucref.Tycon.IsStructRecordOrUnionTycon && ucref.UnionCase.RecdFields.Length >= 1 && ucref.Tycon.UnionCasesArray.Length > 1) -> let v,vexp = mkCompGenLocal m "unionCase" (mkProvenUnionCaseTy ucref tinst) let argexp = GetSubExprOfInput subexpr - let appexp = mkUnionCaseProof(argexp, ucref,tinst,m) - Some(vexp),Some(mkInvisibleBind v appexp) + let appexp = mkUnionCaseProof (argexp, ucref,tinst,m) + Some vexp,Some(mkInvisibleBind v appexp) | _ -> None,None @@ -1052,11 +1068,14 @@ let CompilePatternBasic if (hasParam && i = i') || (discrimsEq g discrim (Option.get (getDiscrimOfPattern pat))) then let aparity = apinfo.Names.Length let accessf' j tpinst _e' = + assert resPreBindOpt.IsSome if aparity <= 1 then Option.get resPreBindOpt else let ucref = mkChoiceCaseRef g m aparity idx - mkUnionCaseFieldGetUnproven(Option.get resPreBindOpt,ucref,instTypes tpinst resTys,j,exprm) + // TODO: In the future we will want active patterns to be able to return struct-unions + // In that eventuality, we need to check we are taking the address correctly + mkUnionCaseFieldGetUnprovenViaExprAddr (Option.get resPreBindOpt,ucref,instTypes tpinst resTys,j,exprm) mkSubFrontiers path accessf' active' [p] (fun path j -> PathQuery(path,int64 j)) elif hasParam then @@ -1068,7 +1087,9 @@ let CompilePatternBasic else if i = i' then let accessf' _j tpinst _ = - mkUnionCaseFieldGetUnproven(Option.get resPreBindOpt, mkSomeCase g, instTypes tpinst resTys, 0, exprm) + // TODO: In the future we will want active patterns to be able to return struct-unions + // In that eventuality, we need to check we are taking the address correctly + mkUnionCaseFieldGetUnprovenViaExprAddr (Option.get resPreBindOpt, mkSomeCase g, instTypes tpinst resTys, 0, exprm) mkSubFrontiers path accessf' active' [p] (fun path j -> PathQuery(path,int64 j)) else // Successful active patterns don't refute other patterns @@ -1080,12 +1101,12 @@ let CompilePatternBasic let accessf' j tpinst e' = #if OPTIMIZE_LIST_MATCHING match resPreBindOpt with - | Some e -> mkUnionCaseFieldGetProven(e,ucref1,tinst,j,exprm) + | Some e -> mkUnionCaseFieldGetProvenViaExprAddr g (e,ucref1,tinst,j,exprm) | None -> #endif match resPostBindOpt with - | Some e -> mkUnionCaseFieldGetProven(e,ucref1,tinst,j,exprm) - | None -> mkUnionCaseFieldGetUnproven(accessf tpinst e',ucref1,instTypes tpinst tyargs,j,exprm) + | Some e -> mkUnionCaseFieldGetProvenViaExprAddr (e,ucref1,tinst,j,exprm) + | None -> mkUnionCaseFieldGetUnprovenViaExprAddr (accessf tpinst e',ucref1,instTypes tpinst tyargs,j,exprm) mkSubFrontiers path accessf' active' argpats (fun path j -> PathUnionConstr(path,ucref1,tyargs,j)) | Test.UnionCase _ -> diff --git a/src/fsharp/PostInferenceChecks.fs b/src/fsharp/PostInferenceChecks.fs index 275ffbe2137..9519c65f50d 100644 --- a/src/fsharp/PostInferenceChecks.fs +++ b/src/fsharp/PostInferenceChecks.fs @@ -731,22 +731,41 @@ and CheckExprOp cenv env (op,tyargs,args,m) context = CheckTypeInstNoByrefs cenv env m tyargs; CheckExprDirectArgs cenv env [arg1]; (* See mkRecdFieldSetViaExprAddr -- byref arg1 when #args=2 *) CheckExprs cenv env [arg2] (* Property setters on mutable structs come through here (TBC). *) + | TOp.Coerce,[_ty1;_ty2],[x],_arity -> CheckTypeInstNoByrefs cenv env m tyargs; CheckExprInContext cenv env x context + | TOp.Reraise,[_ty1],[],_arity -> CheckTypeInstNoByrefs cenv env m tyargs + | TOp.ValFieldGetAddr rfref,tyargs,[],_ -> if context <> DirectArg && cenv.reportErrors then errorR(Error(FSComp.SR.chkNoAddressStaticFieldAtThisPoint(rfref.FieldName), m)); CheckTypeInstNoByrefs cenv env m tyargs (* NOTE: there are no arg exprs to check in this case *) + | TOp.ValFieldGetAddr rfref,tyargs,[rx],_ -> if context <> DirectArg && cenv.reportErrors then errorR(Error(FSComp.SR.chkNoAddressFieldAtThisPoint(rfref.FieldName), m)); (* This construct is used for &(rx.rfield) and &(rx->rfield). Relax to permit byref types for rx. [See Bug 1263]. *) CheckTypeInstNoByrefs cenv env m tyargs; CheckExprInContext cenv env rx DirectArg (* allow rx to be byref here *) + + | TOp.UnionCaseFieldGet _,_,[arg1],_arity -> + CheckTypeInstNoByrefs cenv env m tyargs + CheckExprInContext cenv env arg1 DirectArg + + | TOp.UnionCaseTagGet _,_,[arg1],_arity -> + CheckTypeInstNoByrefs cenv env m tyargs + CheckExprInContext cenv env arg1 DirectArg + + | TOp.UnionCaseFieldGetAddr (uref, _idx),tyargs,[rx],_ -> + if context <> DirectArg && cenv.reportErrors then + errorR(Error(FSComp.SR.chkNoAddressFieldAtThisPoint(uref.CaseName), m)) + CheckTypeInstNoByrefs cenv env m tyargs + CheckExprInContext cenv env rx DirectArg // allow rx to be byref here + | TOp.ILAsm (instrs,tys),_,_,_ -> CheckTypeInstPermitByrefs cenv env m tys; CheckTypeInstNoByrefs cenv env m tyargs; @@ -887,9 +906,9 @@ and CheckDecisionTree cenv env x = | TDSwitch (e,cases,dflt,m) -> CheckDecisionTreeSwitch cenv env (e,cases,dflt,m) and CheckDecisionTreeSwitch cenv env (e,cases,dflt,m) = - CheckExpr cenv env e; - List.iter (fun (TCase(discrim,e)) -> CheckDecisionTreeTest cenv env m discrim; CheckDecisionTree cenv env e) cases; - Option.iter (CheckDecisionTree cenv env) dflt + CheckExprInContext cenv env e DirectArg // can be byref for struct union switch + cases |> List.iter (fun (TCase(discrim,e)) -> CheckDecisionTreeTest cenv env m discrim; CheckDecisionTree cenv env e) + dflt |> Option.iter (CheckDecisionTree cenv env) and CheckDecisionTreeTest cenv env m discrim = match discrim with diff --git a/src/fsharp/QuotationTranslator.fs b/src/fsharp/QuotationTranslator.fs index 22090236d4b..3361b5ec54f 100644 --- a/src/fsharp/QuotationTranslator.fs +++ b/src/fsharp/QuotationTranslator.fs @@ -433,6 +433,9 @@ and private ConvExprCore cenv (env : QuotationTranslationEnv) (expr: Expr) : QP. | TOp.ValFieldGetAddr(_rfref),_tyargs,_ -> wfail(Error(FSComp.SR.crefQuotationsCantContainAddressOf(), m)) + | TOp.UnionCaseFieldGetAddr _,_tyargs,_ -> + wfail(Error(FSComp.SR.crefQuotationsCantContainAddressOf(), m)) + | TOp.ValFieldGet(_rfref),_tyargs,[] -> wfail(Error(FSComp.SR.crefQuotationsCantContainStaticFieldRef(),m)) diff --git a/src/fsharp/TastOps.fs b/src/fsharp/TastOps.fs index d82e0671bf7..fd4e2c2f6be 100755 --- a/src/fsharp/TastOps.fs +++ b/src/fsharp/TastOps.fs @@ -1181,24 +1181,32 @@ let mkStaticRecdFieldGetAddr(fref,tinst,m) = Expr.Op (TOp.ValFieldGetAd let mkStaticRecdFieldGet(fref,tinst,m) = Expr.Op (TOp.ValFieldGet(fref), tinst, [],m) let mkStaticRecdFieldSet(fref,tinst,e,m) = Expr.Op (TOp.ValFieldSet(fref), tinst, [e],m) -let mkRecdFieldSetViaExprAddr(e1,fref,tinst,e2,m) = Expr.Op (TOp.ValFieldSet(fref), tinst, [e1;e2],m) +let mkRecdFieldSetViaExprAddr (e1,fref,tinst,e2,m) = Expr.Op (TOp.ValFieldSet(fref), tinst, [e1;e2],m) -let mkUnionCaseTagGet(e1,cref,tinst,m) = Expr.Op (TOp.UnionCaseTagGet(cref), tinst, [e1],m) -let mkUnionCaseProof(e1,cref,tinst,m) = Expr.Op (TOp.UnionCaseProof(cref), tinst, [e1],m) +let mkUnionCaseTagGetViaExprAddr (e1,cref,tinst,m) = Expr.Op (TOp.UnionCaseTagGet(cref), tinst, [e1],m) -/// Build a 'get' expression for something we've already determined to be a particular union case, and where the -/// input expression has 'TType_ucase', which is an F# compiler internal "type" -let mkUnionCaseFieldGetProven(e1,cref,tinst,j,m) = Expr.Op (TOp.UnionCaseFieldGet(cref,j), tinst, [e1],m) +/// Make a 'TOp.UnionCaseProof' expression, which proves a union value is over a particular case (used only for ref-unions, not struct-unions) +let mkUnionCaseProof (e1,cref:UnionCaseRef,tinst,m) = if cref.Tycon.IsStructOrEnumTycon then e1 else Expr.Op (TOp.UnionCaseProof(cref), tinst, [e1],m) + +/// Build a 'TOp.UnionCaseFieldGet' expression for something we've already determined to be a particular union case. For ref-unions, +/// the input expression has 'TType_ucase', which is an F# compiler internal "type" corresponding to the union case. For struct-unions, +/// the input should be the address of the expression. +let mkUnionCaseFieldGetProvenViaExprAddr (e1,cref,tinst,j,m) = Expr.Op (TOp.UnionCaseFieldGet(cref,j), tinst, [e1],m) + +/// Build a 'TOp.UnionCaseFieldGetAddr' expression for a field of a union when we've already determined the value to be a particular union case. For ref-unions, +/// the input expression has 'TType_ucase', which is an F# compiler internal "type" corresponding to the union case. For struct-unions, +/// the input should be the address of the expression. +let mkUnionCaseFieldGetAddrProvenViaExprAddr (e1,cref,tinst,j,m) = Expr.Op (TOp.UnionCaseFieldGetAddr(cref,j), tinst, [e1],m) /// Build a 'get' expression for something we've already determined to be a particular union case, but where /// the static type of the input is not yet proven to be that particular union case. This requires a type /// cast to 'prove' the condition. -let mkUnionCaseFieldGetUnproven(e1,cref,tinst,j,m) = mkUnionCaseFieldGetProven(mkUnionCaseProof(e1,cref,tinst,m),cref,tinst,j,m) +let mkUnionCaseFieldGetUnprovenViaExprAddr (e1,cref,tinst,j,m) = mkUnionCaseFieldGetProvenViaExprAddr(mkUnionCaseProof(e1,cref,tinst,m),cref,tinst,j,m) -let mkUnionCaseFieldSet(e1,cref,tinst,j,e2,m) = Expr.Op (TOp.UnionCaseFieldSet(cref,j), tinst, [e1;e2],m) +let mkUnionCaseFieldSet (e1,cref,tinst,j,e2,m) = Expr.Op (TOp.UnionCaseFieldSet(cref,j), tinst, [e1;e2],m) -let mkExnCaseFieldGet(e1,ecref,j,m) = Expr.Op (TOp.ExnFieldGet(ecref,j), [],[e1],m) -let mkExnCaseFieldSet(e1,ecref,j,e2,m) = Expr.Op (TOp.ExnFieldSet(ecref,j), [],[e1;e2],m) +let mkExnCaseFieldGet (e1,ecref,j,m) = Expr.Op (TOp.ExnFieldGet(ecref,j), [],[e1],m) +let mkExnCaseFieldSet (e1,ecref,j,e2,m) = Expr.Op (TOp.ExnFieldSet(ecref,j), [],[e1;e2],m) let mkDummyLambda g (e:Expr,ety) = let m = e.Range @@ -1310,6 +1318,9 @@ let actualTyOfRecdFieldForTycon tycon tinst (fspec:RecdField) = let actualTyOfRecdFieldRef (fref:RecdFieldRef) tinst = actualTyOfRecdFieldForTycon fref.Tycon tinst fref.RecdField +let actualTyOfUnionFieldRef (fref:UnionCaseRef) n tinst = + actualTyOfRecdFieldForTycon fref.Tycon tinst (fref.FieldByIndex(n)) + //--------------------------------------------------------------------------- // Apply type functions to types @@ -4130,6 +4141,7 @@ and accFreeInOp opts op acc = // Things containing just a union case reference | TOp.UnionCaseProof cr | TOp.UnionCase cr + | TOp.UnionCaseFieldGetAddr (cr,_) | TOp.UnionCaseFieldGet (cr,_) | TOp.UnionCaseFieldSet (cr,_) -> accFreeUnionCaseRef opts cr acc @@ -4538,7 +4550,7 @@ and remapExpr g (compgen:ValCopyFlag) (tmenv:Remap) x = List.map (remapMethod g compgen tmenvinner) overrides, List.map (remapInterfaceImpl g compgen tmenvinner) iimpls,m) - // Addresses of immutable field may "leak" across assembly boundaries - see CanTakeAddressOfRecdField below. + // Addresses of immutable field may "leak" across assembly boundaries - see CanTakeAddressOfRecdFieldRef below. // This is "ok", in the sense that it is always valid to fix these up to be uses // of a temporary local, e.g. // &(E.RF) --> let mutable v = E.RF in &v @@ -4552,6 +4564,15 @@ and remapExpr g (compgen:ValCopyFlag) (tmenv:Remap) x = let tmp,_ = mkMutableCompGenLocal m "copyOfStruct" (actualTyOfRecdFieldRef rfref tinst) mkCompGenLet m tmp (mkRecdFieldGetViaExprAddr(arg,rfref,tinst,m)) (mkValAddr m (mkLocalValRef tmp)) + | Expr.Op (TOp.UnionCaseFieldGetAddr (uref,cidx),tinst,[arg],m) when + not (uref.FieldByIndex(cidx).IsMutable) && + not (entityRefInThisAssembly g.compilingFslib uref.TyconRef) -> + + let tinst = remapTypes tmenv tinst + let arg = remapExpr g compgen tmenv arg + let tmp,_ = mkMutableCompGenLocal m "copyOfStruct" (actualTyOfUnionFieldRef uref cidx tinst) + mkCompGenLet m tmp (mkUnionCaseFieldGetProvenViaExprAddr(arg,uref,tinst,cidx,m)) (mkValAddr m (mkLocalValRef tmp)) + | Expr.Op (op,tinst,args,m) -> let op' = remapOp tmenv op let tinst' = remapTypes tmenv tinst @@ -5102,6 +5123,7 @@ let rec tyOfExpr g e = | TOp.ValFieldGet(fref) -> actualTyOfRecdFieldRef fref tinst | (TOp.ValFieldSet _ | TOp.UnionCaseFieldSet _ | TOp.ExnFieldSet _ | TOp.LValueOp ((LSet | LByrefSet),_)) ->g.unit_ty | TOp.UnionCaseTagGet _ -> g.int_ty + | TOp.UnionCaseFieldGetAddr(cref,j) -> mkByrefTy g (actualTyOfRecdField (mkTyconRefInst cref.TyconRef tinst) (cref.FieldByIndex j)) | TOp.UnionCaseFieldGet(cref,j) -> actualTyOfRecdField (mkTyconRefInst cref.TyconRef tinst) (cref.FieldByIndex j) | TOp.ExnFieldGet(ecref,j) -> recdFieldTyOfExnDefRefByIdx ecref j | TOp.LValueOp (LByrefGet, v) -> destByrefTy g v.Type @@ -5326,7 +5348,7 @@ let mkAndSimplifyMatch spBind exprm matchm ty tree targets = //------------------------------------------------------------------------- -// mkExprAddrOfExpr +// mkExprAddrOfExprAux //------------------------------------------------------------------------- type Mutates = DefinitelyMutates | PossiblyMutates | NeverMutates @@ -5370,48 +5392,61 @@ let MustTakeAddressOfVal g (v:ValRef) = // We can only take the address of mutable values in the same assembly valRefInThisAssembly g.compilingFslib v -let MustTakeAddressOfRecdField (rfref: RecdFieldRef) = +let MustTakeAddressOfRecdField (rf: RecdField) = // Static mutable fields must be private, hence we don't have to take their address - not rfref.RecdField.IsStatic && - rfref.RecdField.IsMutable + not rf.IsStatic && + rf.IsMutable -let CanTakeAddressOfRecdField g (rfref: RecdFieldRef) mut tinst = +let MustTakeAddressOfRecdFieldRef (rfref: RecdFieldRef) = MustTakeAddressOfRecdField rfref.RecdField + +let CanTakeAddressOfRecdFieldRef g (rfref: RecdFieldRef) mut tinst = mut <> DefinitelyMutates && // We only do this if the field is defined in this assembly because we can't take adddresses across assemblies for immutable fields entityRefInThisAssembly g.compilingFslib rfref.TyconRef && isRecdOrStuctTyImmutable g (actualTyOfRecdFieldRef rfref tinst) +let CanTakeAddressOfUnionFieldRef g (uref: UnionCaseRef) mut tinst cidx = + mut <> DefinitelyMutates && + // We only do this if the field is defined in this assembly because we can't take adddresses across assemblies for immutable fields + entityRefInThisAssembly g.compilingFslib uref.TyconRef && + isRecdOrStuctTyImmutable g (actualTyOfUnionFieldRef uref cidx tinst) + -let rec mkExprAddrOfExpr g mustTakeAddress useReadonlyForGenericArrayAddress mut e addrExprVal m = - if not mustTakeAddress then (fun x -> x),e else +let rec mkExprAddrOfExprAux g mustTakeAddress useReadonlyForGenericArrayAddress mut e addrExprVal m = + if not mustTakeAddress then None,e else match e with // LVALUE: "x" where "x" is byref | Expr.Op (TOp.LValueOp (LByrefGet, v), _,[], m) -> - (fun x -> x), exprForValRef m v + None, exprForValRef m v // LVALUE: "x" where "x" is mutable local, mutable intra-assembly module/static binding, or operation doesn't mutate // Note: we can always take the address of mutable values | Expr.Val(v, _,m) when MustTakeAddressOfVal g v || CanTakeAddressOfImmutableVal g v mut -> - (fun x -> x), mkValAddr m v - // LVALUE: "x" where "e.x" is mutable record field. "e" may be an lvalue - | Expr.Op (TOp.ValFieldGet rfref, tinst,[e],m) when MustTakeAddressOfRecdField rfref || CanTakeAddressOfRecdField g rfref mut tinst -> + None, mkValAddr m v + // LVALUE: "x" where "e.x" is record field. + | Expr.Op (TOp.ValFieldGet rfref, tinst,[e],m) when MustTakeAddressOfRecdFieldRef rfref || CanTakeAddressOfRecdFieldRef g rfref mut tinst -> let exprty = tyOfExpr g e - let wrap,expra = mkExprAddrOfExpr g (isStructTy g exprty) false mut e None m + let wrap,expra = mkExprAddrOfExprAux g (isStructTy g exprty) false mut e None m wrap, mkRecdFieldGetAddrViaExprAddr(expra,rfref,tinst,m) + // LVALUE: "x" where "e.x" is union field + | Expr.Op (TOp.UnionCaseFieldGet (uref,cidx), tinst,[e],m) when MustTakeAddressOfRecdField (uref.FieldByIndex(cidx)) || CanTakeAddressOfUnionFieldRef g uref mut tinst cidx -> + let exprty = tyOfExpr g e + let wrap,expra = mkExprAddrOfExprAux g (isStructTy g exprty) false mut e None m + wrap, mkUnionCaseFieldGetAddrProvenViaExprAddr(expra,uref,tinst,cidx,m) // LVALUE: "x" where "e.x" is a .NET static field. | Expr.Op (TOp.ILAsm ([IL.I_ldsfld(_vol,fspec)],[ty2]), tinst,[],m) -> - (fun x -> x),Expr.Op (TOp.ILAsm ([IL.I_ldsflda(fspec)],[mkByrefTy g ty2]), tinst,[],m) + None,Expr.Op (TOp.ILAsm ([IL.I_ldsflda(fspec)],[mkByrefTy g ty2]), tinst,[],m) // LVALUE: "x" where "e.x" is a .NET instance field. "e" may be an lvalue | Expr.Op (TOp.ILAsm ([IL.I_ldfld(_align,_vol,fspec)],[ty2]), tinst,[e],m) -> let exprty = tyOfExpr g e - let wrap,expra = mkExprAddrOfExpr g (isStructTy g exprty) false mut e None m + let wrap,expra = mkExprAddrOfExprAux g (isStructTy g exprty) false mut e None m wrap,Expr.Op (TOp.ILAsm ([IL.I_ldflda(fspec)],[mkByrefTy g ty2]), tinst,[expra],m) // LVALUE: "x" where "x" is mutable static field. - | Expr.Op (TOp.ValFieldGet rfref, tinst,[],m) when MustTakeAddressOfRecdField rfref || CanTakeAddressOfRecdField g rfref mut tinst -> - (fun x -> x), mkStaticRecdFieldGetAddr(rfref,tinst,m) + | Expr.Op (TOp.ValFieldGet rfref, tinst,[],m) when MustTakeAddressOfRecdFieldRef rfref || CanTakeAddressOfRecdFieldRef g rfref mut tinst -> + None, mkStaticRecdFieldGetAddr(rfref,tinst,m) // LVALUE: "e.[n]" where e is an array of structs | Expr.App(Expr.Val(vf,_,_),_,[elemTy],[aexpr;nexpr],_) @@ -5423,7 +5458,7 @@ let rec mkExprAddrOfExpr g mustTakeAddress useReadonlyForGenericArrayAddress mut match addrExprVal with | Some(vf) -> valRefEq g vf g.addrof2_vref | _ -> false - (fun x -> x), Expr.Op (TOp.ILAsm ([IL.I_ldelema(readonly,isNativePtr,shape,mkILTyvarTy 0us)],[mkByrefTy g elemTy]), [elemTy],[aexpr;nexpr],m) + None, Expr.Op (TOp.ILAsm ([IL.I_ldelema(readonly,isNativePtr,shape,mkILTyvarTy 0us)],[mkByrefTy g elemTy]), [elemTy],[aexpr;nexpr],m) // LVALUE: "e.[n1,n2]", "e.[n1,n2,n3]", "e.[n1,n2,n3,n4]" where e is an array of structs | Expr.App(Expr.Val(vf,_,_),_,[elemTy],(aexpr::args),_) @@ -5436,7 +5471,7 @@ let rec mkExprAddrOfExpr g mustTakeAddress useReadonlyForGenericArrayAddress mut | Some(vf) -> valRefEq g vf g.addrof2_vref | _ -> false - (fun x -> x), Expr.Op (TOp.ILAsm ([IL.I_ldelema(readonly,isNativePtr,shape,mkILTyvarTy 0us)],[mkByrefTy g elemTy]), [elemTy],(aexpr::args),m) + None, Expr.Op (TOp.ILAsm ([IL.I_ldelema(readonly,isNativePtr,shape,mkILTyvarTy 0us)],[mkByrefTy g elemTy]), [elemTy],(aexpr::args),m) // Give a nice error message for DefinitelyMutates on immutable values, or mutable values in other assemblies | Expr.Val(v, _,m) when mut = DefinitelyMutates @@ -5457,15 +5492,24 @@ let rec mkExprAddrOfExpr g mustTakeAddress useReadonlyForGenericArrayAddress mut | PossiblyMutates -> warning(DefensiveCopyWarning(FSComp.SR.tastValueHasBeenCopied(),m)); let tmp,_ = mkMutableCompGenLocal m "copyOfStruct" ty - (fun rest -> mkCompGenLet m tmp e rest), (mkValAddr m (mkLocalValRef tmp)) + Some (tmp,e), (mkValAddr m (mkLocalValRef tmp)) + +let mkExprAddrOfExpr g mustTakeAddress useReadonlyForGenericArrayAddress mut e addrExprVal m = + let optBind, addre = mkExprAddrOfExprAux g mustTakeAddress useReadonlyForGenericArrayAddress mut e addrExprVal m + match optBind with + | None -> (fun x -> x), addre + | Some (tmp,rval) -> (fun x -> mkCompGenLet m tmp rval x), addre let mkRecdFieldGet g (e,fref:RecdFieldRef,tinst,m) = + assert (not (isByrefTy g (tyOfExpr g e))) let wrap,e' = mkExprAddrOfExpr g fref.Tycon.IsStructOrEnumTycon false NeverMutates e None m wrap (mkRecdFieldGetViaExprAddr(e',fref,tinst,m)) -let mkRecdFieldSet g (e,fref:RecdFieldRef,tinst,e2,m) = - let wrap,e' = mkExprAddrOfExpr g fref.Tycon.IsStructOrEnumTycon false DefinitelyMutates e None m - wrap (mkRecdFieldSetViaExprAddr(e',fref,tinst,e2,m)) +let mkUnionCaseFieldGetUnproven g (e,cref:UnionCaseRef,tinst,j,m) = + assert (not (isByrefTy g (tyOfExpr g e))) + let wrap,e' = mkExprAddrOfExpr g cref.Tycon.IsStructOrEnumTycon false NeverMutates e None m + wrap (mkUnionCaseFieldGetUnprovenViaExprAddr (e',cref,tinst,j,m)) + let mkArray (argty, args, m) = Expr.Op(TOp.Array, [argty],args,m) @@ -5505,12 +5549,13 @@ let rec IterateRecursiveFixups g (selfv : Val option) rvs ((access : Expr),set) | Expr.Op (TOp.UnionCase (c),tinst,args,m) -> args |> List.iteri (fun n -> IterateRecursiveFixups g None rvs - (mkUnionCaseFieldGetUnproven(access,c,tinst,n,m), + (mkUnionCaseFieldGetUnprovenViaExprAddr (access,c,tinst,n,m), (fun e -> // NICE: it would be better to do this check in the type checker let tcref = c.TyconRef - errorR(Error(FSComp.SR.tastRecursiveValuesMayNotAppearInConstructionOfType(tcref.LogicalName),m)); - mkUnionCaseFieldSet(access,c,tinst,n,e,m)))) + if not (c.FieldByIndex(n)).IsMutable && not (entityRefInThisAssembly g.compilingFslib tcref) then + errorR(Error(FSComp.SR.tastRecursiveValuesMayNotAppearInConstructionOfType(tcref.LogicalName),m)); + mkUnionCaseFieldSet (access,c,tinst,n,e,m)))) | Expr.Op (TOp.Recd (_,tcref),tinst,args,m) -> (tcref.TrueInstanceFieldsAsRefList, args) ||> List.iter2 (fun fref arg -> @@ -5521,7 +5566,7 @@ let rec IterateRecursiveFixups g (selfv : Val option) rvs ((access : Expr),set) // NICE: it would be better to do this check in the type checker if not fspec.IsMutable && not (entityRefInThisAssembly g.compilingFslib tcref) then errorR(Error(FSComp.SR.tastRecursiveValuesMayNotBeAssignedToNonMutableField(fspec.rfield_id.idText, tcref.LogicalName),m)); - mkRecdFieldSet g (access,fref,tinst,e,m))) arg ) + mkRecdFieldSetViaExprAddr (access,fref,tinst,e,m))) arg ) | Expr.Val _ | Expr.Lambda _ | Expr.Obj _ @@ -5850,8 +5895,8 @@ let mkRecordExpr g (lnk,tcref,tinst,rfrefs:RecdFieldRef list,args,m) = //------------------------------------------------------------------------- let mkRefCell g m ty e = mkRecordExpr g (RecdExpr,g.refcell_tcr_canon,[ty],[mkRefCellContentsRef g],[e],m) -let mkRefCellGet g m ty e = mkRecdFieldGet g (e,mkRefCellContentsRef g,[ty],m) -let mkRefCellSet g m ty e1 e2 = mkRecdFieldSet g (e1,mkRefCellContentsRef g,[ty],e2,m) +let mkRefCellGet g m ty e = mkRecdFieldGetViaExprAddr (e,mkRefCellContentsRef g,[ty],m) +let mkRefCellSet g m ty e1 e2 = mkRecdFieldSetViaExprAddr (e1,mkRefCellContentsRef g,[ty],e2,m) let mkNil g m ty = mkUnionCaseExpr (g.nil_ucref,[ty],[],m) let mkCons g ty h t = mkUnionCaseExpr (g.cons_ucref,[ty],[h;t],unionRanges h.Range t.Range) @@ -7843,8 +7888,8 @@ let DetectAndOptimizeForExpression g option expr = let elemTy = destListTy g enumerableTy let guardExpr = mkNonNullTest g m nextExpr - let headOrDefaultExpr = mkUnionCaseFieldGetUnproven(currentExpr,g.cons_ucref,[elemTy],IndexHead,m) - let tailOrNullExpr = mkUnionCaseFieldGetUnproven(currentExpr,g.cons_ucref,[elemTy],IndexTail,mBody) + let headOrDefaultExpr = mkUnionCaseFieldGetUnprovenViaExprAddr (currentExpr,g.cons_ucref,[elemTy],IndexHead,m) + let tailOrNullExpr = mkUnionCaseFieldGetUnprovenViaExprAddr (currentExpr,g.cons_ucref,[elemTy],IndexTail,mBody) let bodyExpr = mkCompGenLet m elemVar headOrDefaultExpr (mkCompGenSequential mBody diff --git a/src/fsharp/TastOps.fsi b/src/fsharp/TastOps.fsi index 912c72872db..651c927bc04 100755 --- a/src/fsharp/TastOps.fsi +++ b/src/fsharp/TastOps.fsi @@ -188,12 +188,35 @@ val mkStaticRecdFieldGet : RecdFieldRef * TypeInst val mkStaticRecdFieldSet : RecdFieldRef * TypeInst * Expr * range -> Expr val mkStaticRecdFieldGetAddr : RecdFieldRef * TypeInst * range -> Expr val mkRecdFieldSetViaExprAddr : Expr * RecdFieldRef * TypeInst * Expr * range -> Expr -val mkUnionCaseTagGet : Expr * TyconRef * TypeInst * range -> Expr +val mkUnionCaseTagGetViaExprAddr : Expr * TyconRef * TypeInst * range -> Expr + +/// Make a 'TOp.UnionCaseProof' expression, which proves a union value is over a particular case (used only for ref-unions, not struct-unions) val mkUnionCaseProof : Expr * UnionCaseRef * TypeInst * range -> Expr -val mkUnionCaseFieldGetProven : Expr * UnionCaseRef * TypeInst * int * range -> Expr -val mkUnionCaseFieldGetUnproven : Expr * UnionCaseRef * TypeInst * int * range -> Expr -val mkExnCaseFieldGet : Expr * TyconRef * int * range -> Expr + +/// Build a 'TOp.UnionCaseFieldGet' expression for something we've already determined to be a particular union case. For ref-unions, +/// the input expression has 'TType_ucase', which is an F# compiler internal "type" corresponding to the union case. For struct-unions, +/// the input should be the address of the expression. +val mkUnionCaseFieldGetProvenViaExprAddr : Expr * UnionCaseRef * TypeInst * int * range -> Expr + +/// Build a 'TOp.UnionCaseFieldGetAddr' expression for a field of a union when we've already determined the value to be a particular union case. For ref-unions, +/// the input expression has 'TType_ucase', which is an F# compiler internal "type" corresponding to the union case. For struct-unions, +/// the input should be the address of the expression. +val mkUnionCaseFieldGetAddrProvenViaExprAddr : Expr * UnionCaseRef * TypeInst * int * range -> Expr + +/// Build a 'TOp.UnionCaseFieldGetAddr' expression for a field of a union when we've already determined the value to be a particular union case. For ref-unions, +/// the input expression has 'TType_ucase', which is an F# compiler internal "type" corresponding to the union case. For struct-unions, +/// the input should be the address of the expression. +val mkUnionCaseFieldGetUnprovenViaExprAddr : Expr * UnionCaseRef * TypeInst * int * range -> Expr + +/// Build a 'TOp.UnionCaseFieldSet' expression. For ref-unions, the input expression has 'TType_ucase', which is +/// an F# compiler internal "type" corresponding to the union case. For struct-unions, +/// the input should be the address of the expression. val mkUnionCaseFieldSet : Expr * UnionCaseRef * TypeInst * int * Expr * range -> Expr + +/// Like mkUnionCaseFieldGetUnprovenViaExprAddr, but for struct-unions, the input should be a copy of the expression. +val mkUnionCaseFieldGetUnproven : TcGlobals -> Expr * UnionCaseRef * TypeInst * int * range -> Expr + +val mkExnCaseFieldGet : Expr * TyconRef * int * range -> Expr val mkExnCaseFieldSet : Expr * TyconRef * int * Expr * range -> Expr //------------------------------------------------------------------------- @@ -217,6 +240,7 @@ val mkGetTupleItemN : TcGlobals -> range -> int -> ILType -> Expr -> TType -> Ex exception DefensiveCopyWarning of string * range type Mutates = DefinitelyMutates | PossiblyMutates | NeverMutates +val mkExprAddrOfExprAux : TcGlobals -> bool -> bool -> Mutates -> Expr -> ValRef option -> range -> (Val * Expr) option * Expr val mkExprAddrOfExpr : TcGlobals -> bool -> bool -> Mutates -> Expr -> ValRef option -> range -> (Expr -> Expr) * Expr //------------------------------------------------------------------------- @@ -811,7 +835,6 @@ val mkValAddr : range -> ValRef -> Expr //------------------------------------------------------------------------- val mkRecdFieldGet : TcGlobals -> Expr * RecdFieldRef * TypeInst * range -> Expr -val mkRecdFieldSet : TcGlobals -> Expr * RecdFieldRef * TypeInst * Expr * range -> Expr //------------------------------------------------------------------------- // Get the targets used in a decision graph (for reporting warnings) diff --git a/src/fsharp/TastPickle.fs b/src/fsharp/TastPickle.fs index 2b68fbb7c57..cf37fbfc193 100755 --- a/src/fsharp/TastPickle.fs +++ b/src/fsharp/TastPickle.fs @@ -2315,6 +2315,7 @@ and p_op x st = | TOp.ValFieldGetAddr (a) -> p_byte 25 st; p_rfref a st | TOp.UInt16s arr -> p_byte 26 st; p_array p_uint16 arr st | TOp.Reraise -> p_byte 27 st + | TOp.UnionCaseFieldGetAddr (a,b) -> p_byte 28 st; p_tup2 p_ucref p_int (a,b) st | TOp.Goto _ | TOp.Label _ | TOp.Return -> failwith "unexpected backend construct in pickled TAST" #endif @@ -2376,6 +2377,9 @@ and u_op st = TOp.ValFieldGetAddr a | 26 -> TOp.UInt16s (u_array u_uint16 st) | 27 -> TOp.Reraise + | 28 -> let a = u_ucref st + let b = u_int st + TOp.UnionCaseFieldGetAddr (a,b) | _ -> ufailwith st "u_op" #if INCLUDE_METADATA_WRITER diff --git a/src/fsharp/TypeChecker.fs b/src/fsharp/TypeChecker.fs index 5df8b030df1..f9957bc53cf 100755 --- a/src/fsharp/TypeChecker.fs +++ b/src/fsharp/TypeChecker.fs @@ -2988,7 +2988,8 @@ let BuildRecdFieldSet g m objExpr (rfinfo:RecdFieldInfo) argExpr = let tgty = rfinfo.EnclosingType let valu = isStructTy g tgty let objExpr = if valu then objExpr else mkCoerceExpr(objExpr,tgty,m,tyOfExpr g objExpr) - mkRecdFieldSet g (objExpr,rfinfo.RecdFieldRef,rfinfo.TypeInst,argExpr,m) + let wrap,objExpr = mkExprAddrOfExpr g valu false DefinitelyMutates objExpr None m + wrap (mkRecdFieldSetViaExprAddr (objExpr,rfinfo.RecdFieldRef,rfinfo.TypeInst,argExpr,m) ) //------------------------------------------------------------------------- @@ -3622,7 +3623,7 @@ let CheckAndRewriteObjectCtor g env (ctorLambaExpr:Expr) = let thisTy = tyOfExpr g recdExpr let thisExpr = mkGetArg0 m thisTy let thisTyInst = argsOfAppTy g thisTy - let setExpr = mkRecdFieldSet g (thisExpr, rfref, thisTyInst, mkOne g m, m) + let setExpr = mkRecdFieldSetViaExprAddr (thisExpr, rfref, thisTyInst, mkOne g m, m) Expr.Sequential(recdExpr,setExpr,ThenDoSeq,SuppressSequencePointOnExprOfSequential,m) recdExpr @@ -5657,7 +5658,7 @@ and TcExprUndelayed cenv overallTy env tpenv (expr: SynExpr) = | SynExpr.LibraryOnlyUnionCaseFieldGet (e1,c,n,m) -> let e1',ty1,tpenv = TcExprOfUnknownType cenv env tpenv e1 let mkf,ty2 = TcUnionCaseOrExnField cenv env ty1 m c n - ((fun (a,b) n -> mkUnionCaseFieldGetUnproven(e1',a,b,n,m)), + ((fun (a,b) n -> mkUnionCaseFieldGetUnproven cenv.g (e1',a,b,n,m)), (fun a n -> mkExnCaseFieldGet(e1',a,n,m))) UnifyTypes cenv env m overallTy ty2 mkf n,tpenv @@ -5943,18 +5944,19 @@ and TcRecordConstruction cenv overallTy env tpenv optOrigExpr objTy fldsList m = (fname,fieldExpr),tpenv) // Add rebindings for unbound field when an "old value" is available - let oldFldsList = + // Effect order: mutable fields may get modified by other bindings... + let oldFldsList, wrap = match optOrigExpr with - | None -> [] - | Some (_,_,oldve') -> - // When we have an "old" value, append bindings for the unbound fields. - // Effect order - mutable fields may get modified by other bindings... - let fieldNameUnbound nom = List.forall (fun (name,_) -> name <> nom) fldsList - fspecs - |> List.choose (fun rfld -> + | None -> [], id + | Some (_,_,oldve) -> + let wrap,oldveaddr = mkExprAddrOfExpr cenv.g tycon.IsStructOrEnumTycon false NeverMutates oldve None m + let fieldNameUnbound nom = List.forall (fun (name,_) -> name <> nom) fldsList + let flds = + fspecs |> List.choose (fun rfld -> if fieldNameUnbound rfld.Name && not rfld.IsZeroInit - then Some(rfld.Name, mkRecdFieldGet cenv.g (oldve',tcref.MakeNestedRecdFieldRef rfld,tinst,m)) + then Some(rfld.Name, mkRecdFieldGetViaExprAddr (oldveaddr,tcref.MakeNestedRecdFieldRef rfld,tinst,m)) else None) + flds, wrap let fldsList = fldsList @ oldFldsList @@ -5987,7 +5989,7 @@ and TcRecordConstruction cenv overallTy env tpenv optOrigExpr objTy fldsList m = let args = List.map snd fldsList - let expr = mkRecordExpr cenv.g (GetRecdInfo env, tcref, tinst, rfrefs, args, m) + let expr = wrap (mkRecordExpr cenv.g (GetRecdInfo env, tcref, tinst, rfrefs, args, m)) let expr = match optOrigExpr with @@ -5995,10 +5997,10 @@ and TcRecordConstruction cenv overallTy env tpenv optOrigExpr objTy fldsList m = // '{ recd fields }'. // expr - | Some (old',oldv',_) -> + | Some (old,oldv,_) -> // '{ recd with fields }'. // Assign the first object to a tmp and then construct - mkCompGenLet m oldv' old' expr + mkCompGenLet m oldv old expr expr, tpenv @@ -6437,13 +6439,13 @@ and TcRecdExpr cenv overallTy env tpenv (inherits, optOrigExpr, flds, mWholeExpr let optOrigExpr,tpenv = match optOrigExpr with | None -> None, tpenv - | Some (e, _) -> + | Some (origExpr, _) -> match inherits with | Some (_,_,mInherits, _, _) -> error(Error(FSComp.SR.tcInvalidRecordConstruction(),mInherits)) | None -> - let e',tpenv = TcExpr cenv overallTy env tpenv e - let v',ve' = mkCompGenLocal mWholeExpr "inputRecord" overallTy - Some (e',v',ve'), tpenv + let olde,tpenv = TcExpr cenv overallTy env tpenv origExpr + let oldv,oldve = mkCompGenLocal mWholeExpr "inputRecord" overallTy + Some (olde,oldv,oldve), tpenv let fldsList = let flds = @@ -9272,7 +9274,9 @@ and TcMethodApplication match assignedArg.CalledArg.OptArgInfo with | CallerSide _ -> if isOptCallerArg then - mkUnionCaseFieldGetUnproven(expr,mkSomeCase cenv.g,[destOptionTy cenv.g callerArgTy],0,m) + // STRUCT OPTIONS: if we allow struct options as optional arguments then we should take + // the address correctly. + mkUnionCaseFieldGetUnprovenViaExprAddr (expr,mkSomeCase cenv.g,[destOptionTy cenv.g callerArgTy],0,m) else expr | CalleeSide -> @@ -10915,7 +10919,7 @@ and MakeCheckSafeInitField g tinst thisValOpt rfref reqExpr (expr:Expr) = | None -> mkStaticRecdFieldGet (rfref, tinst, m) | Some thisVar -> // This is an instance method, it must have a 'this' var - mkRecdFieldGet g (exprForVal m thisVar, rfref, tinst, m) + mkRecdFieldGetViaExprAddr (exprForVal m thisVar, rfref, tinst, m) let failureExpr = match thisValOpt with None -> mkCallFailStaticInit g m | Some _ -> mkCallFailInit g m mkCompGenSequential m (mkIfThen g m (mkILAsmClt g m availExpr reqExpr) failureExpr) expr @@ -12050,7 +12054,7 @@ module IncrClassChecking = begin let binders = [ match ctorInfo.InstanceCtorSafeInitInfo with | SafeInitField (rfref, _) -> - let setExpr = mkRecdFieldSet cenv.g (exprForVal m thisVal, rfref, thisTyInst, mkOne cenv.g m, m) + let setExpr = mkRecdFieldSetViaExprAddr (exprForVal m thisVal, rfref, thisTyInst, mkOne cenv.g m, m) let setExpr = reps.FixupIncrClassExprPassC (Some(thisVal)) safeStaticInitInfo thisTyInst setExpr let binder = (fun e -> mkSequential SequencePointsAtSeq setExpr.Range setExpr e) let isPriorToSuperInit = false @@ -13567,7 +13571,7 @@ module EstablishTypeDefinitionCores = begin if hasClassAttr && not (match k with TyconClass -> true | _ -> false) || hasMeasureAttr && not (match k with TyconClass | TyconAbbrev | TyconHiddenRepr -> true | _ -> false) || hasInterfaceAttr && not (match k with TyconInterface -> true | _ -> false) || - hasStructAttr && not (match k with TyconStruct | TyconRecord -> true | _ -> false) then + hasStructAttr && not (match k with TyconStruct | TyconRecord | TyconUnion -> true | _ -> false) then error(Error(FSComp.SR.tcKindOfTypeSpecifiedDoesNotMatchDefinition(),m)) k @@ -13594,13 +13598,14 @@ module EstablishTypeDefinitionCores = begin [ match synTyconRepr with | SynTypeDefnSimpleRepr.None _ -> () | SynTypeDefnSimpleRepr.Union (_,unionCases,_) -> + for (UnionCase (_,_,args,_,_,m)) in unionCases do - match args with - | UnionCaseFields flds -> + match args with + | UnionCaseFields flds -> for (Field(_,_,_,ty,_,_,_,m)) in flds do let ty',_ = TcTypeAndRecover cenv NoNewTypars NoCheckCxs ItemOccurence.UseInType env tpenv ty yield (ty',m) - | UnionCaseFullType (ty,arity) -> + | UnionCaseFullType (ty,arity) -> let ty',_ = TcTypeAndRecover cenv NoNewTypars NoCheckCxs ItemOccurence.UseInType env tpenv ty let argtysl,_ = GetTopTauTypeInFSharpForm cenv.g (arity |> TranslateTopValSynInfo m (TcAttributes cenv env) |> TranslatePartialArity []).ArgInfos ty' m if argtysl.Length > 1 then @@ -13638,7 +13643,7 @@ module EstablishTypeDefinitionCores = begin /// but /// - we don't yet 'properly' establish constraints on type parameters let private TcTyconDefnCore_Phase0_BuildInitialTycon cenv env parent (TyconDefnCoreIndexed(synTyconInfo,synTyconRepr,_,preEstablishedHasDefaultCtor,hasSelfReferentialCtor,_)) = - let (ComponentInfo(synAttrs,synTypars, _,id,doc,preferPostfix, vis,_)) = synTyconInfo + let (ComponentInfo(_,synTypars, _,id,doc,preferPostfix, vis,_)) = synTyconInfo let checkedTypars = TcTyparDecls cenv env synTypars id |> List.iter (CheckNamespaceModuleOrTypeName cenv.g) let id = ComputeTyconName (id, (match synTyconRepr with SynTypeDefnSimpleRepr.TypeAbbrev _ -> false | _ -> true), checkedTypars) @@ -13667,15 +13672,7 @@ module EstablishTypeDefinitionCores = begin // If we supported nested types and modules then additions would be needed here let lmtyp = notlazy (NewEmptyModuleOrNamespaceType ModuleOrType) - let isStructRecordType = - match synTyconRepr with - | SynTypeDefnSimpleRepr.Record _ -> - let attrs = TcAttributes cenv env AttributeTargets.TyconDecl synAttrs - HasFSharpAttribute cenv.g cenv.g.attrib_StructAttribute attrs - | _ -> - false - - NewTycon(cpath, id.idText, id.idRange, vis, visOfRepr, TyparKind.Type, LazyWithContext.NotLazy checkedTypars, doc.ToXmlDoc(), preferPostfix, preEstablishedHasDefaultCtor, hasSelfReferentialCtor, isStructRecordType, lmtyp) + NewTycon(cpath, id.idText, id.idRange, vis, visOfRepr, TyparKind.Type, LazyWithContext.NotLazy checkedTypars, doc.ToXmlDoc(), preferPostfix, preEstablishedHasDefaultCtor, hasSelfReferentialCtor, lmtyp) //------------------------------------------------------------------------- /// Establishing type definitions: early phase: work out the basic kind of the type definition @@ -13697,6 +13694,16 @@ module EstablishTypeDefinitionCores = begin let attrs = TcAttributes cenv envinner AttributeTargets.TyconDecl synAttrs let hasMeasureAttr = HasFSharpAttribute cenv.g cenv.g.attrib_MeasureAttribute attrs + let isStructRecordOrUnionType = + match synTyconRepr with + | SynTypeDefnSimpleRepr.Record _ + | SynTypeDefnSimpleRepr.Union _ -> + HasFSharpAttribute cenv.g cenv.g.attrib_StructAttribute attrs + | _ -> + false + + tycon.SetIsStructRecordOrUnion isStructRecordOrUnionType + // Set the compiled name, if any tycon.Data.entity_compiled_name <- TryFindFSharpStringAttribute cenv.g cenv.g.attrib_CompiledNameAttribute attrs @@ -14088,10 +14095,10 @@ module EstablishTypeDefinitionCores = begin match synTyconRepr with | SynTypeDefnSimpleRepr.None _ -> None | SynTypeDefnSimpleRepr.TypeAbbrev _ -> None - | SynTypeDefnSimpleRepr.Union _ -> None | SynTypeDefnSimpleRepr.LibraryOnlyILAssembly _ -> None + | SynTypeDefnSimpleRepr.Union _ | SynTypeDefnSimpleRepr.Record _ -> - if tycon.IsStructRecordTycon then Some(cenv.g.system_Value_typ) + if tycon.IsStructRecordOrUnionTycon then Some(cenv.g.system_Value_typ) else None | SynTypeDefnSimpleRepr.General (kind,_,slotsigs,fields,isConcrete,_,_,_) -> let kind = InferTyconKind cenv.g (kind,attrs,slotsigs,fields,inSig,isConcrete,m) @@ -14286,6 +14293,10 @@ module EstablishTypeDefinitionCores = begin noAllowNullLiteralAttributeCheck() structLayoutAttributeCheck(false) let unionCases = TcRecdUnionAndEnumDeclarations.TcUnionCaseDecls cenv envinner innerParent thisTy tpenv unionCases + + if tycon.IsStructRecordOrUnionTycon && unionCases.Length > 1 then + errorR(Error(FSComp.SR.tcStructUnionMultiCase(),m)) + writeFakeUnionCtorsToSink unionCases MakeUnionRepr unionCases, None, NoSafeInitInfo @@ -14622,11 +14633,18 @@ module EstablishTypeDefinitionCores = begin else // Only collect once from each type instance. let doneTypes = ty :: doneTypes - let fspecs = structTycon.AllFieldsAsList |> List.filter (fun fspec -> includeStaticFields || not fspec.IsStatic) + let fspecs = + if structTycon.IsUnionTycon then + [ for uc in structTycon.UnionCasesArray do + for c in uc.FieldTable.AllFieldsAsList do + yield c] + else + structTycon.AllFieldsAsList + let fspecs = fspecs |> List.filter (fun fspec -> includeStaticFields || not fspec.IsStatic) let doneTypes,acc = List.foldBack (accStructField structTycon tinst) fspecs (doneTypes,acc) doneTypes,acc and accStructInstanceFields ty structTycon tinst (doneTypes,acc) = accStructFields false ty structTycon tinst (doneTypes,acc) - and accStructAllFields ty structTycon tinst (doneTypes,acc) = accStructFields true ty structTycon tinst (doneTypes,acc) + and accStructAllFields ty (structTycon: Tycon) tinst (doneTypes,acc) = accStructFields true ty structTycon tinst (doneTypes,acc) let acc = [] let acc = diff --git a/src/fsharp/infos.fs b/src/fsharp/infos.fs index 93d8287315d..76e45b9b815 100755 --- a/src/fsharp/infos.fs +++ b/src/fsharp/infos.fs @@ -87,7 +87,7 @@ let GetSuperTypeOfType g amap m typ = Some g.obj_ty elif isTupleStructTy g typ then Some g.obj_ty - elif isRecdTy g typ then + elif isRecdTy g typ || isUnionTy g typ then Some g.obj_ty else None diff --git a/src/fsharp/tast.fs b/src/fsharp/tast.fs index 962181713ab..c3154c8eb7b 100755 --- a/src/fsharp/tast.fs +++ b/src/fsharp/tast.fs @@ -350,12 +350,12 @@ type TyparFlags(flags:int32) = [] type EntityFlags(flags:int64) = - new (usesPrefixDisplay, isModuleOrNamespace, preEstablishedHasDefaultCtor, hasSelfReferentialCtor, isStructRecordType) = + new (usesPrefixDisplay, isModuleOrNamespace, preEstablishedHasDefaultCtor, hasSelfReferentialCtor, isStructRecordOrUnionType) = EntityFlags((if isModuleOrNamespace then 0b00000000001L else 0L) ||| (if usesPrefixDisplay then 0b00000000010L else 0L) ||| (if preEstablishedHasDefaultCtor then 0b00000000100L else 0L) ||| (if hasSelfReferentialCtor then 0b00000001000L else 0L) ||| - (if isStructRecordType then 0b00000100000L else 0L)) + (if isStructRecordOrUnionType then 0b00000100000L else 0L)) member x.IsModuleOrNamespace = (flags &&& 0b00000000001L) <> 0x0L member x.IsPrefixDisplay = (flags &&& 0b00000000010L) <> 0x0L @@ -370,7 +370,7 @@ type EntityFlags(flags:int64) = member x.HasSelfReferentialConstructor = (flags &&& 0b00000001000L) <> 0x0L /// This bit represents a F# record that is a value type, or a struct record. - member x.IsStructRecordType = (flags &&& 0b00000100000L) <> 0x0L + member x.IsStructRecordOrUnionType = (flags &&& 0b00000100000L) <> 0x0L /// This bit is reserved for us in the pickle format, see pickle.fs, it's bing listed here to stop it ever being used for anything else static member ReservedBitForPickleFormatTyconReprFlag = 0b00000010000L @@ -776,7 +776,7 @@ type Entity = member x.IsRecordTycon = match x.TypeReprInfo with | TRecdRepr _ -> true | _ -> false /// Indicates if this is an F# type definition whose r.h.s. is known to be a record type definition that is a value type. - member x.IsStructRecordTycon = match x.TypeReprInfo with | TRecdRepr _ -> x.Data.entity_flags.IsStructRecordType | _ -> false + member x.IsStructRecordOrUnionTycon = match x.TypeReprInfo with TRecdRepr _ | TUnionRepr _ -> x.Data.entity_flags.IsStructRecordOrUnionType | _ -> false /// Indicates if this is an F# type definition whose r.h.s. is known to be some kind of F# object model definition member x.IsFSharpObjectModelTycon = match x.TypeReprInfo with | TFSharpObjectRepr _ -> true | _ -> false @@ -822,7 +822,8 @@ type Entity = /// Indicates if this is an F#-defined struct or enum type definition , i.e. a value type definition member x.IsFSharpStructOrEnumTycon = match x.TypeReprInfo with - | TRecdRepr _ -> x.IsStructRecordTycon + | TRecdRepr _ -> x.IsStructRecordOrUnionTycon + | TUnionRepr _ -> x.IsStructRecordOrUnionTycon | TFSharpObjectRepr info -> match info.fsobjmodel_kind with | TTyconClass | TTyconInterface | TTyconDelegate _ -> false @@ -963,6 +964,9 @@ type Entity = /// Set the custom attributes on an F# type definition. member x.SetAttribs attribs = x.Data.entity_attribs <- attribs + /// Sets the structness of a record or union type definition + member x.SetIsStructRecordOrUnion b = let x = x.Data in let flags = x.entity_flags in x.entity_flags <- EntityFlags(flags.IsPrefixDisplay, flags.IsModuleOrNamespace, flags.PreEstablishedHasDefaultConstructor, flags.HasSelfReferentialConstructor, b) + and @@ -1731,7 +1735,7 @@ and Construct = entity_kind=kind entity_range=m entity_other_range=None - entity_flags=EntityFlags(usesPrefixDisplay=false, isModuleOrNamespace=false,preEstablishedHasDefaultCtor=false, hasSelfReferentialCtor=false, isStructRecordType=false) + entity_flags=EntityFlags(usesPrefixDisplay=false, isModuleOrNamespace=false,preEstablishedHasDefaultCtor=false, hasSelfReferentialCtor=false, isStructRecordOrUnionType=false) entity_attribs=[] // fetched on demand via est.fs API entity_typars= LazyWithContext.NotLazy [] entity_tycon_abbrev = None @@ -1760,7 +1764,7 @@ and Construct = entity_stamp=stamp entity_kind=TyparKind.Type entity_modul_contents = mtype - entity_flags=EntityFlags(usesPrefixDisplay=false, isModuleOrNamespace=true, preEstablishedHasDefaultCtor=false, hasSelfReferentialCtor=false,isStructRecordType=false) + entity_flags=EntityFlags(usesPrefixDisplay=false, isModuleOrNamespace=true, preEstablishedHasDefaultCtor=false, hasSelfReferentialCtor=false,isStructRecordOrUnionType=false) entity_typars=LazyWithContext.NotLazy [] entity_tycon_abbrev = None entity_tycon_repr = TNoRepr @@ -3574,15 +3578,16 @@ and /// TDSwitch(input, cases, default, range) /// /// Indicates a decision point in a decision tree. - /// input -- the expression being tested - /// cases -- the list of tests and their subsequent decision trees - /// default -- the default decision tree, if any + /// input -- The expression being tested. If switching over a struct union this + /// must be the address of the expression being tested. + /// cases -- The list of tests and their subsequent decision trees + /// default -- The default decision tree, if any /// range -- (precise documentation needed) | TDSwitch of Expr * DecisionTreeCase list * DecisionTree option * range /// TDSuccess(results, targets) /// - /// Indicates the decision tree has terminated with success, calling the given target with the given parameters. + /// Indicates the decision tree has terminated with success, transferring control to the given target with the given parameters. /// results -- the expressions to be bound to the variables at the target /// target -- the target number for the continuation | TDSuccess of FlatExprs * int @@ -3826,6 +3831,8 @@ and | UnionCaseProof of UnionCaseRef /// An operation representing a field-get from a union value, where that value has been proven to be of the corresponding union case. | UnionCaseFieldGet of UnionCaseRef * int + /// An operation representing a field-get from a union value, where that value has been proven to be of the corresponding union case. + | UnionCaseFieldGetAddr of UnionCaseRef * int /// An operation representing a field-get from a union value. The value is not assumed to have been proven to be of the corresponding union case. | UnionCaseFieldSet of UnionCaseRef * int /// An operation representing a field-get from an F# exception value. @@ -4568,7 +4575,7 @@ let NewExn cpath (id:Ident) access repr attribs doc = entity_typars=LazyWithContext.NotLazy [] entity_tycon_abbrev = None entity_tycon_repr = TNoRepr - entity_flags=EntityFlags(usesPrefixDisplay=false, isModuleOrNamespace=false, preEstablishedHasDefaultCtor=false, hasSelfReferentialCtor=false, isStructRecordType=false) + entity_flags=EntityFlags(usesPrefixDisplay=false, isModuleOrNamespace=false, preEstablishedHasDefaultCtor=false, hasSelfReferentialCtor=false, isStructRecordOrUnionType=false) entity_il_repr_cache= newCache() } let NewRecdField stat konst id ty isMutable isVolatile pattribs fattribs docOption access secret = @@ -4587,7 +4594,7 @@ let NewRecdField stat konst id ty isMutable isVolatile pattribs fattribs docOpt rfield_other_range = None } -let NewTycon (cpath, nm, m, access, reprAccess, kind, typars, docOption, usesPrefixDisplay, preEstablishedHasDefaultCtor, hasSelfReferentialCtor, isStructRecordType, mtyp) = +let NewTycon (cpath, nm, m, access, reprAccess, kind, typars, docOption, usesPrefixDisplay, preEstablishedHasDefaultCtor, hasSelfReferentialCtor, mtyp) = let stamp = newStamp() Tycon.New "tycon" { entity_stamp=stamp @@ -4596,7 +4603,7 @@ let NewTycon (cpath, nm, m, access, reprAccess, kind, typars, docOption, usesPre entity_kind=kind entity_range=m entity_other_range=None - entity_flags=EntityFlags(usesPrefixDisplay=usesPrefixDisplay, isModuleOrNamespace=false,preEstablishedHasDefaultCtor=preEstablishedHasDefaultCtor, hasSelfReferentialCtor=hasSelfReferentialCtor, isStructRecordType=isStructRecordType) + entity_flags=EntityFlags(usesPrefixDisplay=usesPrefixDisplay, isModuleOrNamespace=false,preEstablishedHasDefaultCtor=preEstablishedHasDefaultCtor, hasSelfReferentialCtor=hasSelfReferentialCtor, isStructRecordOrUnionType=false) entity_attribs=[] // fixed up after entity_typars=typars entity_tycon_abbrev = None @@ -4617,7 +4624,7 @@ let NewILTycon nlpath (nm,m) tps (scoref:ILScopeRef, enc, tdef:ILTypeDef) mtyp = // NOTE: hasSelfReferentialCtor=false is an assumption about mscorlib let hasSelfReferentialCtor = tdef.IsClass && (not scoref.IsAssemblyRef && scoref.AssemblyRef.Name = "mscorlib") - let tycon = NewTycon(nlpath, nm, m, taccessPublic, taccessPublic, TyparKind.Type, tps, XmlDoc.Empty, true, false, hasSelfReferentialCtor, false, mtyp) + let tycon = NewTycon(nlpath, nm, m, taccessPublic, taccessPublic, TyparKind.Type, tps, XmlDoc.Empty, true, false, hasSelfReferentialCtor, mtyp) tycon.Data.entity_tycon_repr <- TILObjectRepr (scoref,enc,tdef) tycon.TypeContents.tcaug_closed <- true diff --git a/src/ilx/EraseUnions.fs b/src/ilx/EraseUnions.fs index fac033126f9..c4cdfab0625 100644 --- a/src/ilx/EraseUnions.fs +++ b/src/ilx/EraseUnions.fs @@ -39,8 +39,7 @@ type DiscriminationTechnique = // class (no subclasses), but an integer tag is stored to discriminate between the objects. | IntegerTag -// FLATTEN_SINGLE_NON_NULLARY_AND_ALWAYS_USE_TAGS looks like a useful representation -// optimization - it trades an extra integer tag in the root type +// A potentially useful additional representation trades an extra integer tag in the root type // for faster discrimination, and in the important single-non-nullary constructor case // // type Tree = Tip | Node of int * Tree * Tree @@ -60,14 +59,15 @@ type UnionReprDecisions<'Union,'Alt,'Type> nullPermitted:'Union->bool, isNullary:'Alt->bool, isList:'Union->bool, + isStruct:'Union->bool, nameOfAlt : 'Alt -> string, makeRootType: 'Union -> 'Type, makeNestedType: 'Union * string -> 'Type) = static let TaggingThresholdFixedConstant = 4 - member repr.OptimizeAllAlternativesToConstantFieldsInRootClass cu = - Array.forall isNullary (getAlternatives cu) + member repr.RepresentAllAlternativesAsConstantFieldsInRootClass cu = + cu |> getAlternatives |> Array.forall isNullary member repr.DiscriminationTechnique cu = if isList cu then @@ -77,18 +77,15 @@ type UnionReprDecisions<'Union,'Alt,'Type> if alts.Length = 1 then SingleCase elif -#if FLATTEN_SINGLE_NON_NULLARY_AND_ALWAYS_USE_TAGS - nullPermitted cu then -#else + not (isStruct cu) && alts.Length < TaggingThresholdFixedConstant && - not (repr.OptimizeAllAlternativesToConstantFieldsInRootClass cu) then -#endif + not (repr.RepresentAllAlternativesAsConstantFieldsInRootClass cu) then RuntimeTypes else IntegerTag // WARNING: this must match IsUnionTypeWithNullAsTrueValue in the F# compiler - member repr.OptimizeAlternativeToNull (cu,alt) = + member repr.RepresentAlternativeAsNull (cu,alt) = let alts = getAlternatives cu nullPermitted cu && (repr.DiscriminationTechnique cu = RuntimeTypes) && (* don't use null for tags, lists or single-case *) @@ -96,54 +93,52 @@ type UnionReprDecisions<'Union,'Alt,'Type> Array.exists (isNullary >> not) alts && isNullary alt (* is this the one? *) - member repr.OptimizingOneAlternativeToNull cu = + member repr.RepresentOneAlternativeAsNull cu = let alts = getAlternatives cu nullPermitted cu && - alts |> Array.existsOne (fun alt -> repr.OptimizeAlternativeToNull (cu,alt)) + alts |> Array.existsOne (fun alt -> repr.RepresentAlternativeAsNull (cu,alt)) - member repr.OptimizeSingleNonNullaryAlternativeToRootClassAndAnyOtherAlternativesToNull (cu,alt) = + member repr.RepresentSingleNonNullaryAlternativeAsInstancesOfRootClassAndAnyOtherAlternativesAsNull (cu,alt) = // Check all nullary constructors are being represented without using sub-classes let alts = getAlternatives cu + not (isStruct cu) && not (isNullary alt) && - (alts |> Array.forall (fun alt2 -> not (isNullary alt2) || repr.OptimizeAlternativeToNull (cu,alt2))) && + (alts |> Array.forall (fun alt2 -> not (isNullary alt2) || repr.RepresentAlternativeAsNull (cu,alt2))) && // Check this is the one and only non-nullary constructor Array.existsOne (isNullary >> not) alts -#if FLATTEN_SINGLE_NON_NULLARY_AND_ALWAYS_USE_TAGS - member repr.OptimizeSingleNonNullaryAlternativeToRootClassAndOtherAlternativesToTagged (cu,alt) = - let alts = getAlternatives cu - not (isNullary alt) && - alts.Length > 1 && - Array.existsOne (isNullary >> not) alts && - not (nullPermitted cu) -#endif - - member repr.OptimizeSingleNonNullaryAlternativeToRootClass (cu,alt) = + member repr.RepresentAlternativeAsFreshInstancesOfRootClass (cu,alt) = + // Flattening + isStruct cu || // Check all nullary constructors are being represented without using sub-classes (isList cu && nameOfAlt alt = ALT_NAME_CONS) || - repr.OptimizeSingleNonNullaryAlternativeToRootClassAndAnyOtherAlternativesToNull (cu, alt) -#if FLATTEN_SINGLE_NON_NULLARY_AND_ALWAYS_USE_TAGS - repr.OptimizeSingleNonNullaryAlternativeToRootClassAndOtherAlternativesToTagged (cu,alt) -#endif + repr.RepresentSingleNonNullaryAlternativeAsInstancesOfRootClassAndAnyOtherAlternativesAsNull (cu, alt) - member repr.OptimizeAlternativeToConstantFieldInTaggedRootClass (cu,alt) = + member repr.RepresentAlternativeAsConstantFieldInTaggedRootClass (cu,alt) = + not (isStruct cu) && isNullary alt && - not (repr.OptimizeAlternativeToNull (cu,alt)) && + not (repr.RepresentAlternativeAsNull (cu,alt)) && (repr.DiscriminationTechnique cu <> RuntimeTypes) + member repr.Flatten cu = + isStruct cu + member repr.OptimizeAlternativeToRootClass (cu,alt) = // The list type always collapses to the root class isList cu || - repr.OptimizeAllAlternativesToConstantFieldsInRootClass cu || - repr.OptimizeAlternativeToConstantFieldInTaggedRootClass (cu,alt) || - repr.OptimizeSingleNonNullaryAlternativeToRootClass(cu,alt) + // Structs are always flattened + repr.Flatten cu || + repr.RepresentAllAlternativesAsConstantFieldsInRootClass cu || + repr.RepresentAlternativeAsConstantFieldInTaggedRootClass (cu,alt) || + repr.RepresentAlternativeAsFreshInstancesOfRootClass(cu,alt) member repr.MaintainPossiblyUniqueConstantFieldForAlternative(cu,alt) = - not (repr.OptimizeAlternativeToNull (cu,alt)) && + not (isStruct cu) && + not (repr.RepresentAlternativeAsNull (cu,alt)) && isNullary alt member repr.TypeForAlternative (cuspec,alt) = - if repr.OptimizeAlternativeToRootClass (cuspec,alt) || repr.OptimizeAlternativeToNull (cuspec,alt) then + if repr.OptimizeAlternativeToRootClass (cuspec,alt) || repr.RepresentAlternativeAsNull (cuspec,alt) then makeRootType cuspec else let altName = nameOfAlt alt @@ -153,7 +148,7 @@ type UnionReprDecisions<'Union,'Alt,'Type> let baseTyOfUnionSpec (cuspec : IlxUnionSpec) = - mkILBoxedTyRaw cuspec.TypeRef cuspec.GenericArgs + mkILNamedTyRaw cuspec.Boxity cuspec.TypeRef cuspec.GenericArgs let mkMakerName (cuspec: IlxUnionSpec) nm = match cuspec.HasHelpers with @@ -170,9 +165,10 @@ let cuspecRepr = (fun (cuspec:IlxUnionSpec) -> cuspec.IsNullPermitted), (fun (alt:IlxUnionAlternative) -> alt.IsNullary), (fun cuspec -> cuspec.HasHelpers = IlxUnionHasHelpers.SpecialFSharpListHelpers), + (fun cuspec -> cuspec.Boxity = ILBoxity.AsValue), (fun (alt:IlxUnionAlternative) -> alt.Name), - (fun cuspec -> mkILBoxedTyRaw cuspec.TypeRef cuspec.GenericArgs), - (fun (cuspec,nm) -> mkILBoxedTyRaw (mkILTyRefInTyRef (mkCasesTypeRef cuspec, nm)) cuspec.GenericArgs)) + (fun cuspec -> cuspec.EnclosingType), + (fun (cuspec,nm) -> mkILNamedTyRaw cuspec.Boxity (mkILTyRefInTyRef (mkCasesTypeRef cuspec, nm)) cuspec.GenericArgs)) type NoTypesGeneratedViaThisReprDecider = NoTypesGeneratedViaThisReprDecider let cudefRepr = @@ -181,6 +177,7 @@ let cudefRepr = (fun (_td,cud) -> cud.cudNullPermitted), (fun (alt:IlxUnionAlternative) -> alt.IsNullary), (fun (_td,cud) -> cud.cudHasHelpers = IlxUnionHasHelpers.SpecialFSharpListHelpers), + (fun (td,_cud) -> match td.tdKind with ILTypeDefKind.ValueType -> true | _ -> false), (fun (alt:IlxUnionAlternative) -> alt.Name), (fun (_td,_cud) -> NoTypesGeneratedViaThisReprDecider), (fun ((_td,_cud),_nm) -> NoTypesGeneratedViaThisReprDecider)) @@ -198,7 +195,7 @@ let refToFieldInTy ty (nm, fldTy) = mkILFieldSpecInTy (ty, nm, fldTy) let formalTypeArgs (baseTy:ILType) = ILList.mapi (fun i _ -> mkILTyvarTy (uint16 i)) baseTy.GenericArgs let constFieldName nm = "_unique_" + nm let constFormalFieldTy (baseTy:ILType) = - ILType.Boxed (mkILTySpecRaw (baseTy.TypeRef, formalTypeArgs baseTy)) + mkILNamedTyRaw baseTy.Boxity baseTy.TypeRef (formalTypeArgs baseTy) let mkConstFieldSpecFromId (baseTy:ILType) constFieldId = refToFieldInTy baseTy constFieldId @@ -265,13 +262,22 @@ let mkLdData (avoidHelpers, cuspec, cidx, fidx) = else [ mkNormalCall (mkILNonGenericInstanceMethSpecInTy(altTy,"get_" + adjustFieldName cuspec.HasHelpers fieldDef.Name,[],fieldDef.Type)) ] +let mkLdDataAddr (avoidHelpers, cuspec, cidx, fidx) = + let alt = altOfUnionSpec cuspec cidx + let altTy = tyForAlt cuspec alt + let fieldDef = alt.FieldDef fidx + if avoidHelpers then + [ mkNormalLdflda (mkILFieldSpecInTy(altTy,fieldDef.LowerName, fieldDef.Type)) ] + else + failwith (sprintf "can't load address using helpers, for fieldDef %s" fieldDef.LowerName) + let mkGetTailOrNull avoidHelpers cuspec = mkLdData (avoidHelpers, cuspec, 1, 1) (* tail is in alternative 1, field number 1 *) let mkGetTagFromHelpers ilg (cuspec: IlxUnionSpec) = let baseTy = baseTyOfUnionSpec cuspec - if cuspecRepr.OptimizingOneAlternativeToNull cuspec then + if cuspecRepr.RepresentOneAlternativeAsNull cuspec then mkNormalCall (mkILNonGenericStaticMethSpecInTy (baseTy, "Get" + tagPropertyName, [baseTy], mkTagFieldFormalType ilg cuspec)) else mkNormalCall (mkILNonGenericInstanceMethSpecInTy(baseTy, "get_" + tagPropertyName, [], mkTagFieldFormalType ilg cuspec)) @@ -289,32 +295,29 @@ let mkCeqThen after = let mkTagDiscriminate ilg cuspec _baseTy cidx = - mkGetTag ilg cuspec - @ [ mkLdcInt32 cidx - AI_ceq ] + mkGetTag ilg cuspec @ [ mkLdcInt32 cidx; AI_ceq ] let mkTagDiscriminateThen ilg cuspec cidx after = - mkGetTag ilg cuspec - @ [ mkLdcInt32 cidx ] - @ mkCeqThen after + mkGetTag ilg cuspec @ [ mkLdcInt32 cidx ] @ mkCeqThen after let convNewDataInstrInternal ilg cuspec cidx = let alt = altOfUnionSpec cuspec cidx let altTy = tyForAlt cuspec alt let altName = alt.Name - if cuspecRepr.OptimizeAlternativeToNull (cuspec,alt) then + if cuspecRepr.RepresentAlternativeAsNull (cuspec,alt) then [ AI_ldnull ] elif cuspecRepr.MaintainPossiblyUniqueConstantFieldForAlternative (cuspec,alt) then let baseTy = baseTyOfUnionSpec cuspec [ I_ldsfld (Nonvolatile,mkConstFieldSpec altName baseTy) ] - elif cuspecRepr.OptimizeSingleNonNullaryAlternativeToRootClass (cuspec,alt) then + elif cuspecRepr.RepresentAlternativeAsFreshInstancesOfRootClass (cuspec,alt) then let baseTy = baseTyOfUnionSpec cuspec let instrs, tagfields = match cuspecRepr.DiscriminationTechnique cuspec with | IntegerTag -> [ mkLdcInt32 cidx ], [mkTagFieldType ilg cuspec] | _ -> [], [] - instrs @ [ mkNormalNewobj(mkILCtorMethSpecForTy (baseTy,(Array.toList alt.FieldTypes @ tagfields))) ] + let ctorFieldTys = alt.FieldTypes |> Array.toList + instrs @ [ mkNormalNewobj(mkILCtorMethSpecForTy (baseTy,(ctorFieldTys @ tagfields))) ] else [ mkNormalNewobj(mkILCtorMethSpecForTy (altTy,Array.toList alt.FieldTypes)) ] @@ -334,7 +337,7 @@ let mkNewData ilg (cuspec, cidx) = | AllHelpers | SpecialFSharpListHelpers | SpecialFSharpOptionHelpers -> - if cuspecRepr.OptimizeAlternativeToNull (cuspec,alt) then + if cuspecRepr.RepresentAlternativeAsNull (cuspec,alt) then [ AI_ldnull ] elif alt.IsNullary then [ mkNormalCall (mkILNonGenericStaticMethSpecInTy (baseTy, "get_" + altName, [], constFormalFieldTy baseTy)) ] @@ -353,9 +356,9 @@ let mkIsData ilg (avoidHelpers, cuspec, cidx) = let alt = altOfUnionSpec cuspec cidx let altTy = tyForAlt cuspec alt let altName = alt.Name - if cuspecRepr.OptimizeAlternativeToNull (cuspec,alt) then + if cuspecRepr.RepresentAlternativeAsNull (cuspec,alt) then [ AI_ldnull; AI_ceq ] - elif cuspecRepr.OptimizeSingleNonNullaryAlternativeToRootClassAndAnyOtherAlternativesToNull (cuspec,alt) then + elif cuspecRepr.RepresentSingleNonNullaryAlternativeAsInstancesOfRootClassAndAnyOtherAlternativesAsNull (cuspec,alt) then // in this case we can use a null test [ AI_ldnull; AI_cgt_un ] else @@ -377,7 +380,6 @@ type ICodeGen<'Mark> = abstract EmitInstr : ILInstr -> unit abstract EmitInstrs : ILInstr list -> unit -// TODO: this will be removed let genWith g : ILCode = let instrs = ResizeArray() let lab2pc = Dictionary() @@ -399,9 +401,9 @@ let mkBrIsNotData ilg (avoidHelpers, cuspec,cidx,tg) = let alt = altOfUnionSpec cuspec cidx let altTy = tyForAlt cuspec alt let altName = alt.Name - if cuspecRepr.OptimizeAlternativeToNull (cuspec,alt) then + if cuspecRepr.RepresentAlternativeAsNull (cuspec,alt) then [ I_brcmp (BI_brtrue,tg) ] - elif cuspecRepr.OptimizeSingleNonNullaryAlternativeToRootClassAndAnyOtherAlternativesToNull (cuspec,alt) then + elif cuspecRepr.RepresentSingleNonNullaryAlternativeAsInstancesOfRootClassAndAnyOtherAlternativesAsNull (cuspec,alt) then // in this case we can use a null test [ I_brcmp (BI_brfalse,tg) ] else @@ -454,10 +456,10 @@ let emitLdDataTagPrim ilg ldOpt (cg: ICodeGen<'Mark>) (avoidHelpers,cuspec: IlxU let alt = altOfUnionSpec cuspec cidx let internalLab = cg.GenerateDelayMark() let failLab = cg.GenerateDelayMark () - let cmpNull = cuspecRepr.OptimizeAlternativeToNull (cuspec, alt) + let cmpNull = cuspecRepr.RepresentAlternativeAsNull (cuspec, alt) let test = I_brcmp ((if cmpNull then BI_brtrue else BI_brfalse),cg.CodeLabel failLab) let testBlock = - if cmpNull || cuspecRepr.OptimizeSingleNonNullaryAlternativeToRootClass (cuspec,alt) then + if cmpNull || cuspecRepr.RepresentAlternativeAsFreshInstancesOfRootClass (cuspec,alt) then [ test ] else let altName = alt.Name @@ -479,9 +481,9 @@ let emitLdDataTagPrim ilg ldOpt (cg: ICodeGen<'Mark>) (avoidHelpers,cuspec: IlxU let emitLdDataTag ilg (cg: ICodeGen<'Mark>) (avoidHelpers,cuspec: IlxUnionSpec) = emitLdDataTagPrim ilg None cg (avoidHelpers,cuspec) -let emitCastData ilg (cg: ICodeGen<'Mark>) (canfail,cuspec,cidx) = +let emitCastData ilg (cg: ICodeGen<'Mark>) (canfail,avoidHelpers,cuspec,cidx) = let alt = altOfUnionSpec cuspec cidx - if cuspecRepr.OptimizeAlternativeToNull (cuspec,alt) then + if cuspecRepr.RepresentAlternativeAsNull (cuspec,alt) then if canfail then let outlab = cg.GenerateDelayMark () let internal1 = cg.GenerateDelayMark () @@ -489,7 +491,22 @@ let emitCastData ilg (cg: ICodeGen<'Mark>) (canfail,cuspec,cidx) = cg.SetMarkToHere internal1 cg.EmitInstrs [mkPrimaryAssemblyExnNewobj ilg "System.InvalidCastException"; I_throw ] cg.SetMarkToHere outlab - // If it can't fail, it's still verifiable just to leave the value on the stack unchecked + else + // If it can't fail, it's still verifiable just to leave the value on the stack unchecked + () + elif cuspecRepr.Flatten cuspec then + if canfail then + let outlab = cg.GenerateDelayMark () + let internal1 = cg.GenerateDelayMark () + cg.EmitInstrs [ AI_dup ] + emitLdDataTagPrim ilg None cg (avoidHelpers,cuspec) + cg.EmitInstrs [ mkLdcInt32 cidx; I_brcmp (BI_beq, cg.CodeLabel outlab) ] + cg.SetMarkToHere internal1 + cg.EmitInstrs [mkPrimaryAssemblyExnNewobj ilg "System.InvalidCastException"; I_throw ] + cg.SetMarkToHere outlab + else + // If it can't fail, it's still verifiable just to leave the value on the stack unchecked + () elif cuspecRepr.OptimizeAlternativeToRootClass (cuspec,alt) then () else @@ -510,11 +527,11 @@ let emitDataSwitch ilg (cg: ICodeGen<'Mark>) (avoidHelpers, cuspec, cases) = let altTy = tyForAlt cuspec alt let altName = alt.Name let failLab = cg.GenerateDelayMark () - let cmpNull = cuspecRepr.OptimizeAlternativeToNull (cuspec,alt) + let cmpNull = cuspecRepr.RepresentAlternativeAsNull (cuspec,alt) cg.EmitInstr (mkLdloc locn) let testInstr = I_brcmp ((if cmpNull then BI_brfalse else BI_brtrue),tg) - if cmpNull || cuspecRepr.OptimizeSingleNonNullaryAlternativeToRootClass (cuspec,alt) then + if cmpNull || cuspecRepr.RepresentAlternativeAsFreshInstancesOfRootClass (cuspec,alt) then cg.EmitInstr testInstr else cg.EmitInstrs (mkRuntimeTypeDiscriminateThen ilg avoidHelpers cuspec alt altName altTy testInstr) @@ -644,7 +661,7 @@ let convAlternativeDef ilg num (td:ILTypeDef) cud info cuspec (baseTy:ILType) (a let baseTesterMeths, baseTesterProps = if cud.cudAlternatives.Length <= 1 then [], [] - elif repr.OptimizingOneAlternativeToNull info then [], [] + elif repr.RepresentOneAlternativeAsNull info then [], [] else [ mkILNonGenericInstanceMethod ("get_" + mkTesterName altName, @@ -719,8 +736,8 @@ let convAlternativeDef ilg num (td:ILTypeDef) cud info cuspec (baseTy:ILType) (a [], [] let typeDefs, altDebugTypeDefs, altNullaryFields = - if repr.OptimizeAlternativeToNull (info,alt) then [], [], [] - elif repr.OptimizeSingleNonNullaryAlternativeToRootClass (info,alt) then [], [], [] + if repr.RepresentAlternativeAsNull (info,alt) then [], [], [] + elif repr.RepresentAlternativeAsFreshInstancesOfRootClass (info,alt) then [], [], [] else let altNullaryFields = if repr.MaintainPossiblyUniqueConstantFieldForAlternative(info,alt) then @@ -770,7 +787,8 @@ let convAlternativeDef ilg num (td:ILTypeDef) cud info cuspec (baseTy:ILType) (a mkMethodBody(true,emptyILLocals,2, nonBranchingInstrsToCode [ mkLdarg0 - mkNormalLdfld (mkILFieldSpecInTy (debugProxyTy,debugProxyFieldName,altTy)) + (match td.tdKind with ILTypeDefKind.ValueType -> mkNormalLdflda | _ -> mkNormalLdfld) + (mkILFieldSpecInTy (debugProxyTy,debugProxyFieldName,altTy)) mkNormalLdfld (mkILFieldSpecInTy(altTy,fldName,fldTy))],None)) |> addMethodGeneratedAttrs ilg) |> Array.toList @@ -863,8 +881,9 @@ let convAlternativeDef ilg num (td:ILTypeDef) cud info cuspec (baseTy:ILType) (a let mkClassUnionDef ilg tref td cud = - let baseTy = mkILFormalBoxedTy tref td.GenericParams - let cuspec = IlxUnionSpec(IlxUnionRef(baseTy.TypeRef, cud.cudAlternatives, cud.cudNullPermitted, cud.cudHasHelpers), baseTy.GenericArgs) + let boxity = match td.tdKind with ILTypeDefKind.ValueType -> ILBoxity.AsValue | _ -> ILBoxity.AsObject + let baseTy = mkILFormalNamedTy boxity tref td.GenericParams + let cuspec = IlxUnionSpec(IlxUnionRef(boxity,baseTy.TypeRef, cud.cudAlternatives, cud.cudNullPermitted, cud.cudHasHelpers), baseTy.GenericArgs) let info = (td,cud) let repr = cudefRepr let isTotallyImmutable = (cud.cudHasHelpers <> SpecialFSharpListHelpers) @@ -886,24 +905,33 @@ let mkClassUnionDef ilg tref td cud = | SingleCase | RuntimeTypes | TailOrNull -> [] | IntegerTag -> [ mkTagFieldId ilg cuspec ] - let selfFields, selfMeths, selfProps, _ = - match cud.cudAlternatives |> Array.toList |> List.findi 0 (fun alt -> repr.OptimizeSingleNonNullaryAlternativeToRootClass (info,alt)) with - | Some (alt,altNum) -> - let fields = (alt.FieldDefs |> Array.toList |> List.map mkUnionCaseFieldId) + let selfFields, selfMeths, selfProps = + + [ for alt in cud.cudAlternatives do + if repr.RepresentAlternativeAsFreshInstancesOfRootClass (info,alt) then + // TODO + let fields = alt.FieldDefs |> Array.toList |> List.map mkUnionCaseFieldId + let baseInit = + match td.tdKind with + | ILTypeDefKind.ValueType -> None + | _ -> + match td.Extends with + | None -> Some ilg.tspec_Object + | Some typ -> Some typ.TypeSpec + let ctor = mkILSimpleStorageCtor (cud.cudWhere, - (match td.Extends with None -> Some ilg.tspec_Object | Some typ -> Some typ.TypeSpec), + baseInit, baseTy, (fields @ tagFieldsInObject), (if cuspec.HasHelpers = AllHelpers then ILMemberAccess.Assembly else cud.cudReprAccess)) |> addMethodGeneratedAttrs ilg let props, meths = mkMethodsAndPropertiesForFields ilg cud.cudReprAccess cud.cudWhere cud.cudHasHelpers baseTy alt.FieldDefs - fields,([ctor] @ meths),props,altNum - - | None -> - [],[],[],0 + yield (fields,([ctor] @ meths),props) ] + |> List.unzip3 + |> (fun (a,b,c) -> List.concat a, List.concat b, List.concat c) let selfAndTagFields = [ for (fldName,fldTy) in (selfFields @ tagFieldsInObject) do @@ -912,7 +940,7 @@ let mkClassUnionDef ilg tref td cud = let ctorMeths = if (isNil selfFields && isNil tagFieldsInObject && nonNil selfMeths) - || cud.cudAlternatives |> Array.forall (fun alt -> repr.OptimizeSingleNonNullaryAlternativeToRootClass (info,alt)) then + || cud.cudAlternatives |> Array.forall (fun alt -> repr.RepresentAlternativeAsFreshInstancesOfRootClass (info,alt)) then [] (* no need for a second ctor in these cases *) @@ -962,7 +990,7 @@ let mkClassUnionDef ilg tref td cud = let body = mkMethodBody(true,emptyILLocals,2,genWith (fun cg -> emitLdDataTagPrim ilg (Some mkLdarg0) cg (true, cuspec); cg.EmitInstr I_ret), cud.cudWhere) // // If we are using NULL as a representation for an element of this type then we cannot // // use an instance method - if (repr.OptimizingOneAlternativeToNull info) then + if (repr.RepresentOneAlternativeAsNull info) then [ mkILNonGenericStaticMethod("Get" + tagPropertyName,cud.cudHelpersAccess,[mkILParamAnon baseTy],mkILReturn tagFieldType,body) |> addMethodGeneratedAttrs ilg ], [] @@ -1024,28 +1052,16 @@ let mkClassUnionDef ilg tref td cud = tdKind = ILTypeDefKind.Enum } let baseTypeDef = - { Name = td.Name + { td with NestedTypes = mkILTypeDefs (Option.toList enumTypeDef @ altTypeDefs @ altDebugTypeDefs @ td.NestedTypes.AsList) - GenericParams= td.GenericParams - Access = td.Access IsAbstract = isAbstract IsSealed = altTypeDefs.IsEmpty - IsSerializable=td.IsSerializable IsComInterop=false - Layout=td.Layout - IsSpecialName=td.IsSpecialName - Encoding=td.Encoding - Implements = td.Implements Extends= (match td.Extends with None -> Some ilg.typ_Object | _ -> td.Extends) Methods= mkILMethods (ctorMeths @ baseMethsFromAlt @ selfMeths @ tagMeths @ altUniqObjMeths @ existingMeths) - SecurityDecls=td.SecurityDecls - HasSecurity=td.HasSecurity Fields=mkILFields (selfAndTagFields @ List.map (fun (_,_,_,_,fdef,_) -> fdef) altNullaryFields @ td.Fields.AsList) - MethodImpls=td.MethodImpls InitSemantics=ILTypeInit.BeforeField - Events=td.Events Properties=mkILProperties (tagProps @ basePropsFromAlt @ selfProps @ existingProps) - CustomAttrs=td.CustomAttrs tdKind = ILTypeDefKind.Class } // The .cctor goes on the Cases type since that's where the constant fields for nullary constructors live |> addConstFieldInit diff --git a/src/ilx/EraseUnions.fsi b/src/ilx/EraseUnions.fsi index 09d5e41e29d..47311b27700 100644 --- a/src/ilx/EraseUnions.fsi +++ b/src/ilx/EraseUnions.fsi @@ -9,19 +9,22 @@ module internal Microsoft.FSharp.Compiler.AbstractIL.Extensions.ILX.EraseUnions open Microsoft.FSharp.Compiler.AbstractIL.IL open Microsoft.FSharp.Compiler.AbstractIL.Extensions.ILX.Types -/// Make the instruction sequence for an ILX "newdata" instruction +/// Make the instruction sequence for a "newdata" operation val mkNewData : ILGlobals -> IlxUnionSpec * int -> ILInstr list -/// Make the instruction sequence for an ILX "isdata" instruction +/// Make the instruction sequence for a "isdata" operation val mkIsData : ILGlobals -> bool * IlxUnionSpec * int -> ILInstr list -/// Make the instruction sequence for an ILX "lddata" instruction +/// Make the instruction sequence for a "lddata" operation val mkLdData : bool * IlxUnionSpec * int * int -> ILInstr list -/// Make the instruction sequence for an ILX "stdata" instruction +/// Make the instruction sequence for a "lddataa" operation +val mkLdDataAddr : bool * IlxUnionSpec * int * int -> ILInstr list + +/// Make the instruction sequence for a "stdata" operation val mkStData : IlxUnionSpec * int * int -> ILInstr list -/// Make the instruction sequence for an ILX "brisnotdata" instruction +/// Make the instruction sequence for a "brisnotdata" operation val mkBrIsNotData : ILGlobals -> avoidHelpers:bool * IlxUnionSpec * int * ILCodeLabel -> ILInstr list /// Make the type definition for a union type @@ -39,11 +42,11 @@ type ICodeGen<'Mark> = abstract EmitInstr : ILInstr -> unit abstract EmitInstrs : ILInstr list -> unit -/// Emit the instruction sequence for an ILX "castdata" instruction -val emitCastData : ILGlobals -> ICodeGen<'Mark> -> canfail: bool * IlxUnionSpec * int -> unit +/// Emit the instruction sequence for a "castdata" operation +val emitCastData : ILGlobals -> ICodeGen<'Mark> -> canfail: bool * avoidHelpers:bool * IlxUnionSpec * int -> unit -/// Emit the instruction sequence for an ILX "lddatatag" instruction +/// Emit the instruction sequence for a "lddatatag" operation val emitLdDataTag : ILGlobals -> ICodeGen<'Mark> -> avoidHelpers:bool * IlxUnionSpec -> unit -/// Emit the instruction sequence for an ILX "switchdata" instruction +/// Emit the instruction sequence for a "switchdata" operation val emitDataSwitch : ILGlobals -> ICodeGen<'Mark> -> avoidHelpers:bool * IlxUnionSpec * (int * ILCodeLabel) list -> unit diff --git a/tests/fsharp/typecheck/sigs/neg95.bsl b/tests/fsharp/typecheck/sigs/neg95.bsl index 63c66b9823f..77c5eb51c38 100644 --- a/tests/fsharp/typecheck/sigs/neg95.bsl +++ b/tests/fsharp/typecheck/sigs/neg95.bsl @@ -1,2 +1,6 @@ -neg94.fs(5,6,5,18): typecheck error FS0954: This type definition involves an immediate cyclic reference through a struct field or inheritance relation \ No newline at end of file +neg95.fs(5,6,5,18): typecheck error FS0954: This type definition involves an immediate cyclic reference through a struct field or inheritance relation + +neg95.fs(12,6,12,17): typecheck error FS0954: This type definition involves an immediate cyclic reference through a struct field or inheritance relation + +neg95.fs(15,6,15,18): typecheck error FS3199: A union type which is a struct must have only one case. \ No newline at end of file diff --git a/tests/fsharp/typecheck/sigs/neg95.fs b/tests/fsharp/typecheck/sigs/neg95.fs index 3a58778211b..6422fa14045 100644 --- a/tests/fsharp/typecheck/sigs/neg95.fs +++ b/tests/fsharp/typecheck/sigs/neg95.fs @@ -7,3 +7,9 @@ type StructRecord = X: float Y: StructRecord } + +[] +type StructUnion = StructUnion of float * StructUnion + +[] +type StructUnion2 = A of int | B of string From 75eec14421e5565965c6e99434dc0ac52d84743b Mon Sep 17 00:00:00 2001 From: Don Syme Date: Wed, 15 Jun 2016 20:52:12 +0100 Subject: [PATCH 053/129] struct unions --- src/fsharp/AugmentWithHashCompare.fs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/fsharp/AugmentWithHashCompare.fs b/src/fsharp/AugmentWithHashCompare.fs index 842561c857b..8c59387adfd 100644 --- a/src/fsharp/AugmentWithHashCompare.fs +++ b/src/fsharp/AugmentWithHashCompare.fs @@ -222,7 +222,7 @@ let mkRecdCompareWithComparer g tcref (tycon:Tycon) (_thisv,thise) (_,thate) com (mkRecdFieldGetViaExprAddr(thataddre, fref, tinst, m)) let expr = mkCompareTestConjuncts g m (List.map mkTest fields) - let expr = if tycon.IsStructOrEnumTycon then expr else mkBindNullComparison g m thise tce expr + let expr = if tycon.IsStructOrEnumTycon then expr else mkBindNullComparison g m thise thate expr let expr = mkBindThatAddr g m ty thataddrv tcv tce expr // will be optimized away if not necessary @@ -436,7 +436,7 @@ let mkUnionCompareWithComparer g tcref (tycon:Tycon) (_thisv,thise) (_thatv,that (mkUnionCaseTagGetViaExprAddr (thataddre,tcref,tinst,m)) tagsEqTested) - let expr = if tycon.IsStructOrEnumTycon then expr else mkBindNullComparison g m thise tce expr + let expr = if tycon.IsStructOrEnumTycon then expr else mkBindNullComparison g m thise thate expr let expr = mkBindThatAddr g m ty thataddrv tcv tce expr // will be optimized away if not necessary let expr = mkCompGenLet m tcv thate expr From 4153ebbf428b61c800a82b6a2fdb9b36c0ebcacf Mon Sep 17 00:00:00 2001 From: Don Syme Date: Wed, 15 Jun 2016 23:13:48 +0100 Subject: [PATCH 054/129] fix for test --- src/fsharp/AugmentWithHashCompare.fs | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/fsharp/AugmentWithHashCompare.fs b/src/fsharp/AugmentWithHashCompare.fs index 8c59387adfd..2769415f656 100644 --- a/src/fsharp/AugmentWithHashCompare.fs +++ b/src/fsharp/AugmentWithHashCompare.fs @@ -111,6 +111,11 @@ let mkCombineHashGenerators g m exprs accv acce = //------------------------------------------------------------------------- let mkThatAddrLocal g m ty = mkCompGenLocal m "obj" (mkThisTy g ty) +let mkThatAddrLocalIfNeeded g m tcve ty = + if isStructTy g ty then + let thataddrv, thataddre = mkCompGenLocal m "obj" (mkThisTy g ty) + Some thataddrv, thataddre + else None,tcve let mkThisVarThatVar g m ty = let thisv,thise = mkThisVar g m ty @@ -129,6 +134,12 @@ let mkBindThatAddr g m ty thataddrv thatv thate expr = else mkCompGenLet m thataddrv thate expr +let mkBindThatAddrIfNeeded g m ty thataddrvOpt thatv thate expr = + match thataddrvOpt with + | None -> expr + | Some thataddrv -> + mkCompGenLet m thataddrv (mkValAddr m (mkLocalValRef thatv)) expr + let mkDerefThis g m (thisv: Val) thise = if isByrefTy g thisv.Type then mkAddrGet m (mkLocalValRef thisv) else thise @@ -210,7 +221,7 @@ let mkRecdCompareWithComparer g tcref (tycon:Tycon) (_thisv,thise) (_,thate) com let fields = tycon.AllInstanceFieldsAsList let tinst,ty = mkMinimalTy g tcref let tcv,tce = mkCompGenLocal m "objTemp" ty // let tcv = thate - let thataddrv,thataddre = mkThatAddrLocal g m ty // let thataddrv = &tcv, if a struct + let thataddrv,thataddre = mkThatAddrLocal g m tce ty // let thataddrv = &tcv, if a struct let mkTest (fspec:RecdField) = let fty = fspec.FormalType @@ -381,14 +392,14 @@ let mkUnionCompare g tcref (tycon:Tycon) = /// Build the comparison implementation for a union type when parameterized by a comparer -let mkUnionCompareWithComparer g tcref (tycon:Tycon) (_thisv,thise) (_thatv,thate) compe = +let mkUnionCompareWithComparer g tcref (tycon:Tycon) (_thisv,thise) (_thatobjv,thatcaste) compe = let m = tycon.Range let ucases = tycon.UnionCasesAsList let tinst,ty = mkMinimalTy g tcref + let tcv,tce = mkCompGenLocal m "objTemp" ty // let tcv = (thatobj :?> ty) + let thataddrvOpt,thataddre = mkThatAddrLocalIfNeeded g m tce ty // let thataddrv = &tcv if struct, otherwise thataddre is just tce let thistagv,thistage = mkCompGenLocal m "thisTag" g.int_ty let thattagv,thattage = mkCompGenLocal m "thatTag" g.int_ty - let thataddrv,thataddre = mkThatAddrLocal g m ty - let tcv,tce = mkCompGenLocal m "objTemp" ty // let tcv = thate let expr = let mbuilder = new MatchBuilder(NoSequencePointAtInvisibleBinding,m ) @@ -436,10 +447,9 @@ let mkUnionCompareWithComparer g tcref (tycon:Tycon) (_thisv,thise) (_thatv,that (mkUnionCaseTagGetViaExprAddr (thataddre,tcref,tinst,m)) tagsEqTested) - let expr = if tycon.IsStructOrEnumTycon then expr else mkBindNullComparison g m thise thate expr - let expr = mkBindThatAddr g m ty thataddrv tcv tce expr - // will be optimized away if not necessary - let expr = mkCompGenLet m tcv thate expr + let expr = if tycon.IsStructOrEnumTycon then expr else mkBindNullComparison g m thise thatcaste expr + let expr = mkBindThatAddrIfNeeded g m ty thataddrvOpt tcv tce expr + let expr = mkCompGenLet m tcv thatcaste expr expr From 93f8799d5e57666891fa1cf9395a84e5c01e279f Mon Sep 17 00:00:00 2001 From: Don Syme Date: Wed, 15 Jun 2016 23:20:31 +0100 Subject: [PATCH 055/129] fix for test --- src/fsharp/AugmentWithHashCompare.fs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/fsharp/AugmentWithHashCompare.fs b/src/fsharp/AugmentWithHashCompare.fs index 2769415f656..5199dc223cc 100644 --- a/src/fsharp/AugmentWithHashCompare.fs +++ b/src/fsharp/AugmentWithHashCompare.fs @@ -130,14 +130,17 @@ let mkThatVarBind g m ty thataddrv expr = let mkBindThatAddr g m ty thataddrv thatv thate expr = if isStructTy g ty then - mkCompGenLet m thataddrv (mkValAddr m (mkLocalValRef thatv)) expr + // let thataddrv = &thatv + mkCompGenLet m thataddrv (mkValAddr m (mkLocalValRef thatv)) expr else - mkCompGenLet m thataddrv thate expr + // let thataddrv = that + mkCompGenLet m thataddrv thate expr -let mkBindThatAddrIfNeeded g m ty thataddrvOpt thatv thate expr = +let mkBindThatAddrIfNeeded m thataddrvOpt thatv expr = match thataddrvOpt with | None -> expr | Some thataddrv -> + // let thataddrv = &thatv mkCompGenLet m thataddrv (mkValAddr m (mkLocalValRef thatv)) expr let mkDerefThis g m (thisv: Val) thise = @@ -221,7 +224,7 @@ let mkRecdCompareWithComparer g tcref (tycon:Tycon) (_thisv,thise) (_,thate) com let fields = tycon.AllInstanceFieldsAsList let tinst,ty = mkMinimalTy g tcref let tcv,tce = mkCompGenLocal m "objTemp" ty // let tcv = thate - let thataddrv,thataddre = mkThatAddrLocal g m tce ty // let thataddrv = &tcv, if a struct + let thataddrv,thataddre = mkThatAddrLocal g m ty // let thataddrv = &tcv, if a struct let mkTest (fspec:RecdField) = let fty = fspec.FormalType @@ -448,7 +451,7 @@ let mkUnionCompareWithComparer g tcref (tycon:Tycon) (_thisv,thise) (_thatobjv,t tagsEqTested) let expr = if tycon.IsStructOrEnumTycon then expr else mkBindNullComparison g m thise thatcaste expr - let expr = mkBindThatAddrIfNeeded g m ty thataddrvOpt tcv tce expr + let expr = mkBindThatAddrIfNeeded m thataddrvOpt tcv expr let expr = mkCompGenLet m tcv thatcaste expr expr From 47077f6e7112f654ba3f2af9dd24219ce3ced8e5 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Wed, 15 Jun 2016 23:46:37 +0100 Subject: [PATCH 056/129] limit conditional build and add more tests --- .../FSharp.Core.Unittests.fsproj | 2 +- .../FSharp.Core/RecordTypes.fs | 46 ++++++++++++++++++- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/src/fsharp/FSharp.Core.Unittests/FSharp.Core.Unittests.fsproj b/src/fsharp/FSharp.Core.Unittests/FSharp.Core.Unittests.fsproj index 83ed633defa..4fc578c8f05 100644 --- a/src/fsharp/FSharp.Core.Unittests/FSharp.Core.Unittests.fsproj +++ b/src/fsharp/FSharp.Core.Unittests/FSharp.Core.Unittests.fsproj @@ -112,7 +112,7 @@ - + diff --git a/src/fsharp/FSharp.Core.Unittests/FSharp.Core/RecordTypes.fs b/src/fsharp/FSharp.Core.Unittests/FSharp.Core/RecordTypes.fs index 694052fa4d2..2d9695b08fa 100644 --- a/src/fsharp/FSharp.Core.Unittests/FSharp.Core/RecordTypes.fs +++ b/src/fsharp/FSharp.Core.Unittests/FSharp.Core/RecordTypes.fs @@ -325,4 +325,48 @@ let [] ``can properly construct a struct record using FSharpValue.MakeReco let d = (fields.[1] :?> int) Assert.AreEqual (999, d) - \ No newline at end of file +type DefaultLayoutMutableRecord = + { mutable First : int + mutable Second : float + mutable Third : decimal + mutable Fourth : int + } + +let inline CX_get_A(x: ^T) = + ( (^T : (member A : int) (x)) ) + +let inline CX_get_C(x: ^T) = + ( (^T : (member C : int) (x)) ) + +let inline CX_set_First(x: ^T, v) = + ( (^T : (member First : int with set) (x,v)) ) + + +type Members() = + static member CreateMutableStructRecord() = { M1 = 1; M2 = 2 } + + +let [] ``inline constraints resolve correctly`` () = + let v = CX_get_A ({ A = 1; B = 2 }) + Assert.AreEqual (1, v) + + let v2 = CX_get_C ({ C = 1; D = 2 }) + Assert.AreEqual (1, v2) + + let mutable m : DefaultLayoutMutableRecord = + { First = 0xbaad1 + Second = 0.987654 + Third = 100.32M + Fourth = 0xbaad4 } + + let v3 = CX_set_First (m,1) + Assert.AreEqual (1, m.First) + +let [] ``member setters resolve correctly`` () = + + let v = Members.CreateMutableStructRecord() + Assert.AreEqual (1, v.M1) + + //let v2 = Members.CreateMutableStructRecord(M1 = 100) + //Assert.AreEqual (100, v2.M1) + From 28d4b053d2600c31a99767e399efa77a0815b510 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Thu, 16 Jun 2016 10:19:19 +0100 Subject: [PATCH 057/129] fix tests --- .../ToplevelModule.il.bsl | 8 ++++---- .../ToplevelModuleP.il.bsl | 8 ++++---- .../ToplevelNamespace.il.bsl | 10 +++++----- .../ToplevelNamespaceP.il.bsl | 10 +++++----- .../Optimizations/Inlining/Match01.il.bsl | Bin 129528 -> 129528 bytes 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/SerializableAttribute/ToplevelModule.il.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/SerializableAttribute/ToplevelModule.il.bsl index 075b68845ee..972eced84a0 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/SerializableAttribute/ToplevelModule.il.bsl +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/SerializableAttribute/ToplevelModule.il.bsl @@ -36,13 +36,13 @@ // Offset: 0x00001158 Length: 0x000003FD } .module TopLevelModule.dll -// MVID: {575BE147-37F5-C118-A745-038347E15B57} +// MVID: {576266DB-37F5-C118-A745-0383DB666257} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x00620000 +// Image base: 0x01090000 // =============== CLASS MEMBERS DECLARATION =================== @@ -685,7 +685,7 @@ IL_0019: ldloc.0 IL_001a: stloc.1 - IL_001b: ldloc.1 + IL_001b: ldloc.0 IL_001c: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives/IntrinsicFunctions::TypeTestGeneric(object) IL_0021: brtrue.s IL_0025 @@ -1483,7 +1483,7 @@ IL_0019: ldloc.0 IL_001a: stloc.1 - IL_001b: ldloc.1 + IL_001b: ldloc.0 IL_001c: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives/IntrinsicFunctions::TypeTestGeneric(object) IL_0021: brtrue.s IL_0025 diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/SerializableAttribute/ToplevelModuleP.il.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/SerializableAttribute/ToplevelModuleP.il.bsl index 76df7a86bfb..51e5cc6249a 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/SerializableAttribute/ToplevelModuleP.il.bsl +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/SerializableAttribute/ToplevelModuleP.il.bsl @@ -36,13 +36,13 @@ // Offset: 0x00001158 Length: 0x000003FE } .module ToplevelModuleP.dll -// MVID: {575BE155-5A3A-8E4D-A745-038355E15B57} +// MVID: {576266E1-5A3A-8E4D-A745-0383E1666257} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x009B0000 +// Image base: 0x00A70000 // =============== CLASS MEMBERS DECLARATION =================== @@ -671,7 +671,7 @@ IL_0019: ldloc.0 IL_001a: stloc.1 - IL_001b: ldloc.1 + IL_001b: ldloc.0 IL_001c: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives/IntrinsicFunctions::TypeTestGeneric(object) IL_0021: brtrue.s IL_0025 @@ -1455,7 +1455,7 @@ IL_0019: ldloc.0 IL_001a: stloc.1 - IL_001b: ldloc.1 + IL_001b: ldloc.0 IL_001c: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives/IntrinsicFunctions::TypeTestGeneric(object) IL_0021: brtrue.s IL_0025 diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/SerializableAttribute/ToplevelNamespace.il.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/SerializableAttribute/ToplevelNamespace.il.bsl index 1d33d16bc4c..b9d03a5dc59 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/SerializableAttribute/ToplevelNamespace.il.bsl +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/SerializableAttribute/ToplevelNamespace.il.bsl @@ -36,13 +36,13 @@ // Offset: 0x00001860 Length: 0x0000055C } .module ToplevelNamespace.dll -// MVID: {575BE14E-218B-729A-A745-03834EE15B57} +// MVID: {576266DE-218B-729A-A745-0383DE666257} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x00F30000 +// Image base: 0x00D30000 // =============== CLASS MEMBERS DECLARATION =================== @@ -680,7 +680,7 @@ IL_0019: ldloc.0 IL_001a: stloc.1 - IL_001b: ldloc.1 + IL_001b: ldloc.0 IL_001c: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives/IntrinsicFunctions::TypeTestGeneric(object) IL_0021: brtrue.s IL_0025 @@ -1478,7 +1478,7 @@ IL_0019: ldloc.0 IL_001a: stloc.1 - IL_001b: ldloc.1 + IL_001b: ldloc.0 IL_001c: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives/IntrinsicFunctions::TypeTestGeneric(object) IL_0021: brtrue.s IL_0025 @@ -2276,7 +2276,7 @@ IL_0019: ldloc.0 IL_001a: stloc.1 - IL_001b: ldloc.1 + IL_001b: ldloc.0 IL_001c: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives/IntrinsicFunctions::TypeTestGeneric(object) IL_0021: brtrue.s IL_0025 diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/SerializableAttribute/ToplevelNamespaceP.il.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/SerializableAttribute/ToplevelNamespaceP.il.bsl index 15931872229..a419b7a9c0c 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/SerializableAttribute/ToplevelNamespaceP.il.bsl +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/SerializableAttribute/ToplevelNamespaceP.il.bsl @@ -36,13 +36,13 @@ // Offset: 0x00001860 Length: 0x0000055D } .module ToplevelNamespaceP.dll -// MVID: {575BE15B-88D9-D7FD-A745-03835BE15B57} +// MVID: {576266E4-88D9-D7FD-A745-0383E4666257} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x003C0000 +// Image base: 0x01450000 // =============== CLASS MEMBERS DECLARATION =================== @@ -666,7 +666,7 @@ IL_0019: ldloc.0 IL_001a: stloc.1 - IL_001b: ldloc.1 + IL_001b: ldloc.0 IL_001c: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives/IntrinsicFunctions::TypeTestGeneric(object) IL_0021: brtrue.s IL_0025 @@ -1450,7 +1450,7 @@ IL_0019: ldloc.0 IL_001a: stloc.1 - IL_001b: ldloc.1 + IL_001b: ldloc.0 IL_001c: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives/IntrinsicFunctions::TypeTestGeneric(object) IL_0021: brtrue.s IL_0025 @@ -2234,7 +2234,7 @@ IL_0019: ldloc.0 IL_001a: stloc.1 - IL_001b: ldloc.1 + IL_001b: ldloc.0 IL_001c: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives/IntrinsicFunctions::TypeTestGeneric(object) IL_0021: brtrue.s IL_0025 diff --git a/tests/fsharpqa/Source/Optimizations/Inlining/Match01.il.bsl b/tests/fsharpqa/Source/Optimizations/Inlining/Match01.il.bsl index ddfd9dfcac162f511522f832a3e03e63377203a5..523f7efed861a5c2664420a96c43c1ce833e2920 100644 GIT binary patch delta 41 zcmV+^0M`Hb^9T6z2Y|Ez!q5j)0A&De0C1Nf&;fs!fHMJ3w~(p Date: Thu, 16 Jun 2016 17:05:41 +0100 Subject: [PATCH 058/129] minor fixes and more testing --- .../FSharp.Core/DiscrimantedUnionType.fs | 23 ++++ src/fsharp/PatternMatchCompilation.fs | 70 +++++------ src/ilx/EraseUnions.fs | 8 +- tests/fsharp/core/attributes/testlib.fs | 2 + tests/fsharp/core/fsfromcs/{lib.ml => lib.fs} | 2 +- .../core/fsfromfsviacs/{lib.ml => lib.fs} | 72 ++++++++++- tests/fsharp/core/fsfromfsviacs/lib2.cs | 4 + tests/fsharp/core/fsfromfsviacs/test.fsx | 64 ++++++++++ tests/fsharp/core/quotes/test.fsx | 119 +++++------------- tests/fsharp/core/tests_core.fs | 12 +- 10 files changed, 242 insertions(+), 134 deletions(-) rename tests/fsharp/core/fsfromcs/{lib.ml => lib.fs} (99%) rename tests/fsharp/core/fsfromfsviacs/{lib.ml => lib.fs} (51%) diff --git a/src/fsharp/FSharp.Core.Unittests/FSharp.Core/DiscrimantedUnionType.fs b/src/fsharp/FSharp.Core.Unittests/FSharp.Core/DiscrimantedUnionType.fs index 52ea6fbf388..73f548920dc 100644 --- a/src/fsharp/FSharp.Core.Unittests/FSharp.Core/DiscrimantedUnionType.fs +++ b/src/fsharp/FSharp.Core.Unittests/FSharp.Core/DiscrimantedUnionType.fs @@ -226,3 +226,26 @@ let ``struct unions hold [] [] metadata`` () = Assert.IsTrue (hasAttribute()) Assert.IsTrue (hasAttribute()) + +let [] ``can properly construct a struct union using FSharpValue.MakeUnionCase, and we get the fields`` () = + let cases = Microsoft.FSharp.Reflection.FSharpType.GetUnionCases(typeof) + + Assert.AreEqual (1, cases.Length) + let case = cases.[0] + + Assert.AreEqual ("SU", case.Name) + + let structUnion = Microsoft.FSharp.Reflection.FSharpValue.MakeUnion (case, [|box 1234; box 3456|]) + + Assert.IsTrue (structUnion.GetType().IsValueType) + + let fieldVals = Microsoft.FSharp.Reflection.FSharpValue.GetUnionFields(structUnion, typeof) + + Assert.AreEqual (2, fieldVals.Length) + + let c = (fieldVals.[0] :?> int) + Assert.AreEqual (1234, c) + + let c2 = (fieldVals.[1] :?> int) + Assert.AreEqual (3456, c2) + diff --git a/src/fsharp/PatternMatchCompilation.fs b/src/fsharp/PatternMatchCompilation.fs index 22400641b79..6bff652145d 100644 --- a/src/fsharp/PatternMatchCompilation.fs +++ b/src/fsharp/PatternMatchCompilation.fs @@ -493,7 +493,7 @@ let (|ListEmptyDiscrim|_|) g = function /// - Compact integer switches become a single switch. Non-compact integer /// switches, string switches and floating point switches are treated in the /// same way as Test.IsInst. -let rec BuildSwitch resPreBindOpt g expr edges dflt m = +let rec BuildSwitch inpExprOpt g expr edges dflt m = if verbose then dprintf "--> BuildSwitch@%a, #edges = %A, dflt.IsSome = %A\n" outputRange m (List.length edges) (Option.isSome dflt); match edges,dflt with | [], None -> failwith "internal error: no edges and no default" @@ -505,12 +505,12 @@ let rec BuildSwitch resPreBindOpt g expr edges dflt m = // 'isinst' tests where we have stored the result of the 'isinst' in a variable // In this case the 'expr' already holds the result of the 'isinst' test. - | (TCase(Test.IsInst _,success)):: edges, dflt when isSome resPreBindOpt -> + | (TCase(Test.IsInst _,success)):: edges, dflt when isSome inpExprOpt -> TDSwitch(expr,[TCase(Test.IsNull,BuildSwitch None g expr edges dflt m)],Some success,m) // isnull and isinst tests | (TCase((Test.IsNull | Test.IsInst _),_) as edge):: edges, dflt -> - TDSwitch(expr,[edge],Some (BuildSwitch resPreBindOpt g expr edges dflt m),m) + TDSwitch(expr,[edge],Some (BuildSwitch inpExprOpt g expr edges dflt m),m) #if OPTIMIZE_LIST_MATCHING // 'cons/nil' tests where we have stored the result of the cons test in an 'isinst' in a variable @@ -519,7 +519,7 @@ let rec BuildSwitch resPreBindOpt g expr edges dflt m = | [TCase(ListEmptyDiscrim g tinst, emptyCase)], Some consCase | [TCase(ListEmptyDiscrim g _, emptyCase); TCase(ListConsDiscrim g tinst, consCase)], None | [TCase(ListConsDiscrim g tinst, consCase); TCase(ListEmptyDiscrim g _, emptyCase)], None - when isSome resPreBindOpt -> + when isSome inpExprOpt -> TDSwitch(expr, [TCase(Test.IsNull, emptyCase)], Some consCase, m) #endif @@ -792,10 +792,10 @@ let CompilePatternBasic if debug then dprintf "chooseSimultaneousEdgeSet\n"; let simulSetOfEdgeDiscrims,fallthroughPathFrontiers = ChooseSimultaneousEdges frontiers path - let resPreBindOpt, bindOpt = ChoosePreBinder simulSetOfEdgeDiscrims subexpr + let inpExprOpt, bindOpt = ChoosePreBinder simulSetOfEdgeDiscrims subexpr // For each case, recursively compile the residue decision trees that result if that case successfully matches - let simulSetOfCases, _ = CompileSimultaneousSet frontiers path refuted subexpr simulSetOfEdgeDiscrims resPreBindOpt + let simulSetOfCases, _ = CompileSimultaneousSet frontiers path refuted subexpr simulSetOfEdgeDiscrims inpExprOpt assert (nonNil(simulSetOfCases)); @@ -812,8 +812,8 @@ let CompilePatternBasic // OK, build the whole tree and whack on the binding if any let finalDecisionTree = - let inpExprToSwitch = (match resPreBindOpt with Some vexp -> vexp | None -> GetSubExprOfInput subexpr) - let tree = BuildSwitch resPreBindOpt g inpExprToSwitch simulSetOfCases defaultTreeOpt matchm + let inpExprToSwitch = (match inpExprOpt with Some vexp -> vexp | None -> GetSubExprOfInput subexpr) + let tree = BuildSwitch inpExprOpt g inpExprToSwitch simulSetOfCases defaultTreeOpt matchm match bindOpt with | None -> tree | Some bind -> TDBind (bind,tree) @@ -904,7 +904,7 @@ let CompilePatternBasic let argexp = GetSubExprOfInput subexpr let vOpt,addrexp = mkExprAddrOfExprAux g true false NeverMutates argexp None matchm match vOpt with - | None -> None, None + | None -> Some addrexp, None | Some (v,e) -> if topv.IsMemberOrModuleBinding then AdjustValToTopVal v topv.ActualParent ValReprInfo.emptyValData; @@ -945,7 +945,7 @@ let CompilePatternBasic | _ -> None,None - and CompileSimultaneousSet frontiers path refuted subexpr simulSetOfEdgeDiscrims (resPreBindOpt: Expr option) = + and CompileSimultaneousSet frontiers path refuted subexpr simulSetOfEdgeDiscrims (inpExprOpt: Expr option) = ([],simulSetOfEdgeDiscrims) ||> List.collectFold (fun taken (EdgeDiscrim(i',discrim,m)) -> // Check to see if we've already collected the edge for this case, in which case skip it. @@ -968,7 +968,7 @@ let CompilePatternBasic match discrim with | Test.UnionCase (ucref, tinst) when #if OPTIMIZE_LIST_MATCHING - isNone resPreBindOpt && + isNone inpExprOpt && #endif (isNil topgtvs && not topv.IsMemberOrModuleBinding && @@ -1000,7 +1000,7 @@ let CompilePatternBasic // Project a successful edge through the frontiers. let investigation = Investigation(i',discrim,path) - let frontiers = frontiers |> List.collect (GenerateNewFrontiersAfterSucccessfulInvestigation resPreBindOpt resPostBindOpt investigation) + let frontiers = frontiers |> List.collect (GenerateNewFrontiersAfterSucccessfulInvestigation inpExprOpt resPostBindOpt investigation) let tree = InvestigateFrontiers refuted frontiers // Bind the resVar for the union case, if we have one let tree = @@ -1042,7 +1042,7 @@ let CompilePatternBasic // Build a new frontier that represents the result of a successful investigation // at rule point (i',discrim,path) - and GenerateNewFrontiersAfterSucccessfulInvestigation resPreBindOpt resPostBindOpt (Investigation(i',discrim,path)) (Frontier (i, active,valMap) as frontier) = + and GenerateNewFrontiersAfterSucccessfulInvestigation inpExprOpt resPostBindOpt (Investigation(i',discrim,path)) (Frontier (i, active,valMap) as frontier) = if debug then dprintf "projecting success of investigation encompassing rule %d through rule %d \n" i' i; if (isMemOfActives path active) then @@ -1068,14 +1068,14 @@ let CompilePatternBasic if (hasParam && i = i') || (discrimsEq g discrim (Option.get (getDiscrimOfPattern pat))) then let aparity = apinfo.Names.Length let accessf' j tpinst _e' = - assert resPreBindOpt.IsSome + assert inpExprOpt.IsSome if aparity <= 1 then - Option.get resPreBindOpt + Option.get inpExprOpt else let ucref = mkChoiceCaseRef g m aparity idx // TODO: In the future we will want active patterns to be able to return struct-unions // In that eventuality, we need to check we are taking the address correctly - mkUnionCaseFieldGetUnprovenViaExprAddr (Option.get resPreBindOpt,ucref,instTypes tpinst resTys,j,exprm) + mkUnionCaseFieldGetUnprovenViaExprAddr (Option.get inpExprOpt,ucref,instTypes tpinst resTys,j,exprm) mkSubFrontiers path accessf' active' [p] (fun path j -> PathQuery(path,int64 j)) elif hasParam then @@ -1089,7 +1089,7 @@ let CompilePatternBasic let accessf' _j tpinst _ = // TODO: In the future we will want active patterns to be able to return struct-unions // In that eventuality, we need to check we are taking the address correctly - mkUnionCaseFieldGetUnprovenViaExprAddr (Option.get resPreBindOpt, mkSomeCase g, instTypes tpinst resTys, 0, exprm) + mkUnionCaseFieldGetUnprovenViaExprAddr (Option.get inpExprOpt, mkSomeCase g, instTypes tpinst resTys, 0, exprm) mkSubFrontiers path accessf' active' [p] (fun path j -> PathQuery(path,int64 j)) else // Successful active patterns don't refute other patterns @@ -1098,15 +1098,15 @@ let CompilePatternBasic | TPat_unioncase (ucref1, tyargs, argpats,_) -> match discrim with | Test.UnionCase (ucref2, tinst) when g.unionCaseRefEq ucref1 ucref2 -> - let accessf' j tpinst e' = -#if OPTIMIZE_LIST_MATCHING - match resPreBindOpt with - | Some e -> mkUnionCaseFieldGetProvenViaExprAddr g (e,ucref1,tinst,j,exprm) - | None -> -#endif + let accessf' j tpinst exprIn = match resPostBindOpt with | Some e -> mkUnionCaseFieldGetProvenViaExprAddr (e,ucref1,tinst,j,exprm) - | None -> mkUnionCaseFieldGetUnprovenViaExprAddr (accessf tpinst e',ucref1,instTypes tpinst tyargs,j,exprm) + | None -> + let exprIn = + match inpExprOpt with + | Some addrexp -> addrexp + | None -> accessf tpinst exprIn + mkUnionCaseFieldGetUnprovenViaExprAddr (exprIn,ucref1,instTypes tpinst tyargs,j,exprm) mkSubFrontiers path accessf' active' argpats (fun path j -> PathUnionConstr(path,ucref1,tyargs,j)) | Test.UnionCase _ -> @@ -1119,7 +1119,7 @@ let CompilePatternBasic | TPat_array (argpats,ty,_) -> match discrim with | Test.ArrayLength (n,_) when List.length argpats = n -> - let accessf' j tpinst e' = mkCallArrayGet g exprm ty (accessf tpinst e') (mkInt g exprm j) + let accessf' j tpinst exprIn = mkCallArrayGet g exprm ty (accessf tpinst exprIn) (mkInt g exprm j) mkSubFrontiers path accessf' active' argpats (fun path j -> PathArray(path,ty,List.length argpats,j)) // Successful length tests refute all other lengths | Test.ArrayLength _ -> @@ -1130,7 +1130,7 @@ let CompilePatternBasic | TPat_exnconstr (ecref, argpats,_) -> match discrim with | Test.IsInst (_srcTy,tgtTy) when typeEquiv g (mkAppTy ecref []) tgtTy -> - let accessf' j tpinst e' = mkExnCaseFieldGet(accessf tpinst e',ecref,j,exprm) + let accessf' j tpinst exprIn = mkExnCaseFieldGet(accessf tpinst exprIn,ecref,j,exprm) mkSubFrontiers path accessf' active' argpats (fun path j -> PathExnConstr(path,ecref,j)) | _ -> // Successful type tests against one sealed type refute all other sealed types @@ -1142,16 +1142,16 @@ let CompilePatternBasic | Test.IsInst (_srcTy,tgtTy2) when typeEquiv g tgtTy1 tgtTy2 -> match pbindOpt with | Some pbind -> - let accessf' tpinst e' = + let accessf' tpinst exprIn = // Fetch the result from the place where we saved it, if possible - match resPreBindOpt with + match inpExprOpt with | Some e -> e | _ -> // Otherwise call the helper - mkCallUnboxFast g exprm (instType tpinst tgtTy1) (accessf tpinst e') + mkCallUnboxFast g exprm (instType tpinst tgtTy1) (accessf tpinst exprIn) - let (v,e') = BindSubExprOfInput g amap topgtvs pbind exprm (SubExpr(accessf',ve)) - [Frontier (i, active', valMap.Add v e' )] + let (v,exprIn) = BindSubExprOfInput g amap topgtvs pbind exprm (SubExpr(accessf',ve)) + [Frontier (i, active', valMap.Add v exprIn )] | None -> [Frontier (i, active', valMap)] @@ -1190,17 +1190,17 @@ let CompilePatternBasic | TPat_wild _ -> BindProjectionPatterns [] s | TPat_as(p',pbind,m) -> - let (v,e') = BindSubExprOfInput g amap topgtvs pbind m subExpr - BindProjectionPattern (Active(path,subExpr,p')) (accActive,accValMap.Add v e' ) + let (v,subExpr') = BindSubExprOfInput g amap topgtvs pbind m subExpr + BindProjectionPattern (Active(path,subExpr,p')) (accActive,accValMap.Add v subExpr' ) | TPat_tuple(ps,tyargs,_m) -> - let accessf' j tpinst e' = mkTupleFieldGet(accessf tpinst e',instTypes tpinst tyargs,j,exprm) + let accessf' j tpinst exprIn = mkTupleFieldGet(accessf tpinst exprIn,instTypes tpinst tyargs,j,exprm) let pathBuilder path j = PathTuple(path,tyargs,j) let newActives = List.mapi (mkSubActive pathBuilder accessf') ps BindProjectionPatterns newActives s | TPat_recd(tcref,tinst,ps,_m) -> let newActives = (ps,tcref.TrueInstanceFieldsAsRefList) ||> List.mapi2 (fun j p fref -> - let accessf' fref _j tpinst e' = mkRecdFieldGet g (accessf tpinst e',fref,instTypes tpinst tinst,exprm) + let accessf' fref _j tpinst exprIn = mkRecdFieldGet g (accessf tpinst exprIn,fref,instTypes tpinst tinst,exprm) let pathBuilder path j = PathRecd(path,tcref,tinst,j) mkSubActive pathBuilder (accessf' fref) j p) BindProjectionPatterns newActives s diff --git a/src/ilx/EraseUnions.fs b/src/ilx/EraseUnions.fs index c4cdfab0625..6edcb4c663b 100644 --- a/src/ilx/EraseUnions.fs +++ b/src/ilx/EraseUnions.fs @@ -905,6 +905,8 @@ let mkClassUnionDef ilg tref td cud = | SingleCase | RuntimeTypes | TailOrNull -> [] | IntegerTag -> [ mkTagFieldId ilg cuspec ] + let isStruct = match td.tdKind with ILTypeDefKind.ValueType -> true | _ -> false + let selfFields, selfMeths, selfProps = [ for alt in cud.cudAlternatives do @@ -912,9 +914,7 @@ let mkClassUnionDef ilg tref td cud = // TODO let fields = alt.FieldDefs |> Array.toList |> List.map mkUnionCaseFieldId let baseInit = - match td.tdKind with - | ILTypeDefKind.ValueType -> None - | _ -> + if isStruct then None else match td.Extends with | None -> Some ilg.tspec_Object | Some typ -> Some typ.TypeSpec @@ -936,7 +936,7 @@ let mkClassUnionDef ilg tref td cud = let selfAndTagFields = [ for (fldName,fldTy) in (selfFields @ tagFieldsInObject) do let fdef = mkHiddenGeneratedInstanceFieldDef ilg (fldName,fldTy, None, ILMemberAccess.Assembly) - yield { fdef with IsInitOnly=isTotallyImmutable } ] + yield { fdef with IsInitOnly= (not isStruct && isTotallyImmutable) } ] let ctorMeths = if (isNil selfFields && isNil tagFieldsInObject && nonNil selfMeths) diff --git a/tests/fsharp/core/attributes/testlib.fs b/tests/fsharp/core/attributes/testlib.fs index e5f00296b2c..eddb622fccc 100644 --- a/tests/fsharp/core/attributes/testlib.fs +++ b/tests/fsharp/core/attributes/testlib.fs @@ -116,3 +116,5 @@ module TypeParamAttributesDifferent = type ThisLibAssembly = X | Y + + diff --git a/tests/fsharp/core/fsfromcs/lib.ml b/tests/fsharp/core/fsfromcs/lib.fs similarity index 99% rename from tests/fsharp/core/fsfromcs/lib.ml rename to tests/fsharp/core/fsfromcs/lib.fs index 4e9936fb13c..1ca7ef43135 100644 --- a/tests/fsharp/core/fsfromcs/lib.ml +++ b/tests/fsharp/core/fsfromcs/lib.fs @@ -1,4 +1,4 @@ - +module Lib (* An F# library which we try to access from C# *) type Recd1 = { recd1field1: int } diff --git a/tests/fsharp/core/fsfromfsviacs/lib.ml b/tests/fsharp/core/fsfromfsviacs/lib.fs similarity index 51% rename from tests/fsharp/core/fsfromfsviacs/lib.ml rename to tests/fsharp/core/fsfromfsviacs/lib.fs index f40253dc634..ceb7bc8fbae 100644 --- a/tests/fsharp/core/fsfromfsviacs/lib.ml +++ b/tests/fsharp/core/fsfromfsviacs/lib.fs @@ -1,4 +1,4 @@ - +module Lib (* An F# library which we use in a C# library, where we in turn use both the F# component and the C# library together from F# *) type recd1 = { recd1field1: int } @@ -44,3 +44,73 @@ let tup4 = (2,3,4,5) + +module StructUnionsTests = + + [] + type U0 = U0 + + let f0 x = match x with U0 -> 1 + + let v0 = f0 U0 + + [] + type U1 = U1 of int + + let f1 x = match x with U1(x) -> x + x + + let v1 = f1 (U1(3)) + + [] + type U2 = U2 of int * int + + let f2 x = match x with U2(x,y) -> x + y + + let v2 = f2 (U2(3,4)) + + [] + type Ok3 = Ok3 of int * Ok3 list + +/// Nesting structs inside struct unions means taking the address of things during pattern matching +module NestedStructUnionsTests = + + [] + type U1 = U1 of System.DateTime * string + + [] + type U2 = U2 of U1 * U1 + + + let testPattern1(u2:U2) = + match u2 with + | U2(u1a,u1b) -> + match u1a, u1b with + | U1(dt1,s1), U1(dt2,s2) -> (dt1 = dt2) && (s1 = "a") && (s2 = "b") + + let testPattern2(u2:U2) = + match u2 with + | U2(U1(dt1,s1),U1(dt2,s2)) -> (dt1 = dt2) && (s1 = "a") && (s2 = "b") + + let testPattern3(u2:U2) = + match u2 with + | U2(U1(dt1,"a"),U1(dt2,"b")) -> (dt1 = dt2) + + + let testPattern1mut(u2:U2) = + let mutable u2 = u2 + match u2 with + | U2(u1a,u1b) -> + match u1a, u1b with + | U1(dt1,s1), U1(dt2,s2) -> (dt1 = dt2) && (s1 = "a") && (s2 = "b") + + let testPattern2mut(u2:U2) = + let mutable u2 = u2 + match u2 with + | U2(U1(dt1,s1),U1(dt2,s2)) -> (dt1 = dt2) && (s1 = "a") && (s2 = "b") + + let testPattern3mut(u2:U2) = + let mutable u2 = u2 + match u2 with + | U2(U1(dt1,"a"),U1(dt2,"b")) -> (dt1 = dt2) + + diff --git a/tests/fsharp/core/fsfromfsviacs/lib2.cs b/tests/fsharp/core/fsfromfsviacs/lib2.cs index c86e38e7ac6..969347a49f7 100644 --- a/tests/fsharp/core/fsfromfsviacs/lib2.cs +++ b/tests/fsharp/core/fsfromfsviacs/lib2.cs @@ -32,6 +32,10 @@ public class Lib2 public static FSharpRef ri1 = new FSharpRef(3); public static FSharpRef rr1 = new FSharpRef(r1); + public static Lib.StructUnionsTests.U0 u0 = Lib.StructUnionsTests.U0.U0; + public static Lib.StructUnionsTests.U1 u1 = Lib.StructUnionsTests.U1.NewU1(3); + public static Lib.StructUnionsTests.U2 u2 = Lib.StructUnionsTests.U2.NewU2(3,4); + static Lib2() { r3.recd3field3 = r3; } } diff --git a/tests/fsharp/core/fsfromfsviacs/test.fsx b/tests/fsharp/core/fsfromfsviacs/test.fsx index 742b0f284a5..2c0f1652a0c 100644 --- a/tests/fsharp/core/fsfromfsviacs/test.fsx +++ b/tests/fsharp/core/fsfromfsviacs/test.fsx @@ -27,7 +27,71 @@ let _ = test "fejio2dw" (Lib2.or1 = Some r1) let _ = test "fejio2dw" (Lib2.ri1 = ref 3) let _ = test "fejio2dw" (Lib2.rr1 = ref r1) +let _ = test "structunion3948" (Lib2.u0 = Lib.StructUnionsTests.U0) +let _ = test "structunion3949" (Lib2.u1 = Lib.StructUnionsTests.U1(3)) +let _ = test "structunion3949" (Lib2.u2 = Lib.StructUnionsTests.U2(3,4)) + +let _ = test "structunion3948" (compare Lib2.u0 Lib.StructUnionsTests.U0 = 0) +let _ = test "structunion3949" (compare Lib2.u1 (Lib.StructUnionsTests.U1(3)) = 0) +let _ = test "structunion394a" (compare Lib2.u1 (Lib.StructUnionsTests.U1(4)) = -1) +let _ = test "structunion394b" (compare Lib2.u1 (Lib.StructUnionsTests.U1(2)) = 1) +let dt = System.DateTime.Now +let u1a = Lib.NestedStructUnionsTests.U1(dt,"a") +let u1b = Lib.NestedStructUnionsTests.U1(dt,"b") +let u2 = Lib.NestedStructUnionsTests.U2(u1a,u1b) +let _ = test "structunion394b11" (Lib.NestedStructUnionsTests.testPattern1(u2)) +let _ = test "structunion394b22" (Lib.NestedStructUnionsTests.testPattern2(u2)) +let _ = test "structunion394b33" (Lib.NestedStructUnionsTests.testPattern3(u2)) +let _ = test "structunion394b14" (Lib.NestedStructUnionsTests.testPattern1mut(u2)) +let _ = test "structunion394b25" (Lib.NestedStructUnionsTests.testPattern2mut(u2)) +let _ = test "structunion394b36" (Lib.NestedStructUnionsTests.testPattern3mut(u2)) + + +module NestedStructPatternMatchingAcrossAssemblyBoundaries = + open Lib.NestedStructUnionsTests + + let testPattern1(u2:U2) = + match u2 with + | U2(u1a,u1b) -> + match u1a, u1b with + | U1(dt1,s1), U1(dt2,s2) -> (dt1 = dt2) && (s1 = "a") && (s2 = "b") + + let testPattern2(u2:U2) = + match u2 with + | U2(U1(dt1,s1),U1(dt2,s2)) -> (dt1 = dt2) + + let testPattern3(u2:U2) = + match u2 with + | U2(U1(dt1,"a"),U1(dt2,"b")) -> (dt1 = dt2) + + let testPattern1mut(u2:U2) = + let mutable u2 = u2 + match u2 with + | U2(u1a,u1b) -> + match u1a, u1b with + | U1(dt1,s1), U1(dt2,s2) -> (dt1 = dt2) && (s1 = "a") && (s2 = "b") + + let testPattern2mut(u2:U2) = + let mutable u2 = u2 + match u2 with + | U2(U1(dt1,s1),U1(dt2,s2)) -> (dt1 = dt2) && (s1 = "a") && (s2 = "b") + + let testPattern3mut(u2:U2) = + let mutable u2 = u2 + match u2 with + | U2(U1(dt1,"a"),U1(dt2,"b")) -> (dt1 = dt2) + + + let _ = test "structunion394b1a" (testPattern1(u2)) + let _ = test "structunion394b2b" (testPattern2(u2)) + let _ = test "structunion394b3c" (testPattern3(u2)) + + let _ = test "structunion394b1d" (testPattern1mut(u2)) + let _ = test "structunion394b2e" (testPattern2mut(u2)) + let _ = test "structunion394b3f" (testPattern3mut(u2)) + + (* public Lib.discr1_0 d10a = Lib.discr1_0.MkDiscr1_0_A(); public Lib.discr1_1 d11a = Lib.discr1_1.MkDiscr1_1_A(3); diff --git a/tests/fsharp/core/quotes/test.fsx b/tests/fsharp/core/quotes/test.fsx index 2c45e996577..2ad7e1386a4 100644 --- a/tests/fsharp/core/quotes/test.fsx +++ b/tests/fsharp/core/quotes/test.fsx @@ -1610,93 +1610,38 @@ module MoreQuotationsTests = let _ = <@@ v2.Int32ExtensionMethod5 @@> |> printfn "quote = %A" -module QuotationConstructionTests = - let arr = [| 1;2;3;4;5 |] - let f : int -> int = printfn "hello"; (fun x -> x) - let f2 : int * int -> int -> int = printfn "hello"; (fun (x,y) z -> x + y + z) - let F (x:int) = x - let F2 (x:int,y:int) (z:int) = x + y + z - - type Foo () = - member t.Item with get (index:int) = 1 - and set (index:int) (value:int) = () - - let ctorof q = match q with Patterns.NewObject(cinfo,_) -> cinfo | _ -> failwith "ctorof" - let methodof q = match q with DerivedPatterns.Lambdas(_,Patterns.Call(_,minfo,_)) -> minfo | _ -> failwith "methodof" - let fieldof q = match q with Patterns.FieldGet(_,finfo) -> finfo | _ -> failwith "fieldof" - let ucaseof q = match q with Patterns.NewUnionCase(ucinfo,_) -> ucinfo | _ -> failwith "ucaseof" - let getof q = match q with Patterns.PropertyGet(_,pinfo,_) -> pinfo | _ -> failwith "getof" - let setof q = match q with Patterns.PropertySet(_,pinfo,_,_) -> pinfo | _ -> failwith "setof" - check "vcknwwe01" (match Expr.AddressOf <@@ arr.[3] @@> with AddressOf(expr) -> expr = <@@ arr.[3] @@> | _ -> false) true - check "vcknwwe02" (match Expr.AddressSet (Expr.AddressOf <@@ arr.[3] @@>, <@@ 4 @@>) with AddressSet(AddressOf(expr),v) -> expr = <@@ arr.[3] @@> && v = <@@ 4 @@> | _ -> false) true - check "vcknwwe03" (match Expr.Application(<@@ f @@>,<@@ 5 @@>) with Application(f1,x) -> f1 = <@@ f @@> && x = <@@ 5 @@> | _ -> false) true - check "vcknwwe04" (match Expr.Applications(<@@ f @@>,[[ <@@ 5 @@> ]]) with Applications(f1,[[x]]) -> f1 = <@@ f @@> && x = <@@ 5 @@> | _ -> false) true - check "vcknwwe05" (match Expr.Applications(<@@ f2 @@>,[[ <@@ 5 @@>;<@@ 6 @@> ]; [ <@@ 7 @@> ]]) with Applications(f1,[[x;y];[z]]) -> f1 = <@@ f2 @@> && x = <@@ 5 @@> && y = <@@ 6 @@> && z = <@@ 7 @@> | _ -> false) true - check "vcknwwe06" (match Expr.Call(methodof <@@ F2 @@>,[ <@@ 5 @@>;<@@ 6 @@>; <@@ 7 @@> ]) with Call(None,minfo,[x;y;z]) -> minfo = methodof <@@ F2 @@> && x = <@@ 5 @@> && y = <@@ 6 @@> && z = <@@ 7 @@> | _ -> false) true - check "vcknwwe07" (Expr.Cast(<@@ 5 @@>) : Expr) (<@ 5 @>) - check "vcknwwe08" (try let _ = Expr.Cast(<@@ 5 @@>) : Expr in false with :? System.ArgumentException -> true) true - check "vcknwwe09" (match Expr.Coerce(<@@ 5 @@>, typeof) with Coerce(q,ty) -> ty = typeof && q = <@@ 5 @@> | _ -> false) true - check "vcknwwe0q" (match Expr.DefaultValue(typeof) with DefaultValue(ty) -> ty = typeof | _ -> false) true - check "vcknwwe0w" (match Expr.FieldGet(typeof.GetField("MaxValue")) with FieldGet(None,finfo) -> finfo = typeof.GetField("MaxValue") | _ -> false) true - check "vcknwwe0e" (match Expr.FieldSet(typeof.GetField("MaxValue"),<@@ 1 @@>) with FieldSet(None,finfo,v) -> finfo = typeof.GetField("MaxValue") && v = <@@ 1 @@> | _ -> false) true - check "vcknwwe0r" (match Expr.ForIntegerRangeLoop(Var.Global("i",typeof),<@@ 1 @@>,<@@ 10 @@>,<@@ () @@>) with ForIntegerRangeLoop(v,start,finish,body) -> v = Var.Global("i",typeof) && start = <@@ 1 @@> && finish = <@@ 10 @@> && body = <@@ () @@> | _ -> false) true - check "vcknwwe0t" (match Expr.GlobalVar("i") : Expr with Var(v) -> v = Var.Global("i",typeof) | _ -> false) true - check "vcknwwe0y" (match Expr.IfThenElse(<@@ true @@>,<@@ 1 @@>,<@@ 2 @@>) with IfThenElse(gd,t,e) -> gd = <@@ true @@> && t = <@@ 1 @@> && e = <@@ 2 @@> | _ -> false) true - check "vcknwwe0u" (match Expr.Lambda(Var.Global("i",typeof), <@@ 2 @@>) with Lambda(v,b) -> v = Var.Global("i",typeof) && b = <@@ 2 @@> | _ -> false) true - check "vcknwwe0i" (match Expr.Let(Var.Global("i",typeof), <@@ 2 @@>, <@@ 3 @@>) with Let(v,e,b) -> v = Var.Global("i",typeof) && e = <@@ 2 @@> && b = <@@ 3 @@> | _ -> false) true - check "vcknwwe0o" (match Expr.LetRecursive([(Var.Global("i",typeof), <@@ 2 @@>)], <@@ 3 @@>) with LetRecursive([(v,e)],b) -> v = Var.Global("i",typeof) && e = <@@ 2 @@> && b = <@@ 3 @@> | _ -> false) true - check "vcknwwe0p" (match Expr.LetRecursive([(Var.Global("i",typeof), <@@ 2 @@>);(Var.Global("j",typeof), <@@ 3 @@>)], <@@ 3 @@>) with LetRecursive([(v1,e1);(v2,e2)],b) -> v1 = Var.Global("i",typeof) && v2 = Var.Global("j",typeof) && e1 = <@@ 2 @@> && e2 = <@@ 3 @@> && b = <@@ 3 @@> | _ -> false) true - check "vcknwwe0a" (Expr.NewArray(typeof,[ <@@ 1 @@>; <@@ 2 @@> ])) <@@ [| 1;2 |] @@> - check "vcknwwe0s" (match Expr.NewDelegate(typeof>,[ Var.Global("i",typeof) ], <@@ () @@>) with NewDelegate(ty,[v],e) -> ty = typeof> && v = Var.Global("i",typeof) && e = <@@ () @@> | _ -> false) true - check "vcknwwe0d" (match Expr.NewObject(ctorof <@@ new obj() @@> ,[ ]) with NewObject(ty,[]) -> ty = ctorof <@@ new obj() @@> | _ -> false) true - check "vcknwwe0f" (match Expr.NewObject(ctorof <@@ new System.String('a',3) @@> ,[ <@@ 'b' @@>; <@@ 4 @@>]) with NewObject(ty,[x;y]) -> ty = ctorof <@@ new string('a',3) @@> && x = <@@ 'b' @@> && y = <@@ 4 @@> | _ -> false) true - check "vcknwwe0g" (Expr.NewRecord(typeof ,[ <@@ 4 @@> ])) <@@ { contents = 4 } @@> - check "vcknwwe0h" (try let _ = Expr.NewTuple([]) in false with :? System.ArgumentException -> true) true - check "vcknwwe0j" (try let _ = Expr.NewTuple([ <@@ 1 @@> ]) in true with :? System.ArgumentException -> false) true - check "vcknwwe0k" (match Expr.NewTuple([ <@@ 'b' @@>; <@@ 4 @@>]) with NewTuple([x;y]) -> x = <@@ 'b' @@> && y = <@@ 4 @@> | _ -> false) true - check "vcknwwe0l" (Expr.NewTuple([ <@@ 'b' @@>; <@@ 4 @@>])) <@@ ('b',4) @@> - check "vcknwwe0z" (Expr.NewTuple([ <@@ 'b' @@>; <@@ 4 @@>; <@@ 5 @@>])) <@@ ('b',4,5) @@> - check "vcknwwe0x" (Expr.NewTuple([ <@@ 'b' @@>; <@@ 4 @@>; <@@ 5 @@>; <@@ 6 @@>])) <@@ ('b',4,5,6) @@> - check "vcknwwe0c" (Expr.NewTuple([ <@@ 'b' @@>; <@@ 4 @@>; <@@ 5 @@>; <@@ 6 @@>; <@@ 7 @@>])) <@@ ('b',4,5,6,7) @@> - check "vcknwwe0v" (Expr.NewTuple([ <@@ 'b' @@>; <@@ 4 @@>; <@@ 5 @@>; <@@ 6 @@>; <@@ 7 @@>; <@@ 8 @@>])) <@@ ('b',4,5,6,7,8) @@> - check "vcknwwe0b" (Expr.NewTuple([ <@@ 'b' @@>; <@@ 4 @@>; <@@ 5 @@>; <@@ 6 @@>; <@@ 7 @@>; <@@ 8 @@>; <@@ 9 @@>])) <@@ ('b',4,5,6,7,8,9) @@> - check "vcknwwe0n" (Expr.NewTuple([ <@@ 'b' @@>; <@@ 4 @@>; <@@ 5 @@>; <@@ 6 @@>; <@@ 7 @@>; <@@ 8 @@>; <@@ 9 @@>; <@@ 10 @@>])) <@@ ('b',4,5,6,7,8,9,10) @@> - check "vcknwwe0m" (Expr.NewTuple([ <@@ 'b' @@>; <@@ 4 @@>; <@@ 5 @@>; <@@ 6 @@>; <@@ 7 @@>; <@@ 8 @@>; <@@ 9 @@>; <@@ 10 @@>])) <@@ ('b',4,5,6,7,8,9,10) @@> - check "vcknwwe011" (Expr.NewUnionCase(ucaseof <@@ Some(3) @@>,[ <@@ 4 @@> ])) <@@ Some(4) @@> - check "vcknwwe022" (Expr.NewUnionCase(ucaseof <@@ None @@>,[ ])) <@@ None @@> - check "vcknwwe033" (try let _ = Expr.NewUnionCase(ucaseof <@@ Some(3) @@>,[ ]) in false with :? ArgumentException -> true) true - check "vcknwwe044" (try let _ = Expr.NewUnionCase(ucaseof <@@ None @@>,[ <@@ 1 @@> ]) in false with :? ArgumentException -> true) true - check "vcknwwe055" (Expr.PropertyGet(getof <@@ System.DateTime.Now @@>,[ ])) <@@ System.DateTime.Now @@> - check "vcknwwe066" (try let _ = Expr.PropertyGet(getof <@@ System.DateTime.Now @@>,[ <@@ 1 @@> ]) in false with :? ArgumentException -> true) true - check "vcknwwe077" (Expr.PropertyGet(<@@ "3" @@>, getof <@@ "1".Length @@>)) <@@ "3".Length @@> - check "vcknwwe088" (Expr.PropertyGet(<@@ "3" @@>, getof <@@ "1".Length @@>,[ ])) <@@ "3".Length @@> - #if Portable - #else - check "vcknwwe099" (Expr.PropertySet(<@@ (new System.Windows.Forms.Form()) @@>, setof <@@ (new System.Windows.Forms.Form()).Text <- "2" @@>, <@@ "3" @@> )) <@@ (new System.Windows.Forms.Form()).Text <- "3" @@> - #endif - check "vcknwwe099" (Expr.PropertySet(<@@ (new Foo()) @@>, setof <@@ (new Foo()).[3] <- 1 @@>, <@@ 2 @@> , [ <@@ 3 @@> ] )) <@@ (new Foo()).[3] <- 2 @@> -#if FSHARP_CORE_31 -#else - check "vcknwwe0qq1" (Expr.QuoteRaw(<@ "1" @>)) <@@ <@@ "1" @@> @@> - check "vcknwwe0qq2" (Expr.QuoteRaw(<@@ "1" @@>)) <@@ <@@ "1" @@> @@> - check "vcknwwe0qq3" (Expr.QuoteTyped(<@ "1" @>)) <@@ <@ "1" @> @@> - check "vcknwwe0qq4" (Expr.QuoteTyped(<@@ "1" @@>)) <@@ <@ "1" @> @@> -#endif - check "vcknwwe0ww" (Expr.Sequential(<@@ () @@>, <@@ 1 @@>)) <@@ (); 1 @@> - check "vcknwwe0ee" (Expr.TryFinally(<@@ 1 @@>, <@@ () @@>)) <@@ try 1 finally () @@> - check "vcknwwe0rr" (match Expr.TryWith(<@@ 1 @@>, Var.Global("e1",typeof), <@@ 1 @@>, Var.Global("e2",typeof), <@@ 2 @@>) with TryWith(b,v1,ef,v2,eh) -> b = <@@ 1 @@> && eh = <@@ 2 @@> && ef = <@@ 1 @@> && v1 = Var.Global("e1",typeof) && v2 = Var.Global("e2",typeof)| _ -> false) true - check "vcknwwe0tt" (match Expr.TupleGet(<@@ (1,2) @@>, 0) with TupleGet(b,n) -> b = <@@ (1,2) @@> && n = 0 | _ -> false) true - check "vcknwwe0yy" (match Expr.TupleGet(<@@ (1,2) @@>, 1) with TupleGet(b,n) -> b = <@@ (1,2) @@> && n = 1 | _ -> false) true - check "vcknwwe0uu" (try let _ = Expr.TupleGet(<@@ (1,2) @@>, 2) in false with :? ArgumentException -> true) true - check "vcknwwe0ii" (try let _ = Expr.TupleGet(<@@ (1,2) @@>, -1) in false with :? ArgumentException -> true) true - for i = 0 to 7 do - check "vcknwwe0oo" (match Expr.TupleGet(<@@ (1,2,3,4,5,6,7,8) @@>, i) with TupleGet(b,n) -> b = <@@ (1,2,3,4,5,6,7,8) @@> && n = i | _ -> false) true - check "vcknwwe0pp" (match Expr.TypeTest(<@@ new obj() @@>, typeof) with TypeTest(e,ty) -> e = <@@ new obj() @@> && ty = typeof | _ -> false) true - check "vcknwwe0aa" (match Expr.UnionCaseTest(<@@ [] : int list @@>, ucaseof <@@ [] : int list @@> ) with UnionCaseTest(e,uc) -> e = <@@ [] : int list @@> && uc = ucaseof <@@ [] : int list @@> | _ -> false) true - check "vcknwwe0ss" (Expr.Value(3)) <@@ 3 @@> - check "vcknwwe0dd" (match Expr.Var(Var.Global("i",typeof)) with Var(v) -> v = Var.Global("i",typeof) | _ -> false) true - check "vcknwwe0ff" (match Expr.VarSet(Var.Global("i",typeof), <@@ 4 @@>) with VarSet(v,q) -> v = Var.Global("i",typeof) && q = <@@ 4 @@> | _ -> false) true - check "vcknwwe0gg" (match Expr.WhileLoop(<@@ true @@>, <@@ () @@>) with WhileLoop(g,b) -> g = <@@ true @@> && b = <@@ () @@> | _ -> false) true +module QuotationStructUnionTests = + + [] + type T = | A of int + + test "check NewUnionCase" (<@ A(1) @> |> (function NewUnionCase(unionCase,args) -> true | _ -> false)) + + [] + let foo v = match v with | A(1) -> 0 | _ -> 1 + + test "check TryGetReflectedDefinition (local f)" + ((<@ foo (A(1)) @> |> (function Call(None,minfo,args) -> Quotations.Expr.TryGetReflectedDefinition(minfo).IsSome | _ -> false))) + + [] + let test3297327 v = match v with | A(1) -> 0 | _ -> 1 + + test "check TryGetReflectedDefinition (local f)" + ((<@ foo (A(1)) @> |> (function Call(None,minfo,args) -> Quotations.Expr.TryGetReflectedDefinition(minfo).IsSome | _ -> false))) + + + [] + type T2 = + | A1 of int * int + + test "check NewUnionCase" (<@ A1(1,2) @> |> (function NewUnionCase(unionCase,[ Int32 1; Int32 2 ]) -> true | _ -> false)) + + //[] + //type T3 = + // | A1 of int * int + // + //test "check NewUnionCase" (<@ A1(1,2) @> |> (function NewUnionCase(unionCase,[ Int32 1; Int32 2 ]) -> true | _ -> false)) + module EqualityOnExprDoesntFail = let q = <@ 1 @> diff --git a/tests/fsharp/core/tests_core.fs b/tests/fsharp/core/tests_core.fs index 4e2d891b1d2..68ec3baeb85 100644 --- a/tests/fsharp/core/tests_core.fs +++ b/tests/fsharp/core/tests_core.fs @@ -266,8 +266,8 @@ module FsFromCs = let csc = Printf.ksprintf (Commands.csc exec cfg.CSC) let fsc_flags = cfg.fsc_flags - // "%FSC%" %fsc_flags% -a --doc:lib.xml -o:lib.dll -g lib.ml - do! fsc "%s -a --doc:lib.xml -o:lib.dll -g" fsc_flags ["lib.ml"] + // "%FSC%" %fsc_flags% -a --doc:lib.xml -o:lib.dll -g lib.fs + do! fsc "%s -a --doc:lib.xml -o:lib.dll -g" fsc_flags ["lib.fs"] // "%PEVERIFY%" lib.dll do! peverify "lib.dll" @@ -275,8 +275,8 @@ module FsFromCs = // %CSC% /nologo /r:"%FSCOREDLLPATH%" /r:System.Core.dll /r:lib.dll /out:test.exe test.cs do! csc """/nologo /r:"%s" /r:System.Core.dll /r:lib.dll /out:test.exe""" cfg.FSCOREDLLPATH ["test.cs"] - // "%FSC%" %fsc_flags% -a --doc:lib--optimize.xml -o:lib--optimize.dll -g lib.ml - do! fsc """%s -a --doc:lib--optimize.xml -o:lib--optimize.dll -g""" fsc_flags ["lib.ml"] + // "%FSC%" %fsc_flags% -a --doc:lib--optimize.xml -o:lib--optimize.dll -g lib.fs + do! fsc """%s -a --doc:lib--optimize.xml -o:lib--optimize.dll -g""" fsc_flags ["lib.fs"] // "%PEVERIFY%" lib--optimize.dll do! peverify "lib--optimize.dll" @@ -316,8 +316,8 @@ module FsFromFsViaCs = let csc = Printf.ksprintf (Commands.csc exec cfg.CSC) let fsc_flags = cfg.fsc_flags - // "%FSC%" %fsc_flags% -a -o:lib.dll -g lib.ml - do! fsc "%s -a -o:lib.dll -g" fsc_flags ["lib.ml"] + // "%FSC%" %fsc_flags% -a -o:lib.dll -g lib.fs + do! fsc "%s -a -o:lib.dll -g" fsc_flags ["lib.fs"] // "%PEVERIFY%" lib.dll do! peverify "lib.dll" From b7eb48eedb5c38bde8d7d47ef61954b9b0b00021 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Thu, 16 Jun 2016 17:51:47 +0100 Subject: [PATCH 059/129] fix unit test build --- .../FSharp.Core.Unittests/FSharp.Core/DiscrimantedUnionType.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fsharp/FSharp.Core.Unittests/FSharp.Core/DiscrimantedUnionType.fs b/src/fsharp/FSharp.Core.Unittests/FSharp.Core/DiscrimantedUnionType.fs index 73f548920dc..517e69a9200 100644 --- a/src/fsharp/FSharp.Core.Unittests/FSharp.Core/DiscrimantedUnionType.fs +++ b/src/fsharp/FSharp.Core.Unittests/FSharp.Core/DiscrimantedUnionType.fs @@ -239,7 +239,7 @@ let [] ``can properly construct a struct union using FSharpValue.MakeUnion Assert.IsTrue (structUnion.GetType().IsValueType) - let fieldVals = Microsoft.FSharp.Reflection.FSharpValue.GetUnionFields(structUnion, typeof) + let _uc, fieldVals = Microsoft.FSharp.Reflection.FSharpValue.GetUnionFields(structUnion, typeof) Assert.AreEqual (2, fieldVals.Length) From 6e23f1576b846607e353af12929fc0c809dcd0e1 Mon Sep 17 00:00:00 2001 From: "Avi.Avni" Date: Thu, 16 Jun 2016 21:49:06 +0300 Subject: [PATCH 060/129] add isStatic flag to ClassLetBinding and fix static do test --- src/fsharp/TypeChecker.fs | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/fsharp/TypeChecker.fs b/src/fsharp/TypeChecker.fs index e6df37e2e19..4a862ea90d3 100755 --- a/src/fsharp/TypeChecker.fs +++ b/src/fsharp/TypeChecker.fs @@ -1039,7 +1039,7 @@ type DeclKind = | IntrinsicExtensionBinding /// Extensions to a type in a different assembly | ExtrinsicExtensionBinding - | ClassLetBinding + | ClassLetBinding of (* isStatic *) bool | ObjectExpressionOverrideBinding | ExpressionBinding @@ -1048,7 +1048,7 @@ type DeclKind = | ModuleOrMemberBinding -> true | IntrinsicExtensionBinding -> true | ExtrinsicExtensionBinding -> true - | ClassLetBinding -> false + | ClassLetBinding _ -> false | ObjectExpressionOverrideBinding -> false | ExpressionBinding -> false @@ -1059,7 +1059,7 @@ type DeclKind = | ModuleOrMemberBinding -> true | IntrinsicExtensionBinding -> true | ExtrinsicExtensionBinding -> true - | ClassLetBinding -> true + | ClassLetBinding _ -> true | ObjectExpressionOverrideBinding -> false | ExpressionBinding -> false @@ -1079,7 +1079,7 @@ type DeclKind = | None -> AttributeTargets.Field ||| AttributeTargets.Method ||| AttributeTargets.Property | IntrinsicExtensionBinding -> AttributeTargets.Method ||| AttributeTargets.Property | ExtrinsicExtensionBinding -> AttributeTargets.Method ||| AttributeTargets.Property - | ClassLetBinding -> AttributeTargets.Field ||| AttributeTargets.Method + | ClassLetBinding _ -> AttributeTargets.Field ||| AttributeTargets.Method | ExpressionBinding -> enum 0 // indicates attributes not allowed on expression 'let' bindings // Note: now always true @@ -1088,7 +1088,7 @@ type DeclKind = | ModuleOrMemberBinding -> true | IntrinsicExtensionBinding -> true | ExtrinsicExtensionBinding -> true - | ClassLetBinding -> true + | ClassLetBinding _ -> true | ObjectExpressionOverrideBinding -> true | ExpressionBinding -> true @@ -1097,7 +1097,7 @@ type DeclKind = | ModuleOrMemberBinding -> true | IntrinsicExtensionBinding -> true | ExtrinsicExtensionBinding -> true - | ClassLetBinding -> true + | ClassLetBinding _ -> true | ObjectExpressionOverrideBinding -> true | ExpressionBinding -> false @@ -1106,7 +1106,7 @@ type DeclKind = | ModuleOrMemberBinding -> OverridesOK | IntrinsicExtensionBinding -> WarnOnOverrides | ExtrinsicExtensionBinding -> ErrorOnOverrides - | ClassLetBinding -> ErrorOnOverrides + | ClassLetBinding _ -> ErrorOnOverrides | ObjectExpressionOverrideBinding -> OverridesOK | ExpressionBinding -> ErrorOnOverrides @@ -9650,7 +9650,8 @@ and TcNormalizedBinding declKind (cenv:cenv) env tpenv overallTy safeThisValOpt | MemberKind.Constructor -> Some(".ctor") | _ -> Some(name.idText) | _ -> Some(name.idText) - | ClassLetBinding, DoBinding, _ -> Some(".ctor") + | ClassLetBinding(false), DoBinding, _ -> Some(".ctor") + | ClassLetBinding(true), DoBinding, _ -> Some(".cctor") | ModuleOrMemberBinding, StandaloneExpression, _ -> Some(".cctor") | _, _, _ -> envinner.eCallerMemberName @@ -9686,8 +9687,10 @@ and TcNormalizedBinding declKind (cenv:cenv) env tpenv overallTy safeThisValOpt if isThreadStatic then errorR(DeprecatedThreadStaticBindingWarning(mBinding)) if isVolatile then - if declKind <> ClassLetBinding then - errorR(Error(FSComp.SR.tcVolatileOnlyOnClassLetBindings(),mBinding)) + match declKind with + | ClassLetBinding(_) -> () + | _ -> errorR(Error(FSComp.SR.tcVolatileOnlyOnClassLetBindings(),mBinding)) + if (not isMutable || isThreadStatic) then errorR(Error(FSComp.SR.tcVolatileFieldsMustBeMutable(),mBinding)) @@ -11546,7 +11549,7 @@ module IncrClassChecking = begin // --- Create this for use inside constructor let thisId = ident ("this",m) let thisValScheme = ValScheme(thisId,NonGenericTypeScheme(thisTy),None,None,false,ValInline.Never,CtorThisVal,None,true,false,false,false) - let thisVal = MakeAndPublishVal cenv env (ParentNone,false,ClassLetBinding,ValNotInRecScope,thisValScheme,[],XmlDoc.Empty,None,false) + let thisVal = MakeAndPublishVal cenv env (ParentNone,false,ClassLetBinding(false),ValNotInRecScope,thisValScheme,[],XmlDoc.Empty,None,false) thisVal {TyconRef = tcref @@ -12530,14 +12533,14 @@ module TyconBindingChecking = begin if isRec then // Type check local recursive binding - let binds = binds |> List.map (fun bind -> RecBindingDefn(ExprContainerInfo,NoNewSlots,ClassLetBinding,bind)) + let binds = binds |> List.map (fun bind -> RecBindingDefn(ExprContainerInfo,NoNewSlots,ClassLetBinding(isStatic),bind)) let binds,env,tpenv = TcLetrec ErrorOnOverrides cenv envForBinding tpenv (binds,scopem(*bindsm*),scopem) let bindRs = [IncrClassBindingGroup(binds,isStatic,true)] binds,bindRs,env,tpenv else // Type check local binding - let binds,env,tpenv = TcLetBindings cenv envForBinding ExprContainerInfo ClassLetBinding tpenv (binds,bindsm,scopem) + let binds,env,tpenv = TcLetBindings cenv envForBinding ExprContainerInfo (ClassLetBinding(isStatic)) tpenv (binds,bindsm,scopem) let binds,bindRs = binds |> List.map (function From fe5d94199857c314fc45d4763004b14cbf717d4e Mon Sep 17 00:00:00 2001 From: "Avi.Avni" Date: Thu, 16 Jun 2016 22:24:25 +0300 Subject: [PATCH 061/129] fix merge --- src/fsharp/FSComp.txt | 3 +-- src/fsharp/TypeChecker.fs | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/fsharp/FSComp.txt b/src/fsharp/FSComp.txt index b96c189cf00..5f2d6a014c5 100644 --- a/src/fsharp/FSComp.txt +++ b/src/fsharp/FSComp.txt @@ -1309,5 +1309,4 @@ estApplyStaticArgumentsForMethodNotImplemented,"A type provider implemented GetS 3201,tcModuleAbbrevFirstInMutRec,"In a recursive declaration group, module abbreviations must come after all 'open' declarations and before other declarations" 3202,tcUnsupportedMutRecDecl,"This declaration is not supported in recursive declaration groups" 3203,parsInvalidUseOfRec,"Invalid use of 'rec' keyword" -3204,considerUpcastOperator,"The conversion from %s to %s is a compile-time safe upcast, not a downcast. Consider using the :> (upcast) operator instead of the :?> (downcast) operator." -3205,CallerMemberNameIsOverriden,"The CallerMemberNameAttribute applied to parameter '%s' will have no effect. It is overridden by the CallerFilePathAttribute." \ No newline at end of file +3204,CallerMemberNameIsOverriden,"The CallerMemberNameAttribute applied to parameter '%s' will have no effect. It is overridden by the CallerFilePathAttribute." \ No newline at end of file diff --git a/src/fsharp/TypeChecker.fs b/src/fsharp/TypeChecker.fs index d8e228776c2..e7e04d0d791 100644 --- a/src/fsharp/TypeChecker.fs +++ b/src/fsharp/TypeChecker.fs @@ -12759,7 +12759,7 @@ module MutRecBindingChecking = if isRec then // Type check local recursive binding - let binds = binds |> List.map (fun bind -> RecBindingDefnInfo(ExprContainerInfo,NoNewSlots,ClassLetBinding(isStatic),bind)) + let binds = binds |> List.map (fun bind -> RecDefnBindingInfo(ExprContainerInfo,NoNewSlots,ClassLetBinding(isStatic),bind)) let binds,env,tpenv = TcLetrec ErrorOnOverrides cenv envForBinding tpenv (binds,scopem(*bindsm*),scopem) let bindRs = [IncrClassBindingGroup(binds,isStatic,true)] binds,bindRs,env,tpenv From 4c1f44409b22ce445bdf43d70e4c88d837b8b040 Mon Sep 17 00:00:00 2001 From: "Avi.Avni" Date: Thu, 16 Jun 2016 22:25:52 +0300 Subject: [PATCH 062/129] fix test --- .../Imported/CallerInfo/W_CallerMemberName.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/W_CallerMemberName.fs b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/W_CallerMemberName.fs index 2ee25fac1b0..2e79d315582 100644 --- a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/W_CallerMemberName.fs +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/W_CallerMemberName.fs @@ -1,4 +1,4 @@ -//The CallerMemberNameAttribute applied to parameter 'name' will have no effect. It is overridden by the CallerFilePathAttribute. +//The CallerMemberNameAttribute applied to parameter 'name' will have no effect. It is overridden by the CallerFilePathAttribute. namespace Test open System.Runtime.CompilerServices From cacc03f51f7ee043d3f5d60d04f687766634995e Mon Sep 17 00:00:00 2001 From: Don Syme Date: Fri, 17 Jun 2016 00:01:04 +0100 Subject: [PATCH 063/129] allow elimination of more copy-of-struct locals --- src/fsharp/TastOps.fs | 25 ++++++++++++++----------- src/fsharp/TastOps.fsi | 2 +- src/fsharp/TypeChecker.fs | 2 +- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/fsharp/TastOps.fs b/src/fsharp/TastOps.fs index a1e9a6717f2..969265ac484 100755 --- a/src/fsharp/TastOps.fs +++ b/src/fsharp/TastOps.fs @@ -5041,14 +5041,14 @@ and remarkBind m (TBind(v,repr,_)) = //-------------------------------------------------------------------------- let isRecdOrStructFieldAllocObservable (f:RecdField) = not f.IsStatic && f.IsMutable -let ucaseAllocObservable (uc:UnionCase) = uc.FieldTable.FieldsByIndex |> Array.exists isRecdOrStructFieldAllocObservable -let isUnionCaseAllocObservable (uc:UnionCaseRef) = uc.UnionCase |> ucaseAllocObservable +let isUnionCaseAllocObservable (uc:UnionCase) = uc.FieldTable.FieldsByIndex |> Array.exists isRecdOrStructFieldAllocObservable +let isUnionCaseRefAllocObservable (uc:UnionCaseRef) = uc.UnionCase |> isUnionCaseAllocObservable let isRecdOrUnionOrStructTyconAllocObservable (_g:TcGlobals) (tycon:Tycon) = - if tycon.IsRecordTycon || tycon.IsStructOrEnumTycon then + if tycon.IsUnionTycon then + tycon.UnionCasesArray |> Array.exists isUnionCaseAllocObservable + elif tycon.IsRecordTycon || tycon.IsStructOrEnumTycon then tycon.AllFieldsArray |> Array.exists isRecdOrStructFieldAllocObservable - elif tycon.IsUnionTycon then - tycon.UnionCasesArray |> Array.exists ucaseAllocObservable else false @@ -5374,7 +5374,7 @@ let mkAndSimplifyMatch spBind exprm matchm ty tree targets = type Mutates = DefinitelyMutates | PossiblyMutates | NeverMutates exception DefensiveCopyWarning of string * range -let isRecdOrStuctTyImmutable g ty = +let isRecdOrStructTyImmutable g ty = match tryDestAppTy g ty with | None -> false | Some tcref -> @@ -5393,7 +5393,7 @@ let isRecdOrStuctTyImmutable g ty = // let g1 = A.G(1) // (fun () -> g1.x1) // -// Note: isRecdOrStuctTyImmutable implies PossiblyMutates or NeverMutates +// Note: isRecdOrStructTyImmutable implies PossiblyMutates or NeverMutates // // We only do this for true local or closure fields because we can't take adddresses of immutable static // fields across assemblies. @@ -5404,7 +5404,7 @@ let CanTakeAddressOfImmutableVal g (v:ValRef) mut = not v.IsMemberOrModuleBinding && (match mut with | NeverMutates -> true - | PossiblyMutates -> isRecdOrStuctTyImmutable g v.Type + | PossiblyMutates -> isRecdOrStructTyImmutable g v.Type | DefinitelyMutates -> false) let MustTakeAddressOfVal g (v:ValRef) = @@ -5423,13 +5423,13 @@ let CanTakeAddressOfRecdFieldRef g (rfref: RecdFieldRef) mut tinst = mut <> DefinitelyMutates && // We only do this if the field is defined in this assembly because we can't take adddresses across assemblies for immutable fields entityRefInThisAssembly g.compilingFslib rfref.TyconRef && - isRecdOrStuctTyImmutable g (actualTyOfRecdFieldRef rfref tinst) + isRecdOrStructTyImmutable g (actualTyOfRecdFieldRef rfref tinst) let CanTakeAddressOfUnionFieldRef g (uref: UnionCaseRef) mut tinst cidx = mut <> DefinitelyMutates && // We only do this if the field is defined in this assembly because we can't take adddresses across assemblies for immutable fields entityRefInThisAssembly g.compilingFslib uref.TyconRef && - isRecdOrStuctTyImmutable g (actualTyOfUnionFieldRef uref cidx tinst) + isRecdOrStructTyImmutable g (actualTyOfUnionFieldRef uref cidx tinst) let rec mkExprAddrOfExprAux g mustTakeAddress useReadonlyForGenericArrayAddress mut e addrExprVal m = @@ -5511,7 +5511,10 @@ let rec mkExprAddrOfExprAux g mustTakeAddress useReadonlyForGenericArrayAddress errorR(Error(FSComp.SR.tastInvalidMutationOfConstant(),m)); | PossiblyMutates -> warning(DefensiveCopyWarning(FSComp.SR.tastValueHasBeenCopied(),m)); - let tmp,_ = mkMutableCompGenLocal m "copyOfStruct" ty + let tmp,_ = + match mut with + | NeverMutates -> mkCompGenLocal m "copyOfStruct" ty + | _ -> mkMutableCompGenLocal m "copyOfStruct" ty Some (tmp,e), (mkValAddr m (mkLocalValRef tmp)) let mkExprAddrOfExpr g mustTakeAddress useReadonlyForGenericArrayAddress mut e addrExprVal m = diff --git a/src/fsharp/TastOps.fsi b/src/fsharp/TastOps.fsi index 4eefb78177a..e99cabd7c14 100755 --- a/src/fsharp/TastOps.fsi +++ b/src/fsharp/TastOps.fsi @@ -1046,7 +1046,7 @@ val TypeHasDefaultValue : TcGlobals -> range -> TType -> bool val isAbstractTycon : Tycon -> bool -val isUnionCaseAllocObservable : UnionCaseRef -> bool +val isUnionCaseRefAllocObservable : UnionCaseRef -> bool val isRecdOrUnionOrStructTyconRefAllocObservable : TcGlobals -> TyconRef -> bool val isExnAllocObservable : TyconRef -> bool val isUnionCaseFieldMutable : TcGlobals -> UnionCaseRef -> int -> bool diff --git a/src/fsharp/TypeChecker.fs b/src/fsharp/TypeChecker.fs index 30085eac622..de38c64e531 100755 --- a/src/fsharp/TypeChecker.fs +++ b/src/fsharp/TypeChecker.fs @@ -2037,7 +2037,7 @@ module GeneralizationHelpers = | Expr.Op(op,_,args,_) -> match op with | TOp.Tuple -> true - | TOp.UnionCase uc -> not (isUnionCaseAllocObservable uc) + | TOp.UnionCase uc -> not (isUnionCaseRefAllocObservable uc) | TOp.Recd(ctorInfo,tcref) -> match ctorInfo with | RecdExpr -> not (isRecdOrUnionOrStructTyconRefAllocObservable g tcref) From 0e72bebcf32127089d5c80a6fbb63ef703c5da46 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Fri, 17 Jun 2016 00:17:08 +0100 Subject: [PATCH 064/129] add new test for struct union codegen --- .../Optimizations/Inlining/StructUnion01.fs | 39 + .../Inlining/StructUnion01.il.bsl | 725 ++++++++++++++++++ .../Source/Optimizations/Inlining/env.lst | 1 + 3 files changed, 765 insertions(+) create mode 100644 tests/fsharpqa/Source/Optimizations/Inlining/StructUnion01.fs create mode 100644 tests/fsharpqa/Source/Optimizations/Inlining/StructUnion01.il.bsl diff --git a/tests/fsharpqa/Source/Optimizations/Inlining/StructUnion01.fs b/tests/fsharpqa/Source/Optimizations/Inlining/StructUnion01.fs new file mode 100644 index 00000000000..d3e41ff4788 --- /dev/null +++ b/tests/fsharpqa/Source/Optimizations/Inlining/StructUnion01.fs @@ -0,0 +1,39 @@ +// #NoMono #CodeGen #Optimizations +module StructUnion01 + +[] +type U = U of int * int + +let g1 (U(a,b)) = a + b + +let g2 u = + let (U(a,b)) = u + a + b + +let g3 (x:U) = + match x with + | U(3,a) -> a + | U(a,b) -> a + b + +let g4 (x:U) (y: U) = + match x,y with + | U(3,a), U(5,b) -> a + b + | U(a,b), U(c,d) -> a + b + c + d + +let f1 (x:U byref) = + let (U(a,b)) = x + a + b + +let f2 (x:U byref) = + match x with + | U(a,b) -> a + b + +let f3 (x:U byref) = + match x with + | U(3,a) -> a + | U(a,b) -> a + b + +let f4 (x:U byref) (y: U byref) = + match x,y with + | U(3,a), U(5,b) -> a + b + | U(a,b), U(c,d) -> a + b + c + d diff --git a/tests/fsharpqa/Source/Optimizations/Inlining/StructUnion01.il.bsl b/tests/fsharpqa/Source/Optimizations/Inlining/StructUnion01.il.bsl new file mode 100644 index 00000000000..95df244b59b --- /dev/null +++ b/tests/fsharpqa/Source/Optimizations/Inlining/StructUnion01.il.bsl @@ -0,0 +1,725 @@ + +// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0 +// Copyright (c) Microsoft Corporation. All rights reserved. + + + +// Metadata version: v4.0.30319 +.assembly extern mscorlib +{ + .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. + .ver 4:0:0:0 +} +.assembly extern FSharp.Core +{ + .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....: + .ver 4:4:1:0 +} +.assembly StructUnion01 +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.mresource public FSharpSignatureData.StructUnion01 +{ + // Offset: 0x00000000 Length: 0x0000088A +} +.mresource public FSharpOptimizationData.StructUnion01 +{ + // Offset: 0x00000890 Length: 0x00000421 +} +.module StructUnion01.dll +// MVID: {576332E3-D3E9-6B24-A745-0383E3326357} +.imagebase 0x00400000 +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 // WINDOWS_CUI +.corflags 0x00000001 // ILONLY +// Image base: 0x007C0000 + + +// =============== CLASS MEMBERS DECLARATION =================== + +.class public abstract auto ansi sealed StructUnion01 + extends [mscorlib]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto autochar serializable sealed nested public beforefieldinit U + extends [mscorlib]System.ValueType + implements class [mscorlib]System.IEquatable`1, + [mscorlib]System.Collections.IStructuralEquatable, + class [mscorlib]System.IComparable`1, + [mscorlib]System.IComparable, + [mscorlib]System.Collections.IStructuralComparable + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.StructAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [mscorlib]System.Diagnostics.DebuggerDisplayAttribute::.ctor(string) = ( 01 00 15 7B 5F 5F 44 65 62 75 67 44 69 73 70 6C // ...{__DebugDispl + 61 79 28 29 2C 6E 71 7D 00 00 ) // ay(),nq}.. + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 01 00 00 00 00 00 ) + .field assembly int32 item1 + .custom instance void [mscorlib]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [mscorlib]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .field assembly int32 item2 + .custom instance void [mscorlib]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [mscorlib]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .method public static valuetype StructUnion01/U + NewU(int32 item1, + int32 item2) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 08 00 00 00 00 00 00 00 00 00 ) + // Code size 8 (0x8) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: newobj instance void StructUnion01/U::.ctor(int32, + int32) + IL_0007: ret + } // end of method U::NewU + + .method assembly specialname rtspecialname + instance void .ctor(int32 item1, + int32 item2) cil managed + { + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [mscorlib]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 15 (0xf) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld int32 StructUnion01/U::item1 + IL_0007: ldarg.0 + IL_0008: ldarg.2 + IL_0009: stfld int32 StructUnion01/U::item2 + IL_000e: ret + } // end of method U::.ctor + + .method public hidebysig instance int32 + get_Item1() cil managed + { + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [mscorlib]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld int32 StructUnion01/U::item1 + IL_0006: ret + } // end of method U::get_Item1 + + .method public hidebysig instance int32 + get_Item2() cil managed + { + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [mscorlib]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld int32 StructUnion01/U::item2 + IL_0006: ret + } // end of method U::get_Item2 + + .method public hidebysig instance int32 + get_Tag() cil managed + { + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [mscorlib]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 4 (0x4) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: pop + IL_0002: ldc.i4.0 + IL_0003: ret + } // end of method U::get_Tag + + .method assembly hidebysig specialname + instance object __DebugDisplay() cil managed + { + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [mscorlib]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 27 (0x1b) + .maxstack 8 + IL_0000: ldstr "%+0.8A" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit,string,string,string>::.ctor(string) + IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatToString>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_000f: ldarg.0 + IL_0010: ldobj StructUnion01/U + IL_0015: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_001a: ret + } // end of method U::__DebugDisplay + + .method public hidebysig virtual final + instance int32 CompareTo(valuetype StructUnion01/U obj) cil managed + { + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 77 (0x4d) + .maxstack 4 + .locals init (int32 V_0, + class [mscorlib]System.Collections.IComparer V_1, + int32 V_2, + int32 V_3) + IL_0000: ldarg.0 + IL_0001: pop + IL_0002: call class [mscorlib]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_0007: stloc.1 + IL_0008: ldarg.0 + IL_0009: ldfld int32 StructUnion01/U::item1 + IL_000e: stloc.2 + IL_000f: ldarg.1 + IL_0010: ldfld int32 StructUnion01/U::item1 + IL_0015: stloc.3 + IL_0016: ldloc.2 + IL_0017: ldloc.3 + IL_0018: bge.s IL_001d + + IL_001a: ldc.i4.m1 + IL_001b: br.s IL_0021 + + IL_001d: ldloc.2 + IL_001e: ldloc.3 + IL_001f: cgt + IL_0021: stloc.0 + IL_0022: ldloc.0 + IL_0023: ldc.i4.0 + IL_0024: bge.s IL_0028 + + IL_0026: ldloc.0 + IL_0027: ret + + IL_0028: ldloc.0 + IL_0029: ldc.i4.0 + IL_002a: ble.s IL_002e + + IL_002c: ldloc.0 + IL_002d: ret + + IL_002e: call class [mscorlib]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_0033: stloc.1 + IL_0034: ldarg.0 + IL_0035: ldfld int32 StructUnion01/U::item2 + IL_003a: stloc.2 + IL_003b: ldarg.1 + IL_003c: ldfld int32 StructUnion01/U::item2 + IL_0041: stloc.3 + IL_0042: ldloc.2 + IL_0043: ldloc.3 + IL_0044: bge.s IL_0048 + + IL_0046: ldc.i4.m1 + IL_0047: ret + + IL_0048: ldloc.2 + IL_0049: ldloc.3 + IL_004a: cgt + IL_004c: ret + } // end of method U::CompareTo + + .method public hidebysig virtual final + instance int32 CompareTo(object obj) cil managed + { + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 13 (0xd) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: unbox.any StructUnion01/U + IL_0007: call instance int32 StructUnion01/U::CompareTo(valuetype StructUnion01/U) + IL_000c: ret + } // end of method U::CompareTo + + .method public hidebysig virtual final + instance int32 CompareTo(object obj, + class [mscorlib]System.Collections.IComparer comp) cil managed + { + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 81 (0x51) + .maxstack 4 + .locals init (valuetype StructUnion01/U V_0, + valuetype StructUnion01/U& V_1, + int32 V_2, + int32 V_3, + int32 V_4) + IL_0000: ldarg.1 + IL_0001: unbox.any StructUnion01/U + IL_0006: stloc.0 + IL_0007: ldloca.s V_0 + IL_0009: stloc.1 + IL_000a: ldarg.0 + IL_000b: pop + IL_000c: ldarg.0 + IL_000d: ldfld int32 StructUnion01/U::item1 + IL_0012: stloc.3 + IL_0013: ldloc.1 + IL_0014: ldfld int32 StructUnion01/U::item1 + IL_0019: stloc.s V_4 + IL_001b: ldloc.3 + IL_001c: ldloc.s V_4 + IL_001e: bge.s IL_0023 + + IL_0020: ldc.i4.m1 + IL_0021: br.s IL_0028 + + IL_0023: ldloc.3 + IL_0024: ldloc.s V_4 + IL_0026: cgt + IL_0028: stloc.2 + IL_0029: ldloc.2 + IL_002a: ldc.i4.0 + IL_002b: bge.s IL_002f + + IL_002d: ldloc.2 + IL_002e: ret + + IL_002f: ldloc.2 + IL_0030: ldc.i4.0 + IL_0031: ble.s IL_0035 + + IL_0033: ldloc.2 + IL_0034: ret + + IL_0035: ldarg.0 + IL_0036: ldfld int32 StructUnion01/U::item2 + IL_003b: stloc.3 + IL_003c: ldloc.1 + IL_003d: ldfld int32 StructUnion01/U::item2 + IL_0042: stloc.s V_4 + IL_0044: ldloc.3 + IL_0045: ldloc.s V_4 + IL_0047: bge.s IL_004b + + IL_0049: ldc.i4.m1 + IL_004a: ret + + IL_004b: ldloc.3 + IL_004c: ldloc.s V_4 + IL_004e: cgt + IL_0050: ret + } // end of method U::CompareTo + + .method public hidebysig virtual final + instance int32 GetHashCode(class [mscorlib]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 50 (0x32) + .maxstack 7 + .locals init (int32 V_0) + IL_0000: ldc.i4.0 + IL_0001: stloc.0 + IL_0002: ldarg.0 + IL_0003: pop + IL_0004: ldc.i4.0 + IL_0005: stloc.0 + IL_0006: ldc.i4 0x9e3779b9 + IL_000b: ldarg.0 + IL_000c: ldfld int32 StructUnion01/U::item2 + IL_0011: ldloc.0 + IL_0012: ldc.i4.6 + IL_0013: shl + IL_0014: ldloc.0 + IL_0015: ldc.i4.2 + IL_0016: shr + IL_0017: add + IL_0018: add + IL_0019: add + IL_001a: stloc.0 + IL_001b: ldc.i4 0x9e3779b9 + IL_0020: ldarg.0 + IL_0021: ldfld int32 StructUnion01/U::item1 + IL_0026: ldloc.0 + IL_0027: ldc.i4.6 + IL_0028: shl + IL_0029: ldloc.0 + IL_002a: ldc.i4.2 + IL_002b: shr + IL_002c: add + IL_002d: add + IL_002e: add + IL_002f: stloc.0 + IL_0030: ldloc.0 + IL_0031: ret + } // end of method U::GetHashCode + + .method public hidebysig virtual final + instance int32 GetHashCode() cil managed + { + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 12 (0xc) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call class [mscorlib]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() + IL_0006: call instance int32 StructUnion01/U::GetHashCode(class [mscorlib]System.Collections.IEqualityComparer) + IL_000b: ret + } // end of method U::GetHashCode + + .method public hidebysig virtual final + instance bool Equals(object obj, + class [mscorlib]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 53 (0x35) + .maxstack 4 + .locals init (valuetype StructUnion01/U V_0, + valuetype StructUnion01/U& V_1) + IL_0000: ldarg.1 + IL_0001: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives/IntrinsicFunctions::TypeTestGeneric(object) + IL_0006: brtrue.s IL_000a + + IL_0008: ldc.i4.0 + IL_0009: ret + + IL_000a: ldarg.1 + IL_000b: unbox.any StructUnion01/U + IL_0010: stloc.0 + IL_0011: ldloca.s V_0 + IL_0013: stloc.1 + IL_0014: ldarg.0 + IL_0015: pop + IL_0016: ldarg.0 + IL_0017: ldfld int32 StructUnion01/U::item1 + IL_001c: ldloc.1 + IL_001d: ldfld int32 StructUnion01/U::item1 + IL_0022: bne.un.s IL_0033 + + IL_0024: ldarg.0 + IL_0025: ldfld int32 StructUnion01/U::item2 + IL_002a: ldloc.1 + IL_002b: ldfld int32 StructUnion01/U::item2 + IL_0030: ceq + IL_0032: ret + + IL_0033: ldc.i4.0 + IL_0034: ret + } // end of method U::Equals + + .method public hidebysig virtual final + instance bool Equals(valuetype StructUnion01/U obj) cil managed + { + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 36 (0x24) + .maxstack 4 + .locals init (valuetype StructUnion01/U& V_0) + IL_0000: ldarga.s obj + IL_0002: stloc.0 + IL_0003: ldarg.0 + IL_0004: pop + IL_0005: ldarg.0 + IL_0006: ldfld int32 StructUnion01/U::item1 + IL_000b: ldloc.0 + IL_000c: ldfld int32 StructUnion01/U::item1 + IL_0011: bne.un.s IL_0022 + + IL_0013: ldarg.0 + IL_0014: ldfld int32 StructUnion01/U::item2 + IL_0019: ldloc.0 + IL_001a: ldfld int32 StructUnion01/U::item2 + IL_001f: ceq + IL_0021: ret + + IL_0022: ldc.i4.0 + IL_0023: ret + } // end of method U::Equals + + .method public hidebysig virtual final + instance bool Equals(object obj) cil managed + { + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 23 (0x17) + .maxstack 8 + IL_0000: ldarg.1 + IL_0001: call bool [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives/IntrinsicFunctions::TypeTestGeneric(object) + IL_0006: brtrue.s IL_000a + + IL_0008: ldc.i4.0 + IL_0009: ret + + IL_000a: ldarg.0 + IL_000b: ldarg.1 + IL_000c: unbox.any StructUnion01/U + IL_0011: call instance bool StructUnion01/U::Equals(valuetype StructUnion01/U) + IL_0016: ret + } // end of method U::Equals + + .property instance int32 Tag() + { + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [mscorlib]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [mscorlib]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .get instance int32 StructUnion01/U::get_Tag() + } // end of property U::Tag + .property instance int32 Item1() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [mscorlib]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .get instance int32 StructUnion01/U::get_Item1() + } // end of property U::Item1 + .property instance int32 Item2() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32, + int32) = ( 01 00 04 00 00 00 00 00 00 00 01 00 00 00 00 00 ) + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [mscorlib]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .get instance int32 StructUnion01/U::get_Item2() + } // end of property U::Item2 + } // end of class U + + .method public static int32 g1(valuetype StructUnion01/U _arg1) cil managed + { + // Code size 16 (0x10) + .maxstack 8 + IL_0000: ldarga.s _arg1 + IL_0002: ldfld int32 StructUnion01/U::item1 + IL_0007: ldarga.s _arg1 + IL_0009: ldfld int32 StructUnion01/U::item2 + IL_000e: add + IL_000f: ret + } // end of method StructUnion01::g1 + + .method public static int32 g2(valuetype StructUnion01/U u) cil managed + { + // Code size 16 (0x10) + .maxstack 8 + IL_0000: ldarga.s u + IL_0002: ldfld int32 StructUnion01/U::item1 + IL_0007: ldarga.s u + IL_0009: ldfld int32 StructUnion01/U::item2 + IL_000e: add + IL_000f: ret + } // end of method StructUnion01::g2 + + .method public static int32 g3(valuetype StructUnion01/U x) cil managed + { + // Code size 42 (0x2a) + .maxstack 8 + IL_0000: ldarga.s x + IL_0002: ldfld int32 StructUnion01/U::item1 + IL_0007: ldc.i4.3 + IL_0008: sub + IL_0009: switch ( + IL_0022) + IL_0012: ldarga.s x + IL_0014: ldfld int32 StructUnion01/U::item1 + IL_0019: ldarga.s x + IL_001b: ldfld int32 StructUnion01/U::item2 + IL_0020: add + IL_0021: ret + + IL_0022: ldarga.s x + IL_0024: ldfld int32 StructUnion01/U::item2 + IL_0029: ret + } // end of method StructUnion01::g3 + + .method public static int32 g4(valuetype StructUnion01/U x, + valuetype StructUnion01/U y) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) + // Code size 126 (0x7e) + .maxstack 6 + .locals init (int32 V_0, + int32 V_1, + int32 V_2, + int32 V_3) + IL_0000: ldarga.s x + IL_0002: ldfld int32 StructUnion01/U::item1 + IL_0007: ldc.i4.3 + IL_0008: sub + IL_0009: switch ( + IL_003a) + IL_0012: ldarga.s y + IL_0014: ldfld int32 StructUnion01/U::item2 + IL_0019: stloc.0 + IL_001a: ldarga.s y + IL_001c: ldfld int32 StructUnion01/U::item1 + IL_0021: stloc.1 + IL_0022: ldarga.s x + IL_0024: ldfld int32 StructUnion01/U::item2 + IL_0029: stloc.2 + IL_002a: ldarga.s x + IL_002c: ldfld int32 StructUnion01/U::item1 + IL_0031: stloc.3 + IL_0032: ldloc.3 + IL_0033: ldloc.2 + IL_0034: add + IL_0035: ldloc.1 + IL_0036: add + IL_0037: ldloc.0 + IL_0038: add + IL_0039: ret + + IL_003a: ldarga.s y + IL_003c: ldfld int32 StructUnion01/U::item1 + IL_0041: ldc.i4.5 + IL_0042: sub + IL_0043: switch ( + IL_006e) + IL_004c: ldarga.s y + IL_004e: ldfld int32 StructUnion01/U::item2 + IL_0053: ldarga.s y + IL_0055: ldfld int32 StructUnion01/U::item1 + IL_005a: ldarga.s x + IL_005c: ldfld int32 StructUnion01/U::item2 + IL_0061: ldarga.s x + IL_0063: ldfld int32 StructUnion01/U::item1 + IL_0068: stloc.3 + IL_0069: stloc.2 + IL_006a: stloc.1 + IL_006b: stloc.0 + IL_006c: br.s IL_0032 + + IL_006e: ldarga.s x + IL_0070: ldfld int32 StructUnion01/U::item2 + IL_0075: ldarga.s y + IL_0077: ldfld int32 StructUnion01/U::item2 + IL_007c: add + IL_007d: ret + } // end of method StructUnion01::g4 + + .method public static int32 f1(valuetype StructUnion01/U& x) cil managed + { + // Code size 23 (0x17) + .maxstack 4 + .locals init (valuetype StructUnion01/U V_0) + IL_0000: ldarg.0 + IL_0001: ldobj StructUnion01/U + IL_0006: stloc.0 + IL_0007: ldloca.s V_0 + IL_0009: ldfld int32 StructUnion01/U::item1 + IL_000e: ldloca.s V_0 + IL_0010: ldfld int32 StructUnion01/U::item2 + IL_0015: add + IL_0016: ret + } // end of method StructUnion01::f1 + + .method public static int32 f2(valuetype StructUnion01/U& x) cil managed + { + // Code size 23 (0x17) + .maxstack 4 + .locals init (valuetype StructUnion01/U V_0) + IL_0000: ldarg.0 + IL_0001: ldobj StructUnion01/U + IL_0006: stloc.0 + IL_0007: ldloca.s V_0 + IL_0009: ldfld int32 StructUnion01/U::item1 + IL_000e: ldloca.s V_0 + IL_0010: ldfld int32 StructUnion01/U::item2 + IL_0015: add + IL_0016: ret + } // end of method StructUnion01::f2 + + .method public static int32 f3(valuetype StructUnion01/U& x) cil managed + { + // Code size 49 (0x31) + .maxstack 4 + .locals init (valuetype StructUnion01/U V_0) + IL_0000: ldarg.0 + IL_0001: ldobj StructUnion01/U + IL_0006: stloc.0 + IL_0007: ldloca.s V_0 + IL_0009: ldfld int32 StructUnion01/U::item1 + IL_000e: ldc.i4.3 + IL_000f: sub + IL_0010: switch ( + IL_0029) + IL_0019: ldloca.s V_0 + IL_001b: ldfld int32 StructUnion01/U::item1 + IL_0020: ldloca.s V_0 + IL_0022: ldfld int32 StructUnion01/U::item2 + IL_0027: add + IL_0028: ret + + IL_0029: ldloca.s V_0 + IL_002b: ldfld int32 StructUnion01/U::item2 + IL_0030: ret + } // end of method StructUnion01::f3 + + .method public static int32 f4(valuetype StructUnion01/U& x, + valuetype StructUnion01/U& y) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) + // Code size 146 (0x92) + .maxstack 6 + .locals init (valuetype StructUnion01/U V_0, + valuetype StructUnion01/U V_1, + int32 V_2, + int32 V_3, + int32 V_4, + int32 V_5) + IL_0000: ldarg.0 + IL_0001: ldobj StructUnion01/U + IL_0006: stloc.0 + IL_0007: ldarg.1 + IL_0008: ldobj StructUnion01/U + IL_000d: stloc.1 + IL_000e: ldloca.s V_0 + IL_0010: ldfld int32 StructUnion01/U::item1 + IL_0015: ldc.i4.3 + IL_0016: sub + IL_0017: switch ( + IL_004c) + IL_0020: ldloca.s V_1 + IL_0022: ldfld int32 StructUnion01/U::item2 + IL_0027: stloc.2 + IL_0028: ldloca.s V_1 + IL_002a: ldfld int32 StructUnion01/U::item1 + IL_002f: stloc.3 + IL_0030: ldloca.s V_0 + IL_0032: ldfld int32 StructUnion01/U::item2 + IL_0037: stloc.s V_4 + IL_0039: ldloca.s V_0 + IL_003b: ldfld int32 StructUnion01/U::item1 + IL_0040: stloc.s V_5 + IL_0042: ldloc.s V_5 + IL_0044: ldloc.s V_4 + IL_0046: add + IL_0047: ldloc.3 + IL_0048: add + IL_0049: ldloc.2 + IL_004a: add + IL_004b: ret + + IL_004c: ldloca.s V_1 + IL_004e: ldfld int32 StructUnion01/U::item1 + IL_0053: ldc.i4.5 + IL_0054: sub + IL_0055: switch ( + IL_0082) + IL_005e: ldloca.s V_1 + IL_0060: ldfld int32 StructUnion01/U::item2 + IL_0065: ldloca.s V_1 + IL_0067: ldfld int32 StructUnion01/U::item1 + IL_006c: ldloca.s V_0 + IL_006e: ldfld int32 StructUnion01/U::item2 + IL_0073: ldloca.s V_0 + IL_0075: ldfld int32 StructUnion01/U::item1 + IL_007a: stloc.s V_5 + IL_007c: stloc.s V_4 + IL_007e: stloc.3 + IL_007f: stloc.2 + IL_0080: br.s IL_0042 + + IL_0082: ldloca.s V_0 + IL_0084: ldfld int32 StructUnion01/U::item2 + IL_0089: ldloca.s V_1 + IL_008b: ldfld int32 StructUnion01/U::item2 + IL_0090: add + IL_0091: ret + } // end of method StructUnion01::f4 + +} // end of class StructUnion01 + +.class private abstract auto ansi sealed ''.$StructUnion01 + extends [mscorlib]System.Object +{ +} // end of class ''.$StructUnion01 + + +// ============================================================= + +// *********** DISASSEMBLY COMPLETE *********************** diff --git a/tests/fsharpqa/Source/Optimizations/Inlining/env.lst b/tests/fsharpqa/Source/Optimizations/Inlining/env.lst index 36d62b41f3d..29c1d15832e 100644 --- a/tests/fsharpqa/Source/Optimizations/Inlining/env.lst +++ b/tests/fsharpqa/Source/Optimizations/Inlining/env.lst @@ -1,2 +1,3 @@ NoMT SOURCE=Match01.fs SCFLAGS="-a --optimize+" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd Match01.dll" # Match01.fs NoMT SOURCE=Match02.fs SCFLAGS="-a --optimize+" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd Match02.dll" # Match02.fs +NoMT SOURCE=StructUnion01.fs SCFLAGS="-a --optimize+" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd StructUnion01.dll" # Match02.fs From 583214b7c5a2375cdae0844c7ab9b81e0b0ce767 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Fri, 17 Jun 2016 01:32:43 +0100 Subject: [PATCH 065/129] fix new test for struct union codegen --- tests/fsharpqa/Source/Optimizations/Inlining/env.lst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fsharpqa/Source/Optimizations/Inlining/env.lst b/tests/fsharpqa/Source/Optimizations/Inlining/env.lst index 29c1d15832e..9c95c7c6545 100644 --- a/tests/fsharpqa/Source/Optimizations/Inlining/env.lst +++ b/tests/fsharpqa/Source/Optimizations/Inlining/env.lst @@ -1,3 +1,3 @@ NoMT SOURCE=Match01.fs SCFLAGS="-a --optimize+" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd Match01.dll" # Match01.fs NoMT SOURCE=Match02.fs SCFLAGS="-a --optimize+" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd Match02.dll" # Match02.fs -NoMT SOURCE=StructUnion01.fs SCFLAGS="-a --optimize+" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd StructUnion01.dll" # Match02.fs +NoMT SOURCE=StructUnion01.fs SCFLAGS="-a --optimize+" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd StructUnion01.dll" # StructUnion01.fs From d705557e0c900f41645ea1d5ba892d0fd36e51b6 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Fri, 17 Jun 2016 16:47:26 +0100 Subject: [PATCH 066/129] first draft of fixed support --- VisualFSharp.sln | 87 +++------------------- src/fsharp/FSComp.txt | 1 + src/fsharp/IlxGen.fs | 46 ++++++------ src/fsharp/TypeChecker.fs | 69 ++++++++++++------ src/fsharp/ast.fs | 12 +++- src/fsharp/lexhelp.fs | 3 +- src/fsharp/pars.fsy | 4 ++ src/fsharp/tast.fs | 147 ++++++++++++++++++++------------------ 8 files changed, 179 insertions(+), 190 deletions(-) diff --git a/VisualFSharp.sln b/VisualFSharp.sln index 6224d843be1..26f1b2787c2 100644 --- a/VisualFSharp.sln +++ b/VisualFSharp.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 -VisualStudioVersion = 14.0.25123.0 +VisualStudioVersion = 14.0.24720.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.Compiler", "src\fsharp\FSharp.Compiler\FSharp.Compiler.fsproj", "{2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}" EndProject @@ -120,7 +120,16 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XMLFile", "vsintegration\It EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VisualFSharpVsix", "vsintegration\VisualFSharpVsix\VisualFSharpVsix.csproj", "{E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{D3244A8B-4C62-4247-8DE9-29A32EBA67FB}" + ProjectSection(SolutionItems) = preProject + Performance2.psess = Performance2.psess + Performance3.psess = Performance3.psess + EndProjectSection +EndProject Global + GlobalSection(Performance) = preSolution + HasPerformanceSessions = true + EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Debug|x86 = Debug|x86 @@ -130,54 +139,6 @@ Global Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.Debug|x86.ActiveCfg = Debug|Any CPU - {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.Debug|x86.Build.0 = Debug|Any CPU - {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.Proto|Any CPU.ActiveCfg = Proto|Any CPU - {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.Proto|Any CPU.Build.0 = Proto|Any CPU - {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.Proto|x86.ActiveCfg = Proto|Any CPU - {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.Proto|x86.Build.0 = Proto|Any CPU - {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.Release|Any CPU.Build.0 = Release|Any CPU - {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.Release|x86.ActiveCfg = Release|Any CPU - {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.Release|x86.Build.0 = Release|Any CPU - {493D19F9-35A4-4D0B-9B25-CA948823B709}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {493D19F9-35A4-4D0B-9B25-CA948823B709}.Debug|Any CPU.Build.0 = Debug|Any CPU - {493D19F9-35A4-4D0B-9B25-CA948823B709}.Debug|x86.ActiveCfg = Debug|Any CPU - {493D19F9-35A4-4D0B-9B25-CA948823B709}.Debug|x86.Build.0 = Debug|Any CPU - {493D19F9-35A4-4D0B-9B25-CA948823B709}.Proto|Any CPU.ActiveCfg = Proto|Any CPU - {493D19F9-35A4-4D0B-9B25-CA948823B709}.Proto|Any CPU.Build.0 = Proto|Any CPU - {493D19F9-35A4-4D0B-9B25-CA948823B709}.Proto|x86.ActiveCfg = Proto|Any CPU - {493D19F9-35A4-4D0B-9B25-CA948823B709}.Proto|x86.Build.0 = Proto|Any CPU - {493D19F9-35A4-4D0B-9B25-CA948823B709}.Release|Any CPU.ActiveCfg = Release|Any CPU - {493D19F9-35A4-4D0B-9B25-CA948823B709}.Release|Any CPU.Build.0 = Release|Any CPU - {493D19F9-35A4-4D0B-9B25-CA948823B709}.Release|x86.ActiveCfg = Release|Any CPU - {493D19F9-35A4-4D0B-9B25-CA948823B709}.Release|x86.Build.0 = Release|Any CPU - {530DF8CA-7996-407A-B533-D0C2873257AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {530DF8CA-7996-407A-B533-D0C2873257AF}.Debug|Any CPU.Build.0 = Debug|Any CPU - {530DF8CA-7996-407A-B533-D0C2873257AF}.Debug|x86.ActiveCfg = Debug|Any CPU - {530DF8CA-7996-407A-B533-D0C2873257AF}.Debug|x86.Build.0 = Debug|Any CPU - {530DF8CA-7996-407A-B533-D0C2873257AF}.Proto|Any CPU.ActiveCfg = Proto|Any CPU - {530DF8CA-7996-407A-B533-D0C2873257AF}.Proto|Any CPU.Build.0 = Proto|Any CPU - {530DF8CA-7996-407A-B533-D0C2873257AF}.Proto|x86.ActiveCfg = Proto|Any CPU - {530DF8CA-7996-407A-B533-D0C2873257AF}.Proto|x86.Build.0 = Proto|Any CPU - {530DF8CA-7996-407A-B533-D0C2873257AF}.Release|Any CPU.ActiveCfg = Release|Any CPU - {530DF8CA-7996-407A-B533-D0C2873257AF}.Release|Any CPU.Build.0 = Release|Any CPU - {530DF8CA-7996-407A-B533-D0C2873257AF}.Release|x86.ActiveCfg = Release|Any CPU - {530DF8CA-7996-407A-B533-D0C2873257AF}.Release|x86.Build.0 = Release|Any CPU - {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.Debug|Any CPU.Build.0 = Debug|Any CPU - {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.Debug|x86.ActiveCfg = Debug|Any CPU - {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.Debug|x86.Build.0 = Debug|Any CPU - {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.Proto|Any CPU.ActiveCfg = Proto|Any CPU - {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.Proto|Any CPU.Build.0 = Proto|Any CPU - {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.Proto|x86.ActiveCfg = Proto|Any CPU - {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.Proto|x86.Build.0 = Proto|Any CPU - {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.Release|Any CPU.ActiveCfg = Release|Any CPU - {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.Release|Any CPU.Build.0 = Release|Any CPU - {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.Release|x86.ActiveCfg = Release|Any CPU - {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.Release|x86.Build.0 = Release|Any CPU {2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}.Debug|Any CPU.Build.0 = Debug|Any CPU {2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -502,18 +463,6 @@ Global {C94C257C-3C0A-4858-B5D8-D746498D1F08}.Release|Any CPU.Build.0 = Release|Any CPU {C94C257C-3C0A-4858-B5D8-D746498D1F08}.Release|x86.ActiveCfg = Release|Any CPU {C94C257C-3C0A-4858-B5D8-D746498D1F08}.Release|x86.Build.0 = Release|Any CPU - {CB7D20C4-6506-406D-9144-5342C3595F03}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {CB7D20C4-6506-406D-9144-5342C3595F03}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CB7D20C4-6506-406D-9144-5342C3595F03}.Debug|x86.ActiveCfg = Debug|Any CPU - {CB7D20C4-6506-406D-9144-5342C3595F03}.Debug|x86.Build.0 = Debug|Any CPU - {CB7D20C4-6506-406D-9144-5342C3595F03}.Proto|Any CPU.ActiveCfg = Proto|Any CPU - {CB7D20C4-6506-406D-9144-5342C3595F03}.Proto|Any CPU.Build.0 = Proto|Any CPU - {CB7D20C4-6506-406D-9144-5342C3595F03}.Proto|x86.ActiveCfg = Proto|Any CPU - {CB7D20C4-6506-406D-9144-5342C3595F03}.Proto|x86.Build.0 = Proto|Any CPU - {CB7D20C4-6506-406D-9144-5342C3595F03}.Release|Any CPU.ActiveCfg = Release|Any CPU - {CB7D20C4-6506-406D-9144-5342C3595F03}.Release|Any CPU.Build.0 = Release|Any CPU - {CB7D20C4-6506-406D-9144-5342C3595F03}.Release|x86.ActiveCfg = Release|Any CPU - {CB7D20C4-6506-406D-9144-5342C3595F03}.Release|x86.Build.0 = Release|Any CPU {649FA588-F02E-457C-9FCF-87E46407481E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {649FA588-F02E-457C-9FCF-87E46407481E}.Debug|Any CPU.Build.0 = Debug|Any CPU {649FA588-F02E-457C-9FCF-87E46407481E}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -753,14 +702,6 @@ Global {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.Release|Any CPU.Build.0 = Release|Any CPU {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.Release|x86.ActiveCfg = Release|Any CPU {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.Release|x86.Build.0 = Release|Any CPU - {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.VSRelease|x86.Build.0 = VSRelease|Any CPU {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}.Debug|Any CPU.Build.0 = Debug|Any CPU {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -773,14 +714,6 @@ Global {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}.Release|Any CPU.Build.0 = Release|Any CPU {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}.Release|x86.ActiveCfg = Release|Any CPU {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}.Release|x86.Build.0 = Release|Any CPU - {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}.VSRelease|x86.Build.0 = VSRelease|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/fsharp/FSComp.txt b/src/fsharp/FSComp.txt index 5bbff5d3ffa..2d4980f3c8f 100644 --- a/src/fsharp/FSComp.txt +++ b/src/fsharp/FSComp.txt @@ -1307,3 +1307,4 @@ estApplyStaticArgumentsForMethodNotImplemented,"A type provider implemented GetS 3201,tcModuleAbbrevFirstInMutRec,"In a recursive declaration group, module abbreviations must come after all 'open' declarations and before other declarations" 3202,tcUnsupportedMutRecDecl,"This declaration is not supported in recursive declaration groups" 3203,parsInvalidUseOfRec,"Invalid use of 'rec' keyword" +3204,tcFixedNotAllowed,"'fixed' may only be used in a declaration of the form 'use x = fixed array-or-address-or-string-expression'" diff --git a/src/fsharp/IlxGen.fs b/src/fsharp/IlxGen.fs index 2c5de389d77..722dda09238 100644 --- a/src/fsharp/IlxGen.fs +++ b/src/fsharp/IlxGen.fs @@ -1277,7 +1277,7 @@ type CodeGenBuffer(m:range, alreadyUsedLocals:int, zapFirstSeqPointToStart:bool) = - let locals = new ResizeArray<((string * (Mark * Mark)) list * ILType)>(10) + let locals = new ResizeArray<((string * (Mark * Mark)) list * ILType * bool)>(10) let codebuf = new ResizeArray(200) let exnSpecs = new ResizeArray(10) @@ -1416,20 +1416,20 @@ type CodeGenBuffer(m:range, member cgbuf.MethodName = methodName member cgbuf.PreallocatedArgCount = alreadyUsedArgs - member cgbuf.AllocLocal(ranges,ty) = + member cgbuf.AllocLocal(ranges,ty,isFixed) = let j = locals.Count - locals.Add((ranges,ty)); + locals.Add((ranges,ty,isFixed)); j - member cgbuf.ReallocLocal(cond,ranges,ty) = + member cgbuf.ReallocLocal(cond,ranges,ty,isFixed) = let j = match ResizeArray.tryFindIndexi cond locals with | Some j -> - let (prevRanges,_) = locals.[j] - locals.[j] <- ((ranges@prevRanges),ty); + let (prevRanges,_,isFixed) = locals.[j] + locals.[j] <- ((ranges@prevRanges),ty,isFixed); j | None -> - cgbuf.AllocLocal(ranges,ty) + cgbuf.AllocLocal(ranges,ty,isFixed) let j = j + alreadyUsedLocals j @@ -1561,7 +1561,7 @@ let CodeGenThen cenv mgbuf (zapFirstSeqPointToStart,entryPointInfo,methodName,ee let localDebugSpecs : ILLocalDebugInfo list = locals - |> List.mapi (fun i (nms,_) -> List.map (fun nm -> (i,nm)) nms) + |> List.mapi (fun i (nms,_,_isFixed) -> List.map (fun nm -> (i,nm)) nms) |> List.concat |> List.map (fun (i,(nm,(start,finish))) -> { Range=(start.CodeLabel, finish.CodeLabel); @@ -1569,7 +1569,8 @@ let CodeGenThen cenv mgbuf (zapFirstSeqPointToStart,entryPointInfo,methodName,ee let ilLocals = locals - |> List.map (fun (infos, ty) -> + |> List.map (fun (infos, ty,isFixed) -> + let loc = // in interactive environment, attach name and range info to locals to improve debug experience if cenv.opts.isInteractive && cenv.opts.generateDebugSymbols then match infos with @@ -1579,7 +1580,8 @@ let CodeGenThen cenv mgbuf (zapFirstSeqPointToStart,entryPointInfo,methodName,ee | [] -> mkILLocal ty None // if not interactive, don't bother adding this info else - mkILLocal ty None) + mkILLocal ty None + if isFixed then { loc with IsPinned=true } else loc) (ilLocals, maxStack, @@ -2175,7 +2177,7 @@ and UnionCodeGen (cgbuf: CodeGenBuffer) = { new EraseUnions.ICodeGen with member __.CodeLabel(m) = m.CodeLabel member __.GenerateDelayMark() = CG.GenerateDelayMark cgbuf "unionCodeGenMark" - member __.GenLocal(ilty) = cgbuf.AllocLocal([],ilty) |> uint16 + member __.GenLocal(ilty) = cgbuf.AllocLocal([],ilty,false) |> uint16 member __.SetMarkToHere(m) = CG.SetMarkToHere cgbuf m member __.EmitInstr x = CG.EmitInstr cgbuf (pop 0) (Push []) x member __.EmitInstrs xs = CG.EmitInstrs cgbuf (pop 0) (Push []) xs } @@ -2504,7 +2506,7 @@ and GenApp cenv cgbuf eenv (f,fty,tyargs,args,m) sequel = // Only save arguments that have effects if Optimizer.ExprHasEffect cenv.g laterArg then let ilTy = laterArg |> tyOfExpr cenv.g |> GenType cenv.amap m cenv.g eenv.tyenv - let loc,eenv = AllocLocal cenv cgbuf eenv true (ilxgenGlobalNng.FreshCompilerGeneratedName ("arg",m), ilTy) scopeMarks + let loc,eenv = AllocLocal cenv cgbuf eenv true (ilxgenGlobalNng.FreshCompilerGeneratedName ("arg",m), ilTy, false) scopeMarks GenExpr cenv cgbuf eenv SPSuppress laterArg Continue EmitSetLocal cgbuf loc Choice1Of2 (ilTy,loc),eenv @@ -2637,7 +2639,7 @@ and GenIndirectCall cenv cgbuf eenv (functy,tyargs,args,m) sequel = CountCallFuncInstructions(); // Generate the code code an ILX callfunc operation - let instrs = EraseClosures.mkCallFunc cenv.g.ilxPubCloEnv (fun ty -> cgbuf.AllocLocal([], ty) |> uint16) eenv.tyenv.Count isTailCall ilxClosureApps + let instrs = EraseClosures.mkCallFunc cenv.g.ilxPubCloEnv (fun ty -> cgbuf.AllocLocal([], ty,false) |> uint16) eenv.tyenv.Count isTailCall ilxClosureApps CG.EmitInstrs cgbuf (pop (1+args.Length)) (Push [ilActualRetTy]) instrs; // Done compiling indirect call... @@ -2660,7 +2662,7 @@ and GenTry cenv cgbuf eenv scopeMarks (e1,m,resty,spTry) = let afterHandler = CG.GenerateDelayMark cgbuf "afterHandler" let eenvinner = {eenvinner with withinSEH = true} let ilResultTy = GenType cenv.amap m cenv.g eenvinner.tyenv resty - let whereToSave,eenvinner = AllocLocal cenv cgbuf eenvinner true (ilxgenGlobalNng.FreshCompilerGeneratedName ("tryres",m),ilResultTy) (startTryMark,endTryMark) + let whereToSave,eenvinner = AllocLocal cenv cgbuf eenvinner true (ilxgenGlobalNng.FreshCompilerGeneratedName ("tryres",m),ilResultTy, false) (startTryMark,endTryMark) // Generate the body of the try. In the normal case (SequencePointAtTry) we generate a sequence point // both on the 'try' keyword and on the start of the expression in the 'try'. For inlined code and @@ -2820,7 +2822,7 @@ and GenForLoop cenv cgbuf eenv (spFor,v,e1,dir,e2,loopBody,m) sequel = let finishIdx,eenvinner = if isFSharpStyle then - let v,eenvinner = AllocLocal cenv cgbuf eenvinner true (ilxgenGlobalNng.FreshCompilerGeneratedName ("endLoop",m), cenv.g.ilg.typ_int32) (start,finish) + let v,eenvinner = AllocLocal cenv cgbuf eenvinner true (ilxgenGlobalNng.FreshCompilerGeneratedName ("endLoop",m), cenv.g.ilg.typ_int32, false) (start,finish) v, eenvinner else -1,eenvinner @@ -3253,7 +3255,7 @@ and GenDefaultValue cenv cgbuf eenv (ty,m) = | _ -> let ilTy = GenType cenv.amap m cenv.g eenv.tyenv ty LocalScope "ilzero" cgbuf (fun scopeMarks -> - let locIdx, _ = AllocLocal cenv cgbuf eenv true (ilxgenGlobalNng.FreshCompilerGeneratedName ("default",m), ilTy) scopeMarks + let locIdx, _ = AllocLocal cenv cgbuf eenv true (ilxgenGlobalNng.FreshCompilerGeneratedName ("default",m), ilTy, false) scopeMarks // "initobj" (Generated by EmitInitLocal) doesn't work on byref types // But ilzero(&ty) only gets generated in the built-in get-address function so // we can just rely on zeroinit of all IL locals. @@ -5391,14 +5393,14 @@ and GenStoreVal cgbuf eenv m (vspec:Val) = // Allocate locals for values //-------------------------------------------------------------------------- -and AllocLocal cenv cgbuf eenv compgen (v,ty) (scopeMarks: Mark * Mark) = +and AllocLocal cenv cgbuf eenv compgen (v,ty,isFixed) (scopeMarks: Mark * Mark) = // The debug range for the local let ranges = if compgen then [] else [(v,scopeMarks)] // Get an index for the local let j = if cenv.opts.localOptimizationsAreOn - then cgbuf.ReallocLocal((fun i (_,ty') -> not (IntMap.mem i eenv.liveLocals) && (ty = ty')),ranges,ty) - else cgbuf.AllocLocal(ranges,ty) + then cgbuf.ReallocLocal((fun i (_,ty',isFixed') -> not isFixed' && not isFixed && not (IntMap.mem i eenv.liveLocals) && (ty = ty')),ranges,ty,isFixed) + else cgbuf.AllocLocal(ranges,ty,isFixed) j, { eenv with liveLocals = IntMap.add j () eenv.liveLocals } and AllocLocalVal cenv cgbuf v eenv repr scopeMarks = @@ -5414,11 +5416,11 @@ and AllocLocalVal cenv cgbuf v eenv repr scopeMarks = let cloinfo,_,_ = GetIlxClosureInfo cenv v.Range true None eenvinner (Option.get repr) cloinfo - let idx,eenv = AllocLocal cenv cgbuf eenv v.IsCompilerGenerated (v.CompiledName, cenv.g.ilg.typ_Object) scopeMarks + let idx,eenv = AllocLocal cenv cgbuf eenv v.IsCompilerGenerated (v.CompiledName, cenv.g.ilg.typ_Object, false) scopeMarks Local (idx,Some(ref (NamedLocalIlxClosureInfoGenerator cloinfoGenerate))),eenv else (* normal local *) - let idx,eenv = AllocLocal cenv cgbuf eenv v.IsCompilerGenerated (v.CompiledName, GenTypeOfVal cenv eenv v) scopeMarks + let idx,eenv = AllocLocal cenv cgbuf eenv v.IsCompilerGenerated (v.CompiledName, GenTypeOfVal cenv eenv v, v.IsFixed) scopeMarks Local (idx,None),eenv let eenv = AddStorageForVal cenv.g (v,notlazy repr) eenv Some repr, eenv @@ -5488,7 +5490,7 @@ and AllocTopValWithinExpr cenv cgbuf cloc scopeMarks v eenv = /// - and because IL requires empty stack following a forward br (jump). and EmitSaveStack cenv cgbuf eenv m scopeMarks = let savedStack = (cgbuf.GetCurrentStack()) - let savedStackLocals,eenvinner = List.mapFold (fun eenv ty -> AllocLocal cenv cgbuf eenv true (ilxgenGlobalNng.FreshCompilerGeneratedName ("spill",m), ty) scopeMarks) eenv savedStack + let savedStackLocals,eenvinner = List.mapFold (fun eenv ty -> AllocLocal cenv cgbuf eenv true (ilxgenGlobalNng.FreshCompilerGeneratedName ("spill",m), ty, false) scopeMarks) eenv savedStack List.iter (EmitSetLocal cgbuf) savedStackLocals; cgbuf.AssertEmptyStack(); (savedStack,savedStackLocals),eenvinner (* need to return, it marks locals "live" *) diff --git a/src/fsharp/TypeChecker.fs b/src/fsharp/TypeChecker.fs index c8cfc054800..59e69508f1f 100755 --- a/src/fsharp/TypeChecker.fs +++ b/src/fsharp/TypeChecker.fs @@ -1207,10 +1207,11 @@ type CheckedBindingInfo = TType * range * SequencePointInfoForBinding * - bool * (* compiler generated? *) - Const option (* literal value? *) - member x.Expr = let (CheckedBindingInfo(_,_,_,_,_,_,_,expr,_,_,_,_,_,_)) = x in expr - member x.SeqPoint = let (CheckedBindingInfo(_,_,_,_,_,_,_,_,_,_,_,spBind,_,_)) = x in spBind + bool * // compiler generated? + Const option * // literal value? + bool // fixed? + member x.Expr = let (CheckedBindingInfo(_,_,_,_,_,_,_,expr,_,_,_,_,_,_,_)) = x in expr + member x.SeqPoint = let (CheckedBindingInfo(_,_,_,_,_,_,_,_,_,_,_,spBind,_,_,_)) = x in spBind //------------------------------------------------------------------------- // Helpers related to type schemes @@ -5499,6 +5500,9 @@ and TcExprUndelayed cenv overallTy env tpenv (expr: SynExpr) = | SynExpr.Assert (x,m) -> TcAssertExpr cenv overallTy env m tpenv x + | SynExpr.Fixed (_,m) -> + error(Error(FSComp.SR.tcFixedNotAllowed(),m)) + // e : ty | SynExpr.Typed (e,cty,m) -> let tgty,tpenv = TcTypeAndRecover cenv NewTyparsOK CheckCxs ItemOccurence.UseInType env tpenv cty @@ -6262,7 +6266,7 @@ and TcObjectExprBinding cenv (env: TcEnv) implty tpenv (absSlotInfo,bind) = | _ -> implty --> NewInferenceType () - let (CheckedBindingInfo(inlineFlag,immut,bindingAttribs,_,_,ExplicitTyparInfo(_,declaredTypars,_),nameToPrelimValSchemeMap,rhsExpr,_,_,m,_,_,_),tpenv) = + let (CheckedBindingInfo(inlineFlag,immut,bindingAttribs,_,_,ExplicitTyparInfo(_,declaredTypars,_),nameToPrelimValSchemeMap,rhsExpr,_,_,m,_,_,_,_),tpenv) = let flex, tpenv = TcNonrecBindingTyparDecls cenv env tpenv bind TcNormalizedBinding ObjectExpressionOverrideBinding cenv env tpenv bindingTy None NoSafeInitInfo ([],flex) bind @@ -9727,8 +9731,7 @@ and TcLinearLetExprs bodyChecker cenv env overallTy builder tpenv (processUseBin // TcLinearLetExprs processes multiple 'let' bindings in a tail recursive way // We process one binding, then look for additional linear bindings and accumulate the builder continuation. // Don't processes 'use' bindings (e.g. in sequence expressions) unless directed to. - let mkf,envinner,tpenv = - TcLetBinding cenv isUse env ExprContainerInfo ExpressionBinding tpenv (binds,m,body.Range) + let mkf,envinner,tpenv = TcLetBinding cenv isUse env ExprContainerInfo ExpressionBinding tpenv (binds,m,body.Range) let builder' x = builder (mkf x) match body with | SynExpr.LetOrUse (isRec',isUse',binds',bodyExpr,m') when (not isUse' || processUseBindings) -> @@ -9784,6 +9787,11 @@ and TcNormalizedBinding declKind (cenv:cenv) env tpenv overallTy safeThisValOpt let attrTgt = DeclKind.AllowedAttribTargets memberFlagsOpt declKind + let isFixed,rhsExpr,overallPatTy,overallExprTy = + match rhsExpr with + | SynExpr.Fixed (e,_) -> true, e, NewInferenceType(), overallTy + | e -> false, e, overallTy, overallTy + // Check the attributes of the binding, parameters or return value let TcAttrs tgt attrs = let attrs = TcAttributes cenv envinner tgt attrs @@ -9798,6 +9806,7 @@ and TcNormalizedBinding declKind (cenv:cenv) env tpenv overallTy safeThisValOpt let argAttribs = spatsL |> List.map (SynInfo.InferSynArgInfoFromSimplePats >> List.map (SynInfo.AttribsOfArgData >> TcAttrs AttributeTargets.Parameter)) + let retAttribs = match rtyOpt with | Some (SynBindingReturnInfo(_,_,retAttrs)) -> TcAttrs AttributeTargets.ReturnValue retAttrs @@ -9817,6 +9826,10 @@ and TcNormalizedBinding declKind (cenv:cenv) env tpenv overallTy safeThisValOpt if (not isMutable || isThreadStatic) then errorR(Error(FSComp.SR.tcVolatileFieldsMustBeMutable(),mBinding)) + if isFixed then + if declKind <> ExpressionBinding || isInline || isMutable then + errorR(Error(FSComp.SR.tcFixedNotAllowed(),mBinding)) + if HasFSharpAttributeOpt cenv.g cenv.g.attrib_DllImportAttribute valAttribs then if not declKind.CanBeDllImport || (match memberFlagsOpt with Some memberFlags -> memberFlags.IsInstance | _ -> false) then errorR(Error(FSComp.SR.tcDllImportNotAllowed(),mBinding)) @@ -9828,12 +9841,16 @@ and TcNormalizedBinding declKind (cenv:cenv) env tpenv overallTy safeThisValOpt if isSome(memberFlagsOpt) then errorR(Error(FSComp.SR.tcEntryPointAttributeRequiresFunctionInModule(),mBinding)) else - UnifyTypes cenv env mBinding overallTy (mkArrayType cenv.g cenv.g.string_ty --> cenv.g.int_ty) + UnifyTypes cenv env mBinding overallPatTy (mkArrayType cenv.g cenv.g.string_ty --> cenv.g.int_ty) if isMutable && isInline then errorR(Error(FSComp.SR.tcMutableValuesCannotBeInline(),mBinding)) + if isMutable && nonNil declaredTypars then errorR(Error(FSComp.SR.tcMutableValuesMayNotHaveGenericParameters(),mBinding)) + let flex = if isMutable then dontInferTypars else flex + if isMutable && nonNil spatsL then errorR(Error(FSComp.SR.tcMutableValuesSyntax(),mBinding)) + let isInline = if isInline && isNil spatsL && isNil declaredTypars then errorR(Error(FSComp.SR.tcOnlyFunctionsCanBeInline(),mBinding)) @@ -9848,7 +9865,7 @@ and TcNormalizedBinding declKind (cenv:cenv) env tpenv overallTy safeThisValOpt // Check the pattern of the l.h.s. of the binding let tcPatPhase2,(tpenv,nameToPrelimValSchemeMap,_) = - TcPat AllIdsOK cenv envinner (Some(partialValReprInfo)) (inlineFlag,flex,argAndRetAttribs,isMutable,vis,compgen) (tpenv,NameMap.empty,Set.empty) overallTy pat + TcPat AllIdsOK cenv envinner (Some(partialValReprInfo)) (inlineFlag,flex,argAndRetAttribs,isMutable,vis,compgen) (tpenv,NameMap.empty,Set.empty) overallPatTy pat // Add active pattern result names to the environment @@ -9891,10 +9908,17 @@ and TcNormalizedBinding declKind (cenv:cenv) env tpenv overallTy safeThisValOpt (match rhsExpr with SynExpr.Lambda _ -> false | _ -> true) && synExprContainsError rhsExpr conditionallySuppressErrorReporting atTopNonLambdaDefn (fun () -> - tc cenv overallTy envinner tpenv rhsExpr) + tc cenv overallExprTy envinner tpenv rhsExpr) + + if isFixed then + match overallExprTy with + | ty when isByrefTy cenv.g ty -> UnifyTypes cenv env mBinding overallExprTy overallPatTy + | ty when isStringTy cenv.g ty -> UnifyTypes cenv env mBinding (mkNativePtrType cenv.g cenv.g.char_ty) overallPatTy + | ty when isArray1DTy cenv.g ty -> UnifyTypes cenv env mBinding (mkByrefTy cenv.g (destArrayTy cenv.g overallExprTy)) overallPatTy + | _ -> error(Error(FSComp.SR.tcFixedNotAllowed(),mBinding)) if bkind = StandaloneExpression && not cenv.isScript then - UnifyUnitType cenv env.DisplayEnv mBinding overallTy (Some rhsExpr') |> ignore + UnifyUnitType cenv env.DisplayEnv mBinding overallPatTy (Some rhsExpr') |> ignore // Assert the return type of an active pattern match apinfoOpt with @@ -9906,7 +9930,7 @@ and TcNormalizedBinding declKind (cenv:cenv) env tpenv overallTy safeThisValOpt () // Check other attributes - let hasLiteralAttr,konst = TcLiteral cenv overallTy env tpenv (valAttribs,rhsExpr) + let hasLiteralAttr,konst = TcLiteral cenv overallExprTy env tpenv (valAttribs,rhsExpr) if hasLiteralAttr && isThreadStatic then errorR(Error(FSComp.SR.tcIllegalAttributesForLiteral(),mBinding)) if hasLiteralAttr && isMutable then @@ -9916,7 +9940,7 @@ and TcNormalizedBinding declKind (cenv:cenv) env tpenv overallTy safeThisValOpt if hasLiteralAttr && nonNil declaredTypars then errorR(Error(FSComp.SR.tcLiteralCannotHaveGenericParameters(),mBinding)) - CheckedBindingInfo(inlineFlag,true,valAttribs,doc,tcPatPhase2,flex,nameToPrelimValSchemeMap,rhsExpr',argAndRetAttribs,overallTy,mBinding,spBind,compgen,konst),tpenv + CheckedBindingInfo(inlineFlag,true,valAttribs,doc,tcPatPhase2,flex,nameToPrelimValSchemeMap,rhsExpr',argAndRetAttribs,overallPatTy,mBinding,spBind,compgen,konst,isFixed),tpenv and TcLiteral cenv overallTy env tpenv (attrs,synLiteralValExpr) = let hasLiteralAttr = HasFSharpAttribute cenv.g cenv.g.attrib_LiteralAttribute attrs @@ -10171,7 +10195,7 @@ and TcLetBinding cenv isUse env containerInfo declKind tpenv (binds,bindsm,scope let denv = env.DisplayEnv GeneralizationHelpers.CanonicalizePartialInferenceProblem (cenv,denv,bindsm) (binds' |> List.collect (fun tbinfo -> - let (CheckedBindingInfo(_,_,_,_,_,flex,_,_,_,tauTy,_,_,_,_)) = tbinfo + let (CheckedBindingInfo(_,_,_,_,_,flex,_,_,_,tauTy,_,_,_,_,_)) = tbinfo let (ExplicitTyparInfo(_,declaredTypars,_)) = flex let maxInferredTypars = (freeInTypeLeftToRight cenv.g false tauTy) declaredTypars @ maxInferredTypars)) @@ -10180,7 +10204,7 @@ and TcLetBinding cenv isUse env containerInfo declKind tpenv (binds,bindsm,scope // Generalize the bindings... (((fun x -> x), env, tpenv), binds') ||> List.fold (fun (mkf_sofar,env,tpenv) tbinfo -> - let (CheckedBindingInfo(inlineFlag,immut,attrs,doc,tcPatPhase2,flex,nameToPrelimValSchemeMap,rhsExpr,_,tauTy,m,spBind,_,konst)) = tbinfo + let (CheckedBindingInfo(inlineFlag,immut,attrs,doc,tcPatPhase2,flex,nameToPrelimValSchemeMap,rhsExpr,_,tauTy,m,spBind,_,konst,isFixed)) = tbinfo let enclosingDeclaredTypars = [] let (ExplicitTyparInfo(_,declaredTypars,canInferTypars)) = flex let allDeclaredTypars = enclosingDeclaredTypars @ declaredTypars @@ -10214,7 +10238,7 @@ and TcLetBinding cenv isUse env containerInfo declKind tpenv (binds,bindsm,scope match pat' with // Don't introduce temporary or 'let' for 'match against wild' or 'match against unit' - | (TPat_wild _ | TPat_const (Const.Unit,_)) when not isUse && isNil generalizedTypars -> + | (TPat_wild _ | TPat_const (Const.Unit,_)) when not isUse && not isFixed && isNil generalizedTypars -> let mk_seq_bind (tm,tmty) = (mkSequential SequencePointsAtSeq m rhse tm, tmty) (mk_seq_bind << mkf_sofar,env,tpenv) @@ -10226,13 +10250,15 @@ and TcLetBinding cenv isUse env containerInfo declKind tpenv (binds,bindsm,scope // nice: don't introduce awful temporary for r.h.s. in the 99% case where we know what we're binding it to | TPat_as (pat1,PBind(v,TypeScheme(generalizedTypars',_)),_) when List.lengthsEqAndForall2 typarRefEq generalizedTypars generalizedTypars' -> + + if isFixed then v.SetIsFixed() v, pat1 | _ when mustinline(inlineFlag) -> error(Error(FSComp.SR.tcInvalidInlineSpecification(),m)) | _ -> let tmp,_ = mkCompGenLocal m "patternInput" (generalizedTypars +-> tauTy) - if isUse then + if isUse || isFixed then errorR(Error(FSComp.SR.tcInvalidUseBinding(),m)) // This assignment forces representation as module value, to maintain the invariant from the @@ -10251,7 +10277,7 @@ and TcLetBinding cenv isUse env containerInfo declKind tpenv (binds,bindsm,scope matchx,tmty let mkCleanup (tm,tmty) = - if isUse then + if isUse && not isFixed then (allValsDefinedByPattern,(tm,tmty)) ||> FlatList.foldBack (fun v (tm,tmty) -> AddCxTypeMustSubsumeType ContextInfo.NoContext denv cenv.css v.Range NoTrace cenv.g.system_IDisposable_typ v.Type let cleanupE = BuildDisposableCleanup cenv env m v @@ -11026,7 +11052,7 @@ and TcLetrecComputeAndGeneralizeGenericTyparsForBinding cenv denv freeInEnv (pgr let rbinfo = pgrbind.RecBindingInfo let vspec = rbinfo.Val - let (CheckedBindingInfo(inlineFlag,immut,_,_,_,_,_,expr,_,_,m,_,_,_)) = pgrbind.CheckedBinding + let (CheckedBindingInfo(inlineFlag,immut,_,_,_,_,_,expr,_,_,m,_,_,_,_)) = pgrbind.CheckedBinding let (ExplicitTyparInfo(rigidCopyOfDeclaredTypars,declaredTypars,_)) = rbinfo.ExplicitTyparInfo let allDeclaredTypars = rbinfo.EnclosingDeclaredTypars @ declaredTypars @@ -11065,8 +11091,11 @@ and TcLetrecComputeSupportForBinding cenv (pgrbind : PreGeneralizationRecursiveB and TcLetrecGeneralizeBinding cenv denv generalizedTypars (pgrbind : PreGeneralizationRecursiveBinding) : PostGeneralizationRecursiveBinding = let (RBInfo(_,_,enclosingDeclaredTypars,_,vspec,flex,partialValReprInfo,memberInfoOpt,_,_,_,vis,_,declKind)) = pgrbind.RecBindingInfo - let (CheckedBindingInfo(inlineFlag,_,_,_,_,_,_,expr,argAttribs,_,_,_,compgen,_)) = pgrbind.CheckedBinding + let (CheckedBindingInfo(inlineFlag,_,_,_,_,_,_,expr,argAttribs,_,_,_,compgen,_,isFixed)) = pgrbind.CheckedBinding + if isFixed then + errorR(Error(FSComp.SR.tcFixedNotAllowed(),expr.Range)) + let _,tau = vspec.TypeScheme let pvalscheme1 = PrelimValScheme1(vspec.Id,flex,tau,Some(partialValReprInfo),memberInfoOpt,false,inlineFlag,NormalVal,argAttribs,vis,compgen) diff --git a/src/fsharp/ast.fs b/src/fsharp/ast.fs index afae87233d0..03a9f4c0fe4 100644 --- a/src/fsharp/ast.fs +++ b/src/fsharp/ast.fs @@ -683,6 +683,10 @@ and /// Inserted for error recovery when there is "expr." and missing tokens or error recovery after the dot | DiscardAfterMissingQualificationAfterDot of SynExpr * range + + /// 'use x = fixed expr' + | Fixed of SynExpr * range + /// Get the syntactic range of source code covered by this construct. member e.Range = match e with @@ -742,6 +746,7 @@ and | SynExpr.YieldOrReturnFrom (_,_,m) | SynExpr.LetOrUseBang (_,_,_,_,_,_,m) | SynExpr.DoBang (_,m) -> m + | SynExpr.Fixed (_,m) -> m | SynExpr.Ident id -> id.idRange /// range ignoring any (parse error) extra trailing dots member e.RangeSansAnyExtraDot = @@ -802,6 +807,7 @@ and | SynExpr.DotGet (expr,_,lidwd,m) -> if lidwd.ThereIsAnExtraDotAtTheEnd then unionRanges expr.Range lidwd.RangeSansAnyExtraDot else m | SynExpr.LongIdent (_,lidwd,_,_) -> lidwd.RangeSansAnyExtraDot | SynExpr.DiscardAfterMissingQualificationAfterDot (expr,_) -> expr.Range + | SynExpr.Fixed (_,m) -> m | SynExpr.Ident id -> id.idRange /// Attempt to get the range of the first token or initial portion only - this is extremely ad-hoc, just a cheap way to improve a certain 'query custom operation' error range member e.RangeOfFirstPortion = @@ -869,6 +875,7 @@ and let e = (pat.Range : range).Start mkRange m.FileName start e | SynExpr.Ident id -> id.idRange + | SynExpr.Fixed (_,m) -> m and @@ -2234,8 +2241,9 @@ let rec synExprContainsError inpExpr = | SynExpr.TraitCall(_,_,e,_) | SynExpr.YieldOrReturn (_,e,_) | SynExpr.YieldOrReturnFrom (_,e,_) - | SynExpr.DoBang (e,_) - | SynExpr.Paren(e,_,_,_) -> + | SynExpr.DoBang (e,_) + | SynExpr.Fixed (e,_) + | SynExpr.Paren (e,_,_,_) -> walkExpr e | SynExpr.NamedIndexedPropertySet (_,e1,e2,_) diff --git a/src/fsharp/lexhelp.fs b/src/fsharp/lexhelp.fs index 25f90ab688f..2a0ceee9778 100644 --- a/src/fsharp/lexhelp.fs +++ b/src/fsharp/lexhelp.fs @@ -218,6 +218,7 @@ module Keywords = FSHARP, "extern" ,EXTERN; ALWAYS, "false" ,FALSE; ALWAYS, "finally" ,FINALLY; + FSHARP, "fixed" ,FIXED; ALWAYS, "for" ,FOR; ALWAYS, "fun" ,FUN; ALWAYS, "function" ,FUNCTION; @@ -284,7 +285,7 @@ module Keywords = [ "atomic"; "break"; "checked"; "component"; "constraint"; "constructor"; "continue"; "eager"; - "fixed"; "fori"; "functor"; + "fori"; "functor"; "include"; "measure"; "method"; "mixin"; "object"; diff --git a/src/fsharp/pars.fsy b/src/fsharp/pars.fsy index 4095b35841e..27aab7b2575 100755 --- a/src/fsharp/pars.fsy +++ b/src/fsharp/pars.fsy @@ -252,6 +252,7 @@ let rangeOfLongIdent(lid:LongIdent) = %token OBLOCKEND OBLOCKEND_COMING_SOON OBLOCKEND_IS_HERE /* LexFilter #light inserts when closing CtxtSeqBlock(_,_,AddBlockEnd) */ %token OINTERFACE_MEMBER /* inserted for non-paranthetical use of 'INTERFACE', i.e. not INTERFACE/END */ +%token FIXED %token ODUMMY /* These are artificial */ @@ -3284,6 +3285,9 @@ declExpr: { let spBind = SequencePointAtForLoop(rhs2 parseState 1 2) let (a,b,_) = $2 in SynExpr.ForEach(spBind,SeqExprOnly true,true,a,b,$4,unionRanges (rhs parseState 1) $4.Range) } + | FIXED declExpr + { SynExpr.Fixed($2, (unionRanges (rhs parseState 1) $2.Range)) } + | RARROW typedSeqExprBlockR { errorR(Error(FSComp.SR.parsArrowUseIsLimited(),lhs parseState)); SynExpr.YieldOrReturn((true,true),$2, (unionRanges (rhs parseState 1) $2.Range)) } diff --git a/src/fsharp/tast.fs b/src/fsharp/tast.fs index ea59e6e7238..5e338e3294a 100755 --- a/src/fsharp/tast.fs +++ b/src/fsharp/tast.fs @@ -110,133 +110,140 @@ type ValFlags(flags:int64) = new (recValInfo, baseOrThis, isCompGen, inlineInfo, isMutable, isModuleOrMemberBinding, isExtensionMember, isIncrClassSpecialMember, isTyFunc, allowTypeInst, isGeneratedEventVal) = let flags = (match baseOrThis with - | BaseVal -> 0b000000000000000000L - | CtorThisVal -> 0b000000000000000010L - | NormalVal -> 0b000000000000000100L - | MemberThisVal -> 0b000000000000000110L) ||| - (if isCompGen then 0b000000000000001000L - else 0b000000000000000000L) ||| + | BaseVal -> 0b0000000000000000000L + | CtorThisVal -> 0b0000000000000000010L + | NormalVal -> 0b0000000000000000100L + | MemberThisVal -> 0b0000000000000000110L) ||| + (if isCompGen then 0b0000000000000001000L + else 0b00000000000000000000L) ||| (match inlineInfo with - | ValInline.PseudoVal -> 0b000000000000000000L - | ValInline.Always -> 0b000000000000010000L - | ValInline.Optional -> 0b000000000000100000L - | ValInline.Never -> 0b000000000000110000L) ||| + | ValInline.PseudoVal -> 0b0000000000000000000L + | ValInline.Always -> 0b0000000000000010000L + | ValInline.Optional -> 0b0000000000000100000L + | ValInline.Never -> 0b0000000000000110000L) ||| (match isMutable with - | Immutable -> 0b000000000000000000L - | Mutable -> 0b000000000001000000L) ||| + | Immutable -> 0b0000000000000000000L + | Mutable -> 0b0000000000001000000L) ||| (match isModuleOrMemberBinding with - | false -> 0b000000000000000000L - | true -> 0b000000000010000000L) ||| + | false -> 0b0000000000000000000L + | true -> 0b0000000000010000000L) ||| (match isExtensionMember with - | false -> 0b000000000000000000L - | true -> 0b000000000100000000L) ||| + | false -> 0b0000000000000000000L + | true -> 0b0000000000100000000L) ||| (match isIncrClassSpecialMember with - | false -> 0b000000000000000000L - | true -> 0b000000001000000000L) ||| + | false -> 0b0000000000000000000L + | true -> 0b0000000001000000000L) ||| (match isTyFunc with - | false -> 0b000000000000000000L - | true -> 0b000000010000000000L) ||| + | false -> 0b0000000000000000000L + | true -> 0b0000000010000000000L) ||| (match recValInfo with - | ValNotInRecScope -> 0b000000000000000000L - | ValInRecScope true -> 0b000000100000000000L - | ValInRecScope false -> 0b000001000000000000L) ||| + | ValNotInRecScope -> 0b0000000000000000000L + | ValInRecScope true -> 0b0000000100000000000L + | ValInRecScope false -> 0b0000001000000000000L) ||| (match allowTypeInst with - | false -> 0b000000000000000000L - | true -> 0b000100000000000000L) ||| + | false -> 0b0000000000000000000L + | true -> 0b0000100000000000000L) ||| (match isGeneratedEventVal with - | false -> 0b000000000000000000L - | true -> 0b100000000000000000L) + | false -> 0b0000000000000000000L + | true -> 0b0100000000000000000L) ValFlags(flags) member x.BaseOrThisInfo = - match (flags &&& 0b000000000000000110L) with - | 0b000000000000000000L -> BaseVal - | 0b000000000000000010L -> CtorThisVal - | 0b000000000000000100L -> NormalVal - | 0b000000000000000110L -> MemberThisVal + match (flags &&& 0b0000000000000000110L) with + | 0b0000000000000000000L -> BaseVal + | 0b0000000000000000010L -> CtorThisVal + | 0b0000000000000000100L -> NormalVal + | 0b0000000000000000110L -> MemberThisVal | _ -> failwith "unreachable" - member x.IsCompilerGenerated = (flags &&& 0b000000000000001000L) <> 0x0L + member x.IsCompilerGenerated = (flags &&& 0b0000000000000001000L) <> 0x0L member x.SetIsCompilerGenerated(isCompGen) = - let flags = (flags &&& ~~~0b000000000000001000L) ||| + let flags = (flags &&& ~~~0b0000000000000001000L) ||| (match isCompGen with - | false -> 0b000000000000000000L - | true -> 0b000000000000001000L) + | false -> 0b0000000000000000000L + | true -> 0b0000000000000001000L) ValFlags(flags) member x.InlineInfo = - match (flags &&& 0b000000000000110000L) with - | 0b000000000000000000L -> ValInline.PseudoVal - | 0b000000000000010000L -> ValInline.Always - | 0b000000000000100000L -> ValInline.Optional - | 0b000000000000110000L -> ValInline.Never + match (flags &&& 0b0000000000000110000L) with + | 0b0000000000000000000L -> ValInline.PseudoVal + | 0b0000000000000010000L -> ValInline.Always + | 0b0000000000000100000L -> ValInline.Optional + | 0b0000000000000110000L -> ValInline.Never | _ -> failwith "unreachable" member x.MutabilityInfo = - match (flags &&& 0b000000000001000000L) with - | 0b000000000000000000L -> Immutable - | 0b000000000001000000L -> Mutable + match (flags &&& 0b0000000000001000000L) with + | 0b0000000000000000000L -> Immutable + | 0b0000000000001000000L -> Mutable | _ -> failwith "unreachable" member x.IsMemberOrModuleBinding = - match (flags &&& 0b000000000010000000L) with - | 0b000000000000000000L -> false - | 0b000000000010000000L -> true + match (flags &&& 0b0000000000010000000L) with + | 0b0000000000000000000L -> false + | 0b0000000000010000000L -> true | _ -> failwith "unreachable" - member x.SetIsMemberOrModuleBinding = ValFlags(flags ||| 0b000000000010000000L) + member x.SetIsMemberOrModuleBinding = ValFlags(flags ||| 0b0000000000010000000L) - member x.IsExtensionMember = (flags &&& 0b000000000100000000L) <> 0L - member x.IsIncrClassSpecialMember = (flags &&& 0b000000001000000000L) <> 0L - member x.IsTypeFunction = (flags &&& 0b000000010000000000L) <> 0L + member x.IsExtensionMember = (flags &&& 0b0000000000100000000L) <> 0L + member x.IsIncrClassSpecialMember = (flags &&& 0b0000000001000000000L) <> 0L + member x.IsTypeFunction = (flags &&& 0b0000000010000000000L) <> 0L - member x.RecursiveValInfo = match (flags &&& 0b000001100000000000L) with - | 0b000000000000000000L -> ValNotInRecScope - | 0b000000100000000000L -> ValInRecScope(true) - | 0b000001000000000000L -> ValInRecScope(false) + member x.RecursiveValInfo = match (flags &&& 0b0000001100000000000L) with + | 0b0000000000000000000L -> ValNotInRecScope + | 0b0000000100000000000L -> ValInRecScope(true) + | 0b0000001000000000000L -> ValInRecScope(false) | _ -> failwith "unreachable" member x.SetRecursiveValInfo(recValInfo) = let flags = - (flags &&& ~~~0b000001100000000000L) ||| + (flags &&& ~~~0b0000001100000000000L) ||| (match recValInfo with - | ValNotInRecScope -> 0b000000000000000000L - | ValInRecScope(true) -> 0b000000100000000000L - | ValInRecScope(false) -> 0b000001000000000000L) + | ValNotInRecScope -> 0b0000000000000000000L + | ValInRecScope(true) -> 0b0000000100000000000L + | ValInRecScope(false) -> 0b0000001000000000000L) ValFlags(flags) - member x.MakesNoCriticalTailcalls = (flags &&& 0b000010000000000000L) <> 0L + member x.MakesNoCriticalTailcalls = (flags &&& 0b0000010000000000000L) <> 0L - member x.SetMakesNoCriticalTailcalls = ValFlags(flags ||| 0b000010000000000000L) + member x.SetMakesNoCriticalTailcalls = ValFlags(flags ||| 0b0000010000000000000L) - member x.PermitsExplicitTypeInstantiation = (flags &&& 0b000100000000000000L) <> 0L - member x.HasBeenReferenced = (flags &&& 0b001000000000000000L) <> 0L + member x.PermitsExplicitTypeInstantiation = (flags &&& 0b0000100000000000000L) <> 0L + member x.HasBeenReferenced = (flags &&& 0b0001000000000000000L) <> 0L - member x.SetHasBeenReferenced = ValFlags(flags ||| 0b001000000000000000L) + member x.SetHasBeenReferenced = ValFlags(flags ||| 0b0001000000000000000L) - member x.IsCompiledAsStaticPropertyWithoutField = (flags &&& 0b010000000000000000L) <> 0L + member x.IsCompiledAsStaticPropertyWithoutField = (flags &&& 0b0010000000000000000L) <> 0L - member x.SetIsCompiledAsStaticPropertyWithoutField = ValFlags(flags ||| 0b010000000000000000L) + member x.SetIsCompiledAsStaticPropertyWithoutField = ValFlags(flags ||| 0b0010000000000000000L) - member x.IsGeneratedEventVal = (flags &&& 0b100000000000000000L) <> 0L + + member x.IsGeneratedEventVal = (flags &&& 0b0100000000000000000L) <> 0L + + member x.IsFixed = (flags &&& 0b1000000000000000000L) <> 0L + + member x.SetIsFixed = ValFlags(flags ||| 0b1000000000000000000L) + + /// Get the flags as included in the F# binary metadata member x.PickledBits = // Clear the RecursiveValInfo, only used during inference and irrelevant across assembly boundaries // Clear the IsCompiledAsStaticPropertyWithoutField, only used to determine whether to use a true field for a value, and to eliminate the optimization info for observable bindings // Clear the HasBeenReferenced, only used to report "unreferenced variable" warnings and to help collect 'it' values in FSI.EXE // Clear the IsGeneratedEventVal, since there's no use in propagating specialname information for generated add/remove event vals - (flags &&& ~~~0b011001100000000000L) + (flags &&& ~~~0b1011001100000000000L) /// Represents the kind of a type parameter [] @@ -2190,6 +2197,9 @@ and /// Indicates if the backing field for a static value is suppressed. member x.IsCompiledAsStaticPropertyWithoutField = x.Data.val_flags.IsCompiledAsStaticPropertyWithoutField + /// Indicates if the value is pinned/fixed + member x.IsFixed = x.Data.val_flags.IsFixed + /// Indicates if this value allows the use of an explicit type instantiation (i.e. does it itself have explicit type arguments, /// or does it have a signature?) member x.PermitsExplicitTypeInstantiation = x.Data.val_flags.PermitsExplicitTypeInstantiation @@ -2382,6 +2392,7 @@ and member x.SetMakesNoCriticalTailcalls() = x.Data.val_flags <- x.Data.val_flags.SetMakesNoCriticalTailcalls member x.SetHasBeenReferenced() = x.Data.val_flags <- x.Data.val_flags.SetHasBeenReferenced member x.SetIsCompiledAsStaticPropertyWithoutField() = x.Data.val_flags <- x.Data.val_flags.SetIsCompiledAsStaticPropertyWithoutField + member x.SetIsFixed() = x.Data.val_flags <- x.Data.val_flags.SetIsFixed member x.SetValReprInfo info = x.Data.val_repr_info <- info member x.SetType ty = x.Data.val_type <- ty member x.SetOtherRange m = x.Data.val_other_range <- Some m From 07567504d49b74bae0ab1f2955fd8eede3c1b27d Mon Sep 17 00:00:00 2001 From: Lincoln Atkinson Date: Sun, 19 Jun 2016 12:46:22 -0700 Subject: [PATCH 067/129] Update CallerFilePath tests to use current platform's path separator --- .../Imported/CallerInfo/CallerFilePath.fs | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerFilePath.fs b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerFilePath.fs index a807e51b4b5..c44f97e4d53 100644 --- a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerFilePath.fs +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/CallerInfo/CallerFilePath.fs @@ -12,11 +12,14 @@ type MyTy([] ?p0 : string) = path module Program = - let matchesPath path (s : string) = - s.EndsWith(path) - && not (s.Contains("\\\\")) - && not (path.Contains("\\.\\")) - && not (path.Contains("\\..\\")) + let doubleSeparator = "##".Replace('#', System.IO.Path.DirectorySeparatorChar) + let sameDirectory = "#.#".Replace('#', System.IO.Path.DirectorySeparatorChar) + let parentDirectory = ".." + let matchesPath (path : string) (s : string) = + s.EndsWith(path.Replace('#', System.IO.Path.DirectorySeparatorChar)) + && not (s.Contains(doubleSeparator)) + && not (s.Contains(sameDirectory)) + && not (s.Contains(parentDirectory)) [] @@ -25,7 +28,7 @@ module Program = let o1 = MyTy("42") match o.Path with - | Some(path) when matchesPath "Conformance\\SpecialAttributesAndTypes\\Imported\\CallerInfo\\CallerFilePath.fs" path -> () + | Some(path) when matchesPath "Conformance#SpecialAttributesAndTypes#Imported#CallerInfo#CallerFilePath.fs" path -> () | x -> failwithf "Unexpected: %A" x match o1.Path with @@ -33,7 +36,7 @@ module Program = | x -> failwithf "Unexpected: %A" x match MyTy.GetCallerFilePath() with - | Some(path) when matchesPath "Conformance\\SpecialAttributesAndTypes\\Imported\\CallerInfo\\CallerFilePath.fs" path -> () + | Some(path) when matchesPath "Conformance#SpecialAttributesAndTypes#Imported#CallerInfo#CallerFilePath.fs" path -> () | x -> failwithf "Unexpected: %A" x match MyTy.GetCallerFilePath("42") with @@ -41,7 +44,7 @@ module Program = | x -> failwithf "Unexpected: %A" x match CallerInfoTest.FilePath() with - | path when matchesPath "Conformance\\SpecialAttributesAndTypes\\Imported\\CallerInfo\\CallerFilePath.fs" path -> () + | path when matchesPath "Conformance#SpecialAttributesAndTypes#Imported#CallerInfo#CallerFilePath.fs" path -> () | x -> failwithf "Unexpected: %A" x match CallerInfoTest.FilePath("xyz") with @@ -49,17 +52,17 @@ module Program = | x -> failwithf "Unexpected: %A" x match CallerInfoTest.AllInfo(21) with - | (path, _, _) when matchesPath "Conformance\\SpecialAttributesAndTypes\\Imported\\CallerInfo\\CallerFilePath.fs" path -> () + | (path, _, _) when matchesPath "Conformance#SpecialAttributesAndTypes#Imported#CallerInfo#CallerFilePath.fs" path -> () | x -> failwithf "Unexpected C# result with multiple parameter types: %A" x # 345 "qwerty1" match CallerInfoTest.AllInfo(123) with - | (path, _, _) when matchesPath "Conformance\\SpecialAttributesAndTypes\\Imported\\CallerInfo\\qwerty1" path -> () + | (path, _, _) when matchesPath "Conformance#SpecialAttributesAndTypes#Imported#CallerInfo#qwerty1" path -> () | x -> failwithf "Unexpected C# result with multiple parameter types: %A" x # 456 "qwerty2" match CallerInfoTest.AllInfo(123) with - | (path, _, _) when matchesPath "Conformance\\SpecialAttributesAndTypes\\Imported\\CallerInfo\\qwerty2" path -> () + | (path, _, _) when matchesPath "Conformance#SpecialAttributesAndTypes#Imported#CallerInfo#qwerty2" path -> () | x -> failwithf "Unexpected C# result with multiple parameter types: %A" x 0 \ No newline at end of file From 1c9dba4e7afa5bde0d8f281ddf79f6eabd585fc9 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Mon, 20 Jun 2016 16:48:06 +0100 Subject: [PATCH 068/129] fixed implementation --- src/absil/ilwrite.fs | 13 +- src/fsharp/FSComp.txt | 3 +- src/fsharp/IlxGen.fs | 2 +- src/fsharp/Optimizer.fs | 2 + src/fsharp/TastOps.fs | 4 +- src/fsharp/TastOps.fsi | 2 + src/fsharp/TcGlobals.fs | 3 + src/fsharp/TypeChecker.fs | 120 ++++++++--- tests/fsharp/typecheck/sigs/neg97.bsl | 10 +- tests/fsharp/typecheck/sigs/neg97.fs | 17 ++ .../TestFunction24.il.netfx4.bsl | 189 ++++++++++++++++++ .../EmittedIL/TestFunctions/Testfunction24.fs | 31 +++ .../CodeGen/EmittedIL/TestFunctions/env.lst | 1 + 13 files changed, 365 insertions(+), 32 deletions(-) create mode 100644 tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/TestFunction24.il.netfx4.bsl create mode 100644 tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/Testfunction24.fs diff --git a/src/absil/ilwrite.fs b/src/absil/ilwrite.fs index 667051456cb..98a17a556bf 100644 --- a/src/absil/ilwrite.fs +++ b/src/absil/ilwrite.fs @@ -849,6 +849,12 @@ and GetTypeAsTypeDefOrRef cenv env (ty:ILType) = and GetTypeAsBytes cenv env ty = emitBytesViaBuffer (fun bb -> EmitType cenv env bb ty) +and GetTypeOfLocalAsBytes cenv env (l: ILLocal) = + emitBytesViaBuffer (fun bb -> + if l.IsPinned then + bb.EmitByte et_PINNED + EmitType cenv env bb l.Type) + and GetTypeAsBlobIdx cenv env (ty:ILType) = GetBytesAsBlobIdx cenv (GetTypeAsBytes cenv env ty) @@ -1494,7 +1500,10 @@ let GetCallsigAsStandAloneSigIdx cenv env info = let EmitLocalSig cenv env (bb: ByteBuffer) (locals: ILLocals) = bb.EmitByte e_IMAGE_CEE_CS_CALLCONV_LOCAL_SIG bb.EmitZ32 locals.Length - locals |> ILList.iter (fun l -> EmitType cenv env bb l.Type) + locals |> ILList.iter (fun l -> + if l.IsPinned then + bb.EmitByte et_PINNED + EmitType cenv env bb l.Type) let GetLocalSigAsBlobHeapIdx cenv env locals = GetBytesAsBlobIdx cenv (emitBytesViaBuffer (fun bb -> EmitLocalSig cenv env bb locals)) @@ -2237,7 +2246,7 @@ let GenILMethodBody mname cenv env (il: ILMethodBody) = // Write a fake entry for the local signature headed by e_IMAGE_CEE_CS_CALLCONV_FIELD. This is referenced by the PDB file ignore (FindOrAddSharedRow cenv TableNames.StandAloneSig (SharedRow [| Blob (GetFieldDefTypeAsBlobIdx cenv env l.Type) |])) // Now write the type - GetTypeAsBytes cenv env l.Type) + GetTypeOfLocalAsBytes cenv env l) else [| |] diff --git a/src/fsharp/FSComp.txt b/src/fsharp/FSComp.txt index 2d4980f3c8f..7972f13ca76 100644 --- a/src/fsharp/FSComp.txt +++ b/src/fsharp/FSComp.txt @@ -1307,4 +1307,5 @@ estApplyStaticArgumentsForMethodNotImplemented,"A type provider implemented GetS 3201,tcModuleAbbrevFirstInMutRec,"In a recursive declaration group, module abbreviations must come after all 'open' declarations and before other declarations" 3202,tcUnsupportedMutRecDecl,"This declaration is not supported in recursive declaration groups" 3203,parsInvalidUseOfRec,"Invalid use of 'rec' keyword" -3204,tcFixedNotAllowed,"'fixed' may only be used in a declaration of the form 'use x = fixed array-or-address-or-string-expression'" +3204,tcFixedNotAllowed,"Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is an array, the address of a field, the address of an array element or a string'" +3205,tcCouldNotFindOffsetToStringData,"Could not find method System.Runtime.CompilerServices.OffsetToStringData in references when building 'fixed' expression." \ No newline at end of file diff --git a/src/fsharp/IlxGen.fs b/src/fsharp/IlxGen.fs index 722dda09238..2f3ebdb58c4 100644 --- a/src/fsharp/IlxGen.fs +++ b/src/fsharp/IlxGen.fs @@ -1569,7 +1569,7 @@ let CodeGenThen cenv mgbuf (zapFirstSeqPointToStart,entryPointInfo,methodName,ee let ilLocals = locals - |> List.map (fun (infos, ty,isFixed) -> + |> List.map (fun (infos, ty, isFixed) -> let loc = // in interactive environment, attach name and range info to locals to improve debug experience if cenv.opts.isInteractive && cenv.opts.generateDebugSymbols then diff --git a/src/fsharp/Optimizer.fs b/src/fsharp/Optimizer.fs index 186113ed2a2..c046e7be579 100644 --- a/src/fsharp/Optimizer.fs +++ b/src/fsharp/Optimizer.fs @@ -1254,6 +1254,7 @@ let ValueIsUsedOrHasEffect cenv fvs (b:Binding,binfo) = not (cenv.settings.EliminateUnusedBindings()) || isSome v.MemberInfo || binfo.HasEffect || + v.IsFixed || Zset.contains v (fvs()) let rec SplitValuesByIsUsedOrHasEffect cenv fvs x = @@ -1344,6 +1345,7 @@ let TryEliminateBinding cenv _env (TBind(vspec1,e1,spBind)) e2 _m = if not (cenv.optimizing && cenv.settings.EliminateImmediatelyConsumedLocals()) && not vspec1.IsCompilerGenerated then None + elif vspec1.IsFixed then None else // Peephole on immediate consumption of single bindings, e.g. "let x = e in x" --> "e" // REVIEW: enhance this by general elimination of bindings to diff --git a/src/fsharp/TastOps.fs b/src/fsharp/TastOps.fs index 57320d2205e..9425ea99de5 100755 --- a/src/fsharp/TastOps.fs +++ b/src/fsharp/TastOps.fs @@ -1181,6 +1181,8 @@ let mkStaticRecdFieldGetAddr(fref,tinst,m) = Expr.Op (TOp.ValFieldGetAd let mkStaticRecdFieldGet(fref,tinst,m) = Expr.Op (TOp.ValFieldGet(fref), tinst, [],m) let mkStaticRecdFieldSet(fref,tinst,e,m) = Expr.Op (TOp.ValFieldSet(fref), tinst, [e],m) +let mkArrayElemAddress g (readonly,isNativePtr,shape,elemTy,aexpr,nexpr,m) = Expr.Op (TOp.ILAsm ([IL.I_ldelema(readonly,isNativePtr,shape,mkILTyvarTy 0us)],[mkByrefTy g elemTy]), [elemTy],[aexpr;nexpr],m) + let mkRecdFieldSetViaExprAddr(e1,fref,tinst,e2,m) = Expr.Op (TOp.ValFieldSet(fref), tinst, [e1;e2],m) let mkUnionCaseTagGet(e1,cref,tinst,m) = Expr.Op (TOp.UnionCaseTagGet(cref), tinst, [e1],m) @@ -5443,7 +5445,7 @@ let rec mkExprAddrOfExpr g mustTakeAddress useReadonlyForGenericArrayAddress mut match addrExprVal with | Some(vf) -> valRefEq g vf g.addrof2_vref | _ -> false - (fun x -> x), Expr.Op (TOp.ILAsm ([IL.I_ldelema(readonly,isNativePtr,shape,mkILTyvarTy 0us)],[mkByrefTy g elemTy]), [elemTy],[aexpr;nexpr],m) + (fun x -> x), mkArrayElemAddress g (readonly,isNativePtr,shape,elemTy,aexpr,nexpr,m) // LVALUE: "e.[n1,n2]", "e.[n1,n2,n3]", "e.[n1,n2,n3,n4]" where e is an array of structs | Expr.App(Expr.Val(vf,_,_),_,[elemTy],(aexpr::args),_) diff --git a/src/fsharp/TastOps.fsi b/src/fsharp/TastOps.fsi index e4719f1b86f..58b602d92cb 100755 --- a/src/fsharp/TastOps.fsi +++ b/src/fsharp/TastOps.fsi @@ -196,6 +196,8 @@ val mkExnCaseFieldGet : Expr * TyconRef * int val mkUnionCaseFieldSet : Expr * UnionCaseRef * TypeInst * int * Expr * range -> Expr val mkExnCaseFieldSet : Expr * TyconRef * int * Expr * range -> Expr +val mkArrayElemAddress : TcGlobals -> ILReadonly * bool * ILArrayShape * TType * Expr * Expr * range -> Expr + //------------------------------------------------------------------------- // Compiled view of tuples //------------------------------------------------------------------------- diff --git a/src/fsharp/TcGlobals.fs b/src/fsharp/TcGlobals.fs index a02124d5e42..a27c50ca268 100755 --- a/src/fsharp/TcGlobals.fs +++ b/src/fsharp/TcGlobals.fs @@ -218,6 +218,7 @@ type public TcGlobals = system_Array_typ : TType system_Object_typ : TType system_IDisposable_typ : TType + system_RuntimeHelpers_typ : TType system_Value_typ : TType system_Delegate_typ : TType system_MulticastDelegate_typ : TType @@ -616,6 +617,7 @@ let mkTcGlobals (compilingFslib,sysCcu,ilg,fslibCcu,directoryToResolveRelativePa let sysLinq = ["System";"Linq"] let sysCollections = ["System";"Collections"] let sysGenerics = ["System";"Collections";"Generic"] + let sysCompilerServices = ["System";"Runtime";"CompilerServices"] let lazy_tcr = mkSysTyconRef sys "Lazy`1" let fslib_IEvent2_tcr = mk_MFControl_tcref fslibCcu "IEvent`2" @@ -1099,6 +1101,7 @@ let mkTcGlobals (compilingFslib,sysCcu,ilg,fslibCcu,directoryToResolveRelativePa system_Array_typ = mkSysNonGenericTy sys "Array" system_Object_typ = mkSysNonGenericTy sys "Object" system_IDisposable_typ = mkSysNonGenericTy sys "IDisposable" + system_RuntimeHelpers_typ = mkSysNonGenericTy sysCompilerServices "RuntimeHelpers" system_Value_typ = mkSysNonGenericTy sys "ValueType" system_Delegate_typ = mkSysNonGenericTy sys "Delegate" system_MulticastDelegate_typ = mkSysNonGenericTy sys "MulticastDelegate" diff --git a/src/fsharp/TypeChecker.fs b/src/fsharp/TypeChecker.fs index 59e69508f1f..0602b72c5ea 100755 --- a/src/fsharp/TypeChecker.fs +++ b/src/fsharp/TypeChecker.fs @@ -2946,6 +2946,17 @@ let BuildDisposableCleanup cenv env m (v:Val) = let inpe = mkCoerceExpr(exprForVal v.Range v,cenv.g.obj_ty,m,v.Type) mkIsInstConditional cenv.g m cenv.g.system_IDisposable_typ inpe disposeObjVar disposeExpr (mkUnit cenv.g m) +/// Build call to get_OffsetToStringData as part of 'fixed' +let BuildOffsetToStringData cenv env m = + let ad = env.eAccessRights + let offsetToStringDataMethod = + match TryFindIntrinsicOrExtensionMethInfo cenv env m ad "get_OffsetToStringData" cenv.g.system_RuntimeHelpers_typ with + | [x] -> x + | _ -> error(Error(FSComp.SR.tcCouldNotFindOffsetToStringData(),m)) + + let offsetExpr,_ = BuildPossiblyConditionalMethodCall cenv env NeverMutates m false offsetToStringDataMethod NormalValUse [] [] [] + offsetExpr + let BuildILFieldGet g amap m objExpr (finfo:ILFieldInfo) = let fref = finfo.ILFieldRef let isValueType = finfo.IsValueType @@ -9775,6 +9786,62 @@ and TcStaticOptimizationConstraint cenv env tpenv c = let tp',tpenv = TcTypar cenv env NewTyparsOK tpenv tp TTyconIsStruct(mkTyparTy tp'),tpenv + +/// Fix up the r.h.s. of a 'use x = fixed expr' +and TcAndBuildFixedExpr cenv env (overallPatTy, rhsExprChecked, overallExprTy, mBinding) = + match overallExprTy with + | ty when isByrefTy cenv.g ty -> + let okByRef = + match stripExpr rhsExprChecked with + | Expr.Op (op,tyargs,args,_) -> + match op,tyargs,args with + | TOp.ValFieldGetAddr rfref,_,[_] -> not rfref.Tycon.IsStructOrEnumTycon + | TOp.ILAsm ([ I_ldflda (fspec)],_),_,_ -> fspec.EnclosingType.Boxity = ILBoxity.AsObject + | TOp.ILAsm ([ I_ldelema _],_),_,_ -> true + | TOp.RefAddrGet _,_,_ -> true + | _ -> false + | _ -> false + if not okByRef then + error(Error(FSComp.SR.tcFixedNotAllowed(),mBinding)) + UnifyTypes cenv env mBinding overallExprTy overallPatTy + rhsExprChecked + + | ty when isStringTy cenv.g ty -> + let charPtrTy = (mkNativePtrType cenv.g cenv.g.char_ty) + UnifyTypes cenv env mBinding charPtrTy overallPatTy + let stringObjAsPtr = Expr.Op (TOp.ILAsm ([ AI_conv ILBasicType.DT_I], [ charPtrTy ]),[],[rhsExprChecked],mBinding) + // For strings 'use x = fixed str', we actually generate two pinned variables + // let pinned x = + // let pinned tmp = (char*) str + // tmp + get_OffsettoStringData() + // This is the easiest codegen for F# + + // Store the string into a pinned local + mkCompGenLetIn mBinding "pinnedString" charPtrTy stringObjAsPtr (fun (v,ve) -> + v.SetIsFixed() + let addrOffset = BuildOffsetToStringData cenv env mBinding + let stringPlusOffset = Expr.Op (TOp.ILAsm ([ AI_add ], [ charPtrTy ]),[],[ve; addrOffset],mBinding) + // check for non-null + mkNullTest cenv.g mBinding ve ve stringPlusOffset) + + | ty when isArray1DTy cenv.g ty -> + let elemTy = destArrayTy cenv.g overallExprTy + let elemPtrTy = mkByrefTy cenv.g elemTy + UnifyTypes cenv env mBinding elemPtrTy overallPatTy + // Store the array into a local + mkCompGenLetIn mBinding "tmpArray" overallExprTy rhsExprChecked (fun (_,ve) -> + // This is &arr.[0] + let elemZeroAddress = mkArrayElemAddress cenv.g (ILReadonly.NormalAddress,false,ILArrayShape.SingleDimensional,elemTy,ve,mkInt32 cenv.g mBinding 0,mBinding) + // check for non-null and non-empty + let zero = Expr.Op (TOp.ILAsm ([ AI_conv ILBasicType.DT_U], [ elemPtrTy ]),[],[mkInt32 cenv.g mBinding 0],mBinding) + // This is arr.Length + let arrayLengthExpr = mkCallArrayLength cenv.g mBinding elemTy ve + mkNullTest cenv.g mBinding ve zero (mkNullTest cenv.g mBinding arrayLengthExpr zero elemZeroAddress)) + + + | _ -> error(Error(FSComp.SR.tcFixedNotAllowed(),mBinding)) + + /// Binding checking code, for all bindings including let bindings, let-rec bindings, member bindings and object-expression bindings and and TcNormalizedBinding declKind (cenv:cenv) env tpenv overallTy safeThisValOpt safeInitInfo (enclosingDeclaredTypars,(ExplicitTyparInfo(_,declaredTypars,_) as flex)) bind = let envinner = AddDeclaredTypars NoCheckForDuplicateTypars (enclosingDeclaredTypars@declaredTypars) env @@ -9896,29 +9963,26 @@ and TcNormalizedBinding declKind (cenv:cenv) env tpenv overallTy safeThisValOpt // If binding a ctor then set the ugly counter that permits us to write ctor expressions on the r.h.s. let isCtor = (match memberFlagsOpt with Some memberFlags -> memberFlags.MemberKind = MemberKind.Constructor | _ -> false) - let tc = - if isCtor then TcExprThatIsCtorBody (safeThisValOpt, safeInitInfo) - else TcExprThatCantBeCtorBody - // At each module binding, dive into the expression to check for syntax errors and suppress them if they show. // Don't do this for lambdas, because we always check for suppression for all lambda bodies in TcIteratedLambdas - let rhsExpr',tpenv = + let rhsExprChecked,tpenv = let atTopNonLambdaDefn = DeclKind.IsModuleOrMemberOrExtensionBinding declKind && (match rhsExpr with SynExpr.Lambda _ -> false | _ -> true) && synExprContainsError rhsExpr + conditionallySuppressErrorReporting atTopNonLambdaDefn (fun () -> - tc cenv overallExprTy envinner tpenv rhsExpr) - if isFixed then - match overallExprTy with - | ty when isByrefTy cenv.g ty -> UnifyTypes cenv env mBinding overallExprTy overallPatTy - | ty when isStringTy cenv.g ty -> UnifyTypes cenv env mBinding (mkNativePtrType cenv.g cenv.g.char_ty) overallPatTy - | ty when isArray1DTy cenv.g ty -> UnifyTypes cenv env mBinding (mkByrefTy cenv.g (destArrayTy cenv.g overallExprTy)) overallPatTy - | _ -> error(Error(FSComp.SR.tcFixedNotAllowed(),mBinding)) + if isCtor then TcExprThatIsCtorBody (safeThisValOpt, safeInitInfo) cenv overallExprTy envinner tpenv rhsExpr + else TcExprThatCantBeCtorBody cenv overallExprTy envinner tpenv rhsExpr) if bkind = StandaloneExpression && not cenv.isScript then - UnifyUnitType cenv env.DisplayEnv mBinding overallPatTy (Some rhsExpr') |> ignore + UnifyUnitType cenv env.DisplayEnv mBinding overallPatTy (Some rhsExprChecked) |> ignore + + // Fix up the r.h.s. expression for 'fixed' + let rhsExprChecked = + if isFixed then TcAndBuildFixedExpr cenv env (overallPatTy, rhsExprChecked, overallExprTy, mBinding) + else rhsExprChecked // Assert the return type of an active pattern match apinfoOpt with @@ -9940,7 +10004,7 @@ and TcNormalizedBinding declKind (cenv:cenv) env tpenv overallTy safeThisValOpt if hasLiteralAttr && nonNil declaredTypars then errorR(Error(FSComp.SR.tcLiteralCannotHaveGenericParameters(),mBinding)) - CheckedBindingInfo(inlineFlag,true,valAttribs,doc,tcPatPhase2,flex,nameToPrelimValSchemeMap,rhsExpr',argAndRetAttribs,overallPatTy,mBinding,spBind,compgen,konst,isFixed),tpenv + CheckedBindingInfo(inlineFlag,true,valAttribs,doc,tcPatPhase2,flex,nameToPrelimValSchemeMap,rhsExprChecked,argAndRetAttribs,overallPatTy,mBinding,spBind,compgen,konst,isFixed),tpenv and TcLiteral cenv overallTy env tpenv (attrs,synLiteralValExpr) = let hasLiteralAttr = HasFSharpAttribute cenv.g cenv.g.attrib_LiteralAttribute attrs @@ -10233,13 +10297,13 @@ and TcLetBinding cenv isUse env containerInfo declKind tpenv (binds,bindsm,scope let prelimRecValues = NameMap.map fst values // Now bind the r.h.s. to the l.h.s. - let rhse = mkTypeLambda m generalizedTypars (rhsExpr,tauTy) + let rhsExpr = mkTypeLambda m generalizedTypars (rhsExpr,tauTy) match pat' with // Don't introduce temporary or 'let' for 'match against wild' or 'match against unit' | (TPat_wild _ | TPat_const (Const.Unit,_)) when not isUse && not isFixed && isNil generalizedTypars -> - let mk_seq_bind (tm,tmty) = (mkSequential SequencePointsAtSeq m rhse tm, tmty) + let mk_seq_bind (tm,tmty) = (mkSequential SequencePointsAtSeq m rhsExpr tm, tmty) (mk_seq_bind << mkf_sofar,env,tpenv) | _ -> @@ -10251,7 +10315,8 @@ and TcLetBinding cenv isUse env containerInfo declKind tpenv (binds,bindsm,scope | TPat_as (pat1,PBind(v,TypeScheme(generalizedTypars',_)),_) when List.lengthsEqAndForall2 typarRefEq generalizedTypars generalizedTypars' -> - if isFixed then v.SetIsFixed() + if isFixed then + v.SetIsFixed() v, pat1 | _ when mustinline(inlineFlag) -> error(Error(FSComp.SR.tcInvalidInlineSpecification(),m)) @@ -10265,25 +10330,28 @@ and TcLetBinding cenv isUse env containerInfo declKind tpenv (binds,bindsm,scope // type checker that anything related to binding module-level values is marked with an // val_repr_info, val_actual_parent and is_topbind if (DeclKind.MustHaveArity declKind) then - AdjustValToTopVal tmp altActualParent (InferArityOfExprBinding cenv.g tmp rhse) + AdjustValToTopVal tmp altActualParent (InferArityOfExprBinding cenv.g tmp rhsExpr) tmp,pat' - let mkRhsBind (tm,tmty) = (mkLet spBind m tmp rhse tm),tmty + let mkRhsBind (bodyExpr,bodyExprTy) = + let letExpr = mkLet spBind m tmp rhsExpr bodyExpr + letExpr,bodyExprTy + let allValsDefinedByPattern = (NameMap.range prelimRecValues |> FlatList.ofList) - let mkPatBind (tm,tmty) = + let mkPatBind (bodyExpr,bodyExprTy) = let valsDefinedByMatching = FlatListSet.remove valEq tmp allValsDefinedByPattern - let matchx = CompilePatternForMatch cenv env m m true ThrowIncompleteMatchException (tmp,generalizedTypars) [TClause(pat'',None,TTarget(valsDefinedByMatching,tm,SuppressSequencePointAtTarget),m)] tauTy tmty + let matchx = CompilePatternForMatch cenv env m m true ThrowIncompleteMatchException (tmp,generalizedTypars) [TClause(pat'',None,TTarget(valsDefinedByMatching,bodyExpr,SuppressSequencePointAtTarget),m)] tauTy bodyExprTy let matchx = if (DeclKind.ConvertToLinearBindings declKind) then LinearizeTopMatch cenv.g altActualParent matchx else matchx - matchx,tmty + matchx,bodyExprTy - let mkCleanup (tm,tmty) = + let mkCleanup (bodyExpr,bodyExprTy) = if isUse && not isFixed then - (allValsDefinedByPattern,(tm,tmty)) ||> FlatList.foldBack (fun v (tm,tmty) -> + (allValsDefinedByPattern,(bodyExpr,bodyExprTy)) ||> FlatList.foldBack (fun v (bodyExpr,bodyExprTy) -> AddCxTypeMustSubsumeType ContextInfo.NoContext denv cenv.css v.Range NoTrace cenv.g.system_IDisposable_typ v.Type let cleanupE = BuildDisposableCleanup cenv env m v - mkTryFinally cenv.g (tm,cleanupE,m,tmty,SequencePointInBodyOfTry,NoSequencePointAtFinally),tmty) + mkTryFinally cenv.g (bodyExpr,cleanupE,m,bodyExprTy,SequencePointInBodyOfTry,NoSequencePointAtFinally),bodyExprTy) else - (tm,tmty) + (bodyExpr,bodyExprTy) ((mkRhsBind << mkPatBind << mkCleanup << mkf_sofar), AddLocalValMap cenv.tcSink scopem prelimRecValues env, diff --git a/tests/fsharp/typecheck/sigs/neg97.bsl b/tests/fsharp/typecheck/sigs/neg97.bsl index 4353b29ffc2..3bbeb123ffd 100644 --- a/tests/fsharp/typecheck/sigs/neg97.bsl +++ b/tests/fsharp/typecheck/sigs/neg97.bsl @@ -1,2 +1,10 @@ -neg96.fs(13,1,13,2): typecheck error FS0256: A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...' \ No newline at end of file +neg97.fs(13,1,13,2): typecheck error FS0256: A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...' + +neg97.fs(16,9,16,10): typecheck error FS3204: Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is an array, the address of a field, the address of an array element or a string' + +neg97.fs(20,9,20,10): typecheck error FS3204: Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is an array, the address of a field, the address of an array element or a string' + +neg97.fs(25,9,25,10): typecheck error FS3204: Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is an array, the address of a field, the address of an array element or a string' + +neg97.fs(30,9,30,10): typecheck error FS3204: Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is an array, the address of a field, the address of an array element or a string' diff --git a/tests/fsharp/typecheck/sigs/neg97.fs b/tests/fsharp/typecheck/sigs/neg97.fs index 67a7b104b29..01f68256c9a 100644 --- a/tests/fsharp/typecheck/sigs/neg97.fs +++ b/tests/fsharp/typecheck/sigs/neg97.fs @@ -12,3 +12,20 @@ let x = { X = 1.; Y = 1. } x.Y <- 5. +let pinIntNotAllowed() = + use p = fixed 3 + () + +let pinAnyNotAllowed(x: 'T) = + use p = fixed x + () + +let pinStackAddressNotAllowed(x: 'T) = + let mutable v = 0 + use p = fixed &v + () + +let pinStructAddressNotAllowed(x: 'T) = + let mutable v = { X = 1.0; Y = 1.0 } + use p = fixed &v.Y + () diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/TestFunction24.il.netfx4.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/TestFunction24.il.netfx4.bsl new file mode 100644 index 00000000000..d1422d18107 --- /dev/null +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/TestFunction24.il.netfx4.bsl @@ -0,0 +1,189 @@ + +// Microsoft (R) .NET Framework IL Disassembler. Version 4.0.30319.17376 +// Copyright (c) Microsoft Corporation. All rights reserved. + + + +// Metadata version: v4.0.30319 +.assembly extern mscorlib +{ + .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. + .ver 4:0:0:0 +} +.assembly extern FSharp.Core +{ + .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....: + .ver 4:3:0:0 +} +.assembly TestFunction23 +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + // --- The following custom attribute is added automatically, do not uncomment ------- + // .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 01 01 00 00 00 00 ) + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.mresource public FSharpSignatureData.TestFunction23 +{ + // Offset: 0x00000000 Length: 0x0000036A +} +.mresource public FSharpOptimizationData.TestFunction23 +{ + // Offset: 0x00000370 Length: 0x000000E3 +} +.module TestFunction23.exe +// MVID: {4F20E3B8-A643-451C-A745-0383B8E3204F} +.imagebase 0x00400000 +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 // WINDOWS_CUI +.corflags 0x00000001 // ILONLY +// Image base: 0x0000008C477A0000 + + +// =============== CLASS MEMBERS DECLARATION =================== + +.class public abstract auto ansi sealed TestFunction23 + extends [mscorlib]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable nested public C + extends [mscorlib]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .field assembly string x + .field assembly string x@8 + .method public specialname rtspecialname + instance void .ctor() cil managed + { + // Code size 32 (0x20) + .maxstack 8 + .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' + .line 6,6 : 5,38 + IL_0000: ldarg.0 + IL_0001: callvirt instance void [mscorlib]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: pop + IL_0008: nop + IL_0009: ldarg.0 + IL_000a: call string [mscorlib]System.Console::ReadLine() + IL_000f: stfld string TestFunction23/C::x + .line 8,8 : 5,38 + IL_0014: ldarg.0 + IL_0015: call string [mscorlib]System.Console::ReadLine() + IL_001a: stfld string TestFunction23/C::x@8 + .line 5,5 : 6,7 + IL_001f: ret + } // end of method C::.ctor + + .method public hidebysig instance string + M() cil managed + { + // Code size 19 (0x13) + .maxstack 8 + .line 9,9 : 23,30 + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: ldfld string TestFunction23/C::x@8 + IL_0007: ldarg.0 + IL_0008: callvirt instance string TestFunction23/C::g() + IL_000d: call string [mscorlib]System.String::Concat(string, + string) + IL_0012: ret + } // end of method C::M + + .method assembly hidebysig instance string + g() cil managed + { + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 8 (0x8) + .maxstack 8 + .line 7,7 : 15,16 + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: ldfld string TestFunction23/C::x + IL_0007: ret + } // end of method C::g + + } // end of class C + + .class auto ansi serializable nested assembly beforefieldinit g@13 + extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 + { + .method assembly specialname rtspecialname + instance void .ctor() cil managed + { + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::.ctor() + IL_0006: ret + } // end of method g@13::.ctor + + .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Core.Unit + Invoke(class [FSharp.Core]Microsoft.FSharp.Core.Unit unitVar0) cil managed + { + // Code size 35 (0x23) + .maxstack 8 + .line 13,13 : 9,24 + IL_0000: nop + IL_0001: ldstr "Hello" + IL_0006: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) + IL_000b: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatLine(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_0010: pop + .line 14,14 : 9,24 + IL_0011: ldstr "Hello" + IL_0016: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) + IL_001b: tail. + IL_001d: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatLine(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_0022: ret + } // end of method g@13::Invoke + + } // end of class g@13 + + .method public static class [mscorlib]System.Tuple`2 + f(!!a x) cil managed + { + // Code size 27 (0x1b) + .maxstack 5 + .locals init ([0] class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 g) + .line 12,12 : 9,12 + IL_0000: nop + IL_0001: newobj instance void TestFunction23/g@13::.ctor() + IL_0006: stloc.0 + .line 15,15 : 5,13 + IL_0007: ldloc.0 + IL_0008: ldnull + IL_0009: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_000e: ldloc.0 + IL_000f: ldnull + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0015: newobj instance void class [mscorlib]System.Tuple`2::.ctor(!0, + !1) + IL_001a: ret + } // end of method TestFunction23::f + +} // end of class TestFunction23 + +.class private abstract auto ansi sealed ''.$TestFunction23 + extends [mscorlib]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + // Code size 2 (0x2) + .maxstack 8 + IL_0000: nop + IL_0001: ret + } // end of method $TestFunction23::main@ + +} // end of class ''.$TestFunction23 + + +// ============================================================= + +// *********** DISASSEMBLY COMPLETE *********************** diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/Testfunction24.fs b/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/Testfunction24.fs new file mode 100644 index 00000000000..1f82f6b7048 --- /dev/null +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/Testfunction24.fs @@ -0,0 +1,31 @@ +// Assume that the following class exists. + +type Point = { mutable x : int; mutable y : int } + +let pinObject() = + let point = { x = 1; y = 2 } + use p1 = fixed &point.x // note, fixed is a keyword and would be highlighted + () + +let pinRef() = + let point = ref 1 + use p1 = fixed &point.contents // note, fixed is a keyword and would be highlighted + () + +let pinArray1() = + let arr = [| 0.0; 1.5; 2.3; 3.4; 4.0; 5.9 |] + use p1 = fixed arr + () + +let pinArray2() = + let arr = [| 0.0; 1.5; 2.3; 3.4; 4.0; 5.9 |] + // You can initialize a pointer by using the address of a variable. + use p = fixed &arr.[0] + () + +let pinString() = + let str = "Hello World" + // The following assignment initializes p by using a string. + use pChar = fixed str + () + // some code that uses pChar, which has type char* diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/env.lst b/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/env.lst index 8ffdad5d7fa..c55c1dc11ef 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/env.lst +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/env.lst @@ -43,3 +43,4 @@ SOURCE=Testfunction22g.fs SCFLAGS="-g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd TestFunction22g.exe" # TestFunction22g.fs SOURCE=Testfunction22h.fs SCFLAGS="-g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd TestFunction22h.exe NetFx40" # TestFunction22h.fs - NetFx40 + SOURCE=Testfunction24.fs SCFLAGS="-a -g --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd TestFunction24.dll NetFx40" # TestFunction24.fs - NetFx40 From 07a7ded47595185222a9f287a5ba16471bfac743 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Mon, 20 Jun 2016 17:17:11 +0100 Subject: [PATCH 069/129] fix fixed --- src/fsharp/PostInferenceChecks.fs | 14 ++++++++------ src/fsharp/TypeChecker.fs | 7 +++---- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/fsharp/PostInferenceChecks.fs b/src/fsharp/PostInferenceChecks.fs index d9ea90e1715..f5acda847ba 100644 --- a/src/fsharp/PostInferenceChecks.fs +++ b/src/fsharp/PostInferenceChecks.fs @@ -484,10 +484,12 @@ and CheckExprInContext (cenv:cenv) (env:env) expr (context:ByrefCallContext) = match dir with | NormalSeq -> CheckExprInContext cenv env e2 context // carry context into _;RHS (normal sequencing only) | ThenDoSeq -> CheckExpr cenv {env with limited=false} e2 + | Expr.Let (bind,body,_,_) -> CheckBinding cenv env false bind ; BindVal cenv bind.Var - CheckExpr cenv env body + CheckExprInContext cenv env body context + | Expr.Const (_,m,ty) -> CheckTypePermitByrefs cenv env m ty @@ -643,7 +645,7 @@ and CheckExprInContext (cenv:cenv) (env:env) expr (context:ByrefCallContext) = | Expr.Match(_,_,dtree,targets,m,ty) -> CheckTypeNoByrefs cenv env m ty; CheckDecisionTree cenv env dtree; - CheckDecisionTreeTargets cenv env targets; + CheckDecisionTreeTargets cenv env targets context; | Expr.LetRec (binds,e,_,_) -> BindVals cenv (valsOfBinds binds) CheckBindings cenv env binds; @@ -874,13 +876,13 @@ and CheckFlatExprs cenv env exprs = and CheckExprDirectArgs cenv env exprs = exprs |> List.iter (fun x -> CheckExprInContext cenv env x DirectArg) -and CheckDecisionTreeTargets cenv env targets = - targets |> Array.iter (CheckDecisionTreeTarget cenv env) +and CheckDecisionTreeTargets cenv env targets context = + targets |> Array.iter (CheckDecisionTreeTarget cenv env context ) -and CheckDecisionTreeTarget cenv env (TTarget(vs,e,_)) = +and CheckDecisionTreeTarget cenv env context (TTarget(vs,e,_)) = BindVals cenv vs vs |> FlatList.iter (CheckValSpec cenv env) - CheckExpr cenv env e + CheckExprInContext cenv env e context and CheckDecisionTree cenv env x = match x with diff --git a/src/fsharp/TypeChecker.fs b/src/fsharp/TypeChecker.fs index 0602b72c5ea..d0eea1147a0 100755 --- a/src/fsharp/TypeChecker.fs +++ b/src/fsharp/TypeChecker.fs @@ -9822,7 +9822,7 @@ and TcAndBuildFixedExpr cenv env (overallPatTy, rhsExprChecked, overallExprTy, m let addrOffset = BuildOffsetToStringData cenv env mBinding let stringPlusOffset = Expr.Op (TOp.ILAsm ([ AI_add ], [ charPtrTy ]),[],[ve; addrOffset],mBinding) // check for non-null - mkNullTest cenv.g mBinding ve ve stringPlusOffset) + mkNullTest cenv.g mBinding ve stringPlusOffset ve) | ty when isArray1DTy cenv.g ty -> let elemTy = destArrayTy cenv.g overallExprTy @@ -9833,11 +9833,10 @@ and TcAndBuildFixedExpr cenv env (overallPatTy, rhsExprChecked, overallExprTy, m // This is &arr.[0] let elemZeroAddress = mkArrayElemAddress cenv.g (ILReadonly.NormalAddress,false,ILArrayShape.SingleDimensional,elemTy,ve,mkInt32 cenv.g mBinding 0,mBinding) // check for non-null and non-empty - let zero = Expr.Op (TOp.ILAsm ([ AI_conv ILBasicType.DT_U], [ elemPtrTy ]),[],[mkInt32 cenv.g mBinding 0],mBinding) + let zero = Expr.Op (TOp.ILAsm ([ AI_conv ILBasicType.DT_U], [ cenv.g.nativeint_ty ]),[],[mkInt32 cenv.g mBinding 0],mBinding) // This is arr.Length let arrayLengthExpr = mkCallArrayLength cenv.g mBinding elemTy ve - mkNullTest cenv.g mBinding ve zero (mkNullTest cenv.g mBinding arrayLengthExpr zero elemZeroAddress)) - + mkNullTest cenv.g mBinding ve (mkNullTest cenv.g mBinding arrayLengthExpr elemZeroAddress zero) zero ) | _ -> error(Error(FSComp.SR.tcFixedNotAllowed(),mBinding)) From 3db7a6f9dc8e39d140c03969fa691aa39fdad766 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Mon, 20 Jun 2016 21:20:33 +0100 Subject: [PATCH 070/129] fix tests --- .../TestFunction24.il.netfx4.bsl | 187 +----------------- .../E_ReservedIdentKeywords.fs | 3 +- 2 files changed, 2 insertions(+), 188 deletions(-) diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/TestFunction24.il.netfx4.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/TestFunction24.il.netfx4.bsl index d1422d18107..494be65e9e1 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/TestFunction24.il.netfx4.bsl +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/TestFunction24.il.netfx4.bsl @@ -1,189 +1,4 @@ -// Microsoft (R) .NET Framework IL Disassembler. Version 4.0.30319.17376 +// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.81.0 // Copyright (c) Microsoft Corporation. All rights reserved. - - -// Metadata version: v4.0.30319 -.assembly extern mscorlib -{ - .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. - .ver 4:0:0:0 -} -.assembly extern FSharp.Core -{ - .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....: - .ver 4:3:0:0 -} -.assembly TestFunction23 -{ - .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, - int32, - int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) - - // --- The following custom attribute is added automatically, do not uncomment ------- - // .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 01 01 00 00 00 00 ) - - .hash algorithm 0x00008004 - .ver 0:0:0:0 -} -.mresource public FSharpSignatureData.TestFunction23 -{ - // Offset: 0x00000000 Length: 0x0000036A -} -.mresource public FSharpOptimizationData.TestFunction23 -{ - // Offset: 0x00000370 Length: 0x000000E3 -} -.module TestFunction23.exe -// MVID: {4F20E3B8-A643-451C-A745-0383B8E3204F} -.imagebase 0x00400000 -.file alignment 0x00000200 -.stackreserve 0x00100000 -.subsystem 0x0003 // WINDOWS_CUI -.corflags 0x00000001 // ILONLY -// Image base: 0x0000008C477A0000 - - -// =============== CLASS MEMBERS DECLARATION =================== - -.class public abstract auto ansi sealed TestFunction23 - extends [mscorlib]System.Object -{ - .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) - .class auto ansi serializable nested public C - extends [mscorlib]System.Object - { - .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) - .field assembly string x - .field assembly string x@8 - .method public specialname rtspecialname - instance void .ctor() cil managed - { - // Code size 32 (0x20) - .maxstack 8 - .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' - .line 6,6 : 5,38 - IL_0000: ldarg.0 - IL_0001: callvirt instance void [mscorlib]System.Object::.ctor() - IL_0006: ldarg.0 - IL_0007: pop - IL_0008: nop - IL_0009: ldarg.0 - IL_000a: call string [mscorlib]System.Console::ReadLine() - IL_000f: stfld string TestFunction23/C::x - .line 8,8 : 5,38 - IL_0014: ldarg.0 - IL_0015: call string [mscorlib]System.Console::ReadLine() - IL_001a: stfld string TestFunction23/C::x@8 - .line 5,5 : 6,7 - IL_001f: ret - } // end of method C::.ctor - - .method public hidebysig instance string - M() cil managed - { - // Code size 19 (0x13) - .maxstack 8 - .line 9,9 : 23,30 - IL_0000: nop - IL_0001: ldarg.0 - IL_0002: ldfld string TestFunction23/C::x@8 - IL_0007: ldarg.0 - IL_0008: callvirt instance string TestFunction23/C::g() - IL_000d: call string [mscorlib]System.String::Concat(string, - string) - IL_0012: ret - } // end of method C::M - - .method assembly hidebysig instance string - g() cil managed - { - .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - // Code size 8 (0x8) - .maxstack 8 - .line 7,7 : 15,16 - IL_0000: nop - IL_0001: ldarg.0 - IL_0002: ldfld string TestFunction23/C::x - IL_0007: ret - } // end of method C::g - - } // end of class C - - .class auto ansi serializable nested assembly beforefieldinit g@13 - extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 - { - .method assembly specialname rtspecialname - instance void .ctor() cil managed - { - // Code size 7 (0x7) - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::.ctor() - IL_0006: ret - } // end of method g@13::.ctor - - .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Core.Unit - Invoke(class [FSharp.Core]Microsoft.FSharp.Core.Unit unitVar0) cil managed - { - // Code size 35 (0x23) - .maxstack 8 - .line 13,13 : 9,24 - IL_0000: nop - IL_0001: ldstr "Hello" - IL_0006: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) - IL_000b: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatLine(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) - IL_0010: pop - .line 14,14 : 9,24 - IL_0011: ldstr "Hello" - IL_0016: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) - IL_001b: tail. - IL_001d: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatLine(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) - IL_0022: ret - } // end of method g@13::Invoke - - } // end of class g@13 - - .method public static class [mscorlib]System.Tuple`2 - f(!!a x) cil managed - { - // Code size 27 (0x1b) - .maxstack 5 - .locals init ([0] class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 g) - .line 12,12 : 9,12 - IL_0000: nop - IL_0001: newobj instance void TestFunction23/g@13::.ctor() - IL_0006: stloc.0 - .line 15,15 : 5,13 - IL_0007: ldloc.0 - IL_0008: ldnull - IL_0009: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) - IL_000e: ldloc.0 - IL_000f: ldnull - IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) - IL_0015: newobj instance void class [mscorlib]System.Tuple`2::.ctor(!0, - !1) - IL_001a: ret - } // end of method TestFunction23::f - -} // end of class TestFunction23 - -.class private abstract auto ansi sealed ''.$TestFunction23 - extends [mscorlib]System.Object -{ - .method public static void main@() cil managed - { - .entrypoint - // Code size 2 (0x2) - .maxstack 8 - IL_0000: nop - IL_0001: ret - } // end of method $TestFunction23::main@ - -} // end of class ''.$TestFunction23 - - -// ============================================================= - -// *********** DISASSEMBLY COMPLETE *********************** diff --git a/tests/fsharpqa/Source/Conformance/LexicalAnalysis/IdentifiersAndKeywords/E_ReservedIdentKeywords.fs b/tests/fsharpqa/Source/Conformance/LexicalAnalysis/IdentifiersAndKeywords/E_ReservedIdentKeywords.fs index 2c550ad3d3c..cd69818e422 100644 --- a/tests/fsharpqa/Source/Conformance/LexicalAnalysis/IdentifiersAndKeywords/E_ReservedIdentKeywords.fs +++ b/tests/fsharpqa/Source/Conformance/LexicalAnalysis/IdentifiersAndKeywords/E_ReservedIdentKeywords.fs @@ -10,7 +10,7 @@ let constraint = 10 let constructor = 10 let continue = 10 let eager = 10 -let fixed = 10 + let fori = 10 let functor = 10 let include = 10 @@ -39,7 +39,6 @@ let volatile = 10 //The identifier 'constructor' is reserved for future use by F# //The identifier 'continue' is reserved for future use by F# //The identifier 'eager' is reserved for future use by F# -//The identifier 'fixed' is reserved for future use by F# //The identifier 'fori' is reserved for future use by F# //The identifier 'functor' is reserved for future use by F# //The identifier 'include' is reserved for future use by F# From a682a1823b41af745ed85635cc4fd32bcfbfef2d Mon Sep 17 00:00:00 2001 From: Don Syme Date: Mon, 20 Jun 2016 23:51:53 +0100 Subject: [PATCH 071/129] fix VS --- src/fsharp/vs/ServiceLexing.fs | 2 +- src/fsharp/vs/ServiceParseTreeWalk.fs | 1 + src/fsharp/vs/ServiceUntypedParse.fs | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/fsharp/vs/ServiceLexing.fs b/src/fsharp/vs/ServiceLexing.fs index 8e7df0690a0..85f5f531085 100755 --- a/src/fsharp/vs/ServiceLexing.fs +++ b/src/fsharp/vs/ServiceLexing.fs @@ -250,7 +250,7 @@ module internal TokenClassifications = | FINALLY | LAZY | MATCH | MUTABLE | NEW | OF | OPEN | OR | VOID | EXTERN | INTERFACE | REC | TO | TRUE | TRY | TYPE | VAL | INLINE | WHEN | WHILE | WITH | IF | THEN | ELSE | DO | DONE | LET(_) | IN (*| NAMESPACE*) | CONST - | HIGH_PRECEDENCE_PAREN_APP + | HIGH_PRECEDENCE_PAREN_APP | FIXED | HIGH_PRECEDENCE_BRACK_APP | TYPE_COMING_SOON | TYPE_IS_HERE | MODULE_COMING_SOON | MODULE_IS_HERE -> (FSharpTokenColorKind.Keyword,FSharpTokenCharKind.Keyword,FSharpTokenTriggerClass.None) diff --git a/src/fsharp/vs/ServiceParseTreeWalk.fs b/src/fsharp/vs/ServiceParseTreeWalk.fs index 792af9f4bf6..2f93adbb52e 100755 --- a/src/fsharp/vs/ServiceParseTreeWalk.fs +++ b/src/fsharp/vs/ServiceParseTreeWalk.fs @@ -317,6 +317,7 @@ module internal AstTraversal = |> pick expr | SynExpr.Do(synExpr, _range) -> traverseSynExpr synExpr | SynExpr.Assert(synExpr, _range) -> traverseSynExpr synExpr + | SynExpr.Fixed(synExpr, _range) -> traverseSynExpr synExpr | SynExpr.App(_exprAtomicFlag, isInfix, synExpr, synExpr2, _range) -> if isInfix then [dive synExpr2 synExpr2.Range traverseSynExpr diff --git a/src/fsharp/vs/ServiceUntypedParse.fs b/src/fsharp/vs/ServiceUntypedParse.fs index 41b0b212799..b8e58a15abe 100755 --- a/src/fsharp/vs/ServiceUntypedParse.fs +++ b/src/fsharp/vs/ServiceUntypedParse.fs @@ -171,6 +171,7 @@ type FSharpParseFileResults(errors : FSharpErrorInfo[], input : Ast.ParsedInput | SynExpr.DiscardAfterMissingQualificationAfterDot (e,_) | SynExpr.Do (e,_) | SynExpr.Assert (e,_) + | SynExpr.Fixed (e,_) | SynExpr.DotGet (e,_,_,_) | SynExpr.LongIdentSet (_,e,_) | SynExpr.New (_,_,e,_) From 8f0733cd3bea83ee0e3efcf4642a53cca24c13f1 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Tue, 21 Jun 2016 15:42:22 +0100 Subject: [PATCH 072/129] proper codegen and add tests --- VisualFSharp.sln | 3 - src/fsharp/Optimizer.fs | 15 ++-- src/fsharp/PostInferenceChecks.fs | 26 +++---- src/fsharp/TastOps.fs | 4 +- src/fsharp/TastOps.fsi | 4 +- src/fsharp/TcGlobals.fs | 4 +- src/fsharp/TypeChecker.fs | 68 ++++++++++++------- src/fsharp/import.fs | 4 +- tests/fsharp/core/fsiAndModifiers/test.fsx | 51 ++++++++++++++ tests/fsharp/core/pinvoke/test.fsx | 16 ++--- .../CodeGen/EmittedIL/TestFunctions/env.lst | 20 +++--- 11 files changed, 143 insertions(+), 72 deletions(-) diff --git a/VisualFSharp.sln b/VisualFSharp.sln index 26f1b2787c2..f83f67999d4 100644 --- a/VisualFSharp.sln +++ b/VisualFSharp.sln @@ -127,9 +127,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution EndProjectSection EndProject Global - GlobalSection(Performance) = preSolution - HasPerformanceSessions = true - EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Debug|x86 = Debug|x86 diff --git a/src/fsharp/Optimizer.fs b/src/fsharp/Optimizer.fs index c046e7be579..01f2181a0ea 100644 --- a/src/fsharp/Optimizer.fs +++ b/src/fsharp/Optimizer.fs @@ -431,7 +431,7 @@ let BindExternalLocalVal cenv (v:Val) vval env = CheckInlineValueIsComplete v vval; #endif - if verboseOptimizationInfo then dprintn ("*** Binding "^v.LogicalName); + if verboseOptimizationInfo then dprintn ("*** Binding "+v.LogicalName); let vval = if v.IsMutable then {vval with ValExprInfo=UnknownValue } else vval let env = #if CHECKED @@ -534,7 +534,7 @@ let TryGetInfoForEntity sv n = | Some info -> Some (info.Force()) | None -> if verboseOptimizationInfo then - dprintn ("\n\n*** Optimization info for submodule "^n^" not found in parent module which contains submodules: "^String.concat "," (NameMap.domainL sv.ModuleOrNamespaceInfos)); + dprintn ("\n\n*** Optimization info for submodule "+n+" not found in parent module which contains submodules: "+String.concat "," (NameMap.domainL sv.ModuleOrNamespaceInfos)); None let rec TryGetInfoForPath sv (p:_[]) i = @@ -558,7 +558,7 @@ let GetInfoForNonLocalVal cenv env (vref:ValRef) = match structInfo.ValInfos.TryFind(vref) with | Some ninfo -> snd ninfo | None -> - //dprintn ("\n\n*** Optimization info for value "^n^" from module "^(full_name_of_nlpath smv)^" not found, module contains values: "^String.concat "," (NameMap.domainL structInfo.ValInfos)); + //dprintn ("\n\n*** Optimization info for value "+n+" from module "+(full_name_of_nlpath smv)+" not found, module contains values: "+String.concat "," (NameMap.domainL structInfo.ValInfos)); //System.Diagnostics.Debug.Assert(false,sprintf "Break for module %s, value %s" (full_name_of_nlpath smv) n) if cenv.g.compilingFslib then match structInfo.ValInfos.TryFindForFslib(vref) with @@ -1455,7 +1455,7 @@ let ExpandStructuralBindingRaw cenv expr = else let argTys = destTupleTy cenv.g v.Type let argBind i (arg:Expr) argTy = - let name = v.LogicalName ^ "_" ^ string i + let name = v.LogicalName + "_" + string i let v,ve = mkCompGenLocal arg.Range name argTy ve,mkCompGenBind v arg @@ -2834,7 +2834,8 @@ and ComputeSplitToMethodCondition flag threshold cenv env (e,einfo) = // None of them should be local polymorphic constrained values not (IsGenericValWithGenericContraints cenv.g v) && // None of them should be mutable - not v.IsMutable)))) + not v.IsMutable)))) && + not (isByrefLikeTy cenv.g (tyOfExpr cenv.g e)) and ConsiderSplitToMethod flag threshold cenv env (e,einfo) = if ComputeSplitToMethodCondition flag threshold cenv env (e,einfo) then @@ -2843,7 +2844,7 @@ and ConsiderSplitToMethod flag threshold cenv env (e,einfo) = let ty = tyOfExpr cenv.g e let nm = match env.latestBoundId with - | Some id -> id.idText^suffixForVariablesThatMayNotBeEliminated + | Some id -> id.idText+suffixForVariablesThatMayNotBeEliminated | None -> suffixForVariablesThatMayNotBeEliminated let fv,fe = mkCompGenLocal m nm (cenv.g.unit_ty --> ty) mkInvisibleLet m fv (mkLambda m uv (e,ty)) @@ -3063,7 +3064,7 @@ and OptimizeBinding cenv isRec env (TBind(v,e,spBind)) = then {einfo with Info=UnknownValue} else einfo if v.MustInline && IsPartialExprVal einfo.Info then - errorR(InternalError("the mustinline value '"^v.LogicalName^"' was not inferred to have a known value",v.Range)); + errorR(InternalError("the mustinline value '"+v.LogicalName+"' was not inferred to have a known value",v.Range)); #if DEBUG if verboseOptimizations then dprintf "val %s gets opt info %s\n" (showL(valL v)) (showL(exprValueInfoL cenv.g einfo.Info)); #endif diff --git a/src/fsharp/PostInferenceChecks.fs b/src/fsharp/PostInferenceChecks.fs index f5acda847ba..a8df762c996 100644 --- a/src/fsharp/PostInferenceChecks.fs +++ b/src/fsharp/PostInferenceChecks.fs @@ -643,19 +643,19 @@ and CheckExprInContext (cenv:cenv) (env:env) expr (context:ByrefCallContext) = CheckExpr cenv env e1 | Expr.Match(_,_,dtree,targets,m,ty) -> - CheckTypeNoByrefs cenv env m ty; - CheckDecisionTree cenv env dtree; - CheckDecisionTreeTargets cenv env targets context; + CheckTypePermitByrefs cenv env m ty // computed byrefs allowed at each branch + CheckDecisionTree cenv env dtree + CheckDecisionTreeTargets cenv env targets context | Expr.LetRec (binds,e,_,_) -> BindVals cenv (valsOfBinds binds) - CheckBindings cenv env binds; + CheckBindings cenv env binds CheckExpr cenv env e | Expr.StaticOptimization (constraints,e2,e3,m) -> - CheckExpr cenv env e2; - CheckExpr cenv env e3; + CheckExpr cenv env e2 + CheckExpr cenv env e3 constraints |> List.iter (function | TTyconEqualsTycon(ty1,ty2) -> - CheckTypeNoByrefs cenv env m ty1; + CheckTypeNoByrefs cenv env m ty1 CheckTypeNoByrefs cenv env m ty2 | TTyconIsStruct(ty1) -> CheckTypeNoByrefs cenv env m ty1) @@ -668,8 +668,8 @@ and CheckMethods cenv env baseValOpt l = and CheckMethod cenv env baseValOpt (TObjExprMethod(_,attribs,tps,vs,e,m)) = let env = BindTypars cenv.g env tps let vs = List.concat vs - CheckAttribs cenv env attribs; - CheckNoReraise cenv None e; + CheckAttribs cenv env attribs + CheckNoReraise cenv None e CheckEscapes cenv true m (match baseValOpt with Some x -> x:: vs | None -> vs) e |> ignore CheckExpr cenv env e @@ -682,13 +682,13 @@ and CheckInterfaceImpl cenv env baseValOpt (_ty,overrides) = and CheckExprOp cenv env (op,tyargs,args,m) context = let limitedCheck() = - if env.limited then errorR(Error(FSComp.SR.chkObjCtorsCantUseExceptionHandling(), m)); - List.iter (CheckTypePermitByrefs cenv env m) tyargs; + if env.limited then errorR(Error(FSComp.SR.chkObjCtorsCantUseExceptionHandling(), m)) + List.iter (CheckTypePermitByrefs cenv env m) tyargs (* Special cases *) match op,tyargs,args,context with // Handle these as special cases since mutables are allowed inside their bodies | TOp.While _,_,[Expr.Lambda(_,_,_,[_],e1,_,_);Expr.Lambda(_,_,_,[_],e2,_,_)],_ -> - CheckTypeInstNoByrefs cenv env m tyargs; + CheckTypeInstNoByrefs cenv env m tyargs CheckExprs cenv env [e1;e2] | TOp.TryFinally _,[_],[Expr.Lambda(_,_,_,[_],e1,_,_); Expr.Lambda(_,_,_,[_],e2,_,_)],_ -> @@ -772,6 +772,8 @@ and CheckExprOp cenv env (op,tyargs,args,m) context = errorR(Error(FSComp.SR.chkNoAddressOfArrayElementAtThisPoint(), m)); CheckExprInContext cenv env lhsArray DirectArg (* permit byref for lhs lvalue *) CheckExprs cenv env indices + | [ AI_conv _ ],_ -> + CheckExprDirectArgs cenv env args (* permit byref for args to conv *) | _instrs -> CheckExprs cenv env args end diff --git a/src/fsharp/TastOps.fs b/src/fsharp/TastOps.fs index 9425ea99de5..9a211d4ae95 100755 --- a/src/fsharp/TastOps.fs +++ b/src/fsharp/TastOps.fs @@ -536,7 +536,7 @@ let rec sizeMeasure g ms = // Some basic type builders //--------------------------------------------------------------------------- -let mkNativePtrType g ty = TType_app (g.nativeptr_tcr, [ty]) +let mkNativePtrTy g ty = TType_app (g.nativeptr_tcr, [ty]) let mkByrefTy g ty = TType_app (g.byref_tcr, [ty]) let mkArrayTy g rank ty m = @@ -1458,6 +1458,7 @@ let isUnitTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref,_) -> t let isObjTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref,_) -> tyconRefEq g g.system_Object_tcref tcref | _ -> false) let isVoidTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref,_) -> tyconRefEq g g.system_Void_tcref tcref | _ -> false) let isILAppTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref,_) -> tcref.IsILTycon | _ -> false) +let isNativePtrTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref,_) -> tyconRefEq g g.nativeptr_tcr tcref | _ -> false) let isByrefTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref,_) -> tyconRefEq g g.byref_tcr tcref | _ -> false) let isByrefLikeTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref,_) -> isByrefLikeTyconRef g tcref | _ -> false) #if EXTENSIONTYPING @@ -2653,6 +2654,7 @@ let TyconRefHasAttribute g m attribSpec tcref = //------------------------------------------------------------------------- let destByrefTy g ty = if isByrefTy g ty then List.head (argsOfAppTy g ty) else failwith "destByrefTy: not a byref type" +let destNativePtrTy g ty = if isNativePtrTy g ty then List.head (argsOfAppTy g ty) else failwith "destNativePtrTy: not a native ptr type" let isRefCellTy g ty = match tryDestAppTy g ty with diff --git a/src/fsharp/TastOps.fsi b/src/fsharp/TastOps.fsi index 58b602d92cb..536d04719f7 100755 --- a/src/fsharp/TastOps.fsi +++ b/src/fsharp/TastOps.fsi @@ -909,7 +909,7 @@ val ExprStats : Expr -> string // Make some common types //------------------------------------------------------------------------- -val mkNativePtrType : TcGlobals -> TType -> TType +val mkNativePtrTy : TcGlobals -> TType -> TType val mkArrayType : TcGlobals -> TType -> TType val isOptionTy : TcGlobals -> TType -> bool val destOptionTy : TcGlobals -> TType -> TType @@ -1258,7 +1258,9 @@ val mkCompilerGeneratedAttr : TcGlobals -> int -> ILAtt //------------------------------------------------------------------------- val isByrefTy : TcGlobals -> TType -> bool +val isNativePtrTy : TcGlobals -> TType -> bool val destByrefTy : TcGlobals -> TType -> TType +val destNativePtrTy : TcGlobals -> TType -> TType val isByrefLikeTyconRef : TcGlobals -> TyconRef -> bool val isByrefLikeTy : TcGlobals -> TType -> bool diff --git a/src/fsharp/TcGlobals.fs b/src/fsharp/TcGlobals.fs index a27c50ca268..1fa4b0a7ee2 100755 --- a/src/fsharp/TcGlobals.fs +++ b/src/fsharp/TcGlobals.fs @@ -668,7 +668,7 @@ let mkTcGlobals (compilingFslib,sysCcu,ilg,fslibCcu,directoryToResolveRelativePa (* local helpers to build value infos *) let mkNullableTy ty = TType_app(nullable_tcr, [ty]) let mkByrefTy ty = TType_app(byref_tcr, [ty]) - let mkNativePtrType ty = TType_app(nativeptr_tcr, [ty]) + let mkNativePtrTy ty = TType_app(nativeptr_tcr, [ty]) let mkFunTy d r = TType_fun (d,r) let (-->) d r = mkFunTy d r let mkIteratedFunTy dl r = List.foldBack (-->) dl r @@ -847,7 +847,7 @@ let mkTcGlobals (compilingFslib,sysCcu,ilg,fslibCcu,directoryToResolveRelativePa let and_info = makeIntrinsicValRef(fslib_MFIntrinsicOperators_nleref, CompileOpName "&" ,None ,None ,[], mk_rel_sig bool_ty) let addrof_info = makeIntrinsicValRef(fslib_MFIntrinsicOperators_nleref, CompileOpName "~&" ,None ,None ,[vara], ([[varaTy]], mkByrefTy varaTy)) - let addrof2_info = makeIntrinsicValRef(fslib_MFIntrinsicOperators_nleref, CompileOpName "~&&" ,None ,None ,[vara], ([[varaTy]], mkNativePtrType varaTy)) + let addrof2_info = makeIntrinsicValRef(fslib_MFIntrinsicOperators_nleref, CompileOpName "~&&" ,None ,None ,[vara], ([[varaTy]], mkNativePtrTy varaTy)) let and2_info = makeIntrinsicValRef(fslib_MFIntrinsicOperators_nleref, CompileOpName "&&" ,None ,None ,[], mk_rel_sig bool_ty) let or_info = makeIntrinsicValRef(fslib_MFIntrinsicOperators_nleref, "or" ,None ,Some "Or" ,[], mk_rel_sig bool_ty) let or2_info = makeIntrinsicValRef(fslib_MFIntrinsicOperators_nleref, CompileOpName "||" ,None ,None ,[], mk_rel_sig bool_ty) diff --git a/src/fsharp/TypeChecker.fs b/src/fsharp/TypeChecker.fs index d0eea1147a0..a7575932f20 100755 --- a/src/fsharp/TypeChecker.fs +++ b/src/fsharp/TypeChecker.fs @@ -9786,13 +9786,16 @@ and TcStaticOptimizationConstraint cenv env tpenv c = let tp',tpenv = TcTypar cenv env NewTyparsOK tpenv tp TTyconIsStruct(mkTyparTy tp'),tpenv +/// Emit a conv.i instruction +and mkConvToNativeInt g e m = Expr.Op (TOp.ILAsm ([ AI_conv ILBasicType.DT_I], [ g.nativeint_ty ]),[],[e],m) /// Fix up the r.h.s. of a 'use x = fixed expr' -and TcAndBuildFixedExpr cenv env (overallPatTy, rhsExprChecked, overallExprTy, mBinding) = +and TcAndBuildFixedExpr cenv env (overallPatTy, fixedExpr, overallExprTy, mBinding) = + warning(PossibleUnverifiableCode(mBinding)) match overallExprTy with | ty when isByrefTy cenv.g ty -> let okByRef = - match stripExpr rhsExprChecked with + match stripExpr fixedExpr with | Expr.Op (op,tyargs,args,_) -> match op,tyargs,args with | TOp.ValFieldGetAddr rfref,_,[_] -> not rfref.Tycon.IsStructOrEnumTycon @@ -9803,40 +9806,59 @@ and TcAndBuildFixedExpr cenv env (overallPatTy, rhsExprChecked, overallExprTy, m | _ -> false if not okByRef then error(Error(FSComp.SR.tcFixedNotAllowed(),mBinding)) - UnifyTypes cenv env mBinding overallExprTy overallPatTy - rhsExprChecked - + + let elemTy = destByrefTy cenv.g overallExprTy + UnifyTypes cenv env mBinding (mkNativePtrTy cenv.g elemTy) overallPatTy + mkCompGenLetIn mBinding "pinnedByref" ty fixedExpr (fun (v,ve) -> + v.SetIsFixed() + mkConvToNativeInt cenv.g ve mBinding) + | ty when isStringTy cenv.g ty -> - let charPtrTy = (mkNativePtrType cenv.g cenv.g.char_ty) + let charPtrTy = mkNativePtrTy cenv.g cenv.g.char_ty UnifyTypes cenv env mBinding charPtrTy overallPatTy - let stringObjAsPtr = Expr.Op (TOp.ILAsm ([ AI_conv ILBasicType.DT_I], [ charPtrTy ]),[],[rhsExprChecked],mBinding) - // For strings 'use x = fixed str', we actually generate two pinned variables - // let pinned x = - // let pinned tmp = (char*) str - // tmp + get_OffsettoStringData() - // This is the easiest codegen for F# - - // Store the string into a pinned local - mkCompGenLetIn mBinding "pinnedString" charPtrTy stringObjAsPtr (fun (v,ve) -> + // + // let ptr : nativeptr = + // let pinned s = str + // (nativeptr)s + get_OffsettoStringData() + + mkCompGenLetIn mBinding "pinnedString" cenv.g.string_ty fixedExpr (fun (v,ve) -> v.SetIsFixed() let addrOffset = BuildOffsetToStringData cenv env mBinding - let stringPlusOffset = Expr.Op (TOp.ILAsm ([ AI_add ], [ charPtrTy ]),[],[ve; addrOffset],mBinding) + let stringAsNativeInt = mkConvToNativeInt cenv.g ve mBinding + let plusOffset = Expr.Op (TOp.ILAsm ([ AI_add ], [ cenv.g.nativeint_ty ]),[],[stringAsNativeInt; addrOffset],mBinding) // check for non-null - mkNullTest cenv.g mBinding ve stringPlusOffset ve) + mkNullTest cenv.g mBinding ve plusOffset ve) | ty when isArray1DTy cenv.g ty -> let elemTy = destArrayTy cenv.g overallExprTy - let elemPtrTy = mkByrefTy cenv.g elemTy + let elemPtrTy = mkNativePtrTy cenv.g elemTy UnifyTypes cenv env mBinding elemPtrTy overallPatTy - // Store the array into a local - mkCompGenLetIn mBinding "tmpArray" overallExprTy rhsExprChecked (fun (_,ve) -> + + // let ptr : nativeptr = + // let tmpArray : elem[] = arr + // if nonNull tmpArray then + // if tmpArray.Length <> 0 then + // let pinned tmpArrayByref : byref = &arr.[0] + // (nativeint) tmpArrayByref + // else + // (nativeint) 0 + // else + // (nativeint) 0 + // + mkCompGenLetIn mBinding "tmpArray" overallExprTy fixedExpr (fun (_,ve) -> // This is &arr.[0] let elemZeroAddress = mkArrayElemAddress cenv.g (ILReadonly.NormalAddress,false,ILArrayShape.SingleDimensional,elemTy,ve,mkInt32 cenv.g mBinding 0,mBinding) // check for non-null and non-empty - let zero = Expr.Op (TOp.ILAsm ([ AI_conv ILBasicType.DT_U], [ cenv.g.nativeint_ty ]),[],[mkInt32 cenv.g mBinding 0],mBinding) + let zero = mkConvToNativeInt cenv.g (mkInt32 cenv.g mBinding 0) mBinding // This is arr.Length let arrayLengthExpr = mkCallArrayLength cenv.g mBinding elemTy ve - mkNullTest cenv.g mBinding ve (mkNullTest cenv.g mBinding arrayLengthExpr elemZeroAddress zero) zero ) + mkNullTest cenv.g mBinding ve + (mkNullTest cenv.g mBinding arrayLengthExpr + (mkCompGenLetIn mBinding "pinnedByref" (mkByrefTy cenv.g elemTy) elemZeroAddress (fun (v,ve) -> + v.SetIsFixed() + (mkConvToNativeInt cenv.g ve mBinding))) + zero) + zero) | _ -> error(Error(FSComp.SR.tcFixedNotAllowed(),mBinding)) @@ -10314,8 +10336,6 @@ and TcLetBinding cenv isUse env containerInfo declKind tpenv (binds,bindsm,scope | TPat_as (pat1,PBind(v,TypeScheme(generalizedTypars',_)),_) when List.lengthsEqAndForall2 typarRefEq generalizedTypars generalizedTypars' -> - if isFixed then - v.SetIsFixed() v, pat1 | _ when mustinline(inlineFlag) -> error(Error(FSComp.SR.tcInvalidInlineSpecification(),m)) diff --git a/src/fsharp/import.fs b/src/fsharp/import.fs index 974c7e93d61..7f29cacc8ee 100644 --- a/src/fsharp/import.fs +++ b/src/fsharp/import.fs @@ -162,7 +162,7 @@ let rec ImportILType (env:ImportMap) m tinst typ = ImportTyconRefApp env tcref inst | ILType.Byref ty -> mkByrefTy env.g (ImportILType env m tinst ty) - | ILType.Ptr ty -> mkNativePtrType env.g (ImportILType env m tinst ty) + | ILType.Ptr ty -> mkNativePtrTy env.g (ImportILType env m tinst ty) | ILType.FunctionPointer _ -> env.g.nativeint_ty (* failwith "cannot import this kind of type (ptr, fptr)" *) | ILType.Modified(_,_,ty) -> // All custom modifiers are ignored @@ -244,7 +244,7 @@ let rec ImportProvidedType (env:ImportMap) (m:range) (* (tinst:TypeInst) *) (st: mkByrefTy g elemTy elif st.PUntaint((fun st -> st.IsPointer),m) then let elemTy = (ImportProvidedType env m (* tinst *) (st.PApply((fun st -> st.GetElementType()),m))) - mkNativePtrType g elemTy + mkNativePtrTy g elemTy else // REVIEW: Extension type could try to be its own generic arg (or there could be a type loop) diff --git a/tests/fsharp/core/fsiAndModifiers/test.fsx b/tests/fsharp/core/fsiAndModifiers/test.fsx index 39acf7397aa..16b3d33aee0 100644 --- a/tests/fsharp/core/fsiAndModifiers/test.fsx +++ b/tests/fsharp/core/fsiAndModifiers/test.fsx @@ -86,6 +86,57 @@ module TestPack4 = printfn "got %A" got if got <> expected then fail (sprintf "TestPack4: got %A, expected %A" got expected) +module PinTests = + open FSharp.NativeInterop + // Assume that the following class exists. + + type Point = { mutable x : int; mutable y : int } + + let pinObject() = + let point = { x = 1; y = 2 } + use p1 = fixed &point.x // note, fixed is a keyword and would be highlighted + NativePtr.get p1 0 + NativePtr.get p1 1 + + let pinRef() = + let point = ref 17 + use p1 = fixed &point.contents // note, fixed is a keyword and would be highlighted + NativePtr.read p1 + NativePtr.read p1 + + let pinArray1() = + let arr = [| 0.0; 1.5; 2.3; 3.4; 4.0; 5.9 |] + use p1 = fixed arr + NativePtr.get p1 0 + NativePtr.get p1 1 + + let pinArray2() = + let arr = [| 0.0; 1.5; 2.3; 3.4; 4.0; 5.9 |] + // You can initialize a pointer by using the address of a variable. + use p = fixed &arr.[0] + NativePtr.get p 0 + NativePtr.get p 1 + + let pinNullArray() = + let arr : int[] = null + use p1 = fixed arr + 4 + + let pinEmptyArray() = + let arr : int[] = [| |] + use p1 = fixed arr + 76 + + let pinString() = + let str = "Hello World" + // The following assignment initializes p by using a string. + use pChar = fixed str + NativePtr.get pChar 0, NativePtr.get pChar 1 + + if pinObject() <> 3 then fail "FAILED: pinObject" + if pinRef() <> 34 then fail "FAILED: pinObject" + if pinArray1() <> 1.5 then fail "FAILED: pinArray1" + if pinArray2() <> 1.5 then fail "FAILED: pinArray2" + if pinNullArray() <> 4 then fail "FAILED: pinNullArray" + if pinEmptyArray() <> 76 then fail "FAILED: pinEmptyArray" + if pinString() <> ('H', 'e') then fail "FAILED: pinString" + if errors.IsEmpty then System.IO.File.WriteAllText("test.ok", "") diff --git a/tests/fsharp/core/pinvoke/test.fsx b/tests/fsharp/core/pinvoke/test.fsx index 3d63185df3b..3d8a4831c58 100644 --- a/tests/fsharp/core/pinvoke/test.fsx +++ b/tests/fsharp/core/pinvoke/test.fsx @@ -1,5 +1,5 @@ // #Conformance #Interop #PInvoke #Structs -#light + #nowarn "9" open System @@ -37,12 +37,11 @@ let pinned (obj: obj) f = // (typeof<'a>) == (typeof) or // etc. -type PinBox<'a> = { v : obj } - with +type PinBox<'a> = + { v : obj } static member Create(x) = { v = box(x) } member x.Value = (unbox x.v : 'a) member x.Pin(f) = pinned(x.v) f - end let card_init () = let width = PinBox<_>.Create(300) in @@ -135,7 +134,7 @@ let example1() = -module GetSystemTimeTest = begin +module GetSystemTimeTest = open System open System.Runtime.InteropServices @@ -166,9 +165,8 @@ module GetSystemTimeTest = begin (int32 sysTime.wMinute ) (int32 sysTime.wSecond) -end -module MemoryStatusTest = begin +module MemoryStatusTest = open System open System.Runtime.InteropServices @@ -204,10 +202,9 @@ module MemoryStatusTest = begin printf "%A\n" mex main() -end -module MemoryStatusTest2 = begin +module MemoryStatusTest2 = open System open System.Runtime.InteropServices @@ -243,5 +240,4 @@ module MemoryStatusTest2 = begin printf "%A\n" mex main() -end diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/env.lst b/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/env.lst index c55c1dc11ef..fb6a949b63a 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/env.lst +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/env.lst @@ -34,13 +34,13 @@ SOURCE=TestFunction15.fs SCFLAGS="-g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd TestFunction15.exe" # TestFunction15.fs SOURCE=TestFunction18.fs SCFLAGS="-g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd TestFunction18.exe" # TestFunction18.fs - SOURCE=Testfunction22.fs SCFLAGS="-g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd TestFunction22.exe" # TestFunction22.fs - SOURCE=Testfunction22b.fs SCFLAGS="-g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd TestFunction22b.exe" # TestFunction22b.fs - SOURCE=Testfunction22c.fs SCFLAGS="-g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd TestFunction22c.exe" # TestFunction22c.fs - SOURCE=Testfunction22d.fs SCFLAGS="-g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd TestFunction22d.exe" # TestFunction22d.fs - SOURCE=Testfunction22e.fs SCFLAGS="-g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd TestFunction22e.exe" # TestFunction22e.fs - SOURCE=Testfunction22f.fs SCFLAGS="-g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd TestFunction22f.exe" # TestFunction22f.fs - SOURCE=Testfunction22g.fs SCFLAGS="-g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd TestFunction22g.exe" # TestFunction22g.fs - - SOURCE=Testfunction22h.fs SCFLAGS="-g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd TestFunction22h.exe NetFx40" # TestFunction22h.fs - NetFx40 - SOURCE=Testfunction24.fs SCFLAGS="-a -g --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd TestFunction24.dll NetFx40" # TestFunction24.fs - NetFx40 + SOURCE=TestFunction22.fs SCFLAGS="-g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd TestFunction22.exe" # TestFunction22.fs + SOURCE=TestFunction22b.fs SCFLAGS="-g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd TestFunction22b.exe" # TestFunction22b.fs + SOURCE=TestFunction22c.fs SCFLAGS="-g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd TestFunction22c.exe" # TestFunction22c.fs + SOURCE=TestFunction22d.fs SCFLAGS="-g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd TestFunction22d.exe" # TestFunction22d.fs + SOURCE=TestFunction22e.fs SCFLAGS="-g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd TestFunction22e.exe" # TestFunction22e.fs + SOURCE=TestFunction22f.fs SCFLAGS="-g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd TestFunction22f.exe" # TestFunction22f.fs + SOURCE=TestFunction22g.fs SCFLAGS="-g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd TestFunction22g.exe" # TestFunction22g.fs + + SOURCE=TestFunction22h.fs SCFLAGS="-g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd TestFunction22h.exe NetFx40" # TestFunction22h.fs - NetFx40 + SOURCE=TestFunction24.fs SCFLAGS="-g --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd TestFunction24.exe NetFx40" # TestFunction24.fs - NetFx40 From f1c8a1069abc44634a7d71682f0ba03aafef1108 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Tue, 21 Jun 2016 15:52:11 +0100 Subject: [PATCH 073/129] update tests --- .../TestFunction24.il.netfx4.bsl | 961 +++++++++++++++++- .../EmittedIL/TestFunctions/TestFunction25.fs | 32 + .../TestFunction25.il.netfx4.bsl | 772 ++++++++++++++ .../EmittedIL/TestFunctions/Testfunction24.fs | 15 +- .../CodeGen/EmittedIL/TestFunctions/env.lst | 1 + 5 files changed, 1773 insertions(+), 8 deletions(-) create mode 100644 tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/TestFunction25.fs create mode 100644 tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/TestFunction25.il.netfx4.bsl diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/TestFunction24.il.netfx4.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/TestFunction24.il.netfx4.bsl index 494be65e9e1..171d1faa640 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/TestFunction24.il.netfx4.bsl +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/TestFunction24.il.netfx4.bsl @@ -1,4 +1,963 @@ -// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.81.0 +// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0 // Copyright (c) Microsoft Corporation. All rights reserved. + + +// Metadata version: v4.0.30319 +.assembly extern mscorlib +{ + .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. + .ver 4:0:0:0 +} +.assembly extern FSharp.Core +{ + .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....: + .ver 4:4:1:0 +} +.assembly TestFunction24 +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + // --- The following custom attribute is added automatically, do not uncomment ------- + // .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 00 01 00 00 00 00 ) + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.mresource public FSharpSignatureData.TestFunction24 +{ + // Offset: 0x00000000 Length: 0x0000075B + // WARNING: managed resource file FSharpSignatureData.TestFunction24 created +} +.mresource public FSharpOptimizationData.TestFunction24 +{ + // Offset: 0x00000760 Length: 0x00000228 + // WARNING: managed resource file FSharpOptimizationData.TestFunction24 created +} +.module TestFunction24.exe +// MVID: {5769535C-A643-4587-A745-03835C536957} +.imagebase 0x00400000 +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 // WINDOWS_CUI +.corflags 0x00000001 // ILONLY +// Image base: 0x00890000 + + +// =============== CLASS MEMBERS DECLARATION =================== + +.class public abstract auto ansi sealed TestFunction24 + extends [mscorlib]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable sealed nested public Point + extends [mscorlib]System.Object + implements class [mscorlib]System.IEquatable`1, + [mscorlib]System.Collections.IStructuralEquatable, + class [mscorlib]System.IComparable`1, + [mscorlib]System.IComparable, + [mscorlib]System.Collections.IStructuralComparable + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field public int32 x@ + .custom instance void [mscorlib]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field public int32 y@ + .custom instance void [mscorlib]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public hidebysig specialname + instance int32 get_x() cil managed + { + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld int32 TestFunction24/Point::x@ + IL_0006: ret + } // end of method Point::get_x + + .method public hidebysig specialname + instance int32 get_y() cil managed + { + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld int32 TestFunction24/Point::y@ + IL_0006: ret + } // end of method Point::get_y + + .method public hidebysig specialname + instance void set_x(int32 'value') cil managed + { + // Code size 8 (0x8) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld int32 TestFunction24/Point::x@ + IL_0007: ret + } // end of method Point::set_x + + .method public hidebysig specialname + instance void set_y(int32 'value') cil managed + { + // Code size 8 (0x8) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld int32 TestFunction24/Point::y@ + IL_0007: ret + } // end of method Point::set_y + + .method public specialname rtspecialname + instance void .ctor(int32 x, + int32 y) cil managed + { + // Code size 21 (0x15) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld int32 TestFunction24/Point::x@ + IL_000d: ldarg.0 + IL_000e: ldarg.2 + IL_000f: stfld int32 TestFunction24/Point::y@ + IL_0014: ret + } // end of method Point::.ctor + + .method public hidebysig virtual final + instance int32 CompareTo(class TestFunction24/Point obj) cil managed + { + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 143 (0x8f) + .maxstack 4 + .locals init (int32 V_0, + class [mscorlib]System.Collections.IComparer V_1, + int32 V_2, + int32 V_3, + class [mscorlib]System.Collections.IComparer V_4, + int32 V_5, + int32 V_6) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: ldnull + IL_0003: cgt.un + IL_0005: brfalse.s IL_0009 + + IL_0007: br.s IL_000e + + IL_0009: br IL_0081 + + IL_000e: ldarg.1 + IL_000f: ldnull + IL_0010: cgt.un + IL_0012: brfalse.s IL_0016 + + IL_0014: br.s IL_001b + + IL_0016: br IL_007f + + IL_001b: call class [mscorlib]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_0020: stloc.1 + IL_0021: ldarg.0 + IL_0022: ldfld int32 TestFunction24/Point::x@ + IL_0027: stloc.2 + IL_0028: ldarg.1 + IL_0029: ldfld int32 TestFunction24/Point::x@ + IL_002e: stloc.3 + IL_002f: ldloc.2 + IL_0030: ldloc.3 + IL_0031: bge.s IL_0035 + + IL_0033: br.s IL_0037 + + IL_0035: br.s IL_003b + + IL_0037: ldc.i4.m1 + IL_0038: nop + IL_0039: br.s IL_0040 + + IL_003b: ldloc.2 + IL_003c: ldloc.3 + IL_003d: cgt + IL_003f: nop + IL_0040: stloc.0 + IL_0041: ldloc.0 + IL_0042: ldc.i4.0 + IL_0043: bge.s IL_0047 + + IL_0045: br.s IL_0049 + + IL_0047: br.s IL_004b + + IL_0049: ldloc.0 + IL_004a: ret + + IL_004b: ldloc.0 + IL_004c: ldc.i4.0 + IL_004d: ble.s IL_0051 + + IL_004f: br.s IL_0053 + + IL_0051: br.s IL_0055 + + IL_0053: ldloc.0 + IL_0054: ret + + IL_0055: call class [mscorlib]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_005a: stloc.s V_4 + IL_005c: ldarg.0 + IL_005d: ldfld int32 TestFunction24/Point::y@ + IL_0062: stloc.s V_5 + IL_0064: ldarg.1 + IL_0065: ldfld int32 TestFunction24/Point::y@ + IL_006a: stloc.s V_6 + IL_006c: ldloc.s V_5 + IL_006e: ldloc.s V_6 + IL_0070: bge.s IL_0074 + + IL_0072: br.s IL_0076 + + IL_0074: br.s IL_0078 + + IL_0076: ldc.i4.m1 + IL_0077: ret + + IL_0078: ldloc.s V_5 + IL_007a: ldloc.s V_6 + IL_007c: cgt + IL_007e: ret + + IL_007f: ldc.i4.1 + IL_0080: ret + + IL_0081: ldarg.1 + IL_0082: ldnull + IL_0083: cgt.un + IL_0085: brfalse.s IL_0089 + + IL_0087: br.s IL_008b + + IL_0089: br.s IL_008d + + IL_008b: ldc.i4.m1 + IL_008c: ret + + IL_008d: ldc.i4.0 + IL_008e: ret + } // end of method Point::CompareTo + + .method public hidebysig virtual final + instance int32 CompareTo(object obj) cil managed + { + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 14 (0xe) + .maxstack 8 + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: ldarg.1 + IL_0003: unbox.any TestFunction24/Point + IL_0008: callvirt instance int32 TestFunction24/Point::CompareTo(class TestFunction24/Point) + IL_000d: ret + } // end of method Point::CompareTo + + .method public hidebysig virtual final + instance int32 CompareTo(object obj, + class [mscorlib]System.Collections.IComparer comp) cil managed + { + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 160 (0xa0) + .maxstack 4 + .locals init ([0] class TestFunction24/Point V_0, + [1] class TestFunction24/Point V_1, + [2] int32 V_2, + [3] class [mscorlib]System.Collections.IComparer V_3, + [4] int32 V_4, + [5] int32 V_5, + [6] class [mscorlib]System.Collections.IComparer V_6, + [7] int32 V_7, + [8] int32 V_8) + IL_0000: nop + IL_0001: ldarg.1 + IL_0002: unbox.any TestFunction24/Point + IL_0007: stloc.0 + IL_0008: ldloc.0 + IL_0009: stloc.1 + IL_000a: ldarg.0 + IL_000b: ldnull + IL_000c: cgt.un + IL_000e: brfalse.s IL_0012 + + IL_0010: br.s IL_0017 + + IL_0012: br IL_008d + + IL_0017: ldarg.1 + IL_0018: unbox.any TestFunction24/Point + IL_001d: ldnull + IL_001e: cgt.un + IL_0020: brfalse.s IL_0024 + + IL_0022: br.s IL_0029 + + IL_0024: br IL_008b + + IL_0029: ldarg.2 + IL_002a: stloc.3 + IL_002b: ldarg.0 + IL_002c: ldfld int32 TestFunction24/Point::x@ + IL_0031: stloc.s V_4 + IL_0033: ldloc.1 + IL_0034: ldfld int32 TestFunction24/Point::x@ + IL_0039: stloc.s V_5 + IL_003b: ldloc.s V_4 + IL_003d: ldloc.s V_5 + IL_003f: bge.s IL_0043 + + IL_0041: br.s IL_0045 + + IL_0043: br.s IL_0049 + + IL_0045: ldc.i4.m1 + IL_0046: nop + IL_0047: br.s IL_0050 + + IL_0049: ldloc.s V_4 + IL_004b: ldloc.s V_5 + IL_004d: cgt + IL_004f: nop + IL_0050: stloc.2 + IL_0051: ldloc.2 + IL_0052: ldc.i4.0 + IL_0053: bge.s IL_0057 + + IL_0055: br.s IL_0059 + + IL_0057: br.s IL_005b + + IL_0059: ldloc.2 + IL_005a: ret + + IL_005b: ldloc.2 + IL_005c: ldc.i4.0 + IL_005d: ble.s IL_0061 + + IL_005f: br.s IL_0063 + + IL_0061: br.s IL_0065 + + IL_0063: ldloc.2 + IL_0064: ret + + IL_0065: ldarg.2 + IL_0066: stloc.s V_6 + IL_0068: ldarg.0 + IL_0069: ldfld int32 TestFunction24/Point::y@ + IL_006e: stloc.s V_7 + IL_0070: ldloc.1 + IL_0071: ldfld int32 TestFunction24/Point::y@ + IL_0076: stloc.s V_8 + IL_0078: ldloc.s V_7 + IL_007a: ldloc.s V_8 + IL_007c: bge.s IL_0080 + + IL_007e: br.s IL_0082 + + IL_0080: br.s IL_0084 + + IL_0082: ldc.i4.m1 + IL_0083: ret + + IL_0084: ldloc.s V_7 + IL_0086: ldloc.s V_8 + IL_0088: cgt + IL_008a: ret + + IL_008b: ldc.i4.1 + IL_008c: ret + + IL_008d: ldarg.1 + IL_008e: unbox.any TestFunction24/Point + IL_0093: ldnull + IL_0094: cgt.un + IL_0096: brfalse.s IL_009a + + IL_0098: br.s IL_009c + + IL_009a: br.s IL_009e + + IL_009c: ldc.i4.m1 + IL_009d: ret + + IL_009e: ldc.i4.0 + IL_009f: ret + } // end of method Point::CompareTo + + .method public hidebysig virtual final + instance int32 GetHashCode(class [mscorlib]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 63 (0x3f) + .maxstack 7 + .locals init (int32 V_0, + class [mscorlib]System.Collections.IEqualityComparer V_1, + class [mscorlib]System.Collections.IEqualityComparer V_2) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: ldnull + IL_0003: cgt.un + IL_0005: brfalse.s IL_0009 + + IL_0007: br.s IL_000b + + IL_0009: br.s IL_003d + + IL_000b: ldc.i4.0 + IL_000c: stloc.0 + IL_000d: ldc.i4 0x9e3779b9 + IL_0012: ldarg.1 + IL_0013: stloc.1 + IL_0014: ldarg.0 + IL_0015: ldfld int32 TestFunction24/Point::y@ + IL_001a: ldloc.0 + IL_001b: ldc.i4.6 + IL_001c: shl + IL_001d: ldloc.0 + IL_001e: ldc.i4.2 + IL_001f: shr + IL_0020: add + IL_0021: add + IL_0022: add + IL_0023: stloc.0 + IL_0024: ldc.i4 0x9e3779b9 + IL_0029: ldarg.1 + IL_002a: stloc.2 + IL_002b: ldarg.0 + IL_002c: ldfld int32 TestFunction24/Point::x@ + IL_0031: ldloc.0 + IL_0032: ldc.i4.6 + IL_0033: shl + IL_0034: ldloc.0 + IL_0035: ldc.i4.2 + IL_0036: shr + IL_0037: add + IL_0038: add + IL_0039: add + IL_003a: stloc.0 + IL_003b: ldloc.0 + IL_003c: ret + + IL_003d: ldc.i4.0 + IL_003e: ret + } // end of method Point::GetHashCode + + .method public hidebysig virtual final + instance int32 GetHashCode() cil managed + { + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 13 (0xd) + .maxstack 8 + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: call class [mscorlib]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() + IL_0007: callvirt instance int32 TestFunction24/Point::GetHashCode(class [mscorlib]System.Collections.IEqualityComparer) + IL_000c: ret + } // end of method Point::GetHashCode + + .method public hidebysig virtual final + instance bool Equals(object obj, + class [mscorlib]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 78 (0x4e) + .maxstack 4 + .locals init (class TestFunction24/Point V_0, + class TestFunction24/Point V_1, + class [mscorlib]System.Collections.IEqualityComparer V_2, + class [mscorlib]System.Collections.IEqualityComparer V_3) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: ldnull + IL_0003: cgt.un + IL_0005: brfalse.s IL_0009 + + IL_0007: br.s IL_000b + + IL_0009: br.s IL_0046 + + IL_000b: ldarg.1 + IL_000c: isinst TestFunction24/Point + IL_0011: stloc.0 + IL_0012: ldloc.0 + IL_0013: brfalse.s IL_0017 + + IL_0015: br.s IL_0019 + + IL_0017: br.s IL_0044 + + IL_0019: ldloc.0 + IL_001a: stloc.1 + IL_001b: ldarg.2 + IL_001c: stloc.2 + IL_001d: ldarg.0 + IL_001e: ldfld int32 TestFunction24/Point::x@ + IL_0023: ldloc.1 + IL_0024: ldfld int32 TestFunction24/Point::x@ + IL_0029: ceq + IL_002b: brfalse.s IL_002f + + IL_002d: br.s IL_0031 + + IL_002f: br.s IL_0042 + + IL_0031: ldarg.2 + IL_0032: stloc.3 + IL_0033: ldarg.0 + IL_0034: ldfld int32 TestFunction24/Point::y@ + IL_0039: ldloc.1 + IL_003a: ldfld int32 TestFunction24/Point::y@ + IL_003f: ceq + IL_0041: ret + + IL_0042: ldc.i4.0 + IL_0043: ret + + IL_0044: ldc.i4.0 + IL_0045: ret + + IL_0046: ldarg.1 + IL_0047: ldnull + IL_0048: cgt.un + IL_004a: ldc.i4.0 + IL_004b: ceq + IL_004d: ret + } // end of method Point::Equals + + .method public hidebysig virtual final + instance bool Equals(class TestFunction24/Point obj) cil managed + { + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 66 (0x42) + .maxstack 4 + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: ldnull + IL_0003: cgt.un + IL_0005: brfalse.s IL_0009 + + IL_0007: br.s IL_000b + + IL_0009: br.s IL_003a + + IL_000b: ldarg.1 + IL_000c: ldnull + IL_000d: cgt.un + IL_000f: brfalse.s IL_0013 + + IL_0011: br.s IL_0015 + + IL_0013: br.s IL_0038 + + IL_0015: ldarg.0 + IL_0016: ldfld int32 TestFunction24/Point::x@ + IL_001b: ldarg.1 + IL_001c: ldfld int32 TestFunction24/Point::x@ + IL_0021: bne.un.s IL_0025 + + IL_0023: br.s IL_0027 + + IL_0025: br.s IL_0036 + + IL_0027: ldarg.0 + IL_0028: ldfld int32 TestFunction24/Point::y@ + IL_002d: ldarg.1 + IL_002e: ldfld int32 TestFunction24/Point::y@ + IL_0033: ceq + IL_0035: ret + + IL_0036: ldc.i4.0 + IL_0037: ret + + IL_0038: ldc.i4.0 + IL_0039: ret + + IL_003a: ldarg.1 + IL_003b: ldnull + IL_003c: cgt.un + IL_003e: ldc.i4.0 + IL_003f: ceq + IL_0041: ret + } // end of method Point::Equals + + .method public hidebysig virtual final + instance bool Equals(object obj) cil managed + { + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 25 (0x19) + .maxstack 4 + .locals init (class TestFunction24/Point V_0) + IL_0000: nop + IL_0001: ldarg.1 + IL_0002: isinst TestFunction24/Point + IL_0007: stloc.0 + IL_0008: ldloc.0 + IL_0009: brfalse.s IL_000d + + IL_000b: br.s IL_000f + + IL_000d: br.s IL_0017 + + IL_000f: ldarg.0 + IL_0010: ldloc.0 + IL_0011: callvirt instance bool TestFunction24/Point::Equals(class TestFunction24/Point) + IL_0016: ret + + IL_0017: ldc.i4.0 + IL_0018: ret + } // end of method Point::Equals + + .property instance int32 x() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .set instance void TestFunction24/Point::set_x(int32) + .get instance int32 TestFunction24/Point::get_x() + } // end of property Point::x + .property instance int32 y() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .set instance void TestFunction24/Point::set_y(int32) + .get instance int32 TestFunction24/Point::get_y() + } // end of property Point::y + } // end of class Point + + .method public static int32 pinObject() cil managed + { + // Code size 67 (0x43) + .maxstack 6 + .locals init ([0] class TestFunction24/Point point, + [1] native int p1, + [2] int32& pinned V_2, + [3] native int V_3, + [4] int32 V_4, + [5] native int V_5, + [6] int32 V_6) + IL_0000: nop + IL_0001: ldc.i4.1 + IL_0002: ldc.i4.2 + IL_0003: newobj instance void TestFunction24/Point::.ctor(int32, + int32) + IL_0008: stloc.0 + IL_0009: ldloc.0 + IL_000a: ldflda int32 TestFunction24/Point::x@ + IL_000f: stloc.2 + IL_0010: ldloc.2 + IL_0011: conv.i + IL_0012: stloc.1 + IL_0013: ldloc.1 + IL_0014: stloc.3 + IL_0015: ldc.i4.0 + IL_0016: stloc.s V_4 + IL_0018: ldloc.3 + IL_0019: ldloc.s V_4 + IL_001b: conv.i + IL_001c: sizeof [mscorlib]System.Int32 + IL_0022: mul + IL_0023: add + IL_0024: ldobj [mscorlib]System.Int32 + IL_0029: ldloc.1 + IL_002a: stloc.s V_5 + IL_002c: ldc.i4.1 + IL_002d: stloc.s V_6 + IL_002f: ldloc.s V_5 + IL_0031: ldloc.s V_6 + IL_0033: conv.i + IL_0034: sizeof [mscorlib]System.Int32 + IL_003a: mul + IL_003b: add + IL_003c: ldobj [mscorlib]System.Int32 + IL_0041: add + IL_0042: ret + } // end of method TestFunction24::pinObject + + .method public static int32 pinRef() cil managed + { + // Code size 33 (0x21) + .maxstack 4 + .locals init ([0] class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1 point, + [1] native int p1, + [2] int32& pinned V_2) + IL_0000: nop + IL_0001: ldc.i4.s 17 + IL_0003: call class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1 [FSharp.Core]Microsoft.FSharp.Core.Operators::Ref(!!0) + IL_0008: stloc.0 + IL_0009: ldloc.0 + IL_000a: ldflda !0 class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1::contents@ + IL_000f: stloc.2 + IL_0010: ldloc.2 + IL_0011: conv.i + IL_0012: stloc.1 + IL_0013: ldloc.1 + IL_0014: ldobj [mscorlib]System.Int32 + IL_0019: ldloc.1 + IL_001a: ldobj [mscorlib]System.Int32 + IL_001f: add + IL_0020: ret + } // end of method TestFunction24::pinRef + + .method public static float64 pinArray1() cil managed + { + // Code size 197 (0xc5) + .maxstack 6 + .locals init ([0] float64[] arr, + [1] native int p1, + [2] float64[] V_2, + [3] float64& pinned V_3, + [4] native int V_4, + [5] int32 V_5, + [6] native int V_6, + [7] int32 V_7) + IL_0000: nop + IL_0001: ldc.i4.6 + IL_0002: newarr [mscorlib]System.Double + IL_0007: dup + IL_0008: ldc.i4.0 + IL_0009: ldc.r8 0.0 + IL_0012: stelem [mscorlib]System.Double + IL_0017: dup + IL_0018: ldc.i4.1 + IL_0019: ldc.r8 1.5 + IL_0022: stelem [mscorlib]System.Double + IL_0027: dup + IL_0028: ldc.i4.2 + IL_0029: ldc.r8 2.2999999999999998 + IL_0032: stelem [mscorlib]System.Double + IL_0037: dup + IL_0038: ldc.i4.3 + IL_0039: ldc.r8 3.3999999999999999 + IL_0042: stelem [mscorlib]System.Double + IL_0047: dup + IL_0048: ldc.i4.4 + IL_0049: ldc.r8 4. + IL_0052: stelem [mscorlib]System.Double + IL_0057: dup + IL_0058: ldc.i4.5 + IL_0059: ldc.r8 5.9000000000000004 + IL_0062: stelem [mscorlib]System.Double + IL_0067: stloc.0 + IL_0068: ldloc.0 + IL_0069: stloc.2 + IL_006a: ldloc.2 + IL_006b: brfalse.s IL_006f + + IL_006d: br.s IL_0071 + + IL_006f: br.s IL_008f + + IL_0071: ldloc.2 + IL_0072: call int32 [FSharp.Core]Microsoft.FSharp.Collections.ArrayModule::Length(!!0[]) + IL_0077: brfalse.s IL_007b + + IL_0079: br.s IL_007d + + IL_007b: br.s IL_008a + + IL_007d: ldloc.2 + IL_007e: ldc.i4.0 + IL_007f: ldelema [mscorlib]System.Double + IL_0084: stloc.3 + IL_0085: ldloc.3 + IL_0086: conv.i + IL_0087: nop + IL_0088: br.s IL_0092 + + IL_008a: ldc.i4.0 + IL_008b: conv.i + IL_008c: nop + IL_008d: br.s IL_0092 + + IL_008f: ldc.i4.0 + IL_0090: conv.i + IL_0091: nop + IL_0092: stloc.1 + IL_0093: ldloc.1 + IL_0094: stloc.s V_4 + IL_0096: ldc.i4.0 + IL_0097: stloc.s V_5 + IL_0099: ldloc.s V_4 + IL_009b: ldloc.s V_5 + IL_009d: conv.i + IL_009e: sizeof [mscorlib]System.Double + IL_00a4: mul + IL_00a5: add + IL_00a6: ldobj [mscorlib]System.Double + IL_00ab: ldloc.1 + IL_00ac: stloc.s V_6 + IL_00ae: ldc.i4.1 + IL_00af: stloc.s V_7 + IL_00b1: ldloc.s V_6 + IL_00b3: ldloc.s V_7 + IL_00b5: conv.i + IL_00b6: sizeof [mscorlib]System.Double + IL_00bc: mul + IL_00bd: add + IL_00be: ldobj [mscorlib]System.Double + IL_00c3: add + IL_00c4: ret + } // end of method TestFunction24::pinArray1 + + .method public static float64 pinArray2() cil managed + { + // Code size 163 (0xa3) + .maxstack 6 + .locals init ([0] float64[] arr, + [1] native int p, + [2] float64& pinned V_2, + [3] native int V_3, + [4] int32 V_4, + [5] native int V_5, + [6] int32 V_6) + IL_0000: nop + IL_0001: ldc.i4.6 + IL_0002: newarr [mscorlib]System.Double + IL_0007: dup + IL_0008: ldc.i4.0 + IL_0009: ldc.r8 0.0 + IL_0012: stelem [mscorlib]System.Double + IL_0017: dup + IL_0018: ldc.i4.1 + IL_0019: ldc.r8 1.5 + IL_0022: stelem [mscorlib]System.Double + IL_0027: dup + IL_0028: ldc.i4.2 + IL_0029: ldc.r8 2.2999999999999998 + IL_0032: stelem [mscorlib]System.Double + IL_0037: dup + IL_0038: ldc.i4.3 + IL_0039: ldc.r8 3.3999999999999999 + IL_0042: stelem [mscorlib]System.Double + IL_0047: dup + IL_0048: ldc.i4.4 + IL_0049: ldc.r8 4. + IL_0052: stelem [mscorlib]System.Double + IL_0057: dup + IL_0058: ldc.i4.5 + IL_0059: ldc.r8 5.9000000000000004 + IL_0062: stelem [mscorlib]System.Double + IL_0067: stloc.0 + IL_0068: ldloc.0 + IL_0069: ldc.i4.0 + IL_006a: ldelema [mscorlib]System.Double + IL_006f: stloc.2 + IL_0070: ldloc.2 + IL_0071: conv.i + IL_0072: stloc.1 + IL_0073: ldloc.1 + IL_0074: stloc.3 + IL_0075: ldc.i4.0 + IL_0076: stloc.s V_4 + IL_0078: ldloc.3 + IL_0079: ldloc.s V_4 + IL_007b: conv.i + IL_007c: sizeof [mscorlib]System.Double + IL_0082: mul + IL_0083: add + IL_0084: ldobj [mscorlib]System.Double + IL_0089: ldloc.1 + IL_008a: stloc.s V_5 + IL_008c: ldc.i4.1 + IL_008d: stloc.s V_6 + IL_008f: ldloc.s V_5 + IL_0091: ldloc.s V_6 + IL_0093: conv.i + IL_0094: sizeof [mscorlib]System.Double + IL_009a: mul + IL_009b: add + IL_009c: ldobj [mscorlib]System.Double + IL_00a1: add + IL_00a2: ret + } // end of method TestFunction24::pinArray2 + + .method public static class [mscorlib]System.Tuple`2 + pinString() cil managed + { + // Code size 82 (0x52) + .maxstack 6 + .locals init ([0] string str, + [1] native int pChar, + [2] string pinned V_2, + [3] native int V_3, + [4] int32 V_4, + [5] native int V_5, + [6] int32 V_6) + IL_0000: nop + IL_0001: ldstr "Hello World" + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: stloc.2 + IL_0009: ldloc.2 + IL_000a: brfalse.s IL_000e + + IL_000c: br.s IL_0010 + + IL_000e: br.s IL_001b + + IL_0010: ldloc.2 + IL_0011: conv.i + IL_0012: call int32 [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::get_OffsetToStringData() + IL_0017: add + IL_0018: nop + IL_0019: br.s IL_001d + + IL_001b: ldloc.2 + IL_001c: nop + IL_001d: stloc.1 + IL_001e: ldloc.1 + IL_001f: stloc.3 + IL_0020: ldc.i4.0 + IL_0021: stloc.s V_4 + IL_0023: ldloc.3 + IL_0024: ldloc.s V_4 + IL_0026: conv.i + IL_0027: sizeof [mscorlib]System.Char + IL_002d: mul + IL_002e: add + IL_002f: ldobj [mscorlib]System.Char + IL_0034: ldloc.1 + IL_0035: stloc.s V_5 + IL_0037: ldc.i4.1 + IL_0038: stloc.s V_6 + IL_003a: ldloc.s V_5 + IL_003c: ldloc.s V_6 + IL_003e: conv.i + IL_003f: sizeof [mscorlib]System.Char + IL_0045: mul + IL_0046: add + IL_0047: ldobj [mscorlib]System.Char + IL_004c: newobj instance void class [mscorlib]System.Tuple`2::.ctor(!0, + !1) + IL_0051: ret + } // end of method TestFunction24::pinString + +} // end of class TestFunction24 + +.class private abstract auto ansi sealed ''.$TestFunction24 + extends [mscorlib]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + // Code size 2 (0x2) + .maxstack 8 + IL_0000: nop + IL_0001: ret + } // end of method $TestFunction24::main@ + +} // end of class ''.$TestFunction24 + + +// ============================================================= + +// *********** DISASSEMBLY COMPLETE *********************** +// WARNING: Created Win32 resource file TestFunction24.il.netfx4.res diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/TestFunction25.fs b/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/TestFunction25.fs new file mode 100644 index 00000000000..eb297d2f636 --- /dev/null +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/TestFunction25.fs @@ -0,0 +1,32 @@ +open FSharp.NativeInterop +// Assume that the following class exists. + +type Point = { mutable x : int; mutable y : int } + +let pinObject() = + let point = { x = 1; y = 2 } + use p1 = fixed &point.x // note, fixed is a keyword and would be highlighted + NativePtr.get p1 0 + NativePtr.get p1 1 + +let pinRef() = + let point = ref 17 + use p1 = fixed &point.contents // note, fixed is a keyword and would be highlighted + NativePtr.read p1 + NativePtr.read p1 + +let pinArray1() = + let arr = [| 0.0; 1.5; 2.3; 3.4; 4.0; 5.9 |] + use p1 = fixed arr + NativePtr.get p1 0 + NativePtr.get p1 1 + +let pinArray2() = + let arr = [| 0.0; 1.5; 2.3; 3.4; 4.0; 5.9 |] + // You can initialize a pointer by using the address of a variable. + use p = fixed &arr.[0] + NativePtr.get p 0 + NativePtr.get p 1 + +let pinString() = + let str = "Hello World" + // The following assignment initializes p by using a string. + use pChar = fixed str + NativePtr.get pChar 0, NativePtr.get pChar 1 + diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/TestFunction25.il.netfx4.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/TestFunction25.il.netfx4.bsl new file mode 100644 index 00000000000..181c7175055 --- /dev/null +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/TestFunction25.il.netfx4.bsl @@ -0,0 +1,772 @@ + +// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0 +// Copyright (c) Microsoft Corporation. All rights reserved. + + + +// Metadata version: v4.0.30319 +.assembly extern mscorlib +{ + .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. + .ver 4:0:0:0 +} +.assembly extern FSharp.Core +{ + .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....: + .ver 4:4:1:0 +} +.assembly TestFunction25 +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + // --- The following custom attribute is added automatically, do not uncomment ------- + // .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 02 00 00 00 00 00 ) + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.mresource public FSharpSignatureData.TestFunction25 +{ + // Offset: 0x00000000 Length: 0x0000075B + // WARNING: managed resource file FSharpSignatureData.TestFunction25 created +} +.mresource public FSharpOptimizationData.TestFunction25 +{ + // Offset: 0x00000760 Length: 0x000003D2 + // WARNING: managed resource file FSharpOptimizationData.TestFunction25 created +} +.module TestFunction25.exe +// MVID: {5769538F-A643-4662-A745-03838F536957} +.imagebase 0x00400000 +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 // WINDOWS_CUI +.corflags 0x00000001 // ILONLY +// Image base: 0x01400000 + + +// =============== CLASS MEMBERS DECLARATION =================== + +.class public abstract auto ansi sealed TestFunction25 + extends [mscorlib]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable sealed nested public Point + extends [mscorlib]System.Object + implements class [mscorlib]System.IEquatable`1, + [mscorlib]System.Collections.IStructuralEquatable, + class [mscorlib]System.IComparable`1, + [mscorlib]System.IComparable, + [mscorlib]System.Collections.IStructuralComparable + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field public int32 x@ + .custom instance void [mscorlib]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field public int32 y@ + .custom instance void [mscorlib]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public hidebysig specialname + instance int32 get_x() cil managed + { + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld int32 TestFunction25/Point::x@ + IL_0006: ret + } // end of method Point::get_x + + .method public hidebysig specialname + instance int32 get_y() cil managed + { + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld int32 TestFunction25/Point::y@ + IL_0006: ret + } // end of method Point::get_y + + .method public hidebysig specialname + instance void set_x(int32 'value') cil managed + { + // Code size 8 (0x8) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld int32 TestFunction25/Point::x@ + IL_0007: ret + } // end of method Point::set_x + + .method public hidebysig specialname + instance void set_y(int32 'value') cil managed + { + // Code size 8 (0x8) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld int32 TestFunction25/Point::y@ + IL_0007: ret + } // end of method Point::set_y + + .method public specialname rtspecialname + instance void .ctor(int32 x, + int32 y) cil managed + { + // Code size 21 (0x15) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld int32 TestFunction25/Point::x@ + IL_000d: ldarg.0 + IL_000e: ldarg.2 + IL_000f: stfld int32 TestFunction25/Point::y@ + IL_0014: ret + } // end of method Point::.ctor + + .method public hidebysig virtual final + instance int32 CompareTo(class TestFunction25/Point obj) cil managed + { + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 102 (0x66) + .maxstack 4 + .locals init (int32 V_0, + class [mscorlib]System.Collections.IComparer V_1, + int32 V_2, + int32 V_3) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: ldnull + IL_0003: cgt.un + IL_0005: brfalse.s IL_005c + + IL_0007: ldarg.1 + IL_0008: ldnull + IL_0009: cgt.un + IL_000b: brfalse.s IL_005a + + IL_000d: call class [mscorlib]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_0012: stloc.1 + IL_0013: ldarg.0 + IL_0014: ldfld int32 TestFunction25/Point::x@ + IL_0019: stloc.2 + IL_001a: ldarg.1 + IL_001b: ldfld int32 TestFunction25/Point::x@ + IL_0020: stloc.3 + IL_0021: ldloc.2 + IL_0022: ldloc.3 + IL_0023: bge.s IL_0029 + + IL_0025: ldc.i4.m1 + IL_0026: nop + IL_0027: br.s IL_002e + + IL_0029: ldloc.2 + IL_002a: ldloc.3 + IL_002b: cgt + IL_002d: nop + IL_002e: stloc.0 + IL_002f: ldloc.0 + IL_0030: ldc.i4.0 + IL_0031: bge.s IL_0035 + + IL_0033: ldloc.0 + IL_0034: ret + + IL_0035: ldloc.0 + IL_0036: ldc.i4.0 + IL_0037: ble.s IL_003b + + IL_0039: ldloc.0 + IL_003a: ret + + IL_003b: call class [mscorlib]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() + IL_0040: stloc.1 + IL_0041: ldarg.0 + IL_0042: ldfld int32 TestFunction25/Point::y@ + IL_0047: stloc.2 + IL_0048: ldarg.1 + IL_0049: ldfld int32 TestFunction25/Point::y@ + IL_004e: stloc.3 + IL_004f: ldloc.2 + IL_0050: ldloc.3 + IL_0051: bge.s IL_0055 + + IL_0053: ldc.i4.m1 + IL_0054: ret + + IL_0055: ldloc.2 + IL_0056: ldloc.3 + IL_0057: cgt + IL_0059: ret + + IL_005a: ldc.i4.1 + IL_005b: ret + + IL_005c: ldarg.1 + IL_005d: ldnull + IL_005e: cgt.un + IL_0060: brfalse.s IL_0064 + + IL_0062: ldc.i4.m1 + IL_0063: ret + + IL_0064: ldc.i4.0 + IL_0065: ret + } // end of method Point::CompareTo + + .method public hidebysig virtual final + instance int32 CompareTo(object obj) cil managed + { + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 14 (0xe) + .maxstack 8 + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: ldarg.1 + IL_0003: unbox.any TestFunction25/Point + IL_0008: callvirt instance int32 TestFunction25/Point::CompareTo(class TestFunction25/Point) + IL_000d: ret + } // end of method Point::CompareTo + + .method public hidebysig virtual final + instance int32 CompareTo(object obj, + class [mscorlib]System.Collections.IComparer comp) cil managed + { + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 107 (0x6b) + .maxstack 4 + .locals init ([0] class TestFunction25/Point V_0, + [1] int32 V_1, + [2] int32 V_2, + [3] int32 V_3) + IL_0000: nop + IL_0001: ldarg.1 + IL_0002: unbox.any TestFunction25/Point + IL_0007: stloc.0 + IL_0008: ldarg.0 + IL_0009: ldnull + IL_000a: cgt.un + IL_000c: brfalse.s IL_005c + + IL_000e: ldarg.1 + IL_000f: unbox.any TestFunction25/Point + IL_0014: ldnull + IL_0015: cgt.un + IL_0017: brfalse.s IL_005a + + IL_0019: ldarg.0 + IL_001a: ldfld int32 TestFunction25/Point::x@ + IL_001f: stloc.2 + IL_0020: ldloc.0 + IL_0021: ldfld int32 TestFunction25/Point::x@ + IL_0026: stloc.3 + IL_0027: ldloc.2 + IL_0028: ldloc.3 + IL_0029: bge.s IL_002f + + IL_002b: ldc.i4.m1 + IL_002c: nop + IL_002d: br.s IL_0034 + + IL_002f: ldloc.2 + IL_0030: ldloc.3 + IL_0031: cgt + IL_0033: nop + IL_0034: stloc.1 + IL_0035: ldloc.1 + IL_0036: ldc.i4.0 + IL_0037: bge.s IL_003b + + IL_0039: ldloc.1 + IL_003a: ret + + IL_003b: ldloc.1 + IL_003c: ldc.i4.0 + IL_003d: ble.s IL_0041 + + IL_003f: ldloc.1 + IL_0040: ret + + IL_0041: ldarg.0 + IL_0042: ldfld int32 TestFunction25/Point::y@ + IL_0047: stloc.2 + IL_0048: ldloc.0 + IL_0049: ldfld int32 TestFunction25/Point::y@ + IL_004e: stloc.3 + IL_004f: ldloc.2 + IL_0050: ldloc.3 + IL_0051: bge.s IL_0055 + + IL_0053: ldc.i4.m1 + IL_0054: ret + + IL_0055: ldloc.2 + IL_0056: ldloc.3 + IL_0057: cgt + IL_0059: ret + + IL_005a: ldc.i4.1 + IL_005b: ret + + IL_005c: ldarg.1 + IL_005d: unbox.any TestFunction25/Point + IL_0062: ldnull + IL_0063: cgt.un + IL_0065: brfalse.s IL_0069 + + IL_0067: ldc.i4.m1 + IL_0068: ret + + IL_0069: ldc.i4.0 + IL_006a: ret + } // end of method Point::CompareTo + + .method public hidebysig virtual final + instance int32 GetHashCode(class [mscorlib]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 55 (0x37) + .maxstack 7 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: ldnull + IL_0003: cgt.un + IL_0005: brfalse.s IL_0035 + + IL_0007: ldc.i4.0 + IL_0008: stloc.0 + IL_0009: ldc.i4 0x9e3779b9 + IL_000e: ldarg.0 + IL_000f: ldfld int32 TestFunction25/Point::y@ + IL_0014: ldloc.0 + IL_0015: ldc.i4.6 + IL_0016: shl + IL_0017: ldloc.0 + IL_0018: ldc.i4.2 + IL_0019: shr + IL_001a: add + IL_001b: add + IL_001c: add + IL_001d: stloc.0 + IL_001e: ldc.i4 0x9e3779b9 + IL_0023: ldarg.0 + IL_0024: ldfld int32 TestFunction25/Point::x@ + IL_0029: ldloc.0 + IL_002a: ldc.i4.6 + IL_002b: shl + IL_002c: ldloc.0 + IL_002d: ldc.i4.2 + IL_002e: shr + IL_002f: add + IL_0030: add + IL_0031: add + IL_0032: stloc.0 + IL_0033: ldloc.0 + IL_0034: ret + + IL_0035: ldc.i4.0 + IL_0036: ret + } // end of method Point::GetHashCode + + .method public hidebysig virtual final + instance int32 GetHashCode() cil managed + { + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 13 (0xd) + .maxstack 8 + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: call class [mscorlib]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() + IL_0007: callvirt instance int32 TestFunction25/Point::GetHashCode(class [mscorlib]System.Collections.IEqualityComparer) + IL_000c: ret + } // end of method Point::GetHashCode + + .method public hidebysig virtual final + instance bool Equals(object obj, + class [mscorlib]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 58 (0x3a) + .maxstack 4 + .locals init (class TestFunction25/Point V_0) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: ldnull + IL_0003: cgt.un + IL_0005: brfalse.s IL_0032 + + IL_0007: ldarg.1 + IL_0008: isinst TestFunction25/Point + IL_000d: stloc.0 + IL_000e: ldloc.0 + IL_000f: brfalse.s IL_0030 + + IL_0011: ldarg.0 + IL_0012: ldfld int32 TestFunction25/Point::x@ + IL_0017: ldloc.0 + IL_0018: ldfld int32 TestFunction25/Point::x@ + IL_001d: bne.un.s IL_002e + + IL_001f: ldarg.0 + IL_0020: ldfld int32 TestFunction25/Point::y@ + IL_0025: ldloc.0 + IL_0026: ldfld int32 TestFunction25/Point::y@ + IL_002b: ceq + IL_002d: ret + + IL_002e: ldc.i4.0 + IL_002f: ret + + IL_0030: ldc.i4.0 + IL_0031: ret + + IL_0032: ldarg.1 + IL_0033: ldnull + IL_0034: cgt.un + IL_0036: ldc.i4.0 + IL_0037: ceq + IL_0039: ret + } // end of method Point::Equals + + .method public hidebysig virtual final + instance bool Equals(class TestFunction25/Point obj) cil managed + { + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 54 (0x36) + .maxstack 8 + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: ldnull + IL_0003: cgt.un + IL_0005: brfalse.s IL_002e + + IL_0007: ldarg.1 + IL_0008: ldnull + IL_0009: cgt.un + IL_000b: brfalse.s IL_002c + + IL_000d: ldarg.0 + IL_000e: ldfld int32 TestFunction25/Point::x@ + IL_0013: ldarg.1 + IL_0014: ldfld int32 TestFunction25/Point::x@ + IL_0019: bne.un.s IL_002a + + IL_001b: ldarg.0 + IL_001c: ldfld int32 TestFunction25/Point::y@ + IL_0021: ldarg.1 + IL_0022: ldfld int32 TestFunction25/Point::y@ + IL_0027: ceq + IL_0029: ret + + IL_002a: ldc.i4.0 + IL_002b: ret + + IL_002c: ldc.i4.0 + IL_002d: ret + + IL_002e: ldarg.1 + IL_002f: ldnull + IL_0030: cgt.un + IL_0032: ldc.i4.0 + IL_0033: ceq + IL_0035: ret + } // end of method Point::Equals + + .method public hidebysig virtual final + instance bool Equals(object obj) cil managed + { + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 21 (0x15) + .maxstack 4 + .locals init (class TestFunction25/Point V_0) + IL_0000: nop + IL_0001: ldarg.1 + IL_0002: isinst TestFunction25/Point + IL_0007: stloc.0 + IL_0008: ldloc.0 + IL_0009: brfalse.s IL_0013 + + IL_000b: ldarg.0 + IL_000c: ldloc.0 + IL_000d: callvirt instance bool TestFunction25/Point::Equals(class TestFunction25/Point) + IL_0012: ret + + IL_0013: ldc.i4.0 + IL_0014: ret + } // end of method Point::Equals + + .property instance int32 x() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .set instance void TestFunction25/Point::set_x(int32) + .get instance int32 TestFunction25/Point::get_x() + } // end of property Point::x + .property instance int32 y() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) + .set instance void TestFunction25/Point::set_y(int32) + .get instance int32 TestFunction25/Point::get_y() + } // end of property Point::y + } // end of class Point + + .method public static int32 pinObject() cil managed + { + // Code size 53 (0x35) + .maxstack 6 + .locals init ([0] class TestFunction25/Point point, + [1] native int p1, + [2] int32& pinned V_2) + IL_0000: nop + IL_0001: ldc.i4.1 + IL_0002: ldc.i4.2 + IL_0003: newobj instance void TestFunction25/Point::.ctor(int32, + int32) + IL_0008: stloc.0 + IL_0009: ldloc.0 + IL_000a: ldflda int32 TestFunction25/Point::x@ + IL_000f: stloc.2 + IL_0010: ldloc.2 + IL_0011: conv.i + IL_0012: stloc.1 + IL_0013: ldloc.1 + IL_0014: ldc.i4.0 + IL_0015: conv.i + IL_0016: sizeof [mscorlib]System.Int32 + IL_001c: mul + IL_001d: add + IL_001e: ldobj [mscorlib]System.Int32 + IL_0023: ldloc.1 + IL_0024: ldc.i4.1 + IL_0025: conv.i + IL_0026: sizeof [mscorlib]System.Int32 + IL_002c: mul + IL_002d: add + IL_002e: ldobj [mscorlib]System.Int32 + IL_0033: add + IL_0034: ret + } // end of method TestFunction25::pinObject + + .method public static int32 pinRef() cil managed + { + // Code size 33 (0x21) + .maxstack 4 + .locals init ([0] class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1 point, + [1] native int p1, + [2] int32& pinned V_2) + IL_0000: nop + IL_0001: ldc.i4.s 17 + IL_0003: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1::.ctor(!0) + IL_0008: stloc.0 + IL_0009: ldloc.0 + IL_000a: ldflda !0 class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1::contents@ + IL_000f: stloc.2 + IL_0010: ldloc.2 + IL_0011: conv.i + IL_0012: stloc.1 + IL_0013: ldloc.1 + IL_0014: ldobj [mscorlib]System.Int32 + IL_0019: ldloc.1 + IL_001a: ldobj [mscorlib]System.Int32 + IL_001f: add + IL_0020: ret + } // end of method TestFunction25::pinRef + + .method public static float64 pinArray1() cil managed + { + // Code size 168 (0xa8) + .maxstack 6 + .locals init ([0] float64[] arr, + [1] native int p1, + [2] float64& pinned V_2) + IL_0000: nop + IL_0001: ldc.i4.6 + IL_0002: newarr [mscorlib]System.Double + IL_0007: dup + IL_0008: ldc.i4.0 + IL_0009: ldc.r8 0.0 + IL_0012: stelem [mscorlib]System.Double + IL_0017: dup + IL_0018: ldc.i4.1 + IL_0019: ldc.r8 1.5 + IL_0022: stelem [mscorlib]System.Double + IL_0027: dup + IL_0028: ldc.i4.2 + IL_0029: ldc.r8 2.2999999999999998 + IL_0032: stelem [mscorlib]System.Double + IL_0037: dup + IL_0038: ldc.i4.3 + IL_0039: ldc.r8 3.3999999999999999 + IL_0042: stelem [mscorlib]System.Double + IL_0047: dup + IL_0048: ldc.i4.4 + IL_0049: ldc.r8 4. + IL_0052: stelem [mscorlib]System.Double + IL_0057: dup + IL_0058: ldc.i4.5 + IL_0059: ldc.r8 5.9000000000000004 + IL_0062: stelem [mscorlib]System.Double + IL_0067: stloc.0 + IL_0068: ldloc.0 + IL_0069: brfalse.s IL_0082 + + IL_006b: ldloc.0 + IL_006c: ldlen + IL_006d: conv.i4 + IL_006e: brfalse.s IL_007d + + IL_0070: ldloc.0 + IL_0071: ldc.i4.0 + IL_0072: ldelema [mscorlib]System.Double + IL_0077: stloc.2 + IL_0078: ldloc.2 + IL_0079: conv.i + IL_007a: nop + IL_007b: br.s IL_0085 + + IL_007d: ldc.i4.0 + IL_007e: conv.i + IL_007f: nop + IL_0080: br.s IL_0085 + + IL_0082: ldc.i4.0 + IL_0083: conv.i + IL_0084: nop + IL_0085: stloc.1 + IL_0086: ldloc.1 + IL_0087: ldc.i4.0 + IL_0088: conv.i + IL_0089: sizeof [mscorlib]System.Double + IL_008f: mul + IL_0090: add + IL_0091: ldobj [mscorlib]System.Double + IL_0096: ldloc.1 + IL_0097: ldc.i4.1 + IL_0098: conv.i + IL_0099: sizeof [mscorlib]System.Double + IL_009f: mul + IL_00a0: add + IL_00a1: ldobj [mscorlib]System.Double + IL_00a6: add + IL_00a7: ret + } // end of method TestFunction25::pinArray1 + + .method public static float64 pinArray2() cil managed + { + // Code size 149 (0x95) + .maxstack 6 + .locals init ([0] float64[] arr, + [1] native int p, + [2] float64& pinned V_2) + IL_0000: nop + IL_0001: ldc.i4.6 + IL_0002: newarr [mscorlib]System.Double + IL_0007: dup + IL_0008: ldc.i4.0 + IL_0009: ldc.r8 0.0 + IL_0012: stelem [mscorlib]System.Double + IL_0017: dup + IL_0018: ldc.i4.1 + IL_0019: ldc.r8 1.5 + IL_0022: stelem [mscorlib]System.Double + IL_0027: dup + IL_0028: ldc.i4.2 + IL_0029: ldc.r8 2.2999999999999998 + IL_0032: stelem [mscorlib]System.Double + IL_0037: dup + IL_0038: ldc.i4.3 + IL_0039: ldc.r8 3.3999999999999999 + IL_0042: stelem [mscorlib]System.Double + IL_0047: dup + IL_0048: ldc.i4.4 + IL_0049: ldc.r8 4. + IL_0052: stelem [mscorlib]System.Double + IL_0057: dup + IL_0058: ldc.i4.5 + IL_0059: ldc.r8 5.9000000000000004 + IL_0062: stelem [mscorlib]System.Double + IL_0067: stloc.0 + IL_0068: ldloc.0 + IL_0069: ldc.i4.0 + IL_006a: ldelema [mscorlib]System.Double + IL_006f: stloc.2 + IL_0070: ldloc.2 + IL_0071: conv.i + IL_0072: stloc.1 + IL_0073: ldloc.1 + IL_0074: ldc.i4.0 + IL_0075: conv.i + IL_0076: sizeof [mscorlib]System.Double + IL_007c: mul + IL_007d: add + IL_007e: ldobj [mscorlib]System.Double + IL_0083: ldloc.1 + IL_0084: ldc.i4.1 + IL_0085: conv.i + IL_0086: sizeof [mscorlib]System.Double + IL_008c: mul + IL_008d: add + IL_008e: ldobj [mscorlib]System.Double + IL_0093: add + IL_0094: ret + } // end of method TestFunction25::pinArray2 + + .method public static class [mscorlib]System.Tuple`2 + pinString() cil managed + { + // Code size 58 (0x3a) + .maxstack 6 + .locals init ([0] native int pChar, + [1] string pinned V_1) + IL_0000: nop + IL_0001: ldstr "Hello World" + IL_0006: stloc.1 + IL_0007: ldstr "Hello World" + IL_000c: conv.i + IL_000d: call int32 [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::get_OffsetToStringData() + IL_0012: add + IL_0013: stloc.0 + IL_0014: ldloc.0 + IL_0015: ldc.i4.0 + IL_0016: conv.i + IL_0017: sizeof [mscorlib]System.Char + IL_001d: mul + IL_001e: add + IL_001f: ldobj [mscorlib]System.Char + IL_0024: ldloc.0 + IL_0025: ldc.i4.1 + IL_0026: conv.i + IL_0027: sizeof [mscorlib]System.Char + IL_002d: mul + IL_002e: add + IL_002f: ldobj [mscorlib]System.Char + IL_0034: newobj instance void class [mscorlib]System.Tuple`2::.ctor(!0, + !1) + IL_0039: ret + } // end of method TestFunction25::pinString + +} // end of class TestFunction25 + +.class private abstract auto ansi sealed ''.$TestFunction25 + extends [mscorlib]System.Object +{ + .method public static void main@() cil managed + { + .entrypoint + // Code size 2 (0x2) + .maxstack 8 + IL_0000: nop + IL_0001: ret + } // end of method $TestFunction25::main@ + +} // end of class ''.$TestFunction25 + + +// ============================================================= + +// *********** DISASSEMBLY COMPLETE *********************** +// WARNING: Created Win32 resource file TestFunction25.il.netfx4.res diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/Testfunction24.fs b/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/Testfunction24.fs index 1f82f6b7048..eb297d2f636 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/Testfunction24.fs +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/Testfunction24.fs @@ -1,3 +1,4 @@ +open FSharp.NativeInterop // Assume that the following class exists. type Point = { mutable x : int; mutable y : int } @@ -5,27 +6,27 @@ type Point = { mutable x : int; mutable y : int } let pinObject() = let point = { x = 1; y = 2 } use p1 = fixed &point.x // note, fixed is a keyword and would be highlighted - () + NativePtr.get p1 0 + NativePtr.get p1 1 let pinRef() = - let point = ref 1 + let point = ref 17 use p1 = fixed &point.contents // note, fixed is a keyword and would be highlighted - () + NativePtr.read p1 + NativePtr.read p1 let pinArray1() = let arr = [| 0.0; 1.5; 2.3; 3.4; 4.0; 5.9 |] use p1 = fixed arr - () + NativePtr.get p1 0 + NativePtr.get p1 1 let pinArray2() = let arr = [| 0.0; 1.5; 2.3; 3.4; 4.0; 5.9 |] // You can initialize a pointer by using the address of a variable. use p = fixed &arr.[0] - () + NativePtr.get p 0 + NativePtr.get p 1 let pinString() = let str = "Hello World" // The following assignment initializes p by using a string. use pChar = fixed str - () - // some code that uses pChar, which has type char* + NativePtr.get pChar 0, NativePtr.get pChar 1 + diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/env.lst b/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/env.lst index fb6a949b63a..dcefb74b988 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/env.lst +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/env.lst @@ -44,3 +44,4 @@ SOURCE=TestFunction22h.fs SCFLAGS="-g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd TestFunction22h.exe NetFx40" # TestFunction22h.fs - NetFx40 SOURCE=TestFunction24.fs SCFLAGS="-g --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd TestFunction24.exe NetFx40" # TestFunction24.fs - NetFx40 + SOURCE=TestFunction25.fs SCFLAGS="-g --optimize+" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd TestFunction25.exe NetFx40" # TestFunction25.fs - NetFx40 From daffe337863cd718bb7b59a0a8921640a1a3f1e2 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Tue, 21 Jun 2016 22:09:17 +0100 Subject: [PATCH 074/129] update baseline --- .../TestFunction24.il.netfx4.bsl | 58 +++++++++++++++++-- .../TestFunction25.il.netfx4.bsl | 27 +++++++-- 2 files changed, 73 insertions(+), 12 deletions(-) diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/TestFunction24.il.netfx4.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/TestFunction24.il.netfx4.bsl index 171d1faa640..244989e3132 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/TestFunction24.il.netfx4.bsl +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/TestFunction24.il.netfx4.bsl @@ -1,5 +1,5 @@ -// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0 +// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.81.0 // Copyright (c) Microsoft Corporation. All rights reserved. @@ -30,21 +30,19 @@ .mresource public FSharpSignatureData.TestFunction24 { // Offset: 0x00000000 Length: 0x0000075B - // WARNING: managed resource file FSharpSignatureData.TestFunction24 created } .mresource public FSharpOptimizationData.TestFunction24 { // Offset: 0x00000760 Length: 0x00000228 - // WARNING: managed resource file FSharpOptimizationData.TestFunction24 created } .module TestFunction24.exe -// MVID: {5769535C-A643-4587-A745-03835C536957} +// MVID: {5769ACB2-A643-4587-A745-0383B2AC6957} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x00890000 +// Image base: 0x007A0000 // =============== CLASS MEMBERS DECLARATION =================== @@ -253,6 +251,8 @@ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) // Code size 14 (0xe) .maxstack 8 + .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' + .line 4,4 : 6,11 'C:\\GitHub\\dsyme\\visualfsharp\\tests\\fsharpqa\\Source\\CodeGen\\EmittedIL\\TestFunctions\\TestFunction24.fs' IL_0000: nop IL_0001: ldarg.0 IL_0002: ldarg.1 @@ -277,6 +277,7 @@ [6] class [mscorlib]System.Collections.IComparer V_6, [7] int32 V_7, [8] int32 V_8) + .line 4,4 : 6,11 '' IL_0000: nop IL_0001: ldarg.1 IL_0002: unbox.any TestFunction24/Point @@ -292,6 +293,7 @@ IL_0012: br IL_008d + .line 16707566,16707566 : 0,0 '' IL_0017: ldarg.1 IL_0018: unbox.any TestFunction24/Point IL_001d: ldnull @@ -302,6 +304,7 @@ IL_0024: br IL_008b + .line 16707566,16707566 : 0,0 '' IL_0029: ldarg.2 IL_002a: stloc.3 IL_002b: ldarg.0 @@ -318,14 +321,19 @@ IL_0043: br.s IL_0049 + .line 16707566,16707566 : 0,0 '' IL_0045: ldc.i4.m1 + .line 16707566,16707566 : 0,0 '' IL_0046: nop IL_0047: br.s IL_0050 + .line 16707566,16707566 : 0,0 '' IL_0049: ldloc.s V_4 IL_004b: ldloc.s V_5 IL_004d: cgt + .line 16707566,16707566 : 0,0 '' IL_004f: nop + .line 16707566,16707566 : 0,0 '' IL_0050: stloc.2 IL_0051: ldloc.2 IL_0052: ldc.i4.0 @@ -335,9 +343,11 @@ IL_0057: br.s IL_005b + .line 16707566,16707566 : 0,0 '' IL_0059: ldloc.2 IL_005a: ret + .line 16707566,16707566 : 0,0 '' IL_005b: ldloc.2 IL_005c: ldc.i4.0 IL_005d: ble.s IL_0061 @@ -346,9 +356,11 @@ IL_0061: br.s IL_0065 + .line 16707566,16707566 : 0,0 '' IL_0063: ldloc.2 IL_0064: ret + .line 16707566,16707566 : 0,0 '' IL_0065: ldarg.2 IL_0066: stloc.s V_6 IL_0068: ldarg.0 @@ -365,17 +377,21 @@ IL_0080: br.s IL_0084 + .line 16707566,16707566 : 0,0 '' IL_0082: ldc.i4.m1 IL_0083: ret + .line 16707566,16707566 : 0,0 '' IL_0084: ldloc.s V_7 IL_0086: ldloc.s V_8 IL_0088: cgt IL_008a: ret + .line 16707566,16707566 : 0,0 '' IL_008b: ldc.i4.1 IL_008c: ret + .line 16707566,16707566 : 0,0 '' IL_008d: ldarg.1 IL_008e: unbox.any TestFunction24/Point IL_0093: ldnull @@ -386,9 +402,11 @@ IL_009a: br.s IL_009e + .line 16707566,16707566 : 0,0 '' IL_009c: ldc.i4.m1 IL_009d: ret + .line 16707566,16707566 : 0,0 '' IL_009e: ldc.i4.0 IL_009f: ret } // end of method Point::CompareTo @@ -457,6 +475,7 @@ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) // Code size 13 (0xd) .maxstack 8 + .line 4,4 : 6,11 '' IL_0000: nop IL_0001: ldarg.0 IL_0002: call class [mscorlib]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() @@ -643,18 +662,21 @@ [4] int32 V_4, [5] native int V_5, [6] int32 V_6) + .line 7,7 : 5,33 '' IL_0000: nop IL_0001: ldc.i4.1 IL_0002: ldc.i4.2 IL_0003: newobj instance void TestFunction24/Point::.ctor(int32, int32) IL_0008: stloc.0 + .line 8,8 : 5,28 '' IL_0009: ldloc.0 IL_000a: ldflda int32 TestFunction24/Point::x@ IL_000f: stloc.2 IL_0010: ldloc.2 IL_0011: conv.i IL_0012: stloc.1 + .line 9,9 : 5,44 '' IL_0013: ldloc.1 IL_0014: stloc.3 IL_0015: ldc.i4.0 @@ -688,16 +710,19 @@ .locals init ([0] class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1 point, [1] native int p1, [2] int32& pinned V_2) + .line 12,12 : 5,23 '' IL_0000: nop IL_0001: ldc.i4.s 17 IL_0003: call class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1 [FSharp.Core]Microsoft.FSharp.Core.Operators::Ref(!!0) IL_0008: stloc.0 + .line 13,13 : 5,35 '' IL_0009: ldloc.0 IL_000a: ldflda !0 class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1::contents@ IL_000f: stloc.2 IL_0010: ldloc.2 IL_0011: conv.i IL_0012: stloc.1 + .line 14,14 : 5,42 '' IL_0013: ldloc.1 IL_0014: ldobj [mscorlib]System.Int32 IL_0019: ldloc.1 @@ -718,6 +743,7 @@ [5] int32 V_5, [6] native int V_6, [7] int32 V_7) + .line 17,17 : 5,49 '' IL_0000: nop IL_0001: ldc.i4.6 IL_0002: newarr [mscorlib]System.Double @@ -746,6 +772,7 @@ IL_0059: ldc.r8 5.9000000000000004 IL_0062: stelem [mscorlib]System.Double IL_0067: stloc.0 + .line 18,18 : 5,23 '' IL_0068: ldloc.0 IL_0069: stloc.2 IL_006a: ldloc.2 @@ -755,6 +782,7 @@ IL_006f: br.s IL_008f + .line 16707566,16707566 : 0,0 '' IL_0071: ldloc.2 IL_0072: call int32 [FSharp.Core]Microsoft.FSharp.Collections.ArrayModule::Length(!!0[]) IL_0077: brfalse.s IL_007b @@ -763,24 +791,32 @@ IL_007b: br.s IL_008a + .line 16707566,16707566 : 0,0 '' IL_007d: ldloc.2 IL_007e: ldc.i4.0 IL_007f: ldelema [mscorlib]System.Double IL_0084: stloc.3 IL_0085: ldloc.3 IL_0086: conv.i + .line 16707566,16707566 : 0,0 '' IL_0087: nop IL_0088: br.s IL_0092 + .line 16707566,16707566 : 0,0 '' IL_008a: ldc.i4.0 IL_008b: conv.i + .line 16707566,16707566 : 0,0 '' IL_008c: nop IL_008d: br.s IL_0092 + .line 16707566,16707566 : 0,0 '' IL_008f: ldc.i4.0 IL_0090: conv.i + .line 16707566,16707566 : 0,0 '' IL_0091: nop + .line 16707566,16707566 : 0,0 '' IL_0092: stloc.1 + .line 19,19 : 5,44 '' IL_0093: ldloc.1 IL_0094: stloc.s V_4 IL_0096: ldc.i4.0 @@ -818,6 +854,7 @@ [4] int32 V_4, [5] native int V_5, [6] int32 V_6) + .line 22,22 : 5,49 '' IL_0000: nop IL_0001: ldc.i4.6 IL_0002: newarr [mscorlib]System.Double @@ -846,6 +883,7 @@ IL_0059: ldc.r8 5.9000000000000004 IL_0062: stelem [mscorlib]System.Double IL_0067: stloc.0 + .line 24,24 : 5,27 '' IL_0068: ldloc.0 IL_0069: ldc.i4.0 IL_006a: ldelema [mscorlib]System.Double @@ -853,6 +891,7 @@ IL_0070: ldloc.2 IL_0071: conv.i IL_0072: stloc.1 + .line 25,25 : 5,42 '' IL_0073: ldloc.1 IL_0074: stloc.3 IL_0075: ldc.i4.0 @@ -891,9 +930,11 @@ [4] int32 V_4, [5] native int V_5, [6] int32 V_6) + .line 28,28 : 5,28 '' IL_0000: nop IL_0001: ldstr "Hello World" IL_0006: stloc.0 + .line 30,30 : 5,26 '' IL_0007: ldloc.0 IL_0008: stloc.2 IL_0009: ldloc.2 @@ -903,16 +944,22 @@ IL_000e: br.s IL_001b + .line 16707566,16707566 : 0,0 '' IL_0010: ldloc.2 IL_0011: conv.i IL_0012: call int32 [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::get_OffsetToStringData() IL_0017: add + .line 16707566,16707566 : 0,0 '' IL_0018: nop IL_0019: br.s IL_001d + .line 16707566,16707566 : 0,0 '' IL_001b: ldloc.2 + .line 16707566,16707566 : 0,0 '' IL_001c: nop + .line 16707566,16707566 : 0,0 '' IL_001d: stloc.1 + .line 31,31 : 5,50 '' IL_001e: ldloc.1 IL_001f: stloc.3 IL_0020: ldc.i4.0 @@ -960,4 +1007,3 @@ // ============================================================= // *********** DISASSEMBLY COMPLETE *********************** -// WARNING: Created Win32 resource file TestFunction24.il.netfx4.res diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/TestFunction25.il.netfx4.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/TestFunction25.il.netfx4.bsl index 181c7175055..8eef21c60c1 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/TestFunction25.il.netfx4.bsl +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/TestFunction25.il.netfx4.bsl @@ -1,5 +1,5 @@ -// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0 +// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.81.0 // Copyright (c) Microsoft Corporation. All rights reserved. @@ -30,21 +30,19 @@ .mresource public FSharpSignatureData.TestFunction25 { // Offset: 0x00000000 Length: 0x0000075B - // WARNING: managed resource file FSharpSignatureData.TestFunction25 created } .mresource public FSharpOptimizationData.TestFunction25 { // Offset: 0x00000760 Length: 0x000003D2 - // WARNING: managed resource file FSharpOptimizationData.TestFunction25 created } .module TestFunction25.exe -// MVID: {5769538F-A643-4662-A745-03838F536957} +// MVID: {5769ACB5-A643-4662-A745-0383B5AC6957} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x01400000 +// Image base: 0x02860000 // =============== CLASS MEMBERS DECLARATION =================== @@ -222,6 +220,8 @@ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) // Code size 14 (0xe) .maxstack 8 + .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' + .line 4,4 : 6,11 'C:\\GitHub\\dsyme\\visualfsharp\\tests\\fsharpqa\\Source\\CodeGen\\EmittedIL\\TestFunctions\\TestFunction25.fs' IL_0000: nop IL_0001: ldarg.0 IL_0002: ldarg.1 @@ -241,6 +241,7 @@ [1] int32 V_1, [2] int32 V_2, [3] int32 V_3) + .line 4,4 : 6,11 '' IL_0000: nop IL_0001: ldarg.1 IL_0002: unbox.any TestFunction25/Point @@ -377,6 +378,7 @@ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) // Code size 13 (0xd) .maxstack 8 + .line 4,4 : 6,11 '' IL_0000: nop IL_0001: ldarg.0 IL_0002: call class [mscorlib]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() @@ -521,18 +523,21 @@ .locals init ([0] class TestFunction25/Point point, [1] native int p1, [2] int32& pinned V_2) + .line 7,7 : 5,33 '' IL_0000: nop IL_0001: ldc.i4.1 IL_0002: ldc.i4.2 IL_0003: newobj instance void TestFunction25/Point::.ctor(int32, int32) IL_0008: stloc.0 + .line 8,8 : 5,28 '' IL_0009: ldloc.0 IL_000a: ldflda int32 TestFunction25/Point::x@ IL_000f: stloc.2 IL_0010: ldloc.2 IL_0011: conv.i IL_0012: stloc.1 + .line 9,9 : 5,44 '' IL_0013: ldloc.1 IL_0014: ldc.i4.0 IL_0015: conv.i @@ -558,16 +563,19 @@ .locals init ([0] class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1 point, [1] native int p1, [2] int32& pinned V_2) + .line 12,12 : 5,23 '' IL_0000: nop IL_0001: ldc.i4.s 17 IL_0003: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1::.ctor(!0) IL_0008: stloc.0 + .line 13,13 : 5,35 '' IL_0009: ldloc.0 IL_000a: ldflda !0 class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1::contents@ IL_000f: stloc.2 IL_0010: ldloc.2 IL_0011: conv.i IL_0012: stloc.1 + .line 14,14 : 5,42 '' IL_0013: ldloc.1 IL_0014: ldobj [mscorlib]System.Int32 IL_0019: ldloc.1 @@ -583,6 +591,7 @@ .locals init ([0] float64[] arr, [1] native int p1, [2] float64& pinned V_2) + .line 17,17 : 5,49 '' IL_0000: nop IL_0001: ldc.i4.6 IL_0002: newarr [mscorlib]System.Double @@ -611,6 +620,7 @@ IL_0059: ldc.r8 5.9000000000000004 IL_0062: stelem [mscorlib]System.Double IL_0067: stloc.0 + .line 18,18 : 5,23 '' IL_0068: ldloc.0 IL_0069: brfalse.s IL_0082 @@ -637,6 +647,7 @@ IL_0083: conv.i IL_0084: nop IL_0085: stloc.1 + .line 19,19 : 5,44 '' IL_0086: ldloc.1 IL_0087: ldc.i4.0 IL_0088: conv.i @@ -662,6 +673,7 @@ .locals init ([0] float64[] arr, [1] native int p, [2] float64& pinned V_2) + .line 22,22 : 5,49 '' IL_0000: nop IL_0001: ldc.i4.6 IL_0002: newarr [mscorlib]System.Double @@ -690,6 +702,7 @@ IL_0059: ldc.r8 5.9000000000000004 IL_0062: stelem [mscorlib]System.Double IL_0067: stloc.0 + .line 24,24 : 5,27 '' IL_0068: ldloc.0 IL_0069: ldc.i4.0 IL_006a: ldelema [mscorlib]System.Double @@ -697,6 +710,7 @@ IL_0070: ldloc.2 IL_0071: conv.i IL_0072: stloc.1 + .line 25,25 : 5,42 '' IL_0073: ldloc.1 IL_0074: ldc.i4.0 IL_0075: conv.i @@ -722,6 +736,7 @@ .maxstack 6 .locals init ([0] native int pChar, [1] string pinned V_1) + .line 30,30 : 5,26 '' IL_0000: nop IL_0001: ldstr "Hello World" IL_0006: stloc.1 @@ -730,6 +745,7 @@ IL_000d: call int32 [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::get_OffsetToStringData() IL_0012: add IL_0013: stloc.0 + .line 31,31 : 5,50 '' IL_0014: ldloc.0 IL_0015: ldc.i4.0 IL_0016: conv.i @@ -769,4 +785,3 @@ // ============================================================= // *********** DISASSEMBLY COMPLETE *********************** -// WARNING: Created Win32 resource file TestFunction25.il.netfx4.res From 5c1fa0bfca7ec9d24ec9619137664ad9817ab6bd Mon Sep 17 00:00:00 2001 From: Don Syme Date: Tue, 21 Jun 2016 22:15:03 +0100 Subject: [PATCH 075/129] revert changes to VisualFsharp.sln --- VisualFSharp.sln | 86 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 78 insertions(+), 8 deletions(-) diff --git a/VisualFSharp.sln b/VisualFSharp.sln index f83f67999d4..b83bb2c0738 100644 --- a/VisualFSharp.sln +++ b/VisualFSharp.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 -VisualStudioVersion = 14.0.24720.0 +VisualStudioVersion = 14.0.25123.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.Compiler", "src\fsharp\FSharp.Compiler\FSharp.Compiler.fsproj", "{2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}" EndProject @@ -120,12 +120,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XMLFile", "vsintegration\It EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VisualFSharpVsix", "vsintegration\VisualFSharpVsix\VisualFSharpVsix.csproj", "{E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{D3244A8B-4C62-4247-8DE9-29A32EBA67FB}" - ProjectSection(SolutionItems) = preProject - Performance2.psess = Performance2.psess - Performance3.psess = Performance3.psess - EndProjectSection -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -136,6 +130,54 @@ Global Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.Debug|x86.ActiveCfg = Debug|Any CPU + {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.Debug|x86.Build.0 = Debug|Any CPU + {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.Proto|Any CPU.Build.0 = Proto|Any CPU + {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.Proto|x86.ActiveCfg = Proto|Any CPU + {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.Proto|x86.Build.0 = Proto|Any CPU + {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.Release|Any CPU.Build.0 = Release|Any CPU + {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.Release|x86.ActiveCfg = Release|Any CPU + {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.Release|x86.Build.0 = Release|Any CPU + {493D19F9-35A4-4D0B-9B25-CA948823B709}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {493D19F9-35A4-4D0B-9B25-CA948823B709}.Debug|Any CPU.Build.0 = Debug|Any CPU + {493D19F9-35A4-4D0B-9B25-CA948823B709}.Debug|x86.ActiveCfg = Debug|Any CPU + {493D19F9-35A4-4D0B-9B25-CA948823B709}.Debug|x86.Build.0 = Debug|Any CPU + {493D19F9-35A4-4D0B-9B25-CA948823B709}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {493D19F9-35A4-4D0B-9B25-CA948823B709}.Proto|Any CPU.Build.0 = Proto|Any CPU + {493D19F9-35A4-4D0B-9B25-CA948823B709}.Proto|x86.ActiveCfg = Proto|Any CPU + {493D19F9-35A4-4D0B-9B25-CA948823B709}.Proto|x86.Build.0 = Proto|Any CPU + {493D19F9-35A4-4D0B-9B25-CA948823B709}.Release|Any CPU.ActiveCfg = Release|Any CPU + {493D19F9-35A4-4D0B-9B25-CA948823B709}.Release|Any CPU.Build.0 = Release|Any CPU + {493D19F9-35A4-4D0B-9B25-CA948823B709}.Release|x86.ActiveCfg = Release|Any CPU + {493D19F9-35A4-4D0B-9B25-CA948823B709}.Release|x86.Build.0 = Release|Any CPU + {530DF8CA-7996-407A-B533-D0C2873257AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {530DF8CA-7996-407A-B533-D0C2873257AF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {530DF8CA-7996-407A-B533-D0C2873257AF}.Debug|x86.ActiveCfg = Debug|Any CPU + {530DF8CA-7996-407A-B533-D0C2873257AF}.Debug|x86.Build.0 = Debug|Any CPU + {530DF8CA-7996-407A-B533-D0C2873257AF}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {530DF8CA-7996-407A-B533-D0C2873257AF}.Proto|Any CPU.Build.0 = Proto|Any CPU + {530DF8CA-7996-407A-B533-D0C2873257AF}.Proto|x86.ActiveCfg = Proto|Any CPU + {530DF8CA-7996-407A-B533-D0C2873257AF}.Proto|x86.Build.0 = Proto|Any CPU + {530DF8CA-7996-407A-B533-D0C2873257AF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {530DF8CA-7996-407A-B533-D0C2873257AF}.Release|Any CPU.Build.0 = Release|Any CPU + {530DF8CA-7996-407A-B533-D0C2873257AF}.Release|x86.ActiveCfg = Release|Any CPU + {530DF8CA-7996-407A-B533-D0C2873257AF}.Release|x86.Build.0 = Release|Any CPU + {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.Debug|Any CPU.Build.0 = Debug|Any CPU + {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.Debug|x86.ActiveCfg = Debug|Any CPU + {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.Debug|x86.Build.0 = Debug|Any CPU + {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.Proto|Any CPU.Build.0 = Proto|Any CPU + {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.Proto|x86.ActiveCfg = Proto|Any CPU + {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.Proto|x86.Build.0 = Proto|Any CPU + {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.Release|Any CPU.ActiveCfg = Release|Any CPU + {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.Release|Any CPU.Build.0 = Release|Any CPU + {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.Release|x86.ActiveCfg = Release|Any CPU + {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.Release|x86.Build.0 = Release|Any CPU {2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}.Debug|Any CPU.Build.0 = Debug|Any CPU {2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -460,6 +502,18 @@ Global {C94C257C-3C0A-4858-B5D8-D746498D1F08}.Release|Any CPU.Build.0 = Release|Any CPU {C94C257C-3C0A-4858-B5D8-D746498D1F08}.Release|x86.ActiveCfg = Release|Any CPU {C94C257C-3C0A-4858-B5D8-D746498D1F08}.Release|x86.Build.0 = Release|Any CPU + {CB7D20C4-6506-406D-9144-5342C3595F03}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CB7D20C4-6506-406D-9144-5342C3595F03}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CB7D20C4-6506-406D-9144-5342C3595F03}.Debug|x86.ActiveCfg = Debug|Any CPU + {CB7D20C4-6506-406D-9144-5342C3595F03}.Debug|x86.Build.0 = Debug|Any CPU + {CB7D20C4-6506-406D-9144-5342C3595F03}.Proto|Any CPU.ActiveCfg = Proto|Any CPU + {CB7D20C4-6506-406D-9144-5342C3595F03}.Proto|Any CPU.Build.0 = Proto|Any CPU + {CB7D20C4-6506-406D-9144-5342C3595F03}.Proto|x86.ActiveCfg = Proto|Any CPU + {CB7D20C4-6506-406D-9144-5342C3595F03}.Proto|x86.Build.0 = Proto|Any CPU + {CB7D20C4-6506-406D-9144-5342C3595F03}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CB7D20C4-6506-406D-9144-5342C3595F03}.Release|Any CPU.Build.0 = Release|Any CPU + {CB7D20C4-6506-406D-9144-5342C3595F03}.Release|x86.ActiveCfg = Release|Any CPU + {CB7D20C4-6506-406D-9144-5342C3595F03}.Release|x86.Build.0 = Release|Any CPU {649FA588-F02E-457C-9FCF-87E46407481E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {649FA588-F02E-457C-9FCF-87E46407481E}.Debug|Any CPU.Build.0 = Debug|Any CPU {649FA588-F02E-457C-9FCF-87E46407481E}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -699,6 +753,14 @@ Global {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.Release|Any CPU.Build.0 = Release|Any CPU {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.Release|x86.ActiveCfg = Release|Any CPU {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.Release|x86.Build.0 = Release|Any CPU + {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU + {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU + {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU + {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.VSDebug|x86.Build.0 = VSDebug|Any CPU + {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU + {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU + {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU + {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.VSRelease|x86.Build.0 = VSRelease|Any CPU {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}.Debug|Any CPU.Build.0 = Debug|Any CPU {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -711,6 +773,14 @@ Global {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}.Release|Any CPU.Build.0 = Release|Any CPU {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}.Release|x86.ActiveCfg = Release|Any CPU {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}.Release|x86.Build.0 = Release|Any CPU + {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU + {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU + {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU + {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}.VSDebug|x86.Build.0 = VSDebug|Any CPU + {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU + {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU + {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU + {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}.VSRelease|x86.Build.0 = VSRelease|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -769,4 +839,4 @@ Global {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6} = {F6DAEE9A-8BE1-4C4A-BC83-09215517C7DA} {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090} = {4C7B48D7-19AF-4AE7-9D1D-3BB289D5480D} EndGlobalSection -EndGlobal +EndGlobal \ No newline at end of file From 7bb6e681c5d4f82ec7eadadb634084fa0623af1a Mon Sep 17 00:00:00 2001 From: Don Syme Date: Tue, 21 Jun 2016 23:41:13 +0100 Subject: [PATCH 076/129] simplify tests --- .../EmittedIL/TestFunctions/TestFunction25.fs | 32 - .../TestFunction25.il.netfx4.bsl | 787 ------------------ .../CodeGen/EmittedIL/TestFunctions/env.lst | 1 - 3 files changed, 820 deletions(-) delete mode 100644 tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/TestFunction25.fs delete mode 100644 tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/TestFunction25.il.netfx4.bsl diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/TestFunction25.fs b/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/TestFunction25.fs deleted file mode 100644 index eb297d2f636..00000000000 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/TestFunction25.fs +++ /dev/null @@ -1,32 +0,0 @@ -open FSharp.NativeInterop -// Assume that the following class exists. - -type Point = { mutable x : int; mutable y : int } - -let pinObject() = - let point = { x = 1; y = 2 } - use p1 = fixed &point.x // note, fixed is a keyword and would be highlighted - NativePtr.get p1 0 + NativePtr.get p1 1 - -let pinRef() = - let point = ref 17 - use p1 = fixed &point.contents // note, fixed is a keyword and would be highlighted - NativePtr.read p1 + NativePtr.read p1 - -let pinArray1() = - let arr = [| 0.0; 1.5; 2.3; 3.4; 4.0; 5.9 |] - use p1 = fixed arr - NativePtr.get p1 0 + NativePtr.get p1 1 - -let pinArray2() = - let arr = [| 0.0; 1.5; 2.3; 3.4; 4.0; 5.9 |] - // You can initialize a pointer by using the address of a variable. - use p = fixed &arr.[0] - NativePtr.get p 0 + NativePtr.get p 1 - -let pinString() = - let str = "Hello World" - // The following assignment initializes p by using a string. - use pChar = fixed str - NativePtr.get pChar 0, NativePtr.get pChar 1 - diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/TestFunction25.il.netfx4.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/TestFunction25.il.netfx4.bsl deleted file mode 100644 index 8eef21c60c1..00000000000 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/TestFunction25.il.netfx4.bsl +++ /dev/null @@ -1,787 +0,0 @@ - -// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.81.0 -// Copyright (c) Microsoft Corporation. All rights reserved. - - - -// Metadata version: v4.0.30319 -.assembly extern mscorlib -{ - .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. - .ver 4:0:0:0 -} -.assembly extern FSharp.Core -{ - .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....: - .ver 4:4:1:0 -} -.assembly TestFunction25 -{ - .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, - int32, - int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) - - // --- The following custom attribute is added automatically, do not uncomment ------- - // .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 02 00 00 00 00 00 ) - - .hash algorithm 0x00008004 - .ver 0:0:0:0 -} -.mresource public FSharpSignatureData.TestFunction25 -{ - // Offset: 0x00000000 Length: 0x0000075B -} -.mresource public FSharpOptimizationData.TestFunction25 -{ - // Offset: 0x00000760 Length: 0x000003D2 -} -.module TestFunction25.exe -// MVID: {5769ACB5-A643-4662-A745-0383B5AC6957} -.imagebase 0x00400000 -.file alignment 0x00000200 -.stackreserve 0x00100000 -.subsystem 0x0003 // WINDOWS_CUI -.corflags 0x00000001 // ILONLY -// Image base: 0x02860000 - - -// =============== CLASS MEMBERS DECLARATION =================== - -.class public abstract auto ansi sealed TestFunction25 - extends [mscorlib]System.Object -{ - .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) - .class auto ansi serializable sealed nested public Point - extends [mscorlib]System.Object - implements class [mscorlib]System.IEquatable`1, - [mscorlib]System.Collections.IStructuralEquatable, - class [mscorlib]System.IComparable`1, - [mscorlib]System.IComparable, - [mscorlib]System.Collections.IStructuralComparable - { - .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) - .field public int32 x@ - .custom instance void [mscorlib]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) - .field public int32 y@ - .custom instance void [mscorlib]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) - .method public hidebysig specialname - instance int32 get_x() cil managed - { - // Code size 7 (0x7) - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: ldfld int32 TestFunction25/Point::x@ - IL_0006: ret - } // end of method Point::get_x - - .method public hidebysig specialname - instance int32 get_y() cil managed - { - // Code size 7 (0x7) - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: ldfld int32 TestFunction25/Point::y@ - IL_0006: ret - } // end of method Point::get_y - - .method public hidebysig specialname - instance void set_x(int32 'value') cil managed - { - // Code size 8 (0x8) - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: ldarg.1 - IL_0002: stfld int32 TestFunction25/Point::x@ - IL_0007: ret - } // end of method Point::set_x - - .method public hidebysig specialname - instance void set_y(int32 'value') cil managed - { - // Code size 8 (0x8) - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: ldarg.1 - IL_0002: stfld int32 TestFunction25/Point::y@ - IL_0007: ret - } // end of method Point::set_y - - .method public specialname rtspecialname - instance void .ctor(int32 x, - int32 y) cil managed - { - // Code size 21 (0x15) - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: call instance void [mscorlib]System.Object::.ctor() - IL_0006: ldarg.0 - IL_0007: ldarg.1 - IL_0008: stfld int32 TestFunction25/Point::x@ - IL_000d: ldarg.0 - IL_000e: ldarg.2 - IL_000f: stfld int32 TestFunction25/Point::y@ - IL_0014: ret - } // end of method Point::.ctor - - .method public hidebysig virtual final - instance int32 CompareTo(class TestFunction25/Point obj) cil managed - { - .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - // Code size 102 (0x66) - .maxstack 4 - .locals init (int32 V_0, - class [mscorlib]System.Collections.IComparer V_1, - int32 V_2, - int32 V_3) - IL_0000: nop - IL_0001: ldarg.0 - IL_0002: ldnull - IL_0003: cgt.un - IL_0005: brfalse.s IL_005c - - IL_0007: ldarg.1 - IL_0008: ldnull - IL_0009: cgt.un - IL_000b: brfalse.s IL_005a - - IL_000d: call class [mscorlib]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() - IL_0012: stloc.1 - IL_0013: ldarg.0 - IL_0014: ldfld int32 TestFunction25/Point::x@ - IL_0019: stloc.2 - IL_001a: ldarg.1 - IL_001b: ldfld int32 TestFunction25/Point::x@ - IL_0020: stloc.3 - IL_0021: ldloc.2 - IL_0022: ldloc.3 - IL_0023: bge.s IL_0029 - - IL_0025: ldc.i4.m1 - IL_0026: nop - IL_0027: br.s IL_002e - - IL_0029: ldloc.2 - IL_002a: ldloc.3 - IL_002b: cgt - IL_002d: nop - IL_002e: stloc.0 - IL_002f: ldloc.0 - IL_0030: ldc.i4.0 - IL_0031: bge.s IL_0035 - - IL_0033: ldloc.0 - IL_0034: ret - - IL_0035: ldloc.0 - IL_0036: ldc.i4.0 - IL_0037: ble.s IL_003b - - IL_0039: ldloc.0 - IL_003a: ret - - IL_003b: call class [mscorlib]System.Collections.IComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericComparer() - IL_0040: stloc.1 - IL_0041: ldarg.0 - IL_0042: ldfld int32 TestFunction25/Point::y@ - IL_0047: stloc.2 - IL_0048: ldarg.1 - IL_0049: ldfld int32 TestFunction25/Point::y@ - IL_004e: stloc.3 - IL_004f: ldloc.2 - IL_0050: ldloc.3 - IL_0051: bge.s IL_0055 - - IL_0053: ldc.i4.m1 - IL_0054: ret - - IL_0055: ldloc.2 - IL_0056: ldloc.3 - IL_0057: cgt - IL_0059: ret - - IL_005a: ldc.i4.1 - IL_005b: ret - - IL_005c: ldarg.1 - IL_005d: ldnull - IL_005e: cgt.un - IL_0060: brfalse.s IL_0064 - - IL_0062: ldc.i4.m1 - IL_0063: ret - - IL_0064: ldc.i4.0 - IL_0065: ret - } // end of method Point::CompareTo - - .method public hidebysig virtual final - instance int32 CompareTo(object obj) cil managed - { - .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - // Code size 14 (0xe) - .maxstack 8 - .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' - .line 4,4 : 6,11 'C:\\GitHub\\dsyme\\visualfsharp\\tests\\fsharpqa\\Source\\CodeGen\\EmittedIL\\TestFunctions\\TestFunction25.fs' - IL_0000: nop - IL_0001: ldarg.0 - IL_0002: ldarg.1 - IL_0003: unbox.any TestFunction25/Point - IL_0008: callvirt instance int32 TestFunction25/Point::CompareTo(class TestFunction25/Point) - IL_000d: ret - } // end of method Point::CompareTo - - .method public hidebysig virtual final - instance int32 CompareTo(object obj, - class [mscorlib]System.Collections.IComparer comp) cil managed - { - .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - // Code size 107 (0x6b) - .maxstack 4 - .locals init ([0] class TestFunction25/Point V_0, - [1] int32 V_1, - [2] int32 V_2, - [3] int32 V_3) - .line 4,4 : 6,11 '' - IL_0000: nop - IL_0001: ldarg.1 - IL_0002: unbox.any TestFunction25/Point - IL_0007: stloc.0 - IL_0008: ldarg.0 - IL_0009: ldnull - IL_000a: cgt.un - IL_000c: brfalse.s IL_005c - - IL_000e: ldarg.1 - IL_000f: unbox.any TestFunction25/Point - IL_0014: ldnull - IL_0015: cgt.un - IL_0017: brfalse.s IL_005a - - IL_0019: ldarg.0 - IL_001a: ldfld int32 TestFunction25/Point::x@ - IL_001f: stloc.2 - IL_0020: ldloc.0 - IL_0021: ldfld int32 TestFunction25/Point::x@ - IL_0026: stloc.3 - IL_0027: ldloc.2 - IL_0028: ldloc.3 - IL_0029: bge.s IL_002f - - IL_002b: ldc.i4.m1 - IL_002c: nop - IL_002d: br.s IL_0034 - - IL_002f: ldloc.2 - IL_0030: ldloc.3 - IL_0031: cgt - IL_0033: nop - IL_0034: stloc.1 - IL_0035: ldloc.1 - IL_0036: ldc.i4.0 - IL_0037: bge.s IL_003b - - IL_0039: ldloc.1 - IL_003a: ret - - IL_003b: ldloc.1 - IL_003c: ldc.i4.0 - IL_003d: ble.s IL_0041 - - IL_003f: ldloc.1 - IL_0040: ret - - IL_0041: ldarg.0 - IL_0042: ldfld int32 TestFunction25/Point::y@ - IL_0047: stloc.2 - IL_0048: ldloc.0 - IL_0049: ldfld int32 TestFunction25/Point::y@ - IL_004e: stloc.3 - IL_004f: ldloc.2 - IL_0050: ldloc.3 - IL_0051: bge.s IL_0055 - - IL_0053: ldc.i4.m1 - IL_0054: ret - - IL_0055: ldloc.2 - IL_0056: ldloc.3 - IL_0057: cgt - IL_0059: ret - - IL_005a: ldc.i4.1 - IL_005b: ret - - IL_005c: ldarg.1 - IL_005d: unbox.any TestFunction25/Point - IL_0062: ldnull - IL_0063: cgt.un - IL_0065: brfalse.s IL_0069 - - IL_0067: ldc.i4.m1 - IL_0068: ret - - IL_0069: ldc.i4.0 - IL_006a: ret - } // end of method Point::CompareTo - - .method public hidebysig virtual final - instance int32 GetHashCode(class [mscorlib]System.Collections.IEqualityComparer comp) cil managed - { - .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - // Code size 55 (0x37) - .maxstack 7 - .locals init (int32 V_0) - IL_0000: nop - IL_0001: ldarg.0 - IL_0002: ldnull - IL_0003: cgt.un - IL_0005: brfalse.s IL_0035 - - IL_0007: ldc.i4.0 - IL_0008: stloc.0 - IL_0009: ldc.i4 0x9e3779b9 - IL_000e: ldarg.0 - IL_000f: ldfld int32 TestFunction25/Point::y@ - IL_0014: ldloc.0 - IL_0015: ldc.i4.6 - IL_0016: shl - IL_0017: ldloc.0 - IL_0018: ldc.i4.2 - IL_0019: shr - IL_001a: add - IL_001b: add - IL_001c: add - IL_001d: stloc.0 - IL_001e: ldc.i4 0x9e3779b9 - IL_0023: ldarg.0 - IL_0024: ldfld int32 TestFunction25/Point::x@ - IL_0029: ldloc.0 - IL_002a: ldc.i4.6 - IL_002b: shl - IL_002c: ldloc.0 - IL_002d: ldc.i4.2 - IL_002e: shr - IL_002f: add - IL_0030: add - IL_0031: add - IL_0032: stloc.0 - IL_0033: ldloc.0 - IL_0034: ret - - IL_0035: ldc.i4.0 - IL_0036: ret - } // end of method Point::GetHashCode - - .method public hidebysig virtual final - instance int32 GetHashCode() cil managed - { - .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - // Code size 13 (0xd) - .maxstack 8 - .line 4,4 : 6,11 '' - IL_0000: nop - IL_0001: ldarg.0 - IL_0002: call class [mscorlib]System.Collections.IEqualityComparer [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives::get_GenericEqualityComparer() - IL_0007: callvirt instance int32 TestFunction25/Point::GetHashCode(class [mscorlib]System.Collections.IEqualityComparer) - IL_000c: ret - } // end of method Point::GetHashCode - - .method public hidebysig virtual final - instance bool Equals(object obj, - class [mscorlib]System.Collections.IEqualityComparer comp) cil managed - { - .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - // Code size 58 (0x3a) - .maxstack 4 - .locals init (class TestFunction25/Point V_0) - IL_0000: nop - IL_0001: ldarg.0 - IL_0002: ldnull - IL_0003: cgt.un - IL_0005: brfalse.s IL_0032 - - IL_0007: ldarg.1 - IL_0008: isinst TestFunction25/Point - IL_000d: stloc.0 - IL_000e: ldloc.0 - IL_000f: brfalse.s IL_0030 - - IL_0011: ldarg.0 - IL_0012: ldfld int32 TestFunction25/Point::x@ - IL_0017: ldloc.0 - IL_0018: ldfld int32 TestFunction25/Point::x@ - IL_001d: bne.un.s IL_002e - - IL_001f: ldarg.0 - IL_0020: ldfld int32 TestFunction25/Point::y@ - IL_0025: ldloc.0 - IL_0026: ldfld int32 TestFunction25/Point::y@ - IL_002b: ceq - IL_002d: ret - - IL_002e: ldc.i4.0 - IL_002f: ret - - IL_0030: ldc.i4.0 - IL_0031: ret - - IL_0032: ldarg.1 - IL_0033: ldnull - IL_0034: cgt.un - IL_0036: ldc.i4.0 - IL_0037: ceq - IL_0039: ret - } // end of method Point::Equals - - .method public hidebysig virtual final - instance bool Equals(class TestFunction25/Point obj) cil managed - { - .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - // Code size 54 (0x36) - .maxstack 8 - IL_0000: nop - IL_0001: ldarg.0 - IL_0002: ldnull - IL_0003: cgt.un - IL_0005: brfalse.s IL_002e - - IL_0007: ldarg.1 - IL_0008: ldnull - IL_0009: cgt.un - IL_000b: brfalse.s IL_002c - - IL_000d: ldarg.0 - IL_000e: ldfld int32 TestFunction25/Point::x@ - IL_0013: ldarg.1 - IL_0014: ldfld int32 TestFunction25/Point::x@ - IL_0019: bne.un.s IL_002a - - IL_001b: ldarg.0 - IL_001c: ldfld int32 TestFunction25/Point::y@ - IL_0021: ldarg.1 - IL_0022: ldfld int32 TestFunction25/Point::y@ - IL_0027: ceq - IL_0029: ret - - IL_002a: ldc.i4.0 - IL_002b: ret - - IL_002c: ldc.i4.0 - IL_002d: ret - - IL_002e: ldarg.1 - IL_002f: ldnull - IL_0030: cgt.un - IL_0032: ldc.i4.0 - IL_0033: ceq - IL_0035: ret - } // end of method Point::Equals - - .method public hidebysig virtual final - instance bool Equals(object obj) cil managed - { - .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - // Code size 21 (0x15) - .maxstack 4 - .locals init (class TestFunction25/Point V_0) - IL_0000: nop - IL_0001: ldarg.1 - IL_0002: isinst TestFunction25/Point - IL_0007: stloc.0 - IL_0008: ldloc.0 - IL_0009: brfalse.s IL_0013 - - IL_000b: ldarg.0 - IL_000c: ldloc.0 - IL_000d: callvirt instance bool TestFunction25/Point::Equals(class TestFunction25/Point) - IL_0012: ret - - IL_0013: ldc.i4.0 - IL_0014: ret - } // end of method Point::Equals - - .property instance int32 x() - { - .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, - int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) - .set instance void TestFunction25/Point::set_x(int32) - .get instance int32 TestFunction25/Point::get_x() - } // end of property Point::x - .property instance int32 y() - { - .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, - int32) = ( 01 00 04 00 00 00 01 00 00 00 00 00 ) - .set instance void TestFunction25/Point::set_y(int32) - .get instance int32 TestFunction25/Point::get_y() - } // end of property Point::y - } // end of class Point - - .method public static int32 pinObject() cil managed - { - // Code size 53 (0x35) - .maxstack 6 - .locals init ([0] class TestFunction25/Point point, - [1] native int p1, - [2] int32& pinned V_2) - .line 7,7 : 5,33 '' - IL_0000: nop - IL_0001: ldc.i4.1 - IL_0002: ldc.i4.2 - IL_0003: newobj instance void TestFunction25/Point::.ctor(int32, - int32) - IL_0008: stloc.0 - .line 8,8 : 5,28 '' - IL_0009: ldloc.0 - IL_000a: ldflda int32 TestFunction25/Point::x@ - IL_000f: stloc.2 - IL_0010: ldloc.2 - IL_0011: conv.i - IL_0012: stloc.1 - .line 9,9 : 5,44 '' - IL_0013: ldloc.1 - IL_0014: ldc.i4.0 - IL_0015: conv.i - IL_0016: sizeof [mscorlib]System.Int32 - IL_001c: mul - IL_001d: add - IL_001e: ldobj [mscorlib]System.Int32 - IL_0023: ldloc.1 - IL_0024: ldc.i4.1 - IL_0025: conv.i - IL_0026: sizeof [mscorlib]System.Int32 - IL_002c: mul - IL_002d: add - IL_002e: ldobj [mscorlib]System.Int32 - IL_0033: add - IL_0034: ret - } // end of method TestFunction25::pinObject - - .method public static int32 pinRef() cil managed - { - // Code size 33 (0x21) - .maxstack 4 - .locals init ([0] class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1 point, - [1] native int p1, - [2] int32& pinned V_2) - .line 12,12 : 5,23 '' - IL_0000: nop - IL_0001: ldc.i4.s 17 - IL_0003: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1::.ctor(!0) - IL_0008: stloc.0 - .line 13,13 : 5,35 '' - IL_0009: ldloc.0 - IL_000a: ldflda !0 class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1::contents@ - IL_000f: stloc.2 - IL_0010: ldloc.2 - IL_0011: conv.i - IL_0012: stloc.1 - .line 14,14 : 5,42 '' - IL_0013: ldloc.1 - IL_0014: ldobj [mscorlib]System.Int32 - IL_0019: ldloc.1 - IL_001a: ldobj [mscorlib]System.Int32 - IL_001f: add - IL_0020: ret - } // end of method TestFunction25::pinRef - - .method public static float64 pinArray1() cil managed - { - // Code size 168 (0xa8) - .maxstack 6 - .locals init ([0] float64[] arr, - [1] native int p1, - [2] float64& pinned V_2) - .line 17,17 : 5,49 '' - IL_0000: nop - IL_0001: ldc.i4.6 - IL_0002: newarr [mscorlib]System.Double - IL_0007: dup - IL_0008: ldc.i4.0 - IL_0009: ldc.r8 0.0 - IL_0012: stelem [mscorlib]System.Double - IL_0017: dup - IL_0018: ldc.i4.1 - IL_0019: ldc.r8 1.5 - IL_0022: stelem [mscorlib]System.Double - IL_0027: dup - IL_0028: ldc.i4.2 - IL_0029: ldc.r8 2.2999999999999998 - IL_0032: stelem [mscorlib]System.Double - IL_0037: dup - IL_0038: ldc.i4.3 - IL_0039: ldc.r8 3.3999999999999999 - IL_0042: stelem [mscorlib]System.Double - IL_0047: dup - IL_0048: ldc.i4.4 - IL_0049: ldc.r8 4. - IL_0052: stelem [mscorlib]System.Double - IL_0057: dup - IL_0058: ldc.i4.5 - IL_0059: ldc.r8 5.9000000000000004 - IL_0062: stelem [mscorlib]System.Double - IL_0067: stloc.0 - .line 18,18 : 5,23 '' - IL_0068: ldloc.0 - IL_0069: brfalse.s IL_0082 - - IL_006b: ldloc.0 - IL_006c: ldlen - IL_006d: conv.i4 - IL_006e: brfalse.s IL_007d - - IL_0070: ldloc.0 - IL_0071: ldc.i4.0 - IL_0072: ldelema [mscorlib]System.Double - IL_0077: stloc.2 - IL_0078: ldloc.2 - IL_0079: conv.i - IL_007a: nop - IL_007b: br.s IL_0085 - - IL_007d: ldc.i4.0 - IL_007e: conv.i - IL_007f: nop - IL_0080: br.s IL_0085 - - IL_0082: ldc.i4.0 - IL_0083: conv.i - IL_0084: nop - IL_0085: stloc.1 - .line 19,19 : 5,44 '' - IL_0086: ldloc.1 - IL_0087: ldc.i4.0 - IL_0088: conv.i - IL_0089: sizeof [mscorlib]System.Double - IL_008f: mul - IL_0090: add - IL_0091: ldobj [mscorlib]System.Double - IL_0096: ldloc.1 - IL_0097: ldc.i4.1 - IL_0098: conv.i - IL_0099: sizeof [mscorlib]System.Double - IL_009f: mul - IL_00a0: add - IL_00a1: ldobj [mscorlib]System.Double - IL_00a6: add - IL_00a7: ret - } // end of method TestFunction25::pinArray1 - - .method public static float64 pinArray2() cil managed - { - // Code size 149 (0x95) - .maxstack 6 - .locals init ([0] float64[] arr, - [1] native int p, - [2] float64& pinned V_2) - .line 22,22 : 5,49 '' - IL_0000: nop - IL_0001: ldc.i4.6 - IL_0002: newarr [mscorlib]System.Double - IL_0007: dup - IL_0008: ldc.i4.0 - IL_0009: ldc.r8 0.0 - IL_0012: stelem [mscorlib]System.Double - IL_0017: dup - IL_0018: ldc.i4.1 - IL_0019: ldc.r8 1.5 - IL_0022: stelem [mscorlib]System.Double - IL_0027: dup - IL_0028: ldc.i4.2 - IL_0029: ldc.r8 2.2999999999999998 - IL_0032: stelem [mscorlib]System.Double - IL_0037: dup - IL_0038: ldc.i4.3 - IL_0039: ldc.r8 3.3999999999999999 - IL_0042: stelem [mscorlib]System.Double - IL_0047: dup - IL_0048: ldc.i4.4 - IL_0049: ldc.r8 4. - IL_0052: stelem [mscorlib]System.Double - IL_0057: dup - IL_0058: ldc.i4.5 - IL_0059: ldc.r8 5.9000000000000004 - IL_0062: stelem [mscorlib]System.Double - IL_0067: stloc.0 - .line 24,24 : 5,27 '' - IL_0068: ldloc.0 - IL_0069: ldc.i4.0 - IL_006a: ldelema [mscorlib]System.Double - IL_006f: stloc.2 - IL_0070: ldloc.2 - IL_0071: conv.i - IL_0072: stloc.1 - .line 25,25 : 5,42 '' - IL_0073: ldloc.1 - IL_0074: ldc.i4.0 - IL_0075: conv.i - IL_0076: sizeof [mscorlib]System.Double - IL_007c: mul - IL_007d: add - IL_007e: ldobj [mscorlib]System.Double - IL_0083: ldloc.1 - IL_0084: ldc.i4.1 - IL_0085: conv.i - IL_0086: sizeof [mscorlib]System.Double - IL_008c: mul - IL_008d: add - IL_008e: ldobj [mscorlib]System.Double - IL_0093: add - IL_0094: ret - } // end of method TestFunction25::pinArray2 - - .method public static class [mscorlib]System.Tuple`2 - pinString() cil managed - { - // Code size 58 (0x3a) - .maxstack 6 - .locals init ([0] native int pChar, - [1] string pinned V_1) - .line 30,30 : 5,26 '' - IL_0000: nop - IL_0001: ldstr "Hello World" - IL_0006: stloc.1 - IL_0007: ldstr "Hello World" - IL_000c: conv.i - IL_000d: call int32 [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::get_OffsetToStringData() - IL_0012: add - IL_0013: stloc.0 - .line 31,31 : 5,50 '' - IL_0014: ldloc.0 - IL_0015: ldc.i4.0 - IL_0016: conv.i - IL_0017: sizeof [mscorlib]System.Char - IL_001d: mul - IL_001e: add - IL_001f: ldobj [mscorlib]System.Char - IL_0024: ldloc.0 - IL_0025: ldc.i4.1 - IL_0026: conv.i - IL_0027: sizeof [mscorlib]System.Char - IL_002d: mul - IL_002e: add - IL_002f: ldobj [mscorlib]System.Char - IL_0034: newobj instance void class [mscorlib]System.Tuple`2::.ctor(!0, - !1) - IL_0039: ret - } // end of method TestFunction25::pinString - -} // end of class TestFunction25 - -.class private abstract auto ansi sealed ''.$TestFunction25 - extends [mscorlib]System.Object -{ - .method public static void main@() cil managed - { - .entrypoint - // Code size 2 (0x2) - .maxstack 8 - IL_0000: nop - IL_0001: ret - } // end of method $TestFunction25::main@ - -} // end of class ''.$TestFunction25 - - -// ============================================================= - -// *********** DISASSEMBLY COMPLETE *********************** diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/env.lst b/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/env.lst index dcefb74b988..fb6a949b63a 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/env.lst +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/env.lst @@ -44,4 +44,3 @@ SOURCE=TestFunction22h.fs SCFLAGS="-g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd TestFunction22h.exe NetFx40" # TestFunction22h.fs - NetFx40 SOURCE=TestFunction24.fs SCFLAGS="-g --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd TestFunction24.exe NetFx40" # TestFunction24.fs - NetFx40 - SOURCE=TestFunction25.fs SCFLAGS="-g --optimize+" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd TestFunction25.exe NetFx40" # TestFunction25.fs - NetFx40 From 8cdaecaf63fade31b9a37d0b7bfab195b699c2b4 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Wed, 22 Jun 2016 00:29:49 +0100 Subject: [PATCH 077/129] test function capitalization --- .../CodeGen/EmittedIL/TestFunctions/env.lst | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/env.lst b/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/env.lst index fb6a949b63a..f69b5646511 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/env.lst +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/env.lst @@ -34,13 +34,13 @@ SOURCE=TestFunction15.fs SCFLAGS="-g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd TestFunction15.exe" # TestFunction15.fs SOURCE=TestFunction18.fs SCFLAGS="-g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd TestFunction18.exe" # TestFunction18.fs - SOURCE=TestFunction22.fs SCFLAGS="-g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd TestFunction22.exe" # TestFunction22.fs - SOURCE=TestFunction22b.fs SCFLAGS="-g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd TestFunction22b.exe" # TestFunction22b.fs - SOURCE=TestFunction22c.fs SCFLAGS="-g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd TestFunction22c.exe" # TestFunction22c.fs - SOURCE=TestFunction22d.fs SCFLAGS="-g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd TestFunction22d.exe" # TestFunction22d.fs - SOURCE=TestFunction22e.fs SCFLAGS="-g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd TestFunction22e.exe" # TestFunction22e.fs - SOURCE=TestFunction22f.fs SCFLAGS="-g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd TestFunction22f.exe" # TestFunction22f.fs - SOURCE=TestFunction22g.fs SCFLAGS="-g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd TestFunction22g.exe" # TestFunction22g.fs - - SOURCE=TestFunction22h.fs SCFLAGS="-g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd TestFunction22h.exe NetFx40" # TestFunction22h.fs - NetFx40 + SOURCE=Testfunction22.fs SCFLAGS="-g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd TestFunction22.exe" # TestFunction22.fs + SOURCE=Testfunction22b.fs SCFLAGS="-g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd TestFunction22b.exe" # TestFunction22b.fs + SOURCE=Testfunction22c.fs SCFLAGS="-g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd TestFunction22c.exe" # TestFunction22c.fs + SOURCE=Testfunction22d.fs SCFLAGS="-g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd TestFunction22d.exe" # TestFunction22d.fs + SOURCE=Testfunction22e.fs SCFLAGS="-g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd TestFunction22e.exe" # TestFunction22e.fs + SOURCE=Testfunction22f.fs SCFLAGS="-g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd TestFunction22f.exe" # TestFunction22f.fs + SOURCE=Testfunction22g.fs SCFLAGS="-g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd TestFunction22g.exe" # TestFunction22g.fs + + SOURCE=Testfunction22h.fs SCFLAGS="-g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd TestFunction22h.exe NetFx40" # TestFunction22h.fs - NetFx40 SOURCE=TestFunction24.fs SCFLAGS="-g --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd TestFunction24.exe NetFx40" # TestFunction24.fs - NetFx40 From b322bb283803c807ae320f7e7dcab4cf51fc0aee Mon Sep 17 00:00:00 2001 From: Don Syme Date: Wed, 22 Jun 2016 08:22:06 +0100 Subject: [PATCH 078/129] fix test --- tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/env.lst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/env.lst b/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/env.lst index f69b5646511..9196e88642c 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/env.lst +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/env.lst @@ -43,4 +43,4 @@ SOURCE=Testfunction22g.fs SCFLAGS="-g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd TestFunction22g.exe" # TestFunction22g.fs SOURCE=Testfunction22h.fs SCFLAGS="-g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd TestFunction22h.exe NetFx40" # TestFunction22h.fs - NetFx40 - SOURCE=TestFunction24.fs SCFLAGS="-g --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd TestFunction24.exe NetFx40" # TestFunction24.fs - NetFx40 + SOURCE=TestFunction24.fs SCFLAGS="-g --optimize-" PEVER=/Exp_Fail COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd TestFunction24.exe NetFx40" # TestFunction24.fs - NetFx40 From 38657fa22fc5f232dfffa71c992129ef6d95bfd9 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Wed, 22 Jun 2016 13:10:03 +0100 Subject: [PATCH 079/129] add a warning to mutable use bindings --- src/fsharp/FSComp.txt | 1 + src/fsharp/TypeChecker.fs | 43 ++++++++++++++------------- tests/fsharp/typecheck/sigs/neg96.bsl | 4 ++- tests/fsharp/typecheck/sigs/neg96.fs | 4 +++ 4 files changed, 31 insertions(+), 21 deletions(-) diff --git a/src/fsharp/FSComp.txt b/src/fsharp/FSComp.txt index 5bbff5d3ffa..448d8368967 100644 --- a/src/fsharp/FSComp.txt +++ b/src/fsharp/FSComp.txt @@ -1307,3 +1307,4 @@ estApplyStaticArgumentsForMethodNotImplemented,"A type provider implemented GetS 3201,tcModuleAbbrevFirstInMutRec,"In a recursive declaration group, module abbreviations must come after all 'open' declarations and before other declarations" 3202,tcUnsupportedMutRecDecl,"This declaration is not supported in recursive declaration groups" 3203,parsInvalidUseOfRec,"Invalid use of 'rec' keyword" +3204,tcUseMayNotBeMutable,"This feature is deprecated. A 'use' binding may not be marked 'mutable'." diff --git a/src/fsharp/TypeChecker.fs b/src/fsharp/TypeChecker.fs index c8cfc054800..7567f61b221 100755 --- a/src/fsharp/TypeChecker.fs +++ b/src/fsharp/TypeChecker.fs @@ -1196,7 +1196,6 @@ type TcPatPhase2Input = type CheckedBindingInfo = | CheckedBindingInfo of ValInline * - bool * (* immutable? *) Tast.Attribs * XmlDoc * (TcPatPhase2Input -> PatternMatchCompilation.Pattern) * @@ -1209,8 +1208,8 @@ type CheckedBindingInfo = SequencePointInfoForBinding * bool * (* compiler generated? *) Const option (* literal value? *) - member x.Expr = let (CheckedBindingInfo(_,_,_,_,_,_,_,expr,_,_,_,_,_,_)) = x in expr - member x.SeqPoint = let (CheckedBindingInfo(_,_,_,_,_,_,_,_,_,_,_,spBind,_,_)) = x in spBind + member x.Expr = let (CheckedBindingInfo(_,_,_,_,_,_,expr,_,_,_,_,_,_)) = x in expr + member x.SeqPoint = let (CheckedBindingInfo(_,_,_,_,_,_,_,_,_,_,spBind,_,_)) = x in spBind //------------------------------------------------------------------------- // Helpers related to type schemes @@ -2174,7 +2173,7 @@ module GeneralizationHelpers = let ComputeAndGeneralizeGenericTypars (cenv, denv:DisplayEnv, m, - immut, + canGeneralize, freeInEnv:FreeTypars, canInferTypars, genConstrainedTyparFlag, @@ -2187,7 +2186,7 @@ module GeneralizationHelpers = let allDeclaredTypars = NormalizeDeclaredTyparsForEquiRecursiveInference cenv.g allDeclaredTypars let typarsToAttemptToGeneralize = - if immut && (match exprOpt with None -> true | Some e -> IsGeneralizableValue cenv.g e) + if canGeneralize && (match exprOpt with None -> true | Some e -> IsGeneralizableValue cenv.g e) then (ListSet.unionFavourLeft typarEq allDeclaredTypars maxInferredTypars) else allDeclaredTypars @@ -6262,9 +6261,9 @@ and TcObjectExprBinding cenv (env: TcEnv) implty tpenv (absSlotInfo,bind) = | _ -> implty --> NewInferenceType () - let (CheckedBindingInfo(inlineFlag,immut,bindingAttribs,_,_,ExplicitTyparInfo(_,declaredTypars,_),nameToPrelimValSchemeMap,rhsExpr,_,_,m,_,_,_),tpenv) = + let (CheckedBindingInfo(inlineFlag,bindingAttribs,_,_,ExplicitTyparInfo(_,declaredTypars,_),nameToPrelimValSchemeMap,rhsExpr,_,_,m,_,_,_),tpenv) = let flex, tpenv = TcNonrecBindingTyparDecls cenv env tpenv bind - TcNormalizedBinding ObjectExpressionOverrideBinding cenv env tpenv bindingTy None NoSafeInitInfo ([],flex) bind + TcNormalizedBinding ObjectExpressionOverrideBinding cenv env tpenv false bindingTy None NoSafeInitInfo ([],flex) bind // 4c. generalize the binding - only relevant when implementing a generic virtual method @@ -6283,7 +6282,7 @@ and TcObjectExprBinding cenv (env: TcEnv) implty tpenv (absSlotInfo,bind) = let freeInEnv = GeneralizationHelpers.ComputeUngeneralizableTypars env - let generalizedTypars = GeneralizationHelpers.ComputeAndGeneralizeGenericTypars(cenv,denv,m,immut,freeInEnv,false,CanGeneralizeConstrainedTypars,inlineFlag,Some(rhsExpr),declaredTypars,[],bindingTy,false) + let generalizedTypars = GeneralizationHelpers.ComputeAndGeneralizeGenericTypars(cenv,denv,m,true,freeInEnv,false,CanGeneralizeConstrainedTypars,inlineFlag,Some(rhsExpr),declaredTypars,[],bindingTy,false) let declaredTypars = ChooseCanonicalDeclaredTyparsAfterInference cenv.g env.DisplayEnv declaredTypars m let generalizedTypars = PlaceTyparsInDeclarationOrder declaredTypars generalizedTypars @@ -9773,7 +9772,7 @@ and TcStaticOptimizationConstraint cenv env tpenv c = TTyconIsStruct(mkTyparTy tp'),tpenv /// Binding checking code, for all bindings including let bindings, let-rec bindings, member bindings and object-expression bindings and -and TcNormalizedBinding declKind (cenv:cenv) env tpenv overallTy safeThisValOpt safeInitInfo (enclosingDeclaredTypars,(ExplicitTyparInfo(_,declaredTypars,_) as flex)) bind = +and TcNormalizedBinding declKind (cenv:cenv) env tpenv isUse overallTy safeThisValOpt safeInitInfo (enclosingDeclaredTypars,(ExplicitTyparInfo(_,declaredTypars,_) as flex)) bind = let envinner = AddDeclaredTypars NoCheckForDuplicateTypars (enclosingDeclaredTypars@declaredTypars) env match bind with @@ -9798,6 +9797,7 @@ and TcNormalizedBinding declKind (cenv:cenv) env tpenv overallTy safeThisValOpt let argAttribs = spatsL |> List.map (SynInfo.InferSynArgInfoFromSimplePats >> List.map (SynInfo.AttribsOfArgData >> TcAttrs AttributeTargets.Parameter)) + let retAttribs = match rtyOpt with | Some (SynBindingReturnInfo(_,_,retAttrs)) -> TcAttrs AttributeTargets.ReturnValue retAttrs @@ -9817,6 +9817,9 @@ and TcNormalizedBinding declKind (cenv:cenv) env tpenv overallTy safeThisValOpt if (not isMutable || isThreadStatic) then errorR(Error(FSComp.SR.tcVolatileFieldsMustBeMutable(),mBinding)) + if isUse && isMutable then + warning(Error(FSComp.SR.tcUseMayNotBeMutable(),mBinding)) + if HasFSharpAttributeOpt cenv.g cenv.g.attrib_DllImportAttribute valAttribs then if not declKind.CanBeDllImport || (match memberFlagsOpt with Some memberFlags -> memberFlags.IsInstance | _ -> false) then errorR(Error(FSComp.SR.tcDllImportNotAllowed(),mBinding)) @@ -9916,7 +9919,7 @@ and TcNormalizedBinding declKind (cenv:cenv) env tpenv overallTy safeThisValOpt if hasLiteralAttr && nonNil declaredTypars then errorR(Error(FSComp.SR.tcLiteralCannotHaveGenericParameters(),mBinding)) - CheckedBindingInfo(inlineFlag,true,valAttribs,doc,tcPatPhase2,flex,nameToPrelimValSchemeMap,rhsExpr',argAndRetAttribs,overallTy,mBinding,spBind,compgen,konst),tpenv + CheckedBindingInfo(inlineFlag,valAttribs,doc,tcPatPhase2,flex,nameToPrelimValSchemeMap,rhsExpr',argAndRetAttribs,overallTy,mBinding,spBind,compgen,konst),tpenv and TcLiteral cenv overallTy env tpenv (attrs,synLiteralValExpr) = let hasLiteralAttr = HasFSharpAttribute cenv.g cenv.g.attrib_LiteralAttribute attrs @@ -9958,10 +9961,10 @@ and TcNonrecBindingTyparDecls cenv env tpenv bind = let (NormalizedBinding(_,_,_,_,_,_,synTyparDecls,_,_,_,_,_)) = bind TcBindingTyparDecls true cenv env tpenv synTyparDecls -and TcNonRecursiveBinding declKind cenv env tpenv ty b = +and TcNonRecursiveBinding declKind cenv env tpenv isUse ty b = let b = BindingNormalization.NormalizeBinding ValOrMemberBinding cenv env b let flex, tpenv = TcNonrecBindingTyparDecls cenv env tpenv b - TcNormalizedBinding declKind cenv env tpenv ty None NoSafeInitInfo ([],flex) b + TcNormalizedBinding declKind cenv env tpenv isUse ty None NoSafeInitInfo ([],flex) b //------------------------------------------------------------------------- // TcAttribute* @@ -10164,14 +10167,14 @@ and TcAttributes cenv env attrTgt synAttribs = and TcLetBinding cenv isUse env containerInfo declKind tpenv (binds,bindsm,scopem) = // Typecheck all the bindings... - let binds',tpenv = List.mapFold (fun tpenv b -> TcNonRecursiveBinding declKind cenv env tpenv (NewInferenceType ()) b) tpenv binds + let binds',tpenv = List.mapFold (fun tpenv b -> TcNonRecursiveBinding declKind cenv env tpenv isUse (NewInferenceType ()) b) tpenv binds let (ContainerInfo(altActualParent,_)) = containerInfo // Canonicalize constraints prior to generalization let denv = env.DisplayEnv GeneralizationHelpers.CanonicalizePartialInferenceProblem (cenv,denv,bindsm) (binds' |> List.collect (fun tbinfo -> - let (CheckedBindingInfo(_,_,_,_,_,flex,_,_,_,tauTy,_,_,_,_)) = tbinfo + let (CheckedBindingInfo(_,_,_,_,flex,_,_,_,tauTy,_,_,_,_)) = tbinfo let (ExplicitTyparInfo(_,declaredTypars,_)) = flex let maxInferredTypars = (freeInTypeLeftToRight cenv.g false tauTy) declaredTypars @ maxInferredTypars)) @@ -10180,7 +10183,7 @@ and TcLetBinding cenv isUse env containerInfo declKind tpenv (binds,bindsm,scope // Generalize the bindings... (((fun x -> x), env, tpenv), binds') ||> List.fold (fun (mkf_sofar,env,tpenv) tbinfo -> - let (CheckedBindingInfo(inlineFlag,immut,attrs,doc,tcPatPhase2,flex,nameToPrelimValSchemeMap,rhsExpr,_,tauTy,m,spBind,_,konst)) = tbinfo + let (CheckedBindingInfo(inlineFlag,attrs,doc,tcPatPhase2,flex,nameToPrelimValSchemeMap,rhsExpr,_,tauTy,m,spBind,_,konst)) = tbinfo let enclosingDeclaredTypars = [] let (ExplicitTyparInfo(_,declaredTypars,canInferTypars)) = flex let allDeclaredTypars = enclosingDeclaredTypars @ declaredTypars @@ -10194,7 +10197,7 @@ and TcLetBinding cenv isUse env containerInfo declKind tpenv (binds,bindsm,scope [] else let freeInEnv = lazyFreeInEnv.Force() - GeneralizationHelpers.ComputeAndGeneralizeGenericTypars(cenv,denv, m, immut, freeInEnv, canInferTypars, GeneralizationHelpers.CanGeneralizeConstrainedTyparsForDecl(declKind), inlineFlag, Some rhsExpr, allDeclaredTypars, maxInferredTypars,tauTy,false) + GeneralizationHelpers.ComputeAndGeneralizeGenericTypars(cenv,denv, m, true, freeInEnv, canInferTypars, GeneralizationHelpers.CanGeneralizeConstrainedTyparsForDecl(declKind), inlineFlag, Some rhsExpr, allDeclaredTypars, maxInferredTypars,tauTy,false) let prelimValSchemes2 = GeneralizeVals cenv denv enclosingDeclaredTypars generalizedTypars nameToPrelimValSchemeMap @@ -10809,7 +10812,7 @@ and TcLetrecBinding let envRec = MakeInnerEnvForMember cenv envRec vspec let checkedBind,tpenv = - TcNormalizedBinding declKind cenv envRec tpenv tau safeThisValOpt safeInitInfo (enclosingDeclaredTypars,flex) rbind.SyntacticBinding + TcNormalizedBinding declKind cenv envRec tpenv false tau safeThisValOpt safeInitInfo (enclosingDeclaredTypars,flex) rbind.SyntacticBinding (try UnifyTypes cenv envRec vspec.Range (allDeclaredTypars +-> tau) vspec.Type with e -> error (Recursion(envRec.DisplayEnv,vspec.Id,tau,vspec.Type,vspec.Range))) @@ -11026,7 +11029,7 @@ and TcLetrecComputeAndGeneralizeGenericTyparsForBinding cenv denv freeInEnv (pgr let rbinfo = pgrbind.RecBindingInfo let vspec = rbinfo.Val - let (CheckedBindingInfo(inlineFlag,immut,_,_,_,_,_,expr,_,_,m,_,_,_)) = pgrbind.CheckedBinding + let (CheckedBindingInfo(inlineFlag,_,_,_,_,_,expr,_,_,m,_,_,_)) = pgrbind.CheckedBinding let (ExplicitTyparInfo(rigidCopyOfDeclaredTypars,declaredTypars,_)) = rbinfo.ExplicitTyparInfo let allDeclaredTypars = rbinfo.EnclosingDeclaredTypars @ declaredTypars @@ -11047,7 +11050,7 @@ and TcLetrecComputeAndGeneralizeGenericTyparsForBinding cenv denv freeInEnv (pgr let maxInferredTypars = freeInTypeLeftToRight cenv.g false tau let canGeneralizeConstrained = GeneralizationHelpers.CanGeneralizeConstrainedTyparsForDecl rbinfo.DeclKind - let generalizedTypars = GeneralizationHelpers.ComputeAndGeneralizeGenericTypars (cenv,denv,m,immut,freeInEnv,canInferTypars,canGeneralizeConstrained,inlineFlag, Some(expr), allDeclaredTypars, maxInferredTypars,tau,isCtor) + let generalizedTypars = GeneralizationHelpers.ComputeAndGeneralizeGenericTypars (cenv,denv,m,true,freeInEnv,canInferTypars,canGeneralizeConstrained,inlineFlag, Some(expr), allDeclaredTypars, maxInferredTypars,tau,isCtor) generalizedTypars /// Compute the type variables which may have member constraints that need to be canonicalized prior to generalization @@ -11065,7 +11068,7 @@ and TcLetrecComputeSupportForBinding cenv (pgrbind : PreGeneralizationRecursiveB and TcLetrecGeneralizeBinding cenv denv generalizedTypars (pgrbind : PreGeneralizationRecursiveBinding) : PostGeneralizationRecursiveBinding = let (RBInfo(_,_,enclosingDeclaredTypars,_,vspec,flex,partialValReprInfo,memberInfoOpt,_,_,_,vis,_,declKind)) = pgrbind.RecBindingInfo - let (CheckedBindingInfo(inlineFlag,_,_,_,_,_,_,expr,argAttribs,_,_,_,compgen,_)) = pgrbind.CheckedBinding + let (CheckedBindingInfo(inlineFlag,_,_,_,_,_,expr,argAttribs,_,_,_,compgen,_)) = pgrbind.CheckedBinding let _,tau = vspec.TypeScheme diff --git a/tests/fsharp/typecheck/sigs/neg96.bsl b/tests/fsharp/typecheck/sigs/neg96.bsl index 29902eb4c44..d89370c98a1 100644 --- a/tests/fsharp/typecheck/sigs/neg96.bsl +++ b/tests/fsharp/typecheck/sigs/neg96.bsl @@ -1,2 +1,4 @@ -neg95.fs(11,9,11,21): typecheck error FS0039: The value or constructor 'StructRecord' is not defined \ No newline at end of file +neg95.fs(11,9,11,21): typecheck error FS0039: The value or constructor 'StructRecord' is not defined + +neg96.fs(14,17,14,18): typecheck error FS3204: This feature is deprecated. A 'use' binding may not be marked 'mutable'. \ No newline at end of file diff --git a/tests/fsharp/typecheck/sigs/neg96.fs b/tests/fsharp/typecheck/sigs/neg96.fs index e46b8fb7fee..d823086822a 100644 --- a/tests/fsharp/typecheck/sigs/neg96.fs +++ b/tests/fsharp/typecheck/sigs/neg96.fs @@ -9,3 +9,7 @@ type StructRecord = } let x = StructRecord () + +let invalidUse() = + use mutable x = (null : System.IDisposable) + () From 9fa854701fc6794a85f490d517cbb8472f54d268 Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Wed, 22 Jun 2016 11:19:28 +0200 Subject: [PATCH 080/129] Show better error when using ref cell - fixes #1276 --- src/fsharp/CompileOps.fs | 11 +++++++---- src/fsharp/FSComp.txt | 1 + tests/fsharpqa/Source/Warnings/RefCellInsteadOfNot.fs | 9 +++++++++ .../fsharpqa/Source/Warnings/RefCellInsteadOfNot2.fs | 8 ++++++++ tests/fsharpqa/Source/Warnings/env.lst | 2 ++ 5 files changed, 27 insertions(+), 4 deletions(-) create mode 100644 tests/fsharpqa/Source/Warnings/RefCellInsteadOfNot.fs create mode 100644 tests/fsharpqa/Source/Warnings/RefCellInsteadOfNot2.fs diff --git a/src/fsharp/CompileOps.fs b/src/fsharp/CompileOps.fs index 5f5a532bbfe..2317eb007da 100755 --- a/src/fsharp/CompileOps.fs +++ b/src/fsharp/CompileOps.fs @@ -621,7 +621,7 @@ let OutputPhasedErrorR (os:System.Text.StringBuilder) (err:PhasedError) = (if m.StartLine <> m2.StartLine then os.Append(SeeAlsoE().Format (stringOfRange m)) |> ignore ) | ConstraintSolverTypesNotInEqualityRelation(denv,(TType_measure _ as t1),(TType_measure _ as t2),m,m2) -> - // REVIEW: consider if we need to show _cxs (the type parameter constrants) + // REVIEW: consider if we need to show _cxs (the type parameter constraints) let t1, t2, _cxs = NicePrint.minimalStringsOfTwoTypes denv t1 t2 os.Append(ConstraintSolverTypesNotInEqualityRelation1E().Format t1 t2 ) |> ignore (if m.StartLine <> m2.StartLine then @@ -633,7 +633,7 @@ let OutputPhasedErrorR (os:System.Text.StringBuilder) (err:PhasedError) = (if m.StartLine <> m2.StartLine then os.Append(SeeAlsoE().Format (stringOfRange m)) |> ignore) | ConstraintSolverTypesNotInSubsumptionRelation(denv,t1,t2,m,m2) -> - // REVIEW: consider if we need to show _cxs (the type parameter constrants) + // REVIEW: consider if we need to show _cxs (the type parameter constraints) let t1, t2, cxs= NicePrint.minimalStringsOfTwoTypes denv t1 t2 os.Append(ConstraintSolverTypesNotInSubsumptionRelationE().Format t2 t1 cxs) |> ignore (if m.StartLine <> m2.StartLine then @@ -654,9 +654,12 @@ let OutputPhasedErrorR (os:System.Text.StringBuilder) (err:PhasedError) = match contextInfo with | ContextInfo.OmittedElseBranch -> os.Append(FSComp.SR.missingElseBranch(t2)) |> ignore | ContextInfo.ElseBranch -> os.Append(FSComp.SR.elseBranchHasWrongType(t1,t2)) |> ignore - | ContextInfo.TupleInRecordFields -> + | ContextInfo.TupleInRecordFields -> + os.Append(ErrorFromAddingTypeEquation1E().Format t2 t1 tpcs) |> ignore + os.Append(System.Environment.NewLine + FSComp.SR.commaInsteadOfSemicolonInRecord()) |> ignore + | _ when t2 = "bool" && t1.EndsWith " ref" -> os.Append(ErrorFromAddingTypeEquation1E().Format t2 t1 tpcs) |> ignore - os.Append(System.Environment.NewLine + FSComp.SR.commaInsteadOfSemicolonInRecord()) |> ignore + os.Append(System.Environment.NewLine + FSComp.SR.derefInsteadOfNot()) |> ignore | _ -> os.Append(ErrorFromAddingTypeEquation1E().Format t2 t1 tpcs) |> ignore | ErrorFromAddingTypeEquation(_,_,_,_,((ConstraintSolverTypesNotInSubsumptionRelation _ | ConstraintSolverError _) as e), _, _) -> OutputExceptionR os e diff --git a/src/fsharp/FSComp.txt b/src/fsharp/FSComp.txt index 5bbff5d3ffa..fb2c03b7a50 100644 --- a/src/fsharp/FSComp.txt +++ b/src/fsharp/FSComp.txt @@ -18,6 +18,7 @@ undefinedNamePatternDiscriminator,"The pattern discriminator '%s' is not defined missingElseBranch,"The 'if' expression is missing an 'else' branch. The 'then' branch has type '%s'. Because 'if' is an expression, and not a statement, add an 'else' branch which returns a value of the same type." elseBranchHasWrongType,"All branches of an 'if' expression must return the same type. This expression was expected to have type '%s' but here has type '%s'." commaInsteadOfSemicolonInRecord,"A ';' is used to separate field values in records. Consider replacing ',' with ';'." +derefInsteadOfNot,"The '!' operator is used to dereference a ref cell. Consider using 'not expr' here." buildUnexpectedTypeArgs,"The non-generic type '%s' does not expect any type arguments, but here is given %d type argument(s)" returnUsedInsteadOfReturnBang,"Consider using 'return!' instead of 'return'." yieldUsedInsteadOfYieldBang,"Consider using 'yield!' instead of 'yield'." diff --git a/tests/fsharpqa/Source/Warnings/RefCellInsteadOfNot.fs b/tests/fsharpqa/Source/Warnings/RefCellInsteadOfNot.fs new file mode 100644 index 00000000000..1c6987bfa63 --- /dev/null +++ b/tests/fsharpqa/Source/Warnings/RefCellInsteadOfNot.fs @@ -0,0 +1,9 @@ +// #Warnings +//This expression was expected to have type +//The '!' operator is used to dereference a ref cell. Consider using 'not expr' here. + +let x = true +if !x then + printfn "hello" + +exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/RefCellInsteadOfNot2.fs b/tests/fsharpqa/Source/Warnings/RefCellInsteadOfNot2.fs new file mode 100644 index 00000000000..090934d8f56 --- /dev/null +++ b/tests/fsharpqa/Source/Warnings/RefCellInsteadOfNot2.fs @@ -0,0 +1,8 @@ +// #Warnings +//This expression was expected to have type +//The '!' operator is used to dereference a ref cell. Consider using 'not expr' here. + +let x = true +let y = !x + +exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/env.lst b/tests/fsharpqa/Source/Warnings/env.lst index 89651c646aa..cb14235cc9c 100644 --- a/tests/fsharpqa/Source/Warnings/env.lst +++ b/tests/fsharpqa/Source/Warnings/env.lst @@ -7,6 +7,8 @@ SOURCE=ElseBranchHasWrongType.fs # ElseBranchHasWrongType.fs SOURCE=MissingExpressionAfterLet.fs # MissingExpressionAfterLet.fs SOURCE=AssignmentOnImmutable.fs # AssignmentOnImmutable.fs + SOURCE=RefCellInsteadOfNot.fs # RefCellInsteadOfNot.fs + SOURCE=RefCellInsteadOfNot2.fs # RefCellInsteadOfNot2.fs SOURCE=UpcastInsteadOfDowncast.fs # UpcastInsteadOfDowncast.fs SOURCE=UpcastFunctionInsteadOfDowncast.fs # UpcastFunctionInsteadOfDowncast.fs SOURCE=DowncastInsteadOfUpcast.fs # DowncastInsteadOfUpcast.fs From 1599c24efb6901fb2df96a174cc6e2e68c82505c Mon Sep 17 00:00:00 2001 From: Don Syme Date: Wed, 22 Jun 2016 14:28:55 +0100 Subject: [PATCH 081/129] unreserve various keywords --- src/fsharp/lexhelp.fs | 13 +++---- .../E_ReservedIdentKeywords.fs | 36 +++++++++---------- 2 files changed, 23 insertions(+), 26 deletions(-) diff --git a/src/fsharp/lexhelp.fs b/src/fsharp/lexhelp.fs index 76e317797bf..bb93921b02b 100644 --- a/src/fsharp/lexhelp.fs +++ b/src/fsharp/lexhelp.fs @@ -281,18 +281,15 @@ module Keywords = ] (*------- reserved keywords which are ml-compatibility ids *) @ List.map (fun s -> (FSHARP,s,RESERVED)) - [ "atomic"; "break"; - "checked"; "component"; "constraint"; "constructor"; "continue"; - "eager"; - "fixed"; "fori"; "functor"; + [ "break"; + "checked"; "component"; "constraint"; "continue"; + "fixed"; "fori"; "include"; - "measure"; "method"; "mixin"; - "object"; + "mixin"; "parallel"; "params"; "process"; "protected"; "pure"; - "recursive"; "sealed"; "trait"; "tailcall"; - "virtual"; "volatile"; ] + "virtual"; ] let private unreserveWords = keywordList |> List.choose (function (mode,keyword,_) -> if mode = FSHARP then Some keyword else None) diff --git a/tests/fsharpqa/Source/Conformance/LexicalAnalysis/IdentifiersAndKeywords/E_ReservedIdentKeywords.fs b/tests/fsharpqa/Source/Conformance/LexicalAnalysis/IdentifiersAndKeywords/E_ReservedIdentKeywords.fs index 2c550ad3d3c..ec38124d2be 100644 --- a/tests/fsharpqa/Source/Conformance/LexicalAnalysis/IdentifiersAndKeywords/E_ReservedIdentKeywords.fs +++ b/tests/fsharpqa/Source/Conformance/LexicalAnalysis/IdentifiersAndKeywords/E_ReservedIdentKeywords.fs @@ -1,60 +1,60 @@ // #Regression #Conformance #LexicalAnalysis // Reserved identifiers and keywords // Also cover regression test for FSHARP1.0:5367 (keyword 'virtual') -let atomic = 10 + let break = 10 let checked = 10 let component = 10 let constraint = 10 -let constructor = 10 + let continue = 10 -let eager = 10 + let fixed = 10 let fori = 10 -let functor = 10 + let include = 10 -let method = 10 -let measure = 10 + + let mixin = 10 -let object = 10 + let parallel = 10 let params = 10 let process = 10 let protected = 10 let pure = 10 -let recursive = 10 + let sealed = 10 let tailcall = 10 let trait = 10 let virtual = 10 -let volatile = 10 -//The identifier 'atomic' is reserved for future use by F# + + //The identifier 'break' is reserved for future use by F# //The identifier 'checked' is reserved for future use by F# //The identifier 'component' is reserved for future use by F# //The identifier 'constraint' is reserved for future use by F# -//The identifier 'constructor' is reserved for future use by F# + //The identifier 'continue' is reserved for future use by F# -//The identifier 'eager' is reserved for future use by F# + //The identifier 'fixed' is reserved for future use by F# //The identifier 'fori' is reserved for future use by F# -//The identifier 'functor' is reserved for future use by F# + //The identifier 'include' is reserved for future use by F# -//The identifier 'method' is reserved for future use by F# -//The identifier 'measure' is reserved for future use by F# + + //The identifier 'mixin' is reserved for future use by F# -//The identifier 'object' is reserved for future use by F# + //The identifier 'parallel' is reserved for future use by F# //The identifier 'params' is reserved for future use by F# //The identifier 'process' is reserved for future use by F# //The identifier 'protected' is reserved for future use by F# //The identifier 'pure' is reserved for future use by F# -//The identifier 'recursive' is reserved for future use by F# + //The identifier 'sealed' is reserved for future use by F# //The identifier 'tailcall' is reserved for future use by F# //The identifier 'trait' is reserved for future use by F# //The identifier 'virtual' is reserved for future use by F# -//The identifier 'volatile' is reserved for future use by F# + From f9540e1229362cda40011067a4082e99534b45ed Mon Sep 17 00:00:00 2001 From: Omar Tawfik Date: Wed, 22 Jun 2016 15:30:23 -0700 Subject: [PATCH 082/129] Fix Loc Typo --- src/fsharp/FSComp.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fsharp/FSComp.txt b/src/fsharp/FSComp.txt index 5bbff5d3ffa..02dffd07376 100644 --- a/src/fsharp/FSComp.txt +++ b/src/fsharp/FSComp.txt @@ -221,7 +221,7 @@ forPrecisionMissingAfterDot,"Precision missing after the '.'" forFormatDoesntSupportPrecision,"'%s' format does not support precision" forBadFormatSpecifier,"Bad format specifier (after l or L): Expected ld,li,lo,lu,lx or lX. In F# code you can use %%d, %%x, %%o or %%u instead, which are overloaded to work with all basic integer types." forLIsUnnecessary,"The 'l' or 'L' in this format specifier is unnecessary. In F# code you can use %%d, %%x, %%o or %%u instead, which are overloaded to work with all basic integer types." -forHIsUnnecessary,"The 'h' or 'H' in this format specifier is unnecessary. You can use %%d, %%x, %%o or %%u instead, which are overloaded to work with all basic integer types.." +forHIsUnnecessary,"The 'h' or 'H' in this format specifier is unnecessary. You can use %%d, %%x, %%o or %%u instead, which are overloaded to work with all basic integer types." forDoesNotSupportPrefixFlag,"'%s' does not support prefix '%s' flag" forBadFormatSpecifierGeneral,"Bad format specifier: '%s'" elSysEnvExitDidntExit,"System.Environment.Exit did not exit" From 1ed74347c57235050a99d51ddca48e0733e1dc58 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Thu, 23 Jun 2016 12:36:04 +0100 Subject: [PATCH 083/129] update tests --- .../IdentifiersAndKeywords/W_ReservedWord01.fs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/fsharpqa/Source/Conformance/LexicalAnalysis/IdentifiersAndKeywords/W_ReservedWord01.fs b/tests/fsharpqa/Source/Conformance/LexicalAnalysis/IdentifiersAndKeywords/W_ReservedWord01.fs index 8b3a8681950..070cfca18ff 100644 --- a/tests/fsharpqa/Source/Conformance/LexicalAnalysis/IdentifiersAndKeywords/W_ReservedWord01.fs +++ b/tests/fsharpqa/Source/Conformance/LexicalAnalysis/IdentifiersAndKeywords/W_ReservedWord01.fs @@ -3,8 +3,8 @@ // Verify warning when using a reserved identifier -//The identifier 'atomic' is reserved for future use by F# -let atomic = 1 + + exit 0 From a400ecf3f81c4bae2bfbe4d78a0921c534bd23c2 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Thu, 23 Jun 2016 13:09:16 +0100 Subject: [PATCH 084/129] fix test --- tests/fsharp/typecheck/sigs/neg02.bsl | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/fsharp/typecheck/sigs/neg02.bsl b/tests/fsharp/typecheck/sigs/neg02.bsl index 77a47cc01ce..8648e0076c6 100644 --- a/tests/fsharp/typecheck/sigs/neg02.bsl +++ b/tests/fsharp/typecheck/sigs/neg02.bsl @@ -1,8 +1,4 @@ -neg02.fs(6,8,6,15): parse error FS0046: The identifier 'virtual' is reserved for future use by F# - neg02.fs(6,8,6,15): parse error FS0010: Unexpected identifier in member definition -neg02.fs(11,8,11,14): parse error FS0046: The identifier 'method' is reserved for future use by F# - neg02.fs(17,7,17,13): parse error FS0010: Unexpected keyword 'static' in member definition. Expected 'member', 'override' or other token. From 7cae7f14560bff078ab8d86d8a6a9a62bca6970d Mon Sep 17 00:00:00 2001 From: Don Syme Date: Thu, 23 Jun 2016 14:23:10 +0100 Subject: [PATCH 085/129] fix test --- tests/fsharp/typecheck/sigs/neg02.bsl | 2 ++ .../tests/unittests/Tests.LanguageService.ErrorList.fs | 8 ++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/fsharp/typecheck/sigs/neg02.bsl b/tests/fsharp/typecheck/sigs/neg02.bsl index 8648e0076c6..b7119f8e1d4 100644 --- a/tests/fsharp/typecheck/sigs/neg02.bsl +++ b/tests/fsharp/typecheck/sigs/neg02.bsl @@ -1,4 +1,6 @@ +neg02.fs(6,8,6,15): parse error FS0046: The identifier 'virtual' is reserved for future use by F# + neg02.fs(6,8,6,15): parse error FS0010: Unexpected identifier in member definition neg02.fs(17,7,17,13): parse error FS0010: Unexpected keyword 'static' in member definition. Expected 'member', 'override' or other token. diff --git a/vsintegration/tests/unittests/Tests.LanguageService.ErrorList.fs b/vsintegration/tests/unittests/Tests.LanguageService.ErrorList.fs index 86be53980a5..e06e5d29f24 100644 --- a/vsintegration/tests/unittests/Tests.LanguageService.ErrorList.fs +++ b/vsintegration/tests/unittests/Tests.LanguageService.ErrorList.fs @@ -876,8 +876,8 @@ but here has type member public this.``Warning.ConsistentWithLanguageService``() = let fileContent = """ open System - atomic atomic atomic atomic atomic atomic atomic atomic atomic atomic - atomic atomic atomic atomic atomic atomic atomic atomic atomic atomic""" + mixin mixin mixin mixin mixin mixin mixin mixin mixin mixin + mixin mixin mixin mixin mixin mixin mixin mixin mixin mixin""" let (_, project, file) = this.CreateSingleFileProject(fileContent, fileKind = SourceFileKind.FSX) TakeCoffeeBreak(this.VS) // Wait for the background compiler to catch up. let warnList = GetWarnings(project) @@ -887,8 +887,8 @@ but here has type member public this.``Warning.ConsistentWithLanguageService.Comment``() = let fileContent = """ open System - //atomic atomic atomic atomic atomic atomic atomic atomic atomic atomic - //atomic atomic atomic atomic atomic atomic atomic atomic atomic atomic""" + //mixin mixin mixin mixin mixin mixin mixin mixin mixin mixin + //mixin mixin mixin mixin mixin mixin mixin mixin mixin mixin""" let (_, project, file) = this.CreateSingleFileProject(fileContent, fileKind = SourceFileKind.FSX) TakeCoffeeBreak(this.VS) // Wait for the background compiler to catch up. let warnList = GetWarnings(project) From 6ef35469f7ccc969e99ec9606c6d84e438aeffd2 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Thu, 23 Jun 2016 15:10:43 +0100 Subject: [PATCH 086/129] feedback from code review --- src/absil/ilwrite.fs | 15 +++++++-------- src/fsharp/tast.fs | 2 +- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/absil/ilwrite.fs b/src/absil/ilwrite.fs index 98a17a556bf..556102c43ea 100644 --- a/src/absil/ilwrite.fs +++ b/src/absil/ilwrite.fs @@ -850,10 +850,7 @@ and GetTypeAsTypeDefOrRef cenv env (ty:ILType) = and GetTypeAsBytes cenv env ty = emitBytesViaBuffer (fun bb -> EmitType cenv env bb ty) and GetTypeOfLocalAsBytes cenv env (l: ILLocal) = - emitBytesViaBuffer (fun bb -> - if l.IsPinned then - bb.EmitByte et_PINNED - EmitType cenv env bb l.Type) + emitBytesViaBuffer (fun bb -> EmitLocalInfo cenv env bb l) and GetTypeAsBlobIdx cenv env (ty:ILType) = GetBytesAsBlobIdx cenv (GetTypeAsBytes cenv env ty) @@ -918,6 +915,11 @@ and EmitType cenv env bb ty = EmitType cenv env bb ty | _ -> failwith "EmitType" +and EmitLocalInfo cenv env (bb:ByteBuffer) (l:ILLocal) = + if l.IsPinned then + bb.EmitByte et_PINNED + EmitType cenv env bb l.Type + and EmitCallsig cenv env bb (callconv,args:ILTypes,ret,varargs:ILVarArgs,genarity) = bb.EmitByte (callconvToByte genarity callconv) if genarity > 0 then bb.EmitZ32 genarity @@ -1500,10 +1502,7 @@ let GetCallsigAsStandAloneSigIdx cenv env info = let EmitLocalSig cenv env (bb: ByteBuffer) (locals: ILLocals) = bb.EmitByte e_IMAGE_CEE_CS_CALLCONV_LOCAL_SIG bb.EmitZ32 locals.Length - locals |> ILList.iter (fun l -> - if l.IsPinned then - bb.EmitByte et_PINNED - EmitType cenv env bb l.Type) + locals |> ILList.iter (EmitLocalInfo cenv env bb) let GetLocalSigAsBlobHeapIdx cenv env locals = GetBytesAsBlobIdx cenv (emitBytesViaBuffer (fun bb -> EmitLocalSig cenv env bb locals)) diff --git a/src/fsharp/tast.fs b/src/fsharp/tast.fs index 5e338e3294a..e25efe08d18 100755 --- a/src/fsharp/tast.fs +++ b/src/fsharp/tast.fs @@ -243,7 +243,7 @@ type ValFlags(flags:int64) = // Clear the IsCompiledAsStaticPropertyWithoutField, only used to determine whether to use a true field for a value, and to eliminate the optimization info for observable bindings // Clear the HasBeenReferenced, only used to report "unreferenced variable" warnings and to help collect 'it' values in FSI.EXE // Clear the IsGeneratedEventVal, since there's no use in propagating specialname information for generated add/remove event vals - (flags &&& ~~~0b1011001100000000000L) + (flags &&& ~~~0b0011001100000000000L) /// Represents the kind of a type parameter [] From 8aefe6c71308e7512b79e6142ffde678238800e7 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Sat, 25 Jun 2016 14:55:36 +0100 Subject: [PATCH 087/129] integrate and fix conflicts --- tests/fsharp/typecheck/sigs/neg96.bsl | 2 +- tests/fsharp/typecheck/sigs/neg97.bsl | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/fsharp/typecheck/sigs/neg96.bsl b/tests/fsharp/typecheck/sigs/neg96.bsl index d89370c98a1..99319706645 100644 --- a/tests/fsharp/typecheck/sigs/neg96.bsl +++ b/tests/fsharp/typecheck/sigs/neg96.bsl @@ -1,4 +1,4 @@ neg95.fs(11,9,11,21): typecheck error FS0039: The value or constructor 'StructRecord' is not defined -neg96.fs(14,17,14,18): typecheck error FS3204: This feature is deprecated. A 'use' binding may not be marked 'mutable'. \ No newline at end of file +neg96.fs(14,17,14,18): typecheck error FS3205: This feature is deprecated. A 'use' binding may not be marked 'mutable'. \ No newline at end of file diff --git a/tests/fsharp/typecheck/sigs/neg97.bsl b/tests/fsharp/typecheck/sigs/neg97.bsl index 3bbeb123ffd..860f9fd6f37 100644 --- a/tests/fsharp/typecheck/sigs/neg97.bsl +++ b/tests/fsharp/typecheck/sigs/neg97.bsl @@ -1,10 +1,10 @@ neg97.fs(13,1,13,2): typecheck error FS0256: A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...' -neg97.fs(16,9,16,10): typecheck error FS3204: Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is an array, the address of a field, the address of an array element or a string' +neg97.fs(16,9,16,10): typecheck error FS3207: Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is an array, the address of a field, the address of an array element or a string' -neg97.fs(20,9,20,10): typecheck error FS3204: Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is an array, the address of a field, the address of an array element or a string' +neg97.fs(20,9,20,10): typecheck error FS3207: Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is an array, the address of a field, the address of an array element or a string' -neg97.fs(25,9,25,10): typecheck error FS3204: Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is an array, the address of a field, the address of an array element or a string' +neg97.fs(25,9,25,10): typecheck error FS3207: Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is an array, the address of a field, the address of an array element or a string' -neg97.fs(30,9,30,10): typecheck error FS3204: Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is an array, the address of a field, the address of an array element or a string' +neg97.fs(30,9,30,10): typecheck error FS3207: Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is an array, the address of a field, the address of an array element or a string' From a4032497a19be81bfbd6bf656fd98234931cf9ab Mon Sep 17 00:00:00 2001 From: Enrico Sada Date: Mon, 27 Jun 2016 19:11:35 +0200 Subject: [PATCH 088/129] update buildtools deps to https://github.com/dotnet/corefx/commit/96ae037b9359e2ab220bc5c370bf952b4234a039 --- BuildToolsVersion.txt | 2 +- DotnetCLIVersion.txt | 2 +- init-tools.cmd | 33 +++++++++++++++++++-------------- init-tools.sh | 28 ++++++++++++---------------- 4 files changed, 33 insertions(+), 32 deletions(-) diff --git a/BuildToolsVersion.txt b/BuildToolsVersion.txt index 183e149f4c5..7a2bca562e7 100644 --- a/BuildToolsVersion.txt +++ b/BuildToolsVersion.txt @@ -1 +1 @@ -1.0.25-prerelease-00404-01 +1.0.25-prerelease-00517-05 diff --git a/DotnetCLIVersion.txt b/DotnetCLIVersion.txt index cbe430cd616..dd7bc318fa7 100644 --- a/DotnetCLIVersion.txt +++ b/DotnetCLIVersion.txt @@ -1 +1 @@ -1.0.0-rc2-002665 \ No newline at end of file +1.0.0-preview2-002733 \ No newline at end of file diff --git a/init-tools.cmd b/init-tools.cmd index d48ff4d1248..13d61e8ea4c 100644 --- a/init-tools.cmd +++ b/init-tools.cmd @@ -7,11 +7,11 @@ if [%TOOLRUNTIME_DIR%]==[] set TOOLRUNTIME_DIR=%~dp0Tools set DOTNET_PATH=%TOOLRUNTIME_DIR%\dotnetcli\ if [%DOTNET_CMD%]==[] set DOTNET_CMD=%DOTNET_PATH%dotnet.exe if [%BUILDTOOLS_SOURCE%]==[] set BUILDTOOLS_SOURCE=https://dotnet.myget.org/F/dotnet-buildtools/api/v3/index.json -set /P BUILDTOOLS_VERSION=< %~dp0BuildToolsVersion.txt +set /P BUILDTOOLS_VERSION=< "%~dp0BuildToolsVersion.txt" set BUILD_TOOLS_PATH=%PACKAGES_DIR%Microsoft.DotNet.BuildTools\%BUILDTOOLS_VERSION%\lib\ set PROJECT_JSON_PATH=%TOOLRUNTIME_DIR%\%BUILDTOOLS_VERSION% set PROJECT_JSON_FILE=%PROJECT_JSON_PATH%\project.json -set PROJECT_JSON_CONTENTS={ "dependencies": { "Microsoft.DotNet.BuildTools": "%BUILDTOOLS_VERSION%" }, "frameworks": { "dnxcore50": { } } } +set PROJECT_JSON_CONTENTS={ "dependencies": { "Microsoft.DotNet.BuildTools": "%BUILDTOOLS_VERSION%" }, "frameworks": { "netcoreapp1.0": { } } } set BUILD_TOOLS_SEMAPHORE=%PROJECT_JSON_PATH%\init-tools.completed :: if force option is specified then clean the tool runtime and build tools package directory to force it to get recreated @@ -29,40 +29,45 @@ if exist "%BUILD_TOOLS_SEMAPHORE%" ( if exist "%TOOLRUNTIME_DIR%" rmdir /S /Q "%TOOLRUNTIME_DIR%" if NOT exist "%PROJECT_JSON_PATH%" mkdir "%PROJECT_JSON_PATH%" -echo %PROJECT_JSON_CONTENTS% > %PROJECT_JSON_FILE% -echo Running %0 > %INIT_TOOLS_LOG% +echo %PROJECT_JSON_CONTENTS% > "%PROJECT_JSON_FILE%" +echo Running %0 > "%INIT_TOOLS_LOG%" if exist "%DOTNET_CMD%" goto :afterdotnetrestore echo Installing dotnet cli... if NOT exist "%DOTNET_PATH%" mkdir "%DOTNET_PATH%" -set /p DOTNET_VERSION=< %~dp0DotnetCLIVersion.txt +set /p DOTNET_VERSION=< "%~dp0DotnetCLIVersion.txt" set DOTNET_ZIP_NAME=dotnet-dev-win-x64.%DOTNET_VERSION%.zip -set DOTNET_REMOTE_PATH=https://dotnetcli.blob.core.windows.net/dotnet/beta/Binaries/%DOTNET_VERSION%/%DOTNET_ZIP_NAME% +set DOTNET_REMOTE_PATH=https://dotnetcli.blob.core.windows.net/dotnet/preview/Binaries/%DOTNET_VERSION%/%DOTNET_ZIP_NAME% set DOTNET_LOCAL_PATH=%DOTNET_PATH%%DOTNET_ZIP_NAME% -echo Installing '%DOTNET_REMOTE_PATH%' to '%DOTNET_LOCAL_PATH%' >> %INIT_TOOLS_LOG% -powershell -NoProfile -ExecutionPolicy unrestricted -Command "(New-Object Net.WebClient).DownloadFile('%DOTNET_REMOTE_PATH%', '%DOTNET_LOCAL_PATH%'); Add-Type -Assembly 'System.IO.Compression.FileSystem' -ErrorVariable AddTypeErrors; if ($AddTypeErrors.Count -eq 0) { [System.IO.Compression.ZipFile]::ExtractToDirectory('%DOTNET_LOCAL_PATH%', '%DOTNET_PATH%') } else { (New-Object -com shell.application).namespace('%DOTNET_PATH%').CopyHere((new-object -com shell.application).namespace('%DOTNET_LOCAL_PATH%').Items(),16) }" >> %INIT_TOOLS_LOG% +echo Installing '%DOTNET_REMOTE_PATH%' to '%DOTNET_LOCAL_PATH%' >> "%INIT_TOOLS_LOG%" +powershell -NoProfile -ExecutionPolicy unrestricted -Command "$retryCount = 0; $success = $false; do { try { (New-Object Net.WebClient).DownloadFile('%DOTNET_REMOTE_PATH%', '%DOTNET_LOCAL_PATH%'); $success = $true; } catch { if ($retryCount -ge 6) { throw; } else { $retryCount++; Start-Sleep -Seconds (5 * $retryCount); } } } while ($success -eq $false); Add-Type -Assembly 'System.IO.Compression.FileSystem' -ErrorVariable AddTypeErrors; if ($AddTypeErrors.Count -eq 0) { [System.IO.Compression.ZipFile]::ExtractToDirectory('%DOTNET_LOCAL_PATH%', '%DOTNET_PATH%') } else { (New-Object -com shell.application).namespace('%DOTNET_PATH%').CopyHere((new-object -com shell.application).namespace('%DOTNET_LOCAL_PATH%').Items(),16) }" >> "%INIT_TOOLS_LOG%" if NOT exist "%DOTNET_LOCAL_PATH%" ( echo ERROR: Could not install dotnet cli correctly. See '%INIT_TOOLS_LOG%' for more details. - goto :EOF + exit /b 1 ) :afterdotnetrestore if exist "%BUILD_TOOLS_PATH%" goto :afterbuildtoolsrestore echo Restoring BuildTools version %BUILDTOOLS_VERSION%... -echo Running: "%DOTNET_CMD%" restore "%PROJECT_JSON_FILE%" --packages %PACKAGES_DIR% --source "%BUILDTOOLS_SOURCE%" >> %INIT_TOOLS_LOG% -call "%DOTNET_CMD%" restore "%PROJECT_JSON_FILE%" --packages %PACKAGES_DIR% --source "%BUILDTOOLS_SOURCE%" >> %INIT_TOOLS_LOG% +echo Running: "%DOTNET_CMD%" restore "%PROJECT_JSON_FILE%" --packages %PACKAGES_DIR% --source "%BUILDTOOLS_SOURCE%" >> "%INIT_TOOLS_LOG%" +call "%DOTNET_CMD%" restore "%PROJECT_JSON_FILE%" --packages %PACKAGES_DIR% --source "%BUILDTOOLS_SOURCE%" >> "%INIT_TOOLS_LOG%" if NOT exist "%BUILD_TOOLS_PATH%init-tools.cmd" ( echo ERROR: Could not restore build tools correctly. See '%INIT_TOOLS_LOG%' for more details. - goto :EOF + exit /b 1 ) :afterbuildtoolsrestore echo Initializing BuildTools ... -echo Running: "%BUILD_TOOLS_PATH%init-tools.cmd" "%~dp0" "%DOTNET_CMD%" "%TOOLRUNTIME_DIR%" >> %INIT_TOOLS_LOG% -call "%BUILD_TOOLS_PATH%init-tools.cmd" "%~dp0" "%DOTNET_CMD%" "%TOOLRUNTIME_DIR%" >> %INIT_TOOLS_LOG% +echo Running: "%BUILD_TOOLS_PATH%init-tools.cmd" "%~dp0" "%DOTNET_CMD%" "%TOOLRUNTIME_DIR%" >> "%INIT_TOOLS_LOG%" +call "%BUILD_TOOLS_PATH%init-tools.cmd" "%~dp0" "%DOTNET_CMD%" "%TOOLRUNTIME_DIR%" >> "%INIT_TOOLS_LOG%" +set INIT_TOOLS_ERRORLEVEL=%ERRORLEVEL% +if not [%INIT_TOOLS_ERRORLEVEL%]==[0] ( + echo ERROR: An error occured when trying to initialize the tools. Please check '%INIT_TOOLS_LOG%' for more details. + exit /b %INIT_TOOLS_ERRORLEVEL% +) :: Create sempahore file echo Done initializing tools. diff --git a/init-tools.sh b/init-tools.sh index 033a652cde5..57564e7827a 100644 --- a/init-tools.sh +++ b/init-tools.sh @@ -12,7 +12,7 @@ __DOTNET_TOOLS_VERSION=$(cat $__scriptpath/DotnetCLIVersion.txt) __BUILD_TOOLS_PATH=$__PACKAGES_DIR/Microsoft.DotNet.BuildTools/$__BUILD_TOOLS_PACKAGE_VERSION/lib __PROJECT_JSON_PATH=$__TOOLRUNTIME_DIR/$__BUILD_TOOLS_PACKAGE_VERSION __PROJECT_JSON_FILE=$__PROJECT_JSON_PATH/project.json -__PROJECT_JSON_CONTENTS="{ \"dependencies\": { \"Microsoft.DotNet.BuildTools\": \"$__BUILD_TOOLS_PACKAGE_VERSION\" }, \"frameworks\": { \"dnxcore50\": { } } }" +__PROJECT_JSON_CONTENTS="{ \"dependencies\": { \"Microsoft.DotNet.BuildTools\": \"$__BUILD_TOOLS_PACKAGE_VERSION\" }, \"frameworks\": { \"netcoreapp1.0\": { } } }" OSName=$(uname -s) case $OSName in @@ -24,14 +24,12 @@ case $OSName in Linux) OS=Linux - source /etc/os-release - if [ "$ID" == "centos" -o "$ID" == "rhel" ]; then - __DOTNET_PKG=dotnet-dev-centos-x64 - elif [ "$ID" == "ubuntu" -o "$ID" == "debian" ]; then - __DOTNET_PKG=dotnet-dev-ubuntu-x64 + if [ ! -e /etc/os-release ]; then + echo "Cannot determine Linux distribution, asuming Ubuntu 14.04." + __DOTNET_PKG=dotnet-dev-ubuntu.14.04-x64 else - echo "Unsupported Linux distribution '$ID' detected. Downloading ubuntu-x64 tools." - __DOTNET_PKG=dotnet-dev-ubuntu-x64 + source /etc/os-release + __DOTNET_PKG="dotnet-dev-$ID.$VERSION_ID-x64" fi ;; @@ -47,7 +45,7 @@ if [ ! -e $__PROJECT_JSON_FILE ]; then echo "Running: $__scriptpath/init-tools.sh" > $__init_tools_log if [ ! -e $__DOTNET_PATH ]; then echo "Installing dotnet cli..." - __DOTNET_LOCATION="https://dotnetcli.blob.core.windows.net/dotnet/beta/Binaries/${__DOTNET_TOOLS_VERSION}/${__DOTNET_PKG}.${__DOTNET_TOOLS_VERSION}.tar.gz" + __DOTNET_LOCATION="https://dotnetcli.blob.core.windows.net/dotnet/preview/Binaries/${__DOTNET_TOOLS_VERSION}/${__DOTNET_PKG}.${__DOTNET_TOOLS_VERSION}.tar.gz" # curl has HTTPS CA trust-issues less often than wget, so lets try that first. echo "Installing '${__DOTNET_LOCATION}' to '$__DOTNET_PATH/dotnet.tar'" >> $__init_tools_log which curl > /dev/null 2> /dev/null @@ -55,16 +53,10 @@ if [ ! -e $__PROJECT_JSON_FILE ]; then mkdir -p "$__DOTNET_PATH" wget -q -O $__DOTNET_PATH/dotnet.tar ${__DOTNET_LOCATION} else - curl -sSL --create-dirs -o $__DOTNET_PATH/dotnet.tar ${__DOTNET_LOCATION} + curl --retry 10 -sSL --create-dirs -o $__DOTNET_PATH/dotnet.tar ${__DOTNET_LOCATION} fi cd $__DOTNET_PATH tar -xf $__DOTNET_PATH/dotnet.tar - if [ -n "$BUILDTOOLS_OVERRIDE_RUNTIME" ]; then - find $__DOTNET_PATH -name *.ni.* | xargs rm 2>/dev/null - cp -R $BUILDTOOLS_OVERRIDE_RUNTIME/* $__DOTNET_PATH/bin - cp -R $BUILDTOOLS_OVERRIDE_RUNTIME/* $__DOTNET_PATH/bin/dnx - cp -R $BUILDTOOLS_OVERRIDE_RUNTIME/* $__DOTNET_PATH/runtime/coreclr - fi cd $__scriptpath fi @@ -82,6 +74,10 @@ if [ ! -e $__PROJECT_JSON_FILE ]; then echo "Initializing BuildTools..." echo "Running: $__BUILD_TOOLS_PATH/init-tools.sh $__scriptpath $__DOTNET_CMD $__TOOLRUNTIME_DIR" >> $__init_tools_log $__BUILD_TOOLS_PATH/init-tools.sh $__scriptpath $__DOTNET_CMD $__TOOLRUNTIME_DIR >> $__init_tools_log + if [ "$?" != "0" ]; then + echo "ERROR: An error occured when trying to initialize the tools. Please check '$__init_tools_log' for more details." + exit 1 + fi echo "Done initializing tools." else echo "Tools are already initialized" From 8dcde4fb1cccba5697d3d5f58855d6319033e365 Mon Sep 17 00:00:00 2001 From: Enrico Sada Date: Mon, 27 Jun 2016 19:14:21 +0200 Subject: [PATCH 089/129] let's used .NET Core RTM ( version 1.0.0-preview2-003121 ) --- DotnetCLIVersion.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DotnetCLIVersion.txt b/DotnetCLIVersion.txt index dd7bc318fa7..637c64f4b15 100644 --- a/DotnetCLIVersion.txt +++ b/DotnetCLIVersion.txt @@ -1 +1 @@ -1.0.0-preview2-002733 \ No newline at end of file +1.0.0-preview2-003121 \ No newline at end of file From a2efe03096d2800100b7d5499457c63a92ae9935 Mon Sep 17 00:00:00 2001 From: Enrico Sada Date: Mon, 27 Jun 2016 20:36:29 +0200 Subject: [PATCH 090/129] update deps to .NET Core 1.0 RTM System.Security.Cryptography.Algorithms depends on System.Security.Cryptography.Primitives, removed explicit Microsoft.NETCore.Runtime.CoreCLR 1.0.2 depends on Microsoft.NETCore.Windows.ApiSets 1.0.1, remove explicit System.Reflection.Emit 4.0.1 depends on System.Reflection.Emit.ILGeneration 4.0.1, removed explicit bump from System.Linq.Expressions 4.0.11-rc2-23911 to version 4.1.0 ( 1.0 RTM ) bump from System.Text.RegularExpressions 4.0.12-rc2-24027 to 4.1.0 ( 1.0 RTM ) support osx is 10.11 now, instead of 10.10 update System.Runtime.InteropServices.PInvoke to 4.0.0-rc2-24027 ?? no RTM?? --- src/fsharp/FSharp.Build/project.json | 4 +- ...rosoft.FSharp.Compiler.Host.netcore.nuspec | 11 ++-- .../project.json | 16 +++--- .../Microsoft.FSharp.Compiler.netcore.nuspec | 54 +++++++++---------- src/fsharp/FSharp.Compiler/project.json | 44 ++++++++------- src/fsharp/FSharp.Core/project.json | 54 +++++++++---------- src/fsharp/Fsc/project.json | 12 ++--- .../Microsoft.FSharp.Core.netcore.nuspec | 38 ++++++------- src/fsharp/fsi/project.json | 22 ++++---- 9 files changed, 125 insertions(+), 130 deletions(-) diff --git a/src/fsharp/FSharp.Build/project.json b/src/fsharp/FSharp.Build/project.json index 49e360894f7..40df8833427 100644 --- a/src/fsharp/FSharp.Build/project.json +++ b/src/fsharp/FSharp.Build/project.json @@ -12,11 +12,11 @@ "System.AppContext": "4.1.0-rc2-24027", "System.Diagnostics.Tools": "4.0.1-rc2-24027", "System.Reflection.Primitives": "4.0.1-rc2-24027", - "System.Resources.ResourceManager": "4.0.1-rc2-24027", + "System.Resources.ResourceManager": "4.0.1-rc2-24027" }, "frameworks": { "dnxcore50": { - "imports": "portable-net45+win8", + "imports": "portable-net45+win8" } } } \ No newline at end of file diff --git a/src/fsharp/FSharp.Compiler.Host.netcore.nuget/Microsoft.FSharp.Compiler.Host.netcore.nuspec b/src/fsharp/FSharp.Compiler.Host.netcore.nuget/Microsoft.FSharp.Compiler.Host.netcore.nuspec index c389117159b..db6eb5ef397 100644 --- a/src/fsharp/FSharp.Compiler.Host.netcore.nuget/Microsoft.FSharp.Compiler.Host.netcore.nuspec +++ b/src/fsharp/FSharp.Compiler.Host.netcore.nuget/Microsoft.FSharp.Compiler.Host.netcore.nuspec @@ -3,10 +3,10 @@ Microsoft.FSharp.Compiler.Host.netcore - netcore compatible version of the fsharp compiler fsc.exe. + .NET Core compatible version of the fsharp compiler fsc.exe. Supported Platforms: - - .NET Core (netstandard1.5) + - .NET Core (netstandard1.6) en-US true @@ -16,12 +16,11 @@ $projectUrl$ $tags$ - - - + + + - diff --git a/src/fsharp/FSharp.Compiler.Interactive.Settings/project.json b/src/fsharp/FSharp.Compiler.Interactive.Settings/project.json index 12f15a49c0f..4e1804794a8 100644 --- a/src/fsharp/FSharp.Compiler.Interactive.Settings/project.json +++ b/src/fsharp/FSharp.Compiler.Interactive.Settings/project.json @@ -1,19 +1,19 @@ { "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1-rc2-24027", - "NETStandard.Library": "1.5.0-rc2-24027", - "System.Linq.Expressions": "4.0.11-rc2-24027", - "System.Reflection.TypeExtensions": "4.1.0-rc2-24027", - "System.Runtime.Loader": "4.0.0-rc2-24027", - "System.Threading.Thread": "4.0.0-rc2-24027", + "Microsoft.NETCore.Platforms": "1.0.1", + "NETStandard.Library": "1.6.0", + "System.Linq.Expressions": "4.1.0", + "System.Reflection.TypeExtensions": "4.1.0", + "System.Runtime.Loader": "4.0.0", + "System.Threading.Thread": "4.0.0" }, "runtimes": { "win7-x86": { }, "win7-x64": { }, - "osx.10.10-x64": { }, + "osx.10.11-x64": { }, "ubuntu.14.04-x64": { } }, "frameworks": { - "netstandard1.5": { } + "netstandard1.6": { } } } diff --git a/src/fsharp/FSharp.Compiler.netcore.nuget/Microsoft.FSharp.Compiler.netcore.nuspec b/src/fsharp/FSharp.Compiler.netcore.nuget/Microsoft.FSharp.Compiler.netcore.nuspec index beff3bf51c3..f7fc7c540ae 100644 --- a/src/fsharp/FSharp.Compiler.netcore.nuget/Microsoft.FSharp.Compiler.netcore.nuspec +++ b/src/fsharp/FSharp.Compiler.netcore.nuget/Microsoft.FSharp.Compiler.netcore.nuspec @@ -3,8 +3,8 @@ Microsoft.FSharp.Compiler.netcore - netcore compatible version of the fsharp compiler fsc.exe. - Supported Platforms: - .NET Core (.netstandard1.5) + .NET Core compatible version of the fsharp compiler fsc.exe. + Supported Platforms: - .NET Core (.netstandard1.6) en-US true @@ -14,37 +14,35 @@ $projectUrl$ $tags$ - + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + - - + + - - + + diff --git a/src/fsharp/FSharp.Compiler/project.json b/src/fsharp/FSharp.Compiler/project.json index ac47a5e454c..607931c96ad 100644 --- a/src/fsharp/FSharp.Compiler/project.json +++ b/src/fsharp/FSharp.Compiler/project.json @@ -1,36 +1,34 @@ { "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1-rc2-24027", - "NETStandard.Library": "1.5.0-rc2-24027", - "System.Collections.Immutable":"1.2.0-rc2-24027", - "System.Diagnostics.Process": "4.1.0-rc2-24027", - "System.Diagnostics.TraceSource": "4.0.0-rc2-24027", - "System.Linq.Expressions": "4.0.11-rc2-24027", - "System.Linq.Queryable": "4.0.1-rc2-24027", - "System.Net.Requests": "4.0.11-rc2-24027", - "System.Reflection.Emit": "4.0.1-rc2-24027", - "System.Reflection.Emit.ILGeneration": "4.0.1-rc2-24027", - "System.Reflection.Metadata": "1.3.0-rc2-24027", - "System.Reflection.TypeExtensions": "4.1.0-rc2-24027", - "System.Runtime.InteropServices": "4.1.0-rc2-24027", + "Microsoft.NETCore.Platforms": "1.0.1", + "NETStandard.Library": "1.6.0", + "System.Collections.Immutable":"1.2.0", + "System.Diagnostics.Process": "4.1.0", + "System.Diagnostics.TraceSource": "4.0.0", + "System.Linq.Expressions": "4.1.0", + "System.Linq.Queryable": "4.0.1", + "System.Net.Requests": "4.0.11", + "System.Reflection.Emit": "4.0.1", + "System.Reflection.Metadata": "1.3.0", + "System.Reflection.TypeExtensions": "4.1.0", + "System.Runtime.InteropServices": "4.1.0", "System.Runtime.InteropServices.PInvoke": "4.0.0-rc2-24027", - "System.Runtime.Loader": "4.0.0-rc2-24027", - "System.Security.Cryptography.Algorithms": "4.1.0-rc2-24027", - "System.Security.Cryptography.Primitives": "4.0.0-rc2-24027", - "System.Threading.Tasks.Parallel": "4.0.1-rc2-24027", - "System.Threading.Thread": "4.0.0-rc2-24027", - "System.Threading.ThreadPool": "4.0.10-rc2-24027", - "Microsoft.DiaSymReader.PortablePdb": "1.0.0-rc-60301", - "Microsoft.DiaSymReader": "1.0.7", + "System.Runtime.Loader": "4.0.0", + "System.Security.Cryptography.Algorithms": "4.2.0", + "System.Threading.Tasks.Parallel": "4.0.1", + "System.Threading.Thread": "4.0.0", + "System.Threading.ThreadPool": "4.0.10", + "Microsoft.DiaSymReader.PortablePdb": "1.1.0", + "Microsoft.DiaSymReader": "1.0.8" }, "runtimes": { "win7-x86": { }, "win7-x64": { }, - "osx.10.10-x64": { }, + "osx.10.11-x64": { }, "ubuntu.14.04-x64": { } }, "frameworks": { - "netstandard1.5": { + "netstandard1.6": { "imports": "portable-net45+win8" } } diff --git a/src/fsharp/FSharp.Core/project.json b/src/fsharp/FSharp.Core/project.json index d3ee8bd7886..dbec75ef1bb 100644 --- a/src/fsharp/FSharp.Core/project.json +++ b/src/fsharp/FSharp.Core/project.json @@ -1,38 +1,38 @@ { "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1-rc2-24027", - "Microsoft.NETCore.Runtime": "1.0.2-rc2-24027", - "System.Collections": "4.0.11-rc2-24027", - "System.Console": "4.0.0-rc2-24027", - "System.Diagnostics.Debug": "4.0.11-rc2-24027", - "System.Diagnostics.Tools": "4.0.1-rc2-24027", - "System.Globalization": "4.0.11-rc2-24027", - "System.IO": "4.1.0-rc2-24027", - "System.Linq": "4.1.0-rc2-24027", - "System.Linq.Expressions": "4.0.11-rc2-24027", - "System.Linq.Queryable": "4.0.1-rc2-24027", - "System.Net.Requests": "4.0.11-rc2-24027", - "System.Reflection": "4.1.0-rc2-24027", - "System.Reflection.Extensions": "4.0.1-rc2-24027", - "System.Resources.ResourceManager":"4.0.1-rc2-24027", - "System.Runtime": "4.1.0-rc2-24027", - "System.Runtime.Extensions": "4.1.0-rc2-24027", - "System.Runtime.Numerics": "4.0.1-rc2-24027", - "System.Text.RegularExpressions": "4.0.12-rc2-24027", - "System.Threading": "4.0.11-rc2-24027", - "System.Threading.Tasks": "4.0.11-rc2-24027", - "System.Threading.Tasks.Parallel": "4.0.1-rc2-24027", - "System.Threading.Thread": "4.0.0-rc2-24027", - "System.Threading.ThreadPool": "4.0.10-rc2-24027", - "System.Threading.Timer": "4.0.1-rc2-24027" + "Microsoft.NETCore.Platforms": "1.0.1", + "Microsoft.NETCore.Runtime": "1.0.2", + "System.Collections": "4.0.11", + "System.Console": "4.0.0", + "System.Diagnostics.Debug": "4.0.11", + "System.Diagnostics.Tools": "4.0.1", + "System.Globalization": "4.0.11", + "System.IO": "4.1.0", + "System.Linq": "4.1.0", + "System.Linq.Expressions": "4.1.0", + "System.Linq.Queryable": "4.0.1", + "System.Net.Requests": "4.0.11", + "System.Reflection": "4.1.0", + "System.Reflection.Extensions": "4.0.1", + "System.Resources.ResourceManager":"4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Runtime.Numerics": "4.0.1", + "System.Text.RegularExpressions": "4.1.0", + "System.Threading": "4.0.11", + "System.Threading.Tasks": "4.0.11", + "System.Threading.Tasks.Parallel": "4.0.1", + "System.Threading.Thread": "4.0.0", + "System.Threading.ThreadPool": "4.0.10", + "System.Threading.Timer": "4.0.1" }, "runtimes": { "win7-x86": { }, "win7-x64": { }, - "osx.10.10-x64": { }, + "osx.10.11-x64": { }, "ubuntu.14.04-x64": { } }, "frameworks": { - "netstandard1.5": { } + "netstandard1.6": { } } } diff --git a/src/fsharp/Fsc/project.json b/src/fsharp/Fsc/project.json index 1a1ee3bbd68..230aac3ada0 100644 --- a/src/fsharp/Fsc/project.json +++ b/src/fsharp/Fsc/project.json @@ -1,17 +1,17 @@ { "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1-rc2-24027", - "NETStandard.Library": "1.5.0-rc2-24027", - "System.Linq.Expressions": "4.0.11-rc2-24027", - "System.Reflection.Metadata": "1.3.0-rc2-24027", + "Microsoft.NETCore.Platforms": "1.0.1", + "NETStandard.Library": "1.6.0", + "System.Linq.Expressions": "4.1.0", + "System.Reflection.Metadata": "1.3.0" }, "runtimes": { "win7-x86": { }, "win7-x64": { }, - "osx.10.10-x64": { }, + "osx.10.11-x64": { }, "ubuntu.14.04-x64": { } }, "frameworks": { - "netstandard1.5": { } + "netstandard1.6": { } } } diff --git a/src/fsharp/fsharp.core.netcore.nuget/Microsoft.FSharp.Core.netcore.nuspec b/src/fsharp/fsharp.core.netcore.nuget/Microsoft.FSharp.Core.netcore.nuspec index ddcb33421ab..d62e9eb48a7 100644 --- a/src/fsharp/fsharp.core.netcore.nuget/Microsoft.FSharp.Core.netcore.nuspec +++ b/src/fsharp/fsharp.core.netcore.nuget/Microsoft.FSharp.Core.netcore.nuspec @@ -3,8 +3,8 @@ Microsoft.FSharp.Core.netcore - netcore compatible version of the fsharp core library fsharp.core.dll - Supported Platforms: - .NET Core (netstandard1.5) + .NET Core compatible version of the fsharp core library fsharp.core.dll + Supported Platforms: - .NET Core (netstandard1.6) en-US true @@ -15,27 +15,27 @@ $tags$ - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + diff --git a/src/fsharp/fsi/project.json b/src/fsharp/fsi/project.json index 824fba60719..ab1bfc4de17 100644 --- a/src/fsharp/fsi/project.json +++ b/src/fsharp/fsi/project.json @@ -1,22 +1,22 @@ { "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1-rc2-24027", - "NETStandard.Library": "1.5.0-rc2-24027", - "System.Diagnostics.Process": "4.1.0-rc2-24027", - "System.Linq.Expressions": "4.0.11-rc2-24027", - "System.Reflection.Emit": "4.0.1-rc2-24027", - "System.Reflection.TypeExtensions": "4.1.0-rc2-24027", - "System.Runtime.Loader": "4.0.0-rc2-24027", - "System.Threading.Thread": "4.0.0-rc2-24027", - "System.Reflection.Metadata": "1.3.0-rc2-24027", + "Microsoft.NETCore.Platforms": "1.0.1", + "NETStandard.Library": "1.6.0", + "System.Diagnostics.Process": "4.1.0", + "System.Linq.Expressions": "4.1.0", + "System.Reflection.Emit": "4.0.1", + "System.Reflection.TypeExtensions": "4.1.0", + "System.Runtime.Loader": "4.0.0", + "System.Threading.Thread": "4.0.0", + "System.Reflection.Metadata": "1.3.0" }, "runtimes": { "win7-x86": { }, "win7-x64": { }, - "osx.10.10-x64": { }, + "osx.10.11-x64": { }, "ubuntu.14.04-x64": { } }, "frameworks": { - "netstandard1.5": { } + "netstandard1.6": { } } } From 3cd1705685f1171cd64cce30762e5dd17f4f4653 Mon Sep 17 00:00:00 2001 From: Enrico Sada Date: Mon, 27 Jun 2016 20:45:44 +0200 Subject: [PATCH 091/129] fix tf --- .../Microsoft.FSharp.Core.netcore.nuspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fsharp/fsharp.core.netcore.nuget/Microsoft.FSharp.Core.netcore.nuspec b/src/fsharp/fsharp.core.netcore.nuget/Microsoft.FSharp.Core.netcore.nuspec index d62e9eb48a7..f4dcefd9a8c 100644 --- a/src/fsharp/fsharp.core.netcore.nuget/Microsoft.FSharp.Core.netcore.nuspec +++ b/src/fsharp/fsharp.core.netcore.nuget/Microsoft.FSharp.Core.netcore.nuspec @@ -14,7 +14,7 @@ $projectUrl$ $tags$ - + From 3866b77bca639b7b655d5b20c6ea2cf499c77bf8 Mon Sep 17 00:00:00 2001 From: Omar Tawfik Date: Wed, 22 Jun 2016 17:10:43 -0700 Subject: [PATCH 092/129] Fixed template imports in VSIX --- VisualFSharp.sln | 80 +------- .../ItemTemplates/AppConfig/AppConfig.csproj | 15 ++ .../ItemTemplates/CodeFile/CodeFile.csproj | 15 ++ .../ScriptFile/ScriptFile.csproj | 15 ++ .../SignatureFile/SignatureFile.csproj | 15 ++ .../ItemTemplates/TextFile/TextFile.csproj | 15 ++ .../ItemTemplates/XMLFile/XMLFile.csproj | 15 ++ .../ConsoleProject/ConsoleProject.csproj | 16 ++ .../LibraryProject/LibraryProject.csproj | 16 ++ .../NetCore259Project.csproj | 15 ++ .../NetCore78Project/NetCore78Project.csproj | 16 ++ .../NetCoreProject/NetCoreProject.csproj | 16 ++ .../PortableLibraryProject.csproj | 16 ++ .../SilverlightProject.csproj | 16 ++ .../TutorialProject/TutorialProject.csproj | 16 ++ .../Source.extension.vsixmanifest | 40 ++-- .../VisualFSharpVsix/VisualFSharpVsix.csproj | 194 ++++++++++-------- .../FSharpLanguageService.fs | 4 +- 18 files changed, 349 insertions(+), 186 deletions(-) diff --git a/VisualFSharp.sln b/VisualFSharp.sln index 6224d843be1..99d03d490e0 100644 --- a/VisualFSharp.sln +++ b/VisualFSharp.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25123.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.25123.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.Compiler", "src\fsharp\FSharp.Compiler\FSharp.Compiler.fsproj", "{2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}" EndProject @@ -130,54 +130,6 @@ Global Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.Debug|x86.ActiveCfg = Debug|Any CPU - {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.Debug|x86.Build.0 = Debug|Any CPU - {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.Proto|Any CPU.ActiveCfg = Proto|Any CPU - {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.Proto|Any CPU.Build.0 = Proto|Any CPU - {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.Proto|x86.ActiveCfg = Proto|Any CPU - {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.Proto|x86.Build.0 = Proto|Any CPU - {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.Release|Any CPU.Build.0 = Release|Any CPU - {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.Release|x86.ActiveCfg = Release|Any CPU - {4D7BE558-E6BF-44DA-8CE2-46AA6E0DC2E7}.Release|x86.Build.0 = Release|Any CPU - {493D19F9-35A4-4D0B-9B25-CA948823B709}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {493D19F9-35A4-4D0B-9B25-CA948823B709}.Debug|Any CPU.Build.0 = Debug|Any CPU - {493D19F9-35A4-4D0B-9B25-CA948823B709}.Debug|x86.ActiveCfg = Debug|Any CPU - {493D19F9-35A4-4D0B-9B25-CA948823B709}.Debug|x86.Build.0 = Debug|Any CPU - {493D19F9-35A4-4D0B-9B25-CA948823B709}.Proto|Any CPU.ActiveCfg = Proto|Any CPU - {493D19F9-35A4-4D0B-9B25-CA948823B709}.Proto|Any CPU.Build.0 = Proto|Any CPU - {493D19F9-35A4-4D0B-9B25-CA948823B709}.Proto|x86.ActiveCfg = Proto|Any CPU - {493D19F9-35A4-4D0B-9B25-CA948823B709}.Proto|x86.Build.0 = Proto|Any CPU - {493D19F9-35A4-4D0B-9B25-CA948823B709}.Release|Any CPU.ActiveCfg = Release|Any CPU - {493D19F9-35A4-4D0B-9B25-CA948823B709}.Release|Any CPU.Build.0 = Release|Any CPU - {493D19F9-35A4-4D0B-9B25-CA948823B709}.Release|x86.ActiveCfg = Release|Any CPU - {493D19F9-35A4-4D0B-9B25-CA948823B709}.Release|x86.Build.0 = Release|Any CPU - {530DF8CA-7996-407A-B533-D0C2873257AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {530DF8CA-7996-407A-B533-D0C2873257AF}.Debug|Any CPU.Build.0 = Debug|Any CPU - {530DF8CA-7996-407A-B533-D0C2873257AF}.Debug|x86.ActiveCfg = Debug|Any CPU - {530DF8CA-7996-407A-B533-D0C2873257AF}.Debug|x86.Build.0 = Debug|Any CPU - {530DF8CA-7996-407A-B533-D0C2873257AF}.Proto|Any CPU.ActiveCfg = Proto|Any CPU - {530DF8CA-7996-407A-B533-D0C2873257AF}.Proto|Any CPU.Build.0 = Proto|Any CPU - {530DF8CA-7996-407A-B533-D0C2873257AF}.Proto|x86.ActiveCfg = Proto|Any CPU - {530DF8CA-7996-407A-B533-D0C2873257AF}.Proto|x86.Build.0 = Proto|Any CPU - {530DF8CA-7996-407A-B533-D0C2873257AF}.Release|Any CPU.ActiveCfg = Release|Any CPU - {530DF8CA-7996-407A-B533-D0C2873257AF}.Release|Any CPU.Build.0 = Release|Any CPU - {530DF8CA-7996-407A-B533-D0C2873257AF}.Release|x86.ActiveCfg = Release|Any CPU - {530DF8CA-7996-407A-B533-D0C2873257AF}.Release|x86.Build.0 = Release|Any CPU - {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.Debug|Any CPU.Build.0 = Debug|Any CPU - {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.Debug|x86.ActiveCfg = Debug|Any CPU - {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.Debug|x86.Build.0 = Debug|Any CPU - {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.Proto|Any CPU.ActiveCfg = Proto|Any CPU - {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.Proto|Any CPU.Build.0 = Proto|Any CPU - {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.Proto|x86.ActiveCfg = Proto|Any CPU - {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.Proto|x86.Build.0 = Proto|Any CPU - {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.Release|Any CPU.ActiveCfg = Release|Any CPU - {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.Release|Any CPU.Build.0 = Release|Any CPU - {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.Release|x86.ActiveCfg = Release|Any CPU - {98ABDE09-9E08-49C7-B006-FB3CB5365B54}.Release|x86.Build.0 = Release|Any CPU {2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}.Debug|Any CPU.Build.0 = Debug|Any CPU {2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -502,18 +454,6 @@ Global {C94C257C-3C0A-4858-B5D8-D746498D1F08}.Release|Any CPU.Build.0 = Release|Any CPU {C94C257C-3C0A-4858-B5D8-D746498D1F08}.Release|x86.ActiveCfg = Release|Any CPU {C94C257C-3C0A-4858-B5D8-D746498D1F08}.Release|x86.Build.0 = Release|Any CPU - {CB7D20C4-6506-406D-9144-5342C3595F03}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {CB7D20C4-6506-406D-9144-5342C3595F03}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CB7D20C4-6506-406D-9144-5342C3595F03}.Debug|x86.ActiveCfg = Debug|Any CPU - {CB7D20C4-6506-406D-9144-5342C3595F03}.Debug|x86.Build.0 = Debug|Any CPU - {CB7D20C4-6506-406D-9144-5342C3595F03}.Proto|Any CPU.ActiveCfg = Proto|Any CPU - {CB7D20C4-6506-406D-9144-5342C3595F03}.Proto|Any CPU.Build.0 = Proto|Any CPU - {CB7D20C4-6506-406D-9144-5342C3595F03}.Proto|x86.ActiveCfg = Proto|Any CPU - {CB7D20C4-6506-406D-9144-5342C3595F03}.Proto|x86.Build.0 = Proto|Any CPU - {CB7D20C4-6506-406D-9144-5342C3595F03}.Release|Any CPU.ActiveCfg = Release|Any CPU - {CB7D20C4-6506-406D-9144-5342C3595F03}.Release|Any CPU.Build.0 = Release|Any CPU - {CB7D20C4-6506-406D-9144-5342C3595F03}.Release|x86.ActiveCfg = Release|Any CPU - {CB7D20C4-6506-406D-9144-5342C3595F03}.Release|x86.Build.0 = Release|Any CPU {649FA588-F02E-457C-9FCF-87E46407481E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {649FA588-F02E-457C-9FCF-87E46407481E}.Debug|Any CPU.Build.0 = Debug|Any CPU {649FA588-F02E-457C-9FCF-87E46407481E}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -753,14 +693,6 @@ Global {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.Release|Any CPU.Build.0 = Release|Any CPU {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.Release|x86.ActiveCfg = Release|Any CPU {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.Release|x86.Build.0 = Release|Any CPU - {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {1FB1DD07-06AA-45B4-B5AC-20FF5BEE98B6}.VSRelease|x86.Build.0 = VSRelease|Any CPU {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}.Debug|Any CPU.Build.0 = Debug|Any CPU {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -773,14 +705,6 @@ Global {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}.Release|Any CPU.Build.0 = Release|Any CPU {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}.Release|x86.ActiveCfg = Release|Any CPU {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}.Release|x86.Build.0 = Release|Any CPU - {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}.VSDebug|Any CPU.ActiveCfg = VSDebug|Any CPU - {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}.VSDebug|Any CPU.Build.0 = VSDebug|Any CPU - {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}.VSDebug|x86.ActiveCfg = VSDebug|Any CPU - {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}.VSDebug|x86.Build.0 = VSDebug|Any CPU - {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}.VSRelease|Any CPU.ActiveCfg = VSRelease|Any CPU - {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}.VSRelease|Any CPU.Build.0 = VSRelease|Any CPU - {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}.VSRelease|x86.ActiveCfg = VSRelease|Any CPU - {E7EC4A3E-9D57-45B8-83F5-EDDFD6CEF090}.VSRelease|x86.Build.0 = VSRelease|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/vsintegration/ItemTemplates/AppConfig/AppConfig.csproj b/vsintegration/ItemTemplates/AppConfig/AppConfig.csproj index 76d5830b2ab..51459896268 100644 --- a/vsintegration/ItemTemplates/AppConfig/AppConfig.csproj +++ b/vsintegration/ItemTemplates/AppConfig/AppConfig.csproj @@ -7,6 +7,17 @@ ItemTemplates true true + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + false + false + false + false + false + false + false + false + false + false Debug @@ -16,6 +27,10 @@ + + + + diff --git a/vsintegration/ItemTemplates/CodeFile/CodeFile.csproj b/vsintegration/ItemTemplates/CodeFile/CodeFile.csproj index af65940e8fc..62d04e9abdf 100644 --- a/vsintegration/ItemTemplates/CodeFile/CodeFile.csproj +++ b/vsintegration/ItemTemplates/CodeFile/CodeFile.csproj @@ -7,6 +7,17 @@ ItemTemplates true true + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + false + false + false + false + false + false + false + false + false + false Debug @@ -16,6 +27,10 @@ + + + + diff --git a/vsintegration/ItemTemplates/ScriptFile/ScriptFile.csproj b/vsintegration/ItemTemplates/ScriptFile/ScriptFile.csproj index 53e45efd0c2..aaaee9d49df 100644 --- a/vsintegration/ItemTemplates/ScriptFile/ScriptFile.csproj +++ b/vsintegration/ItemTemplates/ScriptFile/ScriptFile.csproj @@ -7,6 +7,17 @@ ItemTemplates true true + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + false + false + false + false + false + false + false + false + false + false Debug @@ -16,6 +27,10 @@ + + + + diff --git a/vsintegration/ItemTemplates/SignatureFile/SignatureFile.csproj b/vsintegration/ItemTemplates/SignatureFile/SignatureFile.csproj index 556a222f1da..0ef37b0d2ce 100644 --- a/vsintegration/ItemTemplates/SignatureFile/SignatureFile.csproj +++ b/vsintegration/ItemTemplates/SignatureFile/SignatureFile.csproj @@ -7,6 +7,17 @@ ItemTemplates true true + false + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + false + false + false + false + false + false + false + false + false Debug @@ -16,6 +27,10 @@ + + + + diff --git a/vsintegration/ItemTemplates/TextFile/TextFile.csproj b/vsintegration/ItemTemplates/TextFile/TextFile.csproj index 858f48a45b7..49d3fd4931d 100644 --- a/vsintegration/ItemTemplates/TextFile/TextFile.csproj +++ b/vsintegration/ItemTemplates/TextFile/TextFile.csproj @@ -7,6 +7,17 @@ ItemTemplates true true + false + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + false + false + false + false + false + false + false + false + false Debug @@ -16,6 +27,10 @@ + + + + diff --git a/vsintegration/ItemTemplates/XMLFile/XMLFile.csproj b/vsintegration/ItemTemplates/XMLFile/XMLFile.csproj index dee1bb2c2e0..fa24d80c794 100644 --- a/vsintegration/ItemTemplates/XMLFile/XMLFile.csproj +++ b/vsintegration/ItemTemplates/XMLFile/XMLFile.csproj @@ -7,6 +7,17 @@ ItemTemplates true true + false + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + false + false + false + false + false + false + false + false + false Debug @@ -16,6 +27,10 @@ + + + + diff --git a/vsintegration/ProjectTemplates/ConsoleProject/ConsoleProject.csproj b/vsintegration/ProjectTemplates/ConsoleProject/ConsoleProject.csproj index 2b13fd8e53b..8d11aabaea9 100644 --- a/vsintegration/ProjectTemplates/ConsoleProject/ConsoleProject.csproj +++ b/vsintegration/ProjectTemplates/ConsoleProject/ConsoleProject.csproj @@ -7,6 +7,17 @@ ProjectTemplates true true + false + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + false + false + false + false + false + false + false + false + false Debug @@ -30,6 +41,11 @@ false + + + + + diff --git a/vsintegration/ProjectTemplates/LibraryProject/LibraryProject.csproj b/vsintegration/ProjectTemplates/LibraryProject/LibraryProject.csproj index e1afe08cefa..7d7dc3fb15a 100644 --- a/vsintegration/ProjectTemplates/LibraryProject/LibraryProject.csproj +++ b/vsintegration/ProjectTemplates/LibraryProject/LibraryProject.csproj @@ -7,6 +7,17 @@ ProjectTemplates true true + false + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + false + false + false + false + false + false + false + false + false Debug @@ -30,6 +41,11 @@ false + + + + + diff --git a/vsintegration/ProjectTemplates/NetCore259Project/NetCore259Project.csproj b/vsintegration/ProjectTemplates/NetCore259Project/NetCore259Project.csproj index 6110d368738..2b961b74159 100644 --- a/vsintegration/ProjectTemplates/NetCore259Project/NetCore259Project.csproj +++ b/vsintegration/ProjectTemplates/NetCore259Project/NetCore259Project.csproj @@ -7,6 +7,17 @@ ProjectTemplates true true + false + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + false + false + false + false + false + false + false + false + false Debug @@ -31,6 +42,10 @@ + + + + diff --git a/vsintegration/ProjectTemplates/NetCore78Project/NetCore78Project.csproj b/vsintegration/ProjectTemplates/NetCore78Project/NetCore78Project.csproj index 303e9f18612..c809eda8d74 100644 --- a/vsintegration/ProjectTemplates/NetCore78Project/NetCore78Project.csproj +++ b/vsintegration/ProjectTemplates/NetCore78Project/NetCore78Project.csproj @@ -7,6 +7,17 @@ ProjectTemplates true true + false + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + false + false + false + false + false + false + false + false + false Debug @@ -30,6 +41,11 @@ false + + + + + diff --git a/vsintegration/ProjectTemplates/NetCoreProject/NetCoreProject.csproj b/vsintegration/ProjectTemplates/NetCoreProject/NetCoreProject.csproj index 24c9d8bcf3a..2aa6eec186b 100644 --- a/vsintegration/ProjectTemplates/NetCoreProject/NetCoreProject.csproj +++ b/vsintegration/ProjectTemplates/NetCoreProject/NetCoreProject.csproj @@ -7,6 +7,17 @@ ProjectTemplates true true + false + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + false + false + false + false + false + false + false + false + false Debug @@ -30,6 +41,11 @@ false + + + + + diff --git a/vsintegration/ProjectTemplates/PortableLibraryProject/PortableLibraryProject.csproj b/vsintegration/ProjectTemplates/PortableLibraryProject/PortableLibraryProject.csproj index 125c0fbf8bd..6e0987435f0 100644 --- a/vsintegration/ProjectTemplates/PortableLibraryProject/PortableLibraryProject.csproj +++ b/vsintegration/ProjectTemplates/PortableLibraryProject/PortableLibraryProject.csproj @@ -7,6 +7,17 @@ ProjectTemplates true true + false + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + false + false + false + false + false + false + false + false + false Debug @@ -30,6 +41,11 @@ false + + + + + diff --git a/vsintegration/ProjectTemplates/SilverlightProject/SilverlightProject.csproj b/vsintegration/ProjectTemplates/SilverlightProject/SilverlightProject.csproj index abfc6423b5f..cbc0816a9e6 100644 --- a/vsintegration/ProjectTemplates/SilverlightProject/SilverlightProject.csproj +++ b/vsintegration/ProjectTemplates/SilverlightProject/SilverlightProject.csproj @@ -7,6 +7,17 @@ ProjectTemplates true true + false + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + false + false + false + false + false + false + false + false + false Debug @@ -30,6 +41,11 @@ false + + + + + diff --git a/vsintegration/ProjectTemplates/TutorialProject/TutorialProject.csproj b/vsintegration/ProjectTemplates/TutorialProject/TutorialProject.csproj index fc41a78cf21..a5a9595ea17 100644 --- a/vsintegration/ProjectTemplates/TutorialProject/TutorialProject.csproj +++ b/vsintegration/ProjectTemplates/TutorialProject/TutorialProject.csproj @@ -7,6 +7,17 @@ ProjectTemplates true true + false + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + false + false + false + false + false + false + false + false + false Debug @@ -24,6 +35,11 @@ false + + + + + diff --git a/vsintegration/VisualFSharpVsix/Source.extension.vsixmanifest b/vsintegration/VisualFSharpVsix/Source.extension.vsixmanifest index 2701f6f7c7a..e59738de82a 100644 --- a/vsintegration/VisualFSharpVsix/Source.extension.vsixmanifest +++ b/vsintegration/VisualFSharpVsix/Source.extension.vsixmanifest @@ -7,7 +7,7 @@ Deploy Visual F# Tools templates to Visual Studio ..\CommonExtensions\Microsoft\FSharp - + @@ -33,7 +33,7 @@ - + @@ -43,21 +43,25 @@ - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/vsintegration/VisualFSharpVsix/VisualFSharpVsix.csproj b/vsintegration/VisualFSharpVsix/VisualFSharpVsix.csproj index 49c86e14e52..1d596308c6f 100644 --- a/vsintegration/VisualFSharpVsix/VisualFSharpVsix.csproj +++ b/vsintegration/VisualFSharpVsix/VisualFSharpVsix.csproj @@ -5,7 +5,7 @@ ..\..\src ..\src net40 - 14.0 + 15.0 11.0 $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) @@ -43,7 +43,7 @@ false Library Properties - FSharp + FSharpDev true False True @@ -53,13 +53,14 @@ $(FSharpSourcesRoot)\..\$(Configuration)\$(TargetFramework)\bin VisualFSharpVsix $(RootBinPath) + 15.4.1.0 + cs - Program $(DevEnvDir)devenv.exe - /rootsuffix FSharp /log - FSharp + /rootsuffix $(VSRootSuffix) /log + $(VSRootSuffix) true @@ -68,10 +69,7 @@ true /rootsuffix $(VSRootSuffix) /log $(VSRootSuffix) - 15.4.1.0 - cs - Designer @@ -86,83 +84,6 @@ true - - - - Always - true - ProjectTemplates\SilverlightProject.zip - - - Always - true - ProjectTemplates\NetCoreProject.zip - - - Always - true - ProjectTemplates\NetCore78Project.zip - - - Always - true - ProjectTemplates\NetCore259Project.zip - - - Always - true - ProjectTemplates\PortableLibraryProject.zip - - - Always - true - ProjectTemplates\TutorialProject.zip - - - Always - true - ProjectTemplates\ConsoleProject.zip - - - Always - true - ProjectTemplates\LibraryProject.zip - - - - - - Always - true - ItemTemplates\AppConfig.zip - - - Always - true - ItemTemplates\CodeFile.zip - - - Always - true - ItemTemplates\ScriptFile.zip - - - Always - true - ItemTemplates\SignatureFile.zip - - - Always - true - ItemTemplates\TextFile.zip - - - Always - true - ItemTemplates\XMLFile.zip - - - False @@ -180,7 +101,6 @@ false - {649FA588-F02E-457C-9FCF-87E46407481E} @@ -233,9 +153,8 @@ {65e0e82a-eace-4787-8994-888674c2fe87} FSharp.Editor - BuiltProjectOutputGroup%3bGetCopyToOutputDirectoryItems%3bSatelliteDllsProjectOutputGroup%3bPkgDefProjectOutputGroup%3b + BuiltProjectOutputGroup%3bGetCopyToOutputDirectoryItems%3bSatelliteDllsProjectOutputGroup%3bPkgDefProjectOutputGroup%3bBuiltProjectOutputGroup%3bBuiltProjectOutputGroupDependencies%3bGetCopyToOutputDirectoryItems%3bSatelliteDllsProjectOutputGroup%3b DebugSymbolsProjectOutputGroup%3b - false {1C5C163C-37EA-4A3C-8CCC-0D34B74BF8EF} @@ -279,8 +198,105 @@ DebugSymbolsProjectOutputGroup%3b false + + {6ba13aa4-c25f-480f-856b-8e8000299a72} + AppConfig + ItemTemplates + false + TemplateProjectOutputGroup%3b + + + {12ac2813-e895-4aaa-ae6c-94e21da09f64} + CodeFile + ItemTemplates + false + TemplateProjectOutputGroup%3b + + + {a333b85a-dc23-49b6-9797-b89a7951e92d} + ScriptFile + ItemTemplates + false + TemplateProjectOutputGroup%3b + + + {e3fdd4ac-46b6-4b9f-b672-317d1202cc50} + SignatureFile + ItemTemplates + false + TemplateProjectOutputGroup%3b + + + {d11fc318-8f5d-4c8c-9287-ab40a016d13c} + TextFile + ItemTemplates + false + TemplateProjectOutputGroup%3b + + + {1fb1dd07-06aa-45b4-b5ac-20ff5bee98b6} + XMLFile + ItemTemplates + false + TemplateProjectOutputGroup%3b + + + {604f0daa-2d33-48dd-b162-edf0b672803d} + ConsoleProject + ProjectTemplates + false + TemplateProjectOutputGroup%3b + + + {01678cda-a11f-4dee-9344-2edf91cf1ae7} + LibraryProject + ProjectTemplates + false + TemplateProjectOutputGroup%3b + + + {d9d95330-3626-4199-b7af-17b8e4af6d87} + NetCore259Project + ProjectTemplates + false + TemplateProjectOutputGroup%3b + + + {1a8dbf70-4178-4ae3-af5f-39ddd5692210} + NetCore78Project + ProjectTemplates + false + TemplateProjectOutputGroup%3b + + + {5b739cf3-1116-4eb4-b598-6c16bea81ce5} + NetCoreProject + ProjectTemplates + false + TemplateProjectOutputGroup%3b + + + {db374a0c-7560-479f-9b21-d37c81f7624f} + PortableLibraryProject + ProjectTemplates + false + TemplateProjectOutputGroup%3b + + + {15a57828-f9f5-4fb4-8e1e-ae7622a10f70} + SilverlightProject + ProjectTemplates + false + TemplateProjectOutputGroup%3b + + + {2facee44-48bd-40b5-a2ee-b54a0c9bb7c4} + TutorialProject + ProjectTemplates + false + TemplateProjectOutputGroup%3b + - \ No newline at end of file diff --git a/vsintegration/src/FSharp.LanguageService/FSharpLanguageService.fs b/vsintegration/src/FSharp.LanguageService/FSharpLanguageService.fs index 5c7a152a531..f23db9a62ed 100644 --- a/vsintegration/src/FSharp.LanguageService/FSharpLanguageService.fs +++ b/vsintegration/src/FSharp.LanguageService/FSharpLanguageService.fs @@ -71,7 +71,9 @@ type internal FSharpLanguageService(package : FSharpPackage) = | _ -> () | _ -> () -and [] +and + [] + [] internal FSharpPackage() = inherit AbstractPackage() From eeef150725a8e313db8019fe4a199d31e60f6864 Mon Sep 17 00:00:00 2001 From: KevinRansom Date: Tue, 28 Jun 2016 10:17:29 +0100 Subject: [PATCH 093/129] Update to rtm coreclr libraries --- packages.config | 8 +- src/absil/ilwritepdb.fs | 26 +- .../FSharp.Compiler-proto.fsproj | 8 +- .../Microsoft.FSharp.Compiler.netcore.nuspec | 2 +- .../FSharp.Compiler/FSharp.Compiler.fsproj | 10 +- src/fsharp/FSharp.Compiler/project.json | 2 +- src/fsharp/FSharp.Core.Unittests/project.json | 23 +- src/fsharp/FSharp.Core/project.json | 2 +- .../FSharp.LanguageService.Compiler.fsproj | 8 +- src/fsharp/Fsc/project.json | 2 +- src/fsharp/fsi/project.json | 2 +- tests/BuildTestTools.cmd | 16 +- tests/fsharp/project.json | 60 +- .../bin/System.Reflection.Metadata.dll | Bin 408808 -> 432872 bytes .../bin/System.Reflection.Metadata.xml | 3264 ++++++++++++----- 15 files changed, 2493 insertions(+), 940 deletions(-) diff --git a/packages.config b/packages.config index c8c0d183d1d..f9559ed7b88 100644 --- a/packages.config +++ b/packages.config @@ -7,10 +7,10 @@ - - - - + + + + diff --git a/src/absil/ilwritepdb.fs b/src/absil/ilwritepdb.fs index cf397a0041c..c0cb29b7766 100644 --- a/src/absil/ilwritepdb.fs +++ b/src/absil/ilwritepdb.fs @@ -9,7 +9,6 @@ open System.IO open System.Reflection open System.Reflection.Metadata open System.Reflection.Metadata.Ecma335 -open System.Reflection.Metadata.Ecma335.Blobs open System.Reflection.PortableExecutable open Internal.Utilities open Microsoft.FSharp.Compiler.AbstractIL.IL @@ -222,10 +221,10 @@ let writePortablePdbInfo (fixupSPs:bool) showTimes fpdb (info:PdbData) = writer.WriteByte(byte(separator)) for part in name.Split( [| separator |] ) do - let partIndex = MetadataTokens.GetHeapOffset(BlobHandle.op_Implicit(metadata.GetBlobUtf8(part))) + let partIndex = MetadataTokens.GetHeapOffset(BlobHandle.op_Implicit(metadata.GetOrAddBlobUTF8(part))) writer.WriteCompressedInteger(int(partIndex)) - metadata.GetBlob(writer); + metadata.GetOrAddBlob(writer); let corSymLanguageTypeFSharp = System.Guid(0xAB4F38C9u, 0xB6E6us, 0x43baus, 0xBEuy, 0x3Buy, 0x58uy, 0x08uy, 0x0Buy, 0x2Cuy, 0xCCuy, 0xE3uy) let documentIndex = @@ -236,14 +235,14 @@ let writePortablePdbInfo (fixupSPs:bool) showTimes fpdb (info:PdbData) = match checkSum doc.File with | Some (hashAlg, checkSum) -> serializeDocumentName doc.File, - metadata.GetGuid(hashAlg), - metadata.GetBlob(checkSum.ToImmutableArray()), - metadata.GetGuid(corSymLanguageTypeFSharp) + metadata.GetOrAddGuid(hashAlg), + metadata.GetOrAddBlob(checkSum.ToImmutableArray()), + metadata.GetOrAddGuid(corSymLanguageTypeFSharp) | None -> serializeDocumentName doc.File, - metadata.GetGuid(System.Guid.Empty), - metadata.GetBlob(ImmutableArray.Empty), - metadata.GetGuid(corSymLanguageTypeFSharp) + metadata.GetOrAddGuid(System.Guid.Empty), + metadata.GetOrAddBlob(ImmutableArray.Empty), + metadata.GetOrAddGuid(corSymLanguageTypeFSharp) |> metadata.AddDocument index.Add(doc.File, handle) index @@ -332,7 +331,7 @@ let writePortablePdbInfo (fixupSPs:bool) showTimes fpdb (info:PdbData) = previousNonHiddenStartLine <- sps.[i].Line previousNonHiddenStartColumn <- sps.[i].Column - getDocumentHandle singleDocumentIndex, metadata.GetBlob(builder) + getDocumentHandle singleDocumentIndex, metadata.GetOrAddBlob(builder) // Write the scopes let mutable lastLocalVariableHandle = Unchecked.defaultof @@ -347,7 +346,7 @@ let writePortablePdbInfo (fixupSPs:bool) showTimes fpdb (info:PdbData) = scope.StartOffset, scope.EndOffset - scope.StartOffset) |>ignore for localVariable in scope.Locals do - lastLocalVariableHandle <- metadata.AddLocalVariable(LocalVariableAttributes.None, localVariable.Index, metadata.GetString(localVariable.Name)) + lastLocalVariableHandle <- metadata.AddLocalVariable(LocalVariableAttributes.None, localVariable.Index, metadata.GetOrAddString(localVariable.Name)) scope.Children |> Array.iter (writePdbScope false) writePdbScope true minfo.RootScope @@ -358,10 +357,9 @@ let writePortablePdbInfo (fixupSPs:bool) showTimes fpdb (info:PdbData) = | None -> MetadataTokens.MethodDefinitionHandle(0) | Some x -> MetadataTokens.MethodDefinitionHandle(x) - let pdbContentId = ContentId(info.ModuleID, BitConverter.GetBytes(info.Timestamp)) - let serializer = StandaloneDebugMetadataSerializer(metadata, externalRowCounts, entryPoint, false) + let serializer = PortablePdbBuilder(metadata, externalRowCounts, entryPoint, null ) let blobBuilder = new BlobBuilder() - serializer.SerializeMetadata(blobBuilder, (fun builder -> pdbContentId)) |> ignore + serializer.Serialize(blobBuilder) |> ignore reportTime showTimes "PDB: Created" use portablePdbStream = new FileStream(fpdb, FileMode.Create, FileAccess.ReadWrite) diff --git a/src/fsharp/FSharp.Compiler-proto/FSharp.Compiler-proto.fsproj b/src/fsharp/FSharp.Compiler-proto/FSharp.Compiler-proto.fsproj index 7eb20114970..8e5334f9b90 100644 --- a/src/fsharp/FSharp.Compiler-proto/FSharp.Compiler-proto.fsproj +++ b/src/fsharp/FSharp.Compiler-proto/FSharp.Compiler-proto.fsproj @@ -473,10 +473,10 @@ - ..\..\..\packages\Microsoft.DiaSymReader.PortablePdb.1.0.0-rc-60301\lib\portable-net45+win8\Microsoft.DiaSymReader.PortablePdb.dll - ..\..\..\packages\Microsoft.DiaSymReader.1.0.7\lib\portable-net45+win8\Microsoft.DiaSymReader.dll - ..\..\..\packages\System.Reflection.Metadata.1.3.0-beta-23816\lib\portable-net45+win8\System.Reflection.Metadata.dll - ..\..\..\packages\System.Collections.Immutable.1.2.0-rc3-23805\lib\portable-net45+win8+wp8+wpa81 + ..\..\..\packages\Microsoft.DiaSymReader.PortablePdb.1.1.0\lib\portable-net45+win8\Microsoft.DiaSymReader.PortablePdb.dll + ..\..\..\packages\Microsoft.DiaSymReader.1.0.8\lib\portable-net45+win8\Microsoft.DiaSymReader.dll + ..\..\..\packages\System.Reflection.Metadata.1.4.1-beta-24227-04\lib\portable-net45+win8\System.Reflection.Metadata.dll + ..\..\..\packages\System.Collections.Immutable.1.2.0\lib\portable-net45+win8+wp8+wpa81 diff --git a/src/fsharp/FSharp.Compiler.netcore.nuget/Microsoft.FSharp.Compiler.netcore.nuspec b/src/fsharp/FSharp.Compiler.netcore.nuget/Microsoft.FSharp.Compiler.netcore.nuspec index f7fc7c540ae..b9b73220b89 100644 --- a/src/fsharp/FSharp.Compiler.netcore.nuget/Microsoft.FSharp.Compiler.netcore.nuspec +++ b/src/fsharp/FSharp.Compiler.netcore.nuget/Microsoft.FSharp.Compiler.netcore.nuspec @@ -25,7 +25,7 @@ - + diff --git a/src/fsharp/FSharp.Compiler/FSharp.Compiler.fsproj b/src/fsharp/FSharp.Compiler/FSharp.Compiler.fsproj index 9ba9ef50d9f..0e8e0e69532 100644 --- a/src/fsharp/FSharp.Compiler/FSharp.Compiler.fsproj +++ b/src/fsharp/FSharp.Compiler/FSharp.Compiler.fsproj @@ -29,7 +29,7 @@ $(FSharpSourcesRoot)\..\loc\lcl\{Lang}\$(AssemblyName).dll.lcl $(FSharpSourcesRoot)\..\loc\lci\$(AssemblyName).dll.lci false - false + false @@ -523,10 +523,10 @@ - ..\..\..\packages\Microsoft.DiaSymReader.PortablePdb.1.0.0-rc-60301\lib\portable-net45+win8\Microsoft.DiaSymReader.PortablePdb.dll - ..\..\..\packages\Microsoft.DiaSymReader.1.0.7\lib\portable-net45+win8\Microsoft.DiaSymReader.dll - ..\..\..\packages\System.Reflection.Metadata.1.3.0-beta-23816\lib\portable-net45+win8\System.Reflection.Metadata.dll - ..\..\..\packages\System.Collections.Immutable.1.2.0-rc3-23805\lib\portable-net45+win8+wp8+wpa81 + ..\..\..\packages\Microsoft.DiaSymReader.PortablePdb.1.1.0\lib\portable-net45+win8\Microsoft.DiaSymReader.PortablePdb.dll + ..\..\..\packages\Microsoft.DiaSymReader.1.0.8\lib\portable-net45+win8\Microsoft.DiaSymReader.dll + ..\..\..\packages\System.Reflection.Metadata.1.4.1-beta-24227-04\lib\portable-net45+win8\System.Reflection.Metadata.dll + ..\..\..\packages\System.Collections.Immutable.1.2.0\lib\portable-net45+win8+wp8+wpa81 diff --git a/src/fsharp/FSharp.Compiler/project.json b/src/fsharp/FSharp.Compiler/project.json index 607931c96ad..65d0f71c296 100644 --- a/src/fsharp/FSharp.Compiler/project.json +++ b/src/fsharp/FSharp.Compiler/project.json @@ -9,7 +9,7 @@ "System.Linq.Queryable": "4.0.1", "System.Net.Requests": "4.0.11", "System.Reflection.Emit": "4.0.1", - "System.Reflection.Metadata": "1.3.0", + "System.Reflection.Metadata": "1.4.1-beta-24227-04", "System.Reflection.TypeExtensions": "4.1.0", "System.Runtime.InteropServices": "4.1.0", "System.Runtime.InteropServices.PInvoke": "4.0.0-rc2-24027", diff --git a/src/fsharp/FSharp.Core.Unittests/project.json b/src/fsharp/FSharp.Core.Unittests/project.json index 2ab29cb86b4..29385c5b8a9 100644 --- a/src/fsharp/FSharp.Core.Unittests/project.json +++ b/src/fsharp/FSharp.Core.Unittests/project.json @@ -1,23 +1,24 @@ { "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1-rc2-24027", - "NETStandard.Library": "1.5.0-rc2-24027", - "System.Linq.Expressions": "4.0.11-rc2-24027", - "System.Linq.Queryable": "4.0.1-rc2-24027", - "System.Reflection.Emit": "4.0.1-rc2-24027", - "System.Runtime.Loader": "4.0.0-rc2-24027", - "System.Net.Requests": "4.0.11-rc2-24027", + "Microsoft.NETCore.Platforms": "1.0.1", + "NETStandard.Library": "1.6.0", + "System.Linq.Expressions": "4.1.0", + "System.Linq.Queryable": "4.0.1", + "System.Net.Requests": "4.0.11", + "System.Reflection.Emit": "4.0.1", + "System.Runtime.Loader": "4.0.0", + "System.Text.RegularExpressions": "4.1.0", "System.Threading.Tasks.Parallel": "4.0.1-rc2-24027", - "System.Threading.Thread": "4.0.0-rc2-24027", - "System.Threading.ThreadPool": "4.0.10-rc2-24027", + "System.Threading.Thread": "4.0.0", + "System.Threading.ThreadPool": "4.0.10", }, "runtimes": { "win7-x86": { }, "win7-x64": { }, - "osx.10.10-x64": { }, + "osx.10.11-x64": { }, "ubuntu.14.04-x64": { } }, "frameworks": { - "netstandard1.5": { } + "netstandard1.6": { } } } diff --git a/src/fsharp/FSharp.Core/project.json b/src/fsharp/FSharp.Core/project.json index dbec75ef1bb..baca2d8e8e5 100644 --- a/src/fsharp/FSharp.Core/project.json +++ b/src/fsharp/FSharp.Core/project.json @@ -1,7 +1,7 @@ { "dependencies": { "Microsoft.NETCore.Platforms": "1.0.1", - "Microsoft.NETCore.Runtime": "1.0.2", + "Microsoft.NETCore.Runtime": "1.0.2-rc4-24201-00", "System.Collections": "4.0.11", "System.Console": "4.0.0", "System.Diagnostics.Debug": "4.0.11", diff --git a/src/fsharp/FSharp.LanguageService.Compiler/FSharp.LanguageService.Compiler.fsproj b/src/fsharp/FSharp.LanguageService.Compiler/FSharp.LanguageService.Compiler.fsproj index bc4892ad7a0..6044b34a6b6 100644 --- a/src/fsharp/FSharp.LanguageService.Compiler/FSharp.LanguageService.Compiler.fsproj +++ b/src/fsharp/FSharp.LanguageService.Compiler/FSharp.LanguageService.Compiler.fsproj @@ -582,10 +582,10 @@ - ..\..\..\packages\Microsoft.DiaSymReader.PortablePdb.1.0.0-rc-60301\lib\portable-net45+win8\Microsoft.DiaSymReader.PortablePdb.dll - ..\..\..\packages\Microsoft.DiaSymReader.1.0.7\lib\portable-net45+win8\Microsoft.DiaSymReader.dll - ..\..\..\packages\System.Reflection.Metadata.1.3.0-beta-23816\lib\portable-net45+win8\System.Reflection.Metadata.dll - ..\..\..\packages\System.Collections.Immutable.1.2.0-rc3-23805\lib\portable-net45+win8+wp8+wpa81 + ..\..\..\packages\Microsoft.DiaSymReader.PortablePdb.1.1.0\lib\portable-net45+win8\Microsoft.DiaSymReader.PortablePdb.dll + ..\..\..\packages\Microsoft.DiaSymReader.1.0.8\lib\portable-net45+win8\Microsoft.DiaSymReader.dll + ..\..\..\packages\System.Reflection.Metadata.1.4.1-beta-24227-04\lib\portable-net45+win8\System.Reflection.Metadata.dll + ..\..\..\packages\System.Collections.Immutable.1.2.0\lib\portable-net45+win8+wp8+wpa81 {DED3BBD7-53F4-428A-8C9F-27968E768605} FSharp.Core diff --git a/src/fsharp/Fsc/project.json b/src/fsharp/Fsc/project.json index 230aac3ada0..b246aa367ea 100644 --- a/src/fsharp/Fsc/project.json +++ b/src/fsharp/Fsc/project.json @@ -3,7 +3,7 @@ "Microsoft.NETCore.Platforms": "1.0.1", "NETStandard.Library": "1.6.0", "System.Linq.Expressions": "4.1.0", - "System.Reflection.Metadata": "1.3.0" + "System.Reflection.Metadata": "1.4.1-beta-24227-04" }, "runtimes": { "win7-x86": { }, diff --git a/src/fsharp/fsi/project.json b/src/fsharp/fsi/project.json index ab1bfc4de17..d32dabdd033 100644 --- a/src/fsharp/fsi/project.json +++ b/src/fsharp/fsi/project.json @@ -8,7 +8,7 @@ "System.Reflection.TypeExtensions": "4.1.0", "System.Runtime.Loader": "4.0.0", "System.Threading.Thread": "4.0.0", - "System.Reflection.Metadata": "1.3.0" + "System.Reflection.Metadata": "1.4.1-beta-24227-04" }, "runtimes": { "win7-x86": { }, diff --git a/tests/BuildTestTools.cmd b/tests/BuildTestTools.cmd index 9c220651c84..839be2c6275 100644 --- a/tests/BuildTestTools.cmd +++ b/tests/BuildTestTools.cmd @@ -69,20 +69,20 @@ if '%BUILD_CORECLR%' == '1' ( ) rem deploy x86 version of compiler and dependencies - %_fsiexe% --exec %~dp0fsharpqa\testenv\src\DeployProj\DeployProj.fsx --targetPlatformName:.NETStandard,Version=v1.5/win7-x86 --projectJson:%~dp0fsharp\project.json --projectJsonLock:%~dp0fsharp\project.lock.json --packagesDir:%~dp0..\packages --fsharpCore:%~dp0..\%1\coreclr\bin\fsharp.core.dll --output:%~dp0testbin\%1\coreclr\fsc\win7-x86 --nugetPath:%~dp0..\.nuget\nuget.exe --nugetConfig:%~dp0..\.nuget\nuget.config --copyCompiler:yes --v:quiet - %_fsiexe% --exec %~dp0fsharpqa\testenv\src\DeployProj\DeployProj.fsx --targetPlatformName:.NETStandard,Version=v1.5/win7-x86 --projectJson:%~dp0fsharp\project.json --projectJsonLock:%~dp0fsharp\project.lock.json --packagesDir:%~dp0..\packages --fsharpCore:%~dp0..\%1\coreclr\bin\fsharp.core.dll --output:%~dp0testbin\%1\coreclr\win7-x86 --nugetPath:%~dp0..\.nuget\nuget.exe --nugetConfig:%~dp0..\.nuget\nuget.config --copyCompiler:no --v:quiet + %_fsiexe% --exec %~dp0fsharpqa\testenv\src\DeployProj\DeployProj.fsx --targetPlatformName:.NETStandard,Version=v1.6/win7-x86 --projectJson:%~dp0fsharp\project.json --projectJsonLock:%~dp0fsharp\project.lock.json --packagesDir:%~dp0..\packages --fsharpCore:%~dp0..\%1\coreclr\bin\fsharp.core.dll --output:%~dp0testbin\%1\coreclr\fsc\win7-x86 --nugetPath:%~dp0..\.nuget\nuget.exe --nugetConfig:%~dp0..\.nuget\nuget.config --copyCompiler:yes --v:quiet + %_fsiexe% --exec %~dp0fsharpqa\testenv\src\DeployProj\DeployProj.fsx --targetPlatformName:.NETStandard,Version=v1.6/win7-x86 --projectJson:%~dp0fsharp\project.json --projectJsonLock:%~dp0fsharp\project.lock.json --packagesDir:%~dp0..\packages --fsharpCore:%~dp0..\%1\coreclr\bin\fsharp.core.dll --output:%~dp0testbin\%1\coreclr\win7-x86 --nugetPath:%~dp0..\.nuget\nuget.exe --nugetConfig:%~dp0..\.nuget\nuget.config --copyCompiler:no --v:quiet rem deploy x64 version of compiler - %_fsiexe% --exec %~dp0fsharpqa\testenv\src\DeployProj\DeployProj.fsx --targetPlatformName:.NETStandard,Version=v1.5/win7-x64 --projectJson:%~dp0fsharp\project.json --projectJsonLock:%~dp0fsharp\project.lock.json --packagesDir:%~dp0..\packages --fsharpCore:%~dp0..\%1\coreclr\bin\fsharp.core.dll --output:%~dp0testbin\%1\coreclr\fsc\win7-x64 --nugetPath:%~dp0..\.nuget\nuget.exe --nugetConfig:%~dp0..\.nuget\nuget.config --copyCompiler:yes --v:quiet - %_fsiexe% --exec %~dp0fsharpqa\testenv\src\DeployProj\DeployProj.fsx --targetPlatformName:.NETStandard,Version=v1.5/win7-x64 --projectJson:%~dp0fsharp\project.json --projectJsonLock:%~dp0fsharp\project.lock.json --packagesDir:%~dp0..\packages --fsharpCore:%~dp0..\%1\coreclr\bin\fsharp.core.dll --output:%~dp0testbin\%1\coreclr\win7-x64 --nugetPath:%~dp0..\.nuget\nuget.exe --nugetConfig:%~dp0..\.nuget\nuget.config --copyCompiler:no --v:quiet + %_fsiexe% --exec %~dp0fsharpqa\testenv\src\DeployProj\DeployProj.fsx --targetPlatformName:.NETStandard,Version=v1.6/win7-x64 --projectJson:%~dp0fsharp\project.json --projectJsonLock:%~dp0fsharp\project.lock.json --packagesDir:%~dp0..\packages --fsharpCore:%~dp0..\%1\coreclr\bin\fsharp.core.dll --output:%~dp0testbin\%1\coreclr\fsc\win7-x64 --nugetPath:%~dp0..\.nuget\nuget.exe --nugetConfig:%~dp0..\.nuget\nuget.config --copyCompiler:yes --v:quiet + %_fsiexe% --exec %~dp0fsharpqa\testenv\src\DeployProj\DeployProj.fsx --targetPlatformName:.NETStandard,Version=v1.6/win7-x64 --projectJson:%~dp0fsharp\project.json --projectJsonLock:%~dp0fsharp\project.lock.json --packagesDir:%~dp0..\packages --fsharpCore:%~dp0..\%1\coreclr\bin\fsharp.core.dll --output:%~dp0testbin\%1\coreclr\win7-x64 --nugetPath:%~dp0..\.nuget\nuget.exe --nugetConfig:%~dp0..\.nuget\nuget.config --copyCompiler:no --v:quiet rem deploy linux version of built compiler - %_fsiexe% --exec %~dp0fsharpqa\testenv\src\DeployProj\DeployProj.fsx --targetPlatformName:.NETStandard,Version=v1.5/ubuntu.14.04-x64 --projectJson:%~dp0fsharp\project.json --projectJsonLock:%~dp0fsharp\project.lock.json --packagesDir:%~dp0..\packages --fsharpCore:%~dp0..\%1\coreclr\bin\fsharp.core.dll --output:%~dp0testbin\%1\coreclr\fsc\ubuntu.14.04-x64 --nugetPath:%~dp0..\.nuget\nuget.exe --nugetConfig:%~dp0..\.nuget\nuget.config --copyCompiler:yes --v:quiet - %_fsiexe% --exec %~dp0fsharpqa\testenv\src\DeployProj\DeployProj.fsx --targetPlatformName:.NETStandard,Version=v1.5/ubuntu.14.04-x64 --projectJson:%~dp0fsharp\project.json --projectJsonLock:%~dp0fsharp\project.lock.json --packagesDir:%~dp0..\packages --fsharpCore:%~dp0..\%1\coreclr\bin\fsharp.core.dll --output:%~dp0testbin\%1\coreclr\ubuntu.14.04-x64 --nugetPath:%~dp0..\.nuget\nuget.exe --nugetConfig:%~dp0..\.nuget\nuget.config --copyCompiler:no --v:quiet + %_fsiexe% --exec %~dp0fsharpqa\testenv\src\DeployProj\DeployProj.fsx --targetPlatformName:.NETStandard,Version=v1.6/ubuntu.14.04-x64 --projectJson:%~dp0fsharp\project.json --projectJsonLock:%~dp0fsharp\project.lock.json --packagesDir:%~dp0..\packages --fsharpCore:%~dp0..\%1\coreclr\bin\fsharp.core.dll --output:%~dp0testbin\%1\coreclr\fsc\ubuntu.14.04-x64 --nugetPath:%~dp0..\.nuget\nuget.exe --nugetConfig:%~dp0..\.nuget\nuget.config --copyCompiler:yes --v:quiet + %_fsiexe% --exec %~dp0fsharpqa\testenv\src\DeployProj\DeployProj.fsx --targetPlatformName:.NETStandard,Version=v1.6/ubuntu.14.04-x64 --projectJson:%~dp0fsharp\project.json --projectJsonLock:%~dp0fsharp\project.lock.json --packagesDir:%~dp0..\packages --fsharpCore:%~dp0..\%1\coreclr\bin\fsharp.core.dll --output:%~dp0testbin\%1\coreclr\ubuntu.14.04-x64 --nugetPath:%~dp0..\.nuget\nuget.exe --nugetConfig:%~dp0..\.nuget\nuget.config --copyCompiler:no --v:quiet rem deploy osx version of built compiler - %_fsiexe% --exec %~dp0fsharpqa\testenv\src\DeployProj\DeployProj.fsx --targetPlatformName:.NETStandard,Version=v1.5/osx.10.10-x64 --projectJson:%~dp0fsharp\project.json --projectJsonLock:%~dp0fsharp\project.lock.json --packagesDir:%~dp0..\packages --fsharpCore:%~dp0..\%1\coreclr\bin\fsharp.core.dll --output:%~dp0testbin\%1\coreclr\fsc\osx.10.10-x64 --nugetPath:%~dp0..\.nuget\nuget.exe --nugetConfig:%~dp0..\.nuget\nuget.config --copyCompiler:yes --v:quiet - %_fsiexe% --exec %~dp0fsharpqa\testenv\src\DeployProj\DeployProj.fsx --targetPlatformName:.NETStandard,Version=v1.5/osx.10.10-x64 --projectJson:%~dp0fsharp\project.json --projectJsonLock:%~dp0fsharp\project.lock.json --packagesDir:%~dp0..\packages --fsharpCore:%~dp0..\%1\coreclr\bin\fsharp.core.dll --output:%~dp0testbin\%1\coreclr\osx.10.10-x64 --nugetPath:%~dp0..\.nuget\nuget.exe --nugetConfig:%~dp0..\.nuget\nuget.config --copyCompiler:no --v:quiet + %_fsiexe% --exec %~dp0fsharpqa\testenv\src\DeployProj\DeployProj.fsx --targetPlatformName:.NETStandard,Version=v1.6/osx.10.10-x64 --projectJson:%~dp0fsharp\project.json --projectJsonLock:%~dp0fsharp\project.lock.json --packagesDir:%~dp0..\packages --fsharpCore:%~dp0..\%1\coreclr\bin\fsharp.core.dll --output:%~dp0testbin\%1\coreclr\fsc\osx.10.10-x64 --nugetPath:%~dp0..\.nuget\nuget.exe --nugetConfig:%~dp0..\.nuget\nuget.config --copyCompiler:yes --v:quiet + %_fsiexe% --exec %~dp0fsharpqa\testenv\src\DeployProj\DeployProj.fsx --targetPlatformName:.NETStandard,Version=v1.6/osx.10.10-x64 --projectJson:%~dp0fsharp\project.json --projectJsonLock:%~dp0fsharp\project.lock.json --packagesDir:%~dp0..\packages --fsharpCore:%~dp0..\%1\coreclr\bin\fsharp.core.dll --output:%~dp0testbin\%1\coreclr\osx.10.10-x64 --nugetPath:%~dp0..\.nuget\nuget.exe --nugetConfig:%~dp0..\.nuget\nuget.config --copyCompiler:no --v:quiet echo "%NUNITPATH%*.*" "%~dp0fsharpqa\testenv\bin\nunit\*.*" /S /Q /Y xcopy "%NUNITPATH%*.*" "%~dp0fsharpqa\testenv\bin\nunit\*.*" /S /Q /Y diff --git a/tests/fsharp/project.json b/tests/fsharp/project.json index 5090c2c45fb..c9d1f44c1a1 100644 --- a/tests/fsharp/project.json +++ b/tests/fsharp/project.json @@ -1,25 +1,49 @@ { "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1-rc2-24027", - "NETStandard.Library": "1.5.0-rc2-24027", + "Microsoft.NETCore.Platforms": "1.0.1", + "Microsoft.NETCore.Runtime": "1.0.2-rc4-24201-00", + "NETStandard.Library": "1.6.0", + "System.Collections": "4.0.11", + "System.Collections.Immutable":"1.2.0", + "System.Console": "4.0.0", + "System.Diagnostics.Debug": "4.0.11", + "System.Diagnostics.Process": "4.1.0", + "System.Diagnostics.Tools": "4.0.1", + "System.Diagnostics.TraceSource": "4.0.0", + "System.Globalization": "4.0.11", + "System.IO": "4.1.0", + "System.Linq": "4.1.0", + "System.Linq.Expressions": "4.1.0", + "System.Linq.Queryable": "4.0.1", + "System.Net.Requests": "4.0.11", + "System.Reflection": "4.1.0", + "System.Reflection.Emit": "4.0.1", + "System.Reflection.Extensions": "4.0.1", + "System.Reflection.Metadata": "1.4.1-beta-24227-04", + "System.Reflection.TypeExtensions": "4.1.0", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Runtime.InteropServices": "4.1.0", + "System.Runtime.InteropServices.PInvoke": "4.0.0-rc2-24027", + "System.Runtime.Loader": "4.0.0", + "System.Runtime.Numerics": "4.0.1", + "System.Security.Cryptography.Algorithms": "4.2.0", + "System.Text.RegularExpressions": "4.1.0", + "System.Threading": "4.0.11", + "System.Threading.Tasks": "4.0.11", + "System.Threading.Tasks.Parallel": "4.0.1", + "System.Threading.Thread": "4.0.0", + "System.Threading.ThreadPool": "4.0.10", + "System.Threading.Timer": "4.0.1", + + "Microsoft.DiaSymReader.PortablePdb": "1.1.0", + "Microsoft.DiaSymReader": "1.0.8", + "Microsoft.NETCore.Runtime.CoreCLR": "1.0.2-rc2-24027", "Microsoft.NETCore.TestHost": "1.0.0-rc2-24027", "Microsoft.NETCore.ConsoleHost": "1.0.0-rc2-24027", - "System.Collections.Immutable":"1.2.0-rc2-24027", - "System.Diagnostics.Process": "4.1.0-rc2-24027", - "System.Diagnostics.TraceSource": "4.0.0-rc2-24027", - "System.Linq.Expressions": "4.0.11-rc2-24027", - "System.Reflection.Emit": "4.0.1-rc2-24027", - "System.Reflection.Emit.ILGeneration": "4.0.1-rc2-24027", - "System.Reflection.Metadata": "1.3.0-rc2-24027", - "System.Reflection.TypeExtensions": "4.1.0-rc2-24027", - "System.Runtime.InteropServices": "4.1.0-rc2-24027", - "System.Runtime.InteropServices.PInvoke": "4.0.0-rc2-24027", - "System.Runtime.Loader": "4.0.0-rc2-24027", - "System.Security.Cryptography.Algorithms": "4.1.0-rc2-24027", - "System.Security.Cryptography.Primitives": "4.0.0-rc2-24027", - "System.Threading.Thread": "4.0.0-rc2-24027", - "System.Threading.ThreadPool": "4.0.10-rc2-24027" + "System.Reflection.Emit.ILGeneration": "4.0.2", + "System.Security.Cryptography.Primitives": "4.0.1", }, "runtimes": { "win7-x86": { }, @@ -28,6 +52,6 @@ "ubuntu.14.04-x64": { } }, "frameworks": { - "netstandard1.5": { } + "netstandard1.6": { } } } diff --git a/tests/fsharpqa/testenv/bin/System.Reflection.Metadata.dll b/tests/fsharpqa/testenv/bin/System.Reflection.Metadata.dll index cb4cdd3431ca4e308d0c17f3447255babf041999..67c3785946d3fd8183e06efd955178efb5be73f9 100644 GIT binary patch literal 432872 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≥ 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%0D<94 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