diff --git a/README.md b/README.md
index 2026df28022..7ca82c9a92d 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# The F# compiler, F# core library, and F# editor tools
[](https://dev.azure.com/dnceng-public/public/_build/latest?definitionId=90&branchName=main)
-[](https://github.com/dotnet/runtime/labels/help%20wanted)
+[](https://github.com/dotnet/fsharp/labels/help%20wanted)
You're invited to contribute to future releases of the F# compiler, core library, and tools. Development of this repository can be done on any OS supported by [.NET](https://dotnet.microsoft.com/).
diff --git a/eng/Versions.props b/eng/Versions.props
index 334e324e6f6..971e0bc4049 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -31,7 +31,7 @@
6.0.0.0
- 42
+ 437200$(FSRevisionVersion)
diff --git a/src/Compiler/Checking/CheckExpressions.fs b/src/Compiler/Checking/CheckExpressions.fs
index 48fee010206..c25bbfa92ab 100644
--- a/src/Compiler/Checking/CheckExpressions.fs
+++ b/src/Compiler/Checking/CheckExpressions.fs
@@ -453,7 +453,7 @@ let UnifyOverallType (cenv: cenv) (env: TcEnv) m overallTy actualTy =
| None -> ()
match usesTDC with
- | TypeDirectedConversionUsed.Yes(warn, _) -> warning(warn env.DisplayEnv)
+ | TypeDirectedConversionUsed.Yes(warn, _, _) -> warning(warn env.DisplayEnv)
| TypeDirectedConversionUsed.No -> ()
if AddCxTypeMustSubsumeTypeUndoIfFailed env.DisplayEnv cenv.css m reqdTy2 actualTy then
@@ -10950,7 +10950,7 @@ and ComputeIsComplete enclosingDeclaredTypars declaredTypars ty =
/// Determine if a uniquely-identified-abstract-slot exists for an override member (or interface member implementation) based on the information available
/// at the syntactic definition of the member (i.e. prior to type inference). If so, we know the expected signature of the override, and the full slotsig
/// it implements. Apply the inferred slotsig.
-and ApplyAbstractSlotInference (cenv: cenv) (envinner: TcEnv) (argsAndRetTy, m, synTyparDecls, declaredTypars, memberId, tcrefObjTy, renaming, _objTy, intfSlotTyOpt, valSynData, memberFlags: SynMemberFlags, attribs) =
+and ApplyAbstractSlotInference (cenv: cenv) (envinner: TcEnv) (baseValOpt: Val option) (argsAndRetTy, m, synTyparDecls, declaredTypars, memberId, tcrefObjTy, renaming, intfSlotTyOpt, valSynData, memberFlags: SynMemberFlags, attribs) =
let g = cenv.g
let ad = envinner.eAccessRights
@@ -10997,7 +10997,21 @@ and ApplyAbstractSlotInference (cenv: cenv) (envinner: TcEnv) (argsAndRetTy, m,
| _ -> [] // check that method to override is sealed is located at CheckOverridesAreAllUsedOnce (typrelns.fs)
// We hit this case when it is ambiguous which abstract method is being implemented.
-
+ if g.langVersion.SupportsFeature(LanguageFeature.ErrorForNonVirtualMembersOverrides) then
+ // Checks if the declaring type inherits from a base class and is not FSharpObjModelTy
+ // Raises an error if we try to override an non virtual member with the same name in both
+ match baseValOpt with
+ | Some ttype when not(isFSharpObjModelTy g ttype.Type) ->
+ match stripTyEqns g ttype.Type with
+ | TType_app(tyconRef, _, _) ->
+ let ilMethods = tyconRef.ILTyconRawMetadata.Methods.AsList()
+ let nameOpt = ilMethods |> List.tryFind(fun id -> id.Name = memberId.idText)
+ match nameOpt with
+ | Some name when not name.IsVirtual ->
+ errorR(Error(FSComp.SR.tcNoMemberFoundForOverride(), memberId.idRange))
+ | _ -> ()
+ | _ -> ()
+ | _ -> ()
// If we determined a unique member then utilize the type information from the slotsig
let declaredTypars =
@@ -11159,14 +11173,14 @@ and AnalyzeRecursiveStaticMemberOrValDecl
CheckForNonAbstractInterface declKind tcref memberFlags id.idRange
let isExtrinsic = (declKind = ExtrinsicExtensionBinding)
- let tcrefObjTy, enclosingDeclaredTypars, renaming, objTy, _ = FreshenObjectArgType cenv mBinding TyparRigidity.WillBeRigid tcref isExtrinsic declaredTyconTypars
+ let tcrefObjTy, enclosingDeclaredTypars, renaming, _, _ = FreshenObjectArgType cenv mBinding TyparRigidity.WillBeRigid tcref isExtrinsic declaredTyconTypars
let envinner = AddDeclaredTypars CheckForDuplicateTypars enclosingDeclaredTypars envinner
let envinner = MakeInnerEnvForTyconRef envinner tcref isExtrinsic
let (ExplicitTyparInfo(_, declaredTypars, infer)) = explicitTyparInfo
let optInferredImplSlotTys, declaredTypars =
- ApplyAbstractSlotInference cenv envinner (ty, mBinding, synTyparDecls, declaredTypars, id, tcrefObjTy, renaming, objTy, intfSlotTyOpt, valSynInfo, memberFlags, bindingAttribs)
+ ApplyAbstractSlotInference cenv envinner None (ty, mBinding, synTyparDecls, declaredTypars, id, tcrefObjTy, renaming, intfSlotTyOpt, valSynInfo, memberFlags, bindingAttribs)
let explicitTyparInfo = ExplicitTyparInfo(declaredTypars, declaredTypars, infer)
@@ -11231,7 +11245,6 @@ and AnalyzeRecursiveStaticMemberOrValDecl
| _ ->
envinner, tpenv, id, None, None, vis, vis2, None, [], None, explicitTyparInfo, bindingRhs, declaredTypars
-
and AnalyzeRecursiveInstanceMemberDecl
(cenv: cenv,
envinner: TcEnv,
@@ -11290,7 +11303,7 @@ and AnalyzeRecursiveInstanceMemberDecl
// at the member signature. If so, we know the type of this member, and the full slotsig
// it implements. Apply the inferred slotsig.
let optInferredImplSlotTys, declaredTypars =
- ApplyAbstractSlotInference cenv envinner (argsAndRetTy, mBinding, synTyparDecls, declaredTypars, memberId, tcrefObjTy, renaming, objTy, intfSlotTyOpt, valSynInfo, memberFlags, bindingAttribs)
+ ApplyAbstractSlotInference cenv envinner baseValOpt (argsAndRetTy, mBinding, synTyparDecls, declaredTypars, memberId, tcrefObjTy, renaming, intfSlotTyOpt, valSynInfo, memberFlags, bindingAttribs)
// Update the ExplicitTyparInfo to reflect the declaredTypars inferred from the abstract slot
let explicitTyparInfo = ExplicitTyparInfo(declaredTypars, declaredTypars, infer)
diff --git a/src/Compiler/Checking/ConstraintSolver.fs b/src/Compiler/Checking/ConstraintSolver.fs
index 751e71bff5c..6b0ef85d5e8 100644
--- a/src/Compiler/Checking/ConstraintSolver.fs
+++ b/src/Compiler/Checking/ConstraintSolver.fs
@@ -2738,7 +2738,7 @@ and ArgsMustSubsumeOrConvert
msg csenv.DisplayEnv
| None -> ()
match usesTDC with
- | TypeDirectedConversionUsed.Yes(warn, _) -> do! WarnD(warn csenv.DisplayEnv)
+ | TypeDirectedConversionUsed.Yes(warn, _, _) -> do! WarnD(warn csenv.DisplayEnv)
| TypeDirectedConversionUsed.No -> ()
do! SolveTypeSubsumesTypeWithReport csenv ndeep m trace cxsln (Some calledArg.CalledArgumentType) calledArgTy callerArg.CallerArgumentType
if calledArg.IsParamArray && isArray1DTy g calledArgTy && not (isArray1DTy g callerArg.CallerArgumentType) then
@@ -2769,7 +2769,7 @@ and ArgsMustSubsumeOrConvertWithContextualReport
msg csenv.DisplayEnv
| None -> ()
match usesTDC with
- | TypeDirectedConversionUsed.Yes(warn, _) -> do! WarnD(warn csenv.DisplayEnv)
+ | TypeDirectedConversionUsed.Yes(warn, _, _) -> do! WarnD(warn csenv.DisplayEnv)
| TypeDirectedConversionUsed.No -> ()
do! SolveTypeSubsumesTypeWithWrappedContextualReport csenv ndeep m trace cxsln (Some calledArg.CalledArgumentType) calledArgTy callerArgTy (fun e -> ArgDoesNotMatchError(e :?> _, calledMeth, calledArg, callerArg))
return usesTDC
@@ -2796,7 +2796,7 @@ and ReturnTypesMustSubsumeOrConvert (csenv: ConstraintSolverEnv) ad ndeep trace
msg csenv.DisplayEnv
| None -> ()
match usesTDC with
- | TypeDirectedConversionUsed.Yes(warn, _) -> do! WarnD(warn csenv.DisplayEnv)
+ | TypeDirectedConversionUsed.Yes(warn, _, _) -> do! WarnD(warn csenv.DisplayEnv)
| TypeDirectedConversionUsed.No -> ()
do! SolveTypeSubsumesTypeWithReport csenv ndeep m trace cxsln None reqdTy actualTy
return usesTDC
@@ -2813,7 +2813,7 @@ and ArgsEquivOrConvert (csenv: ConstraintSolverEnv) ad ndeep trace cxsln isConst
msg csenv.DisplayEnv
| None -> ()
match usesTDC with
- | TypeDirectedConversionUsed.Yes(warn, _) -> do! WarnD(warn csenv.DisplayEnv)
+ | TypeDirectedConversionUsed.Yes(warn, _, _) -> do! WarnD(warn csenv.DisplayEnv)
| TypeDirectedConversionUsed.No -> ()
if not (typeEquiv csenv.g calledArgTy callerArgTy) then
return! ErrorD(Error(FSComp.SR.csArgumentTypesDoNotMatch(), m))
@@ -3225,7 +3225,11 @@ and GetMostApplicableOverload csenv ndeep candidates applicableMeths calledMethG
if c <> 0 then c else
// Prefer methods that need less type-directed conversion
- let c = compare (match usesTDC1 with TypeDirectedConversionUsed.Yes(_, false) -> 1 | _ -> 0) (match usesTDC2 with TypeDirectedConversionUsed.Yes(_, false) -> 1 | _ -> 0)
+ let c = compare (match usesTDC1 with TypeDirectedConversionUsed.Yes(_, false, _) -> 1 | _ -> 0) (match usesTDC2 with TypeDirectedConversionUsed.Yes(_, false, _) -> 1 | _ -> 0)
+ if c <> 0 then c else
+
+ // Prefer methods that only have nullable type-directed conversions
+ let c = compare (match usesTDC1 with TypeDirectedConversionUsed.Yes(_, _, true) -> 1 | _ -> 0) (match usesTDC2 with TypeDirectedConversionUsed.Yes(_, _, true) -> 1 | _ -> 0)
if c <> 0 then c else
// Prefer methods that don't give "this code is less generic" warnings
diff --git a/src/Compiler/Checking/MethodCalls.fs b/src/Compiler/Checking/MethodCalls.fs
index 1536277c506..c7523e7ba50 100644
--- a/src/Compiler/Checking/MethodCalls.fs
+++ b/src/Compiler/Checking/MethodCalls.fs
@@ -236,12 +236,16 @@ type TypeDirectedConversion =
[]
type TypeDirectedConversionUsed =
- | Yes of (DisplayEnv -> exn) * isTwoStepConversion: bool
+ | Yes of (DisplayEnv -> exn) * isTwoStepConversion: bool * isNullable: bool
| No
static member Combine a b =
match a, b with
- | Yes(_,true), _ -> a
- | _, Yes(_,true) -> b
+ // We want to know which candidates have one or more nullable conversions exclusively
+ // If one of the values is false we flow false for both.
+ | Yes(_, true, false), _ -> a
+ | _, Yes(_, true, false) -> b
+ | Yes(_, true, _), _ -> a
+ | _, Yes(_, true, _) -> b
| Yes _, _ -> a
| _, Yes _ -> b
| No, No -> a
@@ -282,25 +286,25 @@ let rec AdjustRequiredTypeForTypeDirectedConversions (infoReader: InfoReader) ad
// Adhoc int32 --> int64
elif g.langVersion.SupportsFeature LanguageFeature.AdditionalTypeDirectedConversions && typeEquiv g g.int64_ty reqdTy && typeEquiv g g.int32_ty actualTy then
- g.int32_ty, TypeDirectedConversionUsed.Yes(warn TypeDirectedConversion.BuiltIn, false), None
+ g.int32_ty, TypeDirectedConversionUsed.Yes(warn TypeDirectedConversion.BuiltIn, false, false), None
// Adhoc int32 --> nativeint
elif g.langVersion.SupportsFeature LanguageFeature.AdditionalTypeDirectedConversions && typeEquiv g g.nativeint_ty reqdTy && typeEquiv g g.int32_ty actualTy then
- g.int32_ty, TypeDirectedConversionUsed.Yes(warn TypeDirectedConversion.BuiltIn, false), None
+ g.int32_ty, TypeDirectedConversionUsed.Yes(warn TypeDirectedConversion.BuiltIn, false, false), None
// Adhoc int32 --> float64
elif g.langVersion.SupportsFeature LanguageFeature.AdditionalTypeDirectedConversions && typeEquiv g g.float_ty reqdTy && typeEquiv g g.int32_ty actualTy then
- g.int32_ty, TypeDirectedConversionUsed.Yes(warn TypeDirectedConversion.BuiltIn, false), None
+ g.int32_ty, TypeDirectedConversionUsed.Yes(warn TypeDirectedConversion.BuiltIn, false, false), None
elif g.langVersion.SupportsFeature LanguageFeature.NullableOptionalInterop && isMethodArg && isNullableTy g reqdTy && not (isNullableTy g actualTy) then
let underlyingTy = destNullableTy g reqdTy
// shortcut
if typeEquiv g underlyingTy actualTy then
- actualTy, TypeDirectedConversionUsed.Yes(warn TypeDirectedConversion.BuiltIn, false), None
+ actualTy, TypeDirectedConversionUsed.Yes(warn TypeDirectedConversion.BuiltIn, false, true), None
else
let adjustedTy, _, _ = AdjustRequiredTypeForTypeDirectedConversions infoReader ad isMethodArg isConstraint underlyingTy actualTy m
if typeEquiv g adjustedTy actualTy then
- actualTy, TypeDirectedConversionUsed.Yes(warn TypeDirectedConversion.BuiltIn, true), None
+ actualTy, TypeDirectedConversionUsed.Yes(warn TypeDirectedConversion.BuiltIn, true, true), None
else
reqdTy, TypeDirectedConversionUsed.No, None
@@ -308,7 +312,7 @@ let rec AdjustRequiredTypeForTypeDirectedConversions (infoReader: InfoReader) ad
// eliminate articifical constrained type variables.
elif g.langVersion.SupportsFeature LanguageFeature.AdditionalTypeDirectedConversions then
match TryFindRelevantImplicitConversion infoReader ad reqdTy actualTy m with
- | Some (minfo, _staticTy, eqn) -> actualTy, TypeDirectedConversionUsed.Yes(warn (TypeDirectedConversion.Implicit minfo), false), Some eqn
+ | Some (minfo, _staticTy, eqn) -> actualTy, TypeDirectedConversionUsed.Yes(warn (TypeDirectedConversion.Implicit minfo), false, false), Some eqn
| None -> reqdTy, TypeDirectedConversionUsed.No, None
else reqdTy, TypeDirectedConversionUsed.No, None
diff --git a/src/Compiler/Checking/MethodCalls.fsi b/src/Compiler/Checking/MethodCalls.fsi
index a70827d8fec..60a5ace7201 100644
--- a/src/Compiler/Checking/MethodCalls.fsi
+++ b/src/Compiler/Checking/MethodCalls.fsi
@@ -119,7 +119,7 @@ type CallerArgs<'T> =
/// has been used in F# code
[]
type TypeDirectedConversionUsed =
- | Yes of (DisplayEnv -> exn) * isTwoStepConversion: bool
+ | Yes of (DisplayEnv -> exn) * isTwoStepConversion: bool * isNullable: bool
| No
static member Combine: TypeDirectedConversionUsed -> TypeDirectedConversionUsed -> TypeDirectedConversionUsed
diff --git a/src/Compiler/FSComp.txt b/src/Compiler/FSComp.txt
index 9c9da192081..2fca7afeb60 100644
--- a/src/Compiler/FSComp.txt
+++ b/src/Compiler/FSComp.txt
@@ -962,10 +962,6 @@ typeInfoFromFirst,"from %s"
typeInfoFromNext,"also from %s"
typeInfoGeneratedProperty,"generated property"
typeInfoGeneratedType,"generated type"
-assemblyResolutionFoundByAssemblyFoldersKey,"Found by AssemblyFolders registry key"
-assemblyResolutionFoundByAssemblyFoldersExKey,"Found by AssemblyFoldersEx registry key"
-assemblyResolutionNetFramework,".NET Framework"
-assemblyResolutionGAC,"Global Assembly Cache"
1089,recursiveClassHierarchy,"Recursive class hierarchy in type '%s'"
1090,InvalidRecursiveReferenceToAbstractSlot,"Invalid recursive reference to an abstract slot"
1091,eventHasNonStandardType,"The event '%s' has a non-standard type. If this event is declared in another CLI language, you may need to access this event using the explicit %s and %s methods for the event. If this event is declared in F#, make the type of the event an instantiation of either 'IDelegateEvent<_>' or 'IEvent<_,_>'."
@@ -1561,6 +1557,7 @@ featureInitProperties,"support for consuming init properties"
featureLowercaseDUWhenRequireQualifiedAccess,"Allow lowercase DU when RequireQualifiedAccess attribute"
featureMatchNotAllowedForUnionCaseWithNoData,"Pattern match discard is not allowed for union case that takes no data."
featureCSharpExtensionAttributeNotRequired,"Allow implicit Extension attribute on declaring types, modules"
+featureErrorForNonVirtualMembersOverrides,"Raises errors for non-virtual members overrides"
3353,fsiInvalidDirective,"Invalid directive '#%s %s'"
3354,tcNotAFunctionButIndexerNamedIndexingNotYetEnabled,"This value supports indexing, e.g. '%s.[index]'. The syntax '%s[index]' requires /langversion:preview. See https://aka.ms/fsharp-index-notation."
3354,tcNotAFunctionButIndexerIndexingNotYetEnabled,"This expression supports indexing, e.g. 'expr.[index]'. The syntax 'expr[index]' requires /langversion:preview. See https://aka.ms/fsharp-index-notation."
diff --git a/src/Compiler/FSharp.Compiler.Service.fsproj b/src/Compiler/FSharp.Compiler.Service.fsproj
index e7468b34086..eedb771f0f3 100644
--- a/src/Compiler/FSharp.Compiler.Service.fsproj
+++ b/src/Compiler/FSharp.Compiler.Service.fsproj
@@ -461,8 +461,6 @@
-
-
@@ -492,9 +490,6 @@
-
-
-
diff --git a/src/Compiler/FSharp.Compiler.Service.nuspec b/src/Compiler/FSharp.Compiler.Service.nuspec
index c7b55ebb613..a60bdb81021 100644
--- a/src/Compiler/FSharp.Compiler.Service.nuspec
+++ b/src/Compiler/FSharp.Compiler.Service.nuspec
@@ -6,9 +6,6 @@
-
-
-
diff --git a/src/Compiler/Facilities/LanguageFeatures.fs b/src/Compiler/Facilities/LanguageFeatures.fs
index 00ddd74b6c5..14302b05132 100644
--- a/src/Compiler/Facilities/LanguageFeatures.fs
+++ b/src/Compiler/Facilities/LanguageFeatures.fs
@@ -56,6 +56,7 @@ type LanguageFeature =
| SelfTypeConstraints
| MatchNotAllowedForUnionCaseWithNoData
| CSharpExtensionAttributeNotRequired
+ | ErrorForNonVirtualMembersOverrides
/// LanguageVersion management
type LanguageVersion(versionText) =
@@ -128,6 +129,7 @@ type LanguageVersion(versionText) =
LanguageFeature.FromEndSlicing, previewVersion
LanguageFeature.MatchNotAllowedForUnionCaseWithNoData, previewVersion
LanguageFeature.CSharpExtensionAttributeNotRequired, previewVersion
+ LanguageFeature.ErrorForNonVirtualMembersOverrides, previewVersion
]
@@ -237,6 +239,7 @@ type LanguageVersion(versionText) =
| LanguageFeature.SelfTypeConstraints -> FSComp.SR.featureSelfTypeConstraints ()
| LanguageFeature.MatchNotAllowedForUnionCaseWithNoData -> FSComp.SR.featureMatchNotAllowedForUnionCaseWithNoData ()
| LanguageFeature.CSharpExtensionAttributeNotRequired -> FSComp.SR.featureCSharpExtensionAttributeNotRequired ()
+ | LanguageFeature.ErrorForNonVirtualMembersOverrides -> FSComp.SR.featureErrorForNonVirtualMembersOverrides ()
/// Get a version string associated with the given feature.
static member GetFeatureVersionString feature =
diff --git a/src/Compiler/Facilities/LanguageFeatures.fsi b/src/Compiler/Facilities/LanguageFeatures.fsi
index 1b3d68e8f2a..f471f371b95 100644
--- a/src/Compiler/Facilities/LanguageFeatures.fsi
+++ b/src/Compiler/Facilities/LanguageFeatures.fsi
@@ -46,6 +46,7 @@ type LanguageFeature =
| SelfTypeConstraints
| MatchNotAllowedForUnionCaseWithNoData
| CSharpExtensionAttributeNotRequired
+ | ErrorForNonVirtualMembersOverrides
/// LanguageVersion management
type LanguageVersion =
diff --git a/src/Compiler/Facilities/ReferenceResolver.fs b/src/Compiler/Facilities/ReferenceResolver.fs
index d4eeb29871d..7e825741942 100644
--- a/src/Compiler/Facilities/ReferenceResolver.fs
+++ b/src/Compiler/Facilities/ReferenceResolver.fs
@@ -2,7 +2,7 @@
namespace FSharp.Compiler.CodeAnalysis
-exception internal LegacyResolutionFailure
+exception LegacyResolutionFailure
[]
type LegacyResolutionEnvironment =
@@ -28,7 +28,7 @@ type LegacyResolvedFile =
sprintf "LegacyResolvedFile(%s)" this.itemSpec
[]
-type internal ILegacyReferenceResolver =
+type ILegacyReferenceResolver =
/// Get the "v4.5.1"-style moniker for the highest installed .NET Framework version.
/// This is the value passed back to Resolve if no explicit "mscorlib" has been given.
///
diff --git a/src/Compiler/Facilities/ReferenceResolver.fsi b/src/Compiler/Facilities/ReferenceResolver.fsi
index 619c21d423c..8371775f956 100644
--- a/src/Compiler/Facilities/ReferenceResolver.fsi
+++ b/src/Compiler/Facilities/ReferenceResolver.fsi
@@ -4,17 +4,17 @@ namespace FSharp.Compiler.CodeAnalysis
open System
-exception internal LegacyResolutionFailure
+exception LegacyResolutionFailure
[]
-type internal LegacyResolutionEnvironment =
+type LegacyResolutionEnvironment =
/// Indicates a script or source being edited or compiled. Uses reference assemblies (not implementation assemblies).
| EditingOrCompilation of isEditing: bool
/// Indicates a script or source being dynamically compiled and executed. Uses implementation assemblies.
| CompilationAndEvaluation
-type internal LegacyResolvedFile =
+type LegacyResolvedFile =
{
/// Item specification.
itemSpec: string
@@ -27,7 +27,7 @@ type internal LegacyResolvedFile =
}
[]
-type internal ILegacyReferenceResolver =
+type ILegacyReferenceResolver =
/// Get the "v4.5.1"-style moniker for the highest installed .NET Framework version.
/// This is the value passed back to Resolve if no explicit "mscorlib" has been given.
///
@@ -59,5 +59,5 @@ type internal ILegacyReferenceResolver =
// outside FSharp.Compiler.Service
[]
type LegacyReferenceResolver =
- internal new: impl: ILegacyReferenceResolver -> LegacyReferenceResolver
+ new: impl: ILegacyReferenceResolver -> LegacyReferenceResolver
member internal Impl: ILegacyReferenceResolver
diff --git a/src/Compiler/Facilities/SimulatedMSBuildReferenceResolver.fs b/src/Compiler/Facilities/SimulatedMSBuildReferenceResolver.fs
index 21d3260c5c8..b3492cb81ac 100644
--- a/src/Compiler/Facilities/SimulatedMSBuildReferenceResolver.fs
+++ b/src/Compiler/Facilities/SimulatedMSBuildReferenceResolver.fs
@@ -2,340 +2,318 @@
module internal FSharp.Compiler.CodeAnalysis.SimulatedMSBuildReferenceResolver
-open System
-open System.IO
-open System.Reflection
-open Microsoft.Build.Utilities
-open Internal.Utilities.Library
-open FSharp.Compiler.IO
-
-// ATTENTION!: the following code needs to be updated every time we are switching to the new MSBuild version because new .NET framework version was released
-// 1. List of frameworks
-// 2. DeriveTargetFrameworkDirectoriesFor45Plus
-// 3. HighestInstalledRefAssembliesOrDotNETFramework
-// 4. GetPathToDotNetFrameworkImlpementationAssemblies
-[]
-let private Net45 = "v4.5"
-
-[]
-let private Net451 = "v4.5.1"
-
-[]
-let private Net452 = "v4.5.2" // not available in Dev15 MSBuild version
-
-[]
-let private Net46 = "v4.6"
-
-[]
-let private Net461 = "v4.6.1"
-
-[]
-let private Net462 = "v4.6.2"
-
-[]
-let private Net47 = "v4.7"
-
-[]
-let private Net471 = "v4.7.1"
-
-[]
-let private Net472 = "v4.7.2"
-
-[]
-let private Net48 = "v4.8"
-
-let SupportedDesktopFrameworkVersions =
- [ Net48; Net472; Net471; Net47; Net462; Net461; Net46; Net452; Net451; Net45 ]
-
-let private SimulatedMSBuildResolver =
-
- /// Get the path to the .NET Framework implementation assemblies by using ToolLocationHelper.GetPathToDotNetFramework
- /// This is only used to specify the "last resort" path for assembly resolution.
- let GetPathToDotNetFrameworkImlpementationAssemblies v =
- let v =
- match v with
- | Net45 -> Some TargetDotNetFrameworkVersion.Version45
- | Net451 -> Some TargetDotNetFrameworkVersion.Version451
- | Net452 -> Some TargetDotNetFrameworkVersion.Version452
- | Net46 -> Some TargetDotNetFrameworkVersion.Version46
- | Net461 -> Some TargetDotNetFrameworkVersion.Version461
- | Net462 -> Some TargetDotNetFrameworkVersion.Version462
- | Net47 -> Some TargetDotNetFrameworkVersion.Version47
- | Net471 -> Some TargetDotNetFrameworkVersion.Version471
- | Net472 -> Some TargetDotNetFrameworkVersion.Version472
- | Net48 -> Some TargetDotNetFrameworkVersion.Version48
- | _ ->
- assert false
- None
-
- match v with
- | Some v ->
- match ToolLocationHelper.GetPathToDotNetFramework v with
- | null -> []
- | x -> [ x ]
- | _ -> []
-
- let GetPathToDotNetFrameworkReferenceAssemblies version =
-#if NETSTANDARD
- ignore version
- let r: string list = []
- r
-#else
- match Microsoft.Build.Utilities.ToolLocationHelper.GetPathToStandardLibraries(".NETFramework", version, "") with
- | null
- | "" -> []
- | x -> [ x ]
-#endif
-
- { new ILegacyReferenceResolver with
- member x.HighestInstalledNetFrameworkVersion() =
-
- let root = x.DotNetFrameworkReferenceAssembliesRootDirectory
-
- let fwOpt =
- SupportedDesktopFrameworkVersions
- |> Seq.tryFind (fun fw -> FileSystem.DirectoryExistsShim(Path.Combine(root, fw)))
-
- match fwOpt with
- | Some fw -> fw
- | None -> "v4.5"
-
- member _.DotNetFrameworkReferenceAssembliesRootDirectory =
- if Environment.OSVersion.Platform = PlatformID.Win32NT then
- let PF =
- match Environment.GetEnvironmentVariable("ProgramFiles(x86)") with
- | null -> Environment.GetEnvironmentVariable("ProgramFiles") // if PFx86 is null, then we are 32-bit and just get PF
- | s -> s
-
- PF + @"\Reference Assemblies\Microsoft\Framework\.NETFramework"
+ open System
+ open System.IO
+ open System.Reflection
+ open Internal.Utilities.Library
+ open FSharp.Compiler.IO
+
+ // ATTENTION!: the following code needs to be updated every time we are switching to the new MSBuild version because new .NET framework version was released
+ // 1. List of frameworks
+ // 2. DeriveTargetFrameworkDirectoriesFor45Plus
+ // 3. HighestInstalledRefAssembliesOrDotNETFramework
+ // 4. GetPathToDotNetFrameworkImlpementationAssemblies
+ []
+ let private Net45 = "v4.5"
+
+ []
+ let private Net451 = "v4.5.1"
+
+ []
+ let private Net452 = "v4.5.2" // not available in Dev15 MSBuild version
+
+ []
+ let private Net46 = "v4.6"
+
+ []
+ let private Net461 = "v4.6.1"
+
+ []
+ let private Net462 = "v4.6.2"
+
+ []
+ let private Net47 = "v4.7"
+
+ []
+ let private Net471 = "v4.7.1"
+
+ []
+ let private Net472 = "v4.7.2"
+
+ []
+ let private Net48 = "v4.8"
+
+ let SupportedDesktopFrameworkVersions =
+ [ Net48; Net472; Net471; Net47; Net462; Net461; Net46; Net452; Net451; Net45 ]
+
+ let private SimulatedMSBuildResolver =
+
+ /// Get the path to the .NET Framework implementation assemblies by using ToolLocationHelper.GetPathToDotNetFramework
+ /// This is only used to specify the "last resort" path for assembly resolution.
+ let GetPathToDotNetFrameworkImlpementationAssemblies _ =
+ let isDesktop = typeof.Assembly.GetName().Name = "mscorlib"
+ if isDesktop then
+ match System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory() with
+ | null -> []
+ | x -> [ x ]
else
- ""
-
- member _.Resolve
- (
- resolutionEnvironment,
- references,
- targetFrameworkVersion,
- targetFrameworkDirectories,
- targetProcessorArchitecture,
- fsharpCoreDir,
- explicitIncludeDirs,
- implicitIncludeDir,
- logMessage,
- logWarningOrError
- ) =
-
-
- let results = ResizeArray()
-
- let searchPaths =
- [
- yield! targetFrameworkDirectories
- yield! explicitIncludeDirs
- yield fsharpCoreDir
- yield implicitIncludeDir
- yield! GetPathToDotNetFrameworkReferenceAssemblies targetFrameworkVersion
- yield! GetPathToDotNetFrameworkImlpementationAssemblies targetFrameworkVersion
- ]
-
- for r, baggage in references do
- //printfn "resolving %s" r
- let mutable found = false
-
- let success path =
- if not found then
- //printfn "resolved %s --> %s" r path
- found <- true
-
- results.Add
- {
- itemSpec = path
- prepareToolTip = snd
- baggage = baggage
- }
-
- try
- if not found && FileSystem.IsPathRootedShim r then
- if FileSystem.FileExistsShim r then success r
- with e ->
- logWarningOrError false "SR001" (e.ToString())
-
- // For this one we need to get the version search exactly right, without doing a load
- try
- if not found
- && r.StartsWithOrdinal("FSharp.Core, Version=")
- && Environment.OSVersion.Platform = PlatformID.Win32NT then
- let n = AssemblyName r
-
- let fscoreDir0 =
- let PF =
- match Environment.GetEnvironmentVariable("ProgramFiles(x86)") with
- | null -> Environment.GetEnvironmentVariable("ProgramFiles")
- | s -> s
-
- PF
- + @"\Reference Assemblies\Microsoft\FSharp\.NETFramework\v4.0\"
- + n.Version.ToString()
-
- let trialPath = Path.Combine(fscoreDir0, n.Name + ".dll")
-
- if FileSystem.FileExistsShim trialPath then
- success trialPath
- with e ->
- logWarningOrError false "SR001" (e.ToString())
-
- let isFileName =
- r.EndsWith("dll", StringComparison.OrdinalIgnoreCase)
- || r.EndsWith("exe", StringComparison.OrdinalIgnoreCase)
-
- let qual =
- if isFileName then
- r
- else
- try
- AssemblyName(r).Name + ".dll"
- with _ ->
- r + ".dll"
+ []
+
+ let GetPathToDotNetFrameworkReferenceAssemblies version =
+ ignore version
+ let r: string list = []
+ r
+
+ { new ILegacyReferenceResolver with
+ member x.HighestInstalledNetFrameworkVersion() =
+
+ let root = x.DotNetFrameworkReferenceAssembliesRootDirectory
+
+ let fwOpt =
+ SupportedDesktopFrameworkVersions
+ |> Seq.tryFind (fun fw -> FileSystem.DirectoryExistsShim(Path.Combine(root, fw)))
+
+ match fwOpt with
+ | Some fw -> fw
+ | None -> Net45
+
+
+ member _.DotNetFrameworkReferenceAssembliesRootDirectory =
+ if Environment.OSVersion.Platform = PlatformID.Win32NT then
+ let PF =
+ match Environment.GetEnvironmentVariable("ProgramFiles(x86)") with
+ | null -> Environment.GetEnvironmentVariable("ProgramFiles") // if PFx86 is null, then we are 32-bit and just get PF
+ | s -> s
+
+ PF + @"\Reference Assemblies\Microsoft\Framework\.NETFramework"
+ else
+ ""
+
+ member _.Resolve
+ (
+ resolutionEnvironment,
+ references,
+ targetFrameworkVersion,
+ targetFrameworkDirectories,
+ targetProcessorArchitecture,
+ fsharpCoreDir,
+ explicitIncludeDirs,
+ implicitIncludeDir,
+ logMessage,
+ logWarningOrError
+ ) =
+
+
+ let results = ResizeArray()
+
+ let searchPaths =
+ [
+ yield! targetFrameworkDirectories
+ yield! explicitIncludeDirs
+ yield fsharpCoreDir
+ yield implicitIncludeDir
+ yield! GetPathToDotNetFrameworkReferenceAssemblies targetFrameworkVersion
+ yield! GetPathToDotNetFrameworkImlpementationAssemblies targetFrameworkVersion
+ ]
+
+ for r, baggage in references do
+ //printfn "resolving %s" r
+ let mutable found = false
+
+ let success path =
+ if not found then
+ //printfn "resolved %s --> %s" r path
+ found <- true
+
+ results.Add
+ {
+ itemSpec = path
+ prepareToolTip = snd
+ baggage = baggage
+ }
- for searchPath in searchPaths do
try
- if not found then
- let trialPath = Path.Combine(searchPath, qual)
+ if not found && FileSystem.IsPathRootedShim r then
+ if FileSystem.FileExistsShim r then success r
+ with e ->
+ logWarningOrError false "SR001" (e.ToString())
+
+ // For this one we need to get the version search exactly right, without doing a load
+ try
+ if not found
+ && r.StartsWithOrdinal("FSharp.Core, Version=")
+ && Environment.OSVersion.Platform = PlatformID.Win32NT then
+ let n = AssemblyName r
+
+ let fscoreDir0 =
+ let PF =
+ match Environment.GetEnvironmentVariable("ProgramFiles(x86)") with
+ | null -> Environment.GetEnvironmentVariable("ProgramFiles")
+ | s -> s
+
+ PF
+ + @"\Reference Assemblies\Microsoft\FSharp\.NETFramework\v4.0\"
+ + n.Version.ToString()
+
+ let trialPath = Path.Combine(fscoreDir0, n.Name + ".dll")
if FileSystem.FileExistsShim trialPath then
success trialPath
with e ->
logWarningOrError false "SR001" (e.ToString())
- try
- // Search the GAC on Windows
- if not found
- && not isFileName
- && Environment.OSVersion.Platform = PlatformID.Win32NT then
- let n = AssemblyName r
- let netFx = System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory()
-
- let gac =
- Path.Combine(Path.GetDirectoryName(Path.GetDirectoryName(netFx.TrimEnd('\\'))), "assembly")
-
- match n.Version, n.GetPublicKeyToken() with
- | null, _
- | _, null ->
- let options =
- [
- if FileSystem.DirectoryExistsShim gac then
- for gacDir in FileSystem.EnumerateDirectoriesShim gac do
- let assemblyDir = Path.Combine(gacDir, n.Name)
-
- if FileSystem.DirectoryExistsShim assemblyDir then
- for tdir in FileSystem.EnumerateDirectoriesShim assemblyDir do
- let trialPath = Path.Combine(tdir, qual)
- if FileSystem.FileExistsShim trialPath then yield trialPath
- ]
- //printfn "sorting GAC paths: %A" options
- options
- |> List.sort // puts latest version last
- |> List.tryLast
- |> function
- | None -> ()
- | Some p -> success p
-
- | v, tok ->
- if FileSystem.DirectoryExistsShim gac then
- for gacDir in Directory.EnumerateDirectories gac do
- //printfn "searching GAC directory: %s" gacDir
- let assemblyDir = Path.Combine(gacDir, n.Name)
-
- if FileSystem.DirectoryExistsShim assemblyDir then
- //printfn "searching GAC directory: %s" assemblyDir
-
- let tokText = String.concat "" [| for b in tok -> sprintf "%02x" b |]
- let verDir = Path.Combine(assemblyDir, "v4.0_" + v.ToString() + "__" + tokText)
- //printfn "searching GAC directory: %s" verDir
-
- if FileSystem.DirectoryExistsShim verDir then
- let trialPath = Path.Combine(verDir, qual)
- //printfn "searching GAC: %s" trialPath
- if FileSystem.FileExistsShim trialPath then
- success trialPath
- with e ->
- logWarningOrError false "SR001" (e.ToString())
-
- results.ToArray()
- }
- |> LegacyReferenceResolver
-
-let internal getResolver () = SimulatedMSBuildResolver
-
-#if INTERACTIVE
-// Some manual testing
-SimulatedMSBuildResolver.DotNetFrameworkReferenceAssembliesRootDirectory
-SimulatedMSBuildResolver.HighestInstalledNetFrameworkVersion()
-
-let fscoreDir =
- if System.Environment.OSVersion.Platform = System.PlatformID.Win32NT then // file references only valid on Windows
- let PF =
- match Environment.GetEnvironmentVariable("ProgramFiles(x86)") with
- | null -> Environment.GetEnvironmentVariable("ProgramFiles") // if PFx86 is null, then we are 32-bit and just get PF
- | s -> s
-
- PF + @"\Reference Assemblies\Microsoft\FSharp\.NETFramework\v4.0\4.4.0.0"
- else
- System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory()
-
-let resolve s =
- SimulatedMSBuildResolver.Resolve(
- ResolutionEnvironment.EditingOrCompilation,
- [| for a in s -> (a, "") |],
- "v4.5.1",
+ let isFileName =
+ r.EndsWith("dll", StringComparison.OrdinalIgnoreCase)
+ || r.EndsWith("exe", StringComparison.OrdinalIgnoreCase)
+
+ let qual =
+ if isFileName then
+ r
+ else
+ try
+ AssemblyName(r).Name + ".dll"
+ with _ ->
+ r + ".dll"
+
+ for searchPath in searchPaths do
+ try
+ if not found then
+ let trialPath = Path.Combine(searchPath, qual)
+
+ if FileSystem.FileExistsShim trialPath then
+ success trialPath
+ with e ->
+ logWarningOrError false "SR001" (e.ToString())
+
+ try
+ // Search the GAC on Windows
+ if not found
+ && not isFileName
+ && Environment.OSVersion.Platform = PlatformID.Win32NT then
+ let n = AssemblyName r
+ let netFx = System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory()
+
+ let gac =
+ Path.Combine(Path.GetDirectoryName(Path.GetDirectoryName(netFx.TrimEnd('\\'))), "assembly")
+
+ match n.Version, n.GetPublicKeyToken() with
+ | null, _
+ | _, null ->
+ let options =
+ [
+ if FileSystem.DirectoryExistsShim gac then
+ for gacDir in FileSystem.EnumerateDirectoriesShim gac do
+ let assemblyDir = Path.Combine(gacDir, n.Name)
+
+ if FileSystem.DirectoryExistsShim assemblyDir then
+ for tdir in FileSystem.EnumerateDirectoriesShim assemblyDir do
+ let trialPath = Path.Combine(tdir, qual)
+ if FileSystem.FileExistsShim trialPath then yield trialPath
+ ]
+ //printfn "sorting GAC paths: %A" options
+ options
+ |> List.sort // puts latest version last
+ |> List.tryLast
+ |> function
+ | None -> ()
+ | Some p -> success p
+
+ | v, tok ->
+ if FileSystem.DirectoryExistsShim gac then
+ for gacDir in Directory.EnumerateDirectories gac do
+ //printfn "searching GAC directory: %s" gacDir
+ let assemblyDir = Path.Combine(gacDir, n.Name)
+
+ if FileSystem.DirectoryExistsShim assemblyDir then
+ //printfn "searching GAC directory: %s" assemblyDir
+
+ let tokText = String.concat "" [| for b in tok -> sprintf "%02x" b |]
+ let verDir = Path.Combine(assemblyDir, "v4.0_" + v.ToString() + "__" + tokText)
+ //printfn "searching GAC directory: %s" verDir
+
+ if FileSystem.DirectoryExistsShim verDir then
+ let trialPath = Path.Combine(verDir, qual)
+ //printfn "searching GAC: %s" trialPath
+ if FileSystem.FileExistsShim trialPath then
+ success trialPath
+ with e ->
+ logWarningOrError false "SR001" (e.ToString())
+
+ results.ToArray()
+ }
+ |> LegacyReferenceResolver
+
+ let internal getResolver () = SimulatedMSBuildResolver
+
+ #if INTERACTIVE
+ // Some manual testing
+ SimulatedMSBuildResolver.DotNetFrameworkReferenceAssembliesRootDirectory
+ SimulatedMSBuildResolver.HighestInstalledNetFrameworkVersion()
+
+ let fscoreDir =
+ if System.Environment.OSVersion.Platform = System.PlatformID.Win32NT then // file references only valid on Windows
+ let PF =
+ match Environment.GetEnvironmentVariable("ProgramFiles(x86)") with
+ | null -> Environment.GetEnvironmentVariable("ProgramFiles") // if PFx86 is null, then we are 32-bit and just get PF
+ | s -> s
+
+ PF + @"\Reference Assemblies\Microsoft\FSharp\.NETFramework\v4.0\4.4.0.0"
+ else
+ System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory()
+
+ let resolve s =
+ SimulatedMSBuildResolver.Resolve(
+ ResolutionEnvironment.EditingOrCompilation,
+ [| for a in s -> (a, "") |],
+ "v4.5.1",
+ [
+ SimulatedMSBuildResolver.DotNetFrameworkReferenceAssembliesRootDirectory
+ + @"\v4.5.1"
+ ],
+ "",
+ "",
+ fscoreDir,
+ [],
+ __SOURCE_DIRECTORY__,
+ ignore,
+ (fun _ _ -> ()),
+ (fun _ _ -> ())
+ )
+
+ // Resolve partial name to something on search path
+ resolve [ "FSharp.Core" ]
+
+ // Resolve DLL name to something on search path
+ resolve [ "FSharp.Core.dll" ]
+
+ // Resolve from reference assemblies
+ resolve [ "System"; "mscorlib"; "mscorlib.dll" ]
+
+ // Resolve from Registry AssemblyFolders
+ resolve [ "Microsoft.SqlServer.Dmf.dll"; "Microsoft.SqlServer.Dmf" ]
+
+ // Resolve exact version of FSharp.Core
+ resolve
+ [
+ "FSharp.Core, Version=4.4.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
+ ]
+
+ // Resolve from GAC:
+ resolve
+ [
+ "EventViewer, Version=6.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
+ ]
+
+ // Resolve from GAC:
+ resolve [ "EventViewer" ]
+
+ resolve
+ [
+ "Microsoft.SharePoint.Client, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"
+ ]
+
+ resolve
[
- SimulatedMSBuildResolver.DotNetFrameworkReferenceAssembliesRootDirectory
- + @"\v4.5.1"
- ],
- "",
- "",
- fscoreDir,
- [],
- __SOURCE_DIRECTORY__,
- ignore,
- (fun _ _ -> ()),
- (fun _ _ -> ())
- )
-
-// Resolve partial name to something on search path
-resolve [ "FSharp.Core" ]
-
-// Resolve DLL name to something on search path
-resolve [ "FSharp.Core.dll" ]
-
-// Resolve from reference assemblies
-resolve [ "System"; "mscorlib"; "mscorlib.dll" ]
-
-// Resolve from Registry AssemblyFolders
-resolve [ "Microsoft.SqlServer.Dmf.dll"; "Microsoft.SqlServer.Dmf" ]
-
-// Resolve exact version of FSharp.Core
-resolve
- [
- "FSharp.Core, Version=4.4.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
- ]
-
-// Resolve from GAC:
-resolve
- [
- "EventViewer, Version=6.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
- ]
-
-// Resolve from GAC:
-resolve [ "EventViewer" ]
-
-resolve
- [
- "Microsoft.SharePoint.Client, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"
- ]
-
-resolve
- [
- "Microsoft.SharePoint.Client, Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"
- ]
-#endif
+ "Microsoft.SharePoint.Client, Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"
+ ]
+ #endif
diff --git a/src/Compiler/Legacy/LegacyMSBuildReferenceResolver.fs b/src/Compiler/Legacy/LegacyMSBuildReferenceResolver.fs
deleted file mode 100644
index 516695e7e18..00000000000
--- a/src/Compiler/Legacy/LegacyMSBuildReferenceResolver.fs
+++ /dev/null
@@ -1,366 +0,0 @@
-// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.
-
-module FSharp.Compiler.CodeAnalysis.LegacyMSBuildReferenceResolver
-
- open System
- open System.IO
- open System.Reflection
- open Internal.Utilities.Library
- open Microsoft.Build.Tasks
- open Microsoft.Build.Utilities
- open Microsoft.Build.Framework
- open FSharp.Compiler.IO
-
- // Reflection wrapper for properties
- type Object with
- member this.GetPropertyValue(propName) =
- this.GetType().GetProperty(propName, BindingFlags.Public).GetValue(this, null)
-
- /// Get the Reference Assemblies directory for the .NET Framework on Window.
- let DotNetFrameworkReferenceAssembliesRootDirectory =
- // ProgramFilesX86 is correct for both x86 and x64 architectures
- // (the reference assemblies are always in the 32-bit location, which is PF(x86) on an x64 machine)
- let PF =
- match Environment.GetEnvironmentVariable("ProgramFiles(x86)") with
- | Null -> Environment.GetEnvironmentVariable("ProgramFiles") // if PFx86 is null, then we are 32-bit and just get PF
- | NonNull s -> s
- PF + @"\Reference Assemblies\Microsoft\Framework\.NETFramework"
-
- /// When targeting .NET 2.0-3.5 on Windows, we expand the {WindowsFramework} and {ReferenceAssemblies} paths manually
- let internal ReplaceVariablesForLegacyFxOnWindows(dirs: string list) =
- let windowsFramework = Environment.GetEnvironmentVariable("windir")+ @"\Microsoft.NET\Framework"
- let referenceAssemblies = DotNetFrameworkReferenceAssembliesRootDirectory
- dirs |> List.map(fun d -> d.Replace("{WindowsFramework}",windowsFramework).Replace("{ReferenceAssemblies}",referenceAssemblies))
-
- // ATTENTION!: the following code needs to be updated every time we are switching to the new MSBuild version because new .NET framework version was released
- // 1. List of frameworks
- // 2. DeriveTargetFrameworkDirectoriesFor45Plus
- // 3. HighestInstalledRefAssembliesOrDotNETFramework
- // 4. GetPathToDotNetFrameworkImlpementationAssemblies
- []
- let private Net45 = "v4.5"
-
- []
- let private Net451 = "v4.5.1"
-
- []
- let private Net452 = "v4.5.2" // not available in Dev15 MSBuild version
-
- []
- let private Net46 = "v4.6"
-
- []
- let private Net461 = "v4.6.1"
-
- []
- let private Net462 = "v4.6.2"
-
- []
- let private Net47 = "v4.7"
-
- []
- let private Net471 = "v4.7.1"
-
- []
- let private Net472 = "v4.7.2"
-
- []
- let private Net48 = "v4.8"
-
- let SupportedDesktopFrameworkVersions = [ Net48; Net472; Net471; Net47; Net462; Net461; Net46; Net452; Net451; Net45 ]
-
- /// Get the path to the .NET Framework implementation assemblies by using ToolLocationHelper.GetPathToDotNetFramework
- /// This is only used to specify the "last resort" path for assembly resolution.
- let GetPathToDotNetFrameworkImlpementationAssemblies v : string list =
- let v =
- match v with
- | Net45 -> Some TargetDotNetFrameworkVersion.Version45
- | Net451 -> Some TargetDotNetFrameworkVersion.Version451
- | Net452 -> Some TargetDotNetFrameworkVersion.Version452
- | Net46 -> Some TargetDotNetFrameworkVersion.Version46
- | Net461 -> Some TargetDotNetFrameworkVersion.Version461
- | Net462 -> Some TargetDotNetFrameworkVersion.Version462
- | Net47 -> Some TargetDotNetFrameworkVersion.Version47
- | Net471 -> Some TargetDotNetFrameworkVersion.Version471
- | Net472 -> Some TargetDotNetFrameworkVersion.Version472
- | Net48 -> Some TargetDotNetFrameworkVersion.Version48
- | _ -> assert false; None
- match v with
- | Some v ->
- match ToolLocationHelper.GetPathToDotNetFramework v with
- | Null -> []
- | NonNull x -> [x]
- | _ -> []
-
- let GetPathToDotNetFrameworkReferenceAssemblies version =
-#if NETSTANDARD
- ignore version
- let r : string list = []
- r
-#else
- match Microsoft.Build.Utilities.ToolLocationHelper.GetPathToStandardLibraries(".NETFramework",version,"") with
- | Null | "" -> []
- | NonNull x -> [x]
-#endif
-
- /// Use MSBuild to determine the version of the highest installed set of reference assemblies, failing that grab the highest installed framework version
- let HighestInstalledRefAssembliesOrDotNETFramework () =
- let getHighestInstalledDotNETFramework () =
- try
- if box (ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version48)) <> null then Net48
- elif box (ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version472)) <> null then Net472
- elif box (ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version471)) <> null then Net471
- elif box (ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version47)) <> null then Net47
- elif box (ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version462)) <> null then Net462
- elif box (ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version461)) <> null then Net461
- elif box (ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version461)) <> null then Net461
- elif box (ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version46)) <> null then Net46
- elif box (ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version452)) <> null then Net452
- elif box (ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version451)) <> null then Net451
- elif box (ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version45)) <> null then Net45
- else Net45 // version is 4.5 assumed since this code is running.
- with _ -> Net45
-
- // 1. First look to see if we can find the highest installed set of dotnet reference assemblies, if yes then select that framework
- // 2. Otherwise ask msbuild for the highestinstalled framework
- let checkFrameworkForReferenceAssemblies (dotNetVersion:string) =
- if not (String.IsNullOrEmpty(dotNetVersion)) then
- try
- let v = if dotNetVersion.StartsWith("v") then dotNetVersion.Substring(1) else dotNetVersion
- let frameworkName = System.Runtime.Versioning.FrameworkName(".NETFramework", Version(v))
- match ToolLocationHelper.GetPathToReferenceAssemblies(frameworkName) |> Seq.tryHead with
- | Some p -> FileSystem.DirectoryExistsShim(p)
- | None -> false
- with _ -> false
- else false
- match SupportedDesktopFrameworkVersions |> Seq.tryFind(fun v -> checkFrameworkForReferenceAssemblies v) with
- | Some v -> v
- | None -> getHighestInstalledDotNETFramework()
-
- /// Derive the target framework directories.
- let DeriveTargetFrameworkDirectories (targetFrameworkVersion:string, logMessage) =
-
- let targetFrameworkVersion =
- if not(targetFrameworkVersion.StartsWith("v",StringComparison.Ordinal)) then "v"+targetFrameworkVersion
- else targetFrameworkVersion
-
- let result = GetPathToDotNetFrameworkReferenceAssemblies(targetFrameworkVersion) |> Array.ofList
- logMessage (sprintf "Derived target framework directories for version %s are: %s" targetFrameworkVersion (String.Join(",", result)))
- result
-
- /// Describes the location where the reference was found, used only for debug and tooltip output
- type ResolvedFrom =
- | AssemblyFolders
- | AssemblyFoldersEx
- | TargetFrameworkDirectory
- | RawFileName
- | GlobalAssemblyCache
- | Path of string
- | Unknown
-
- /// Decode the ResolvedFrom code from MSBuild.
- let DecodeResolvedFrom(resolvedFrom:string) : ResolvedFrom =
- match resolvedFrom with
- | "{RawFileName}" -> RawFileName
- | "{GAC}" -> GlobalAssemblyCache
- | "{TargetFrameworkDirectory}" -> TargetFrameworkDirectory
- | "{AssemblyFolders}" -> AssemblyFolders
- | r when r.Length >= 10 && "{Registry:" = r.Substring(0,10) -> AssemblyFoldersEx
- | r -> ResolvedFrom.Path r
-
- let TooltipForResolvedFrom(resolvedFrom, fusionName, redist) =
- fun (originalReference,resolvedPath) ->
- let originalReferenceName = originalReference
-
- let resolvedPath = // Don't show the resolved path if it is identical to what was referenced.
- if originalReferenceName = resolvedPath then String.Empty
- else resolvedPath
-
- let lineIfExists text =
- if String.IsNullOrEmpty text then ""
- else text.Trim(' ')+"\n"
-
- match resolvedFrom with
- | AssemblyFolders ->
- lineIfExists resolvedPath
- + lineIfExists fusionName
- + FSComp.SR.assemblyResolutionFoundByAssemblyFoldersKey()
- | AssemblyFoldersEx ->
- lineIfExists resolvedPath
- + lineIfExists fusionName
- + FSComp.SR.assemblyResolutionFoundByAssemblyFoldersExKey()
- | TargetFrameworkDirectory ->
- lineIfExists resolvedPath
- + lineIfExists fusionName
- + FSComp.SR.assemblyResolutionNetFramework()
- | Unknown ->
- // Unknown when resolved by plain directory search without help from MSBuild resolver.
- lineIfExists resolvedPath
- + lineIfExists fusionName
- | RawFileName ->
- lineIfExists fusionName
- | GlobalAssemblyCache ->
- lineIfExists fusionName
- + lineIfExists (FSComp.SR.assemblyResolutionGAC())
- + lineIfExists redist
- | Path _ ->
- lineIfExists resolvedPath
- + lineIfExists fusionName
-
- /// Perform assembly resolution by instantiating the ResolveAssembly task directly from the MSBuild SDK.
- let ResolveCore(resolutionEnvironment: LegacyResolutionEnvironment,
- references:(string*string)[],
- targetFrameworkVersion: string,
- targetFrameworkDirectories: string list,
- targetProcessorArchitecture: string,
- fsharpCoreDir: string,
- explicitIncludeDirs: string list,
- implicitIncludeDir: string,
- allowRawFileName: bool,
- logMessage: string -> unit,
- logDiagnostic: bool -> string -> string -> unit) =
-
- let frameworkRegistryBase, assemblyFoldersSuffix, assemblyFoldersConditions =
- "Software\Microsoft\.NetFramework", "AssemblyFoldersEx" , ""
- if Array.isEmpty references then [| |] else
-
- let mutable backgroundException = false
-
- let protect f =
- if not backgroundException then
- try f()
- with _ -> backgroundException <- true
-
- let engine =
- { new IBuildEngine with
- member _.BuildProjectFile(projectFileName, targetNames, globalProperties, targetOutputs) = true
- member _.LogCustomEvent(e) = protect (fun () -> logMessage e.Message)
- member _.LogErrorEvent(e) = protect (fun () -> logDiagnostic true e.Code e.Message)
- member _.LogMessageEvent(e) = protect (fun () -> logMessage e.Message)
- member _.LogWarningEvent(e) = protect (fun () -> logDiagnostic false e.Code e.Message)
- member _.ColumnNumberOfTaskNode with get() = 1
- member _.LineNumberOfTaskNode with get() = 1
- member _.ContinueOnError with get() = true
- member _.ProjectFileOfTaskNode with get() = "" }
-
- // Derive the target framework directory if none was supplied.
- let targetFrameworkDirectories =
- if targetFrameworkDirectories=[] then DeriveTargetFrameworkDirectories(targetFrameworkVersion, logMessage)
- else targetFrameworkDirectories |> Array.ofList
-
-
- // Filter for null and zero length
- let references = references |> Array.filter(fst >> String.IsNullOrEmpty >> not)
-
- // Determine the set of search paths for the resolution
- let searchPaths =
-
- let explicitIncludeDirs = explicitIncludeDirs |> List.filter(String.IsNullOrEmpty >> not)
-
- let registry = sprintf "{Registry:%s,%s,%s%s}" frameworkRegistryBase targetFrameworkVersion assemblyFoldersSuffix assemblyFoldersConditions
-
- [| // When compiling scripts using fsc.exe, for some reason we have always historically put TargetFrameworkDirectory first
- // It is unclear why. This is the only place we look at the 'isdifference between ResolutionEnvironment.EditingOrCompilation and ResolutionEnvironment.EditingTime.
- match resolutionEnvironment with
- | LegacyResolutionEnvironment.EditingOrCompilation false -> yield "{TargetFrameworkDirectory}"
- | LegacyResolutionEnvironment.EditingOrCompilation true
- | LegacyResolutionEnvironment.CompilationAndEvaluation -> ()
-
- // Quick-resolve straight to file name first
- if allowRawFileName then
- yield "{RawFileName}"
- yield! explicitIncludeDirs // From -I, #I
- yield fsharpCoreDir // Location of explicit reference to FSharp.Core, otherwise location of fsc.exe
- yield implicitIncludeDir // Usually the project directory
-
- match resolutionEnvironment with
- | LegacyResolutionEnvironment.EditingOrCompilation true
- | LegacyResolutionEnvironment.CompilationAndEvaluation -> yield "{TargetFrameworkDirectory}"
- | LegacyResolutionEnvironment.EditingOrCompilation false -> ()
-
- yield registry
- yield "{AssemblyFolders}"
- yield "{GAC}"
- // use path to implementation assemblies as the last resort
- yield! GetPathToDotNetFrameworkImlpementationAssemblies targetFrameworkVersion
- |]
-
- let assemblies =
- [| for referenceName,baggage in references ->
- let item = TaskItem(referenceName) :> ITaskItem
- item.SetMetadata("Baggage", baggage)
- item |]
- let rar =
- ResolveAssemblyReference(BuildEngine=engine, TargetFrameworkDirectories=targetFrameworkDirectories,
- FindRelatedFiles=false, FindDependencies=false, FindSatellites=false,
- FindSerializationAssemblies=false, Assemblies=assemblies,
- SearchPaths=searchPaths,
- AllowedAssemblyExtensions= [| ".dll" ; ".exe" |])
- rar.TargetProcessorArchitecture <- targetProcessorArchitecture
- let targetedRuntimeVersionValue = typeof.Assembly.ImageRuntimeVersion
- rar.TargetedRuntimeVersion <- targetedRuntimeVersionValue
- rar.CopyLocalDependenciesWhenParentReferenceInGac <- true
-
- let succeeded = rar.Execute()
-
- if not succeeded then
- raise LegacyResolutionFailure
-
- let resolvedFiles =
- [| for p in rar.ResolvedFiles ->
- let resolvedFrom = DecodeResolvedFrom(p.GetMetadata("ResolvedFrom"))
- let fusionName = p.GetMetadata("FusionName")
- let redist = p.GetMetadata("Redist")
- { itemSpec = p.ItemSpec
- prepareToolTip = TooltipForResolvedFrom(resolvedFrom, fusionName, redist)
- baggage = p.GetMetadata("Baggage") } |]
-
- resolvedFiles
-
- let getResolver () =
- { new ILegacyReferenceResolver with
- member _.HighestInstalledNetFrameworkVersion() = HighestInstalledRefAssembliesOrDotNETFramework()
- member _.DotNetFrameworkReferenceAssembliesRootDirectory = DotNetFrameworkReferenceAssembliesRootDirectory
-
- /// Perform the resolution on rooted and unrooted paths, and then combine the results.
- member _.Resolve(resolutionEnvironment, references, targetFrameworkVersion, targetFrameworkDirectories, targetProcessorArchitecture,
- fsharpCoreDir, explicitIncludeDirs, implicitIncludeDir, logMessage, logDiagnostic) =
-
- // The {RawFileName} target is 'dangerous', in the sense that is uses Directory.GetCurrentDirectory() to resolve unrooted file paths.
- // It is unreliable to use this mutable global state inside Visual Studio. As a result, we partition all references into a "rooted" set
- // (which contains e.g. C:\MyDir\MyAssem.dll) and "unrooted" (everything else). We only allow "rooted" to use {RawFileName}. Note that
- // unrooted may still find 'local' assemblies by virtue of the fact that "implicitIncludeDir" is one of the places searched during
- // assembly resolution.
- let references =
- [| for fileName, baggage as data in references ->
- // However, MSBuild will not resolve 'relative' paths, even when e.g. implicitIncludeDir is part of the search. As a result,
- // if we have an unrooted path + file name, we'll assume this is relative to the project directory and root it.
- if FileSystem.IsPathRootedShim(fileName) then
- data // fine, e.g. "C:\Dir\foo.dll"
- elif not(fileName.Contains("\\") || fileName.Contains("/")) then
- data // fine, e.g. "System.Transactions.dll"
- else
- // We have a 'relative path', e.g. "bin/Debug/foo.exe" or "..\Yadda\bar.dll"
- // turn it into an absolute path based at implicitIncludeDir
- (Path.Combine(implicitIncludeDir, fileName), baggage) |]
-
- let rooted, unrooted = references |> Array.partition (fst >> FileSystem.IsPathRootedShim)
-
- let rootedResults =
- ResolveCore
- (resolutionEnvironment, rooted, targetFrameworkVersion,
- targetFrameworkDirectories, targetProcessorArchitecture,
- fsharpCoreDir, explicitIncludeDirs, implicitIncludeDir,
- true, logMessage, logDiagnostic)
-
- let unrootedResults =
- ResolveCore
- (resolutionEnvironment, unrooted, targetFrameworkVersion,
- targetFrameworkDirectories, targetProcessorArchitecture,
- fsharpCoreDir, explicitIncludeDirs, implicitIncludeDir,
- false, logMessage, logDiagnostic)
-
- // now unify the two sets of results
- Array.concat [| rootedResults; unrootedResults |]
- }
- |> LegacyReferenceResolver
diff --git a/src/Compiler/SyntaxTree/LexFilter.fs b/src/Compiler/SyntaxTree/LexFilter.fs
index 88a743a6bf2..14a43332424 100644
--- a/src/Compiler/SyntaxTree/LexFilter.fs
+++ b/src/Compiler/SyntaxTree/LexFilter.fs
@@ -699,6 +699,8 @@ type LexFilterImpl (
let mutable prevWasAtomicEnd = false
let peekInitial() =
+ // Forget the lexbuf state we might have saved from previous input
+ haveLexbufState <- false
let initialLookaheadTokenTup = popNextTokenTup()
if debug then dprintf "first token: initialLookaheadTokenLexbufState = %a\n" outputPos (startPosOfTokenTup initialLookaheadTokenTup)
diff --git a/src/Compiler/TypedTree/TcGlobals.fs b/src/Compiler/TypedTree/TcGlobals.fs
index 9eaac69024a..96dc59428e2 100755
--- a/src/Compiler/TypedTree/TcGlobals.fs
+++ b/src/Compiler/TypedTree/TcGlobals.fs
@@ -1831,12 +1831,12 @@ type TcGlobals(
let info = makeOtherIntrinsicValRef (fslib_MFOperators_nleref, "atan2", None, Some "Atan2", [vara; varb], ([[varaTy]; [varaTy]], varbTy))
let tyargs = [aty;bty]
Some (info, tyargs, argExprs)
- | "get_Zero", _, Some aty, [_] ->
+ | "get_Zero", _, Some aty, ([] | [_]) ->
// Call LanguagePrimitives.GenericZero
let info = makeOtherIntrinsicValRef (fslib_MFLanguagePrimitives_nleref, "GenericZero", None, None, [vara], ([], varaTy))
let tyargs = [aty]
Some (info, tyargs, [])
- | "get_One", _, Some aty, [_] ->
+ | "get_One", _, Some aty, ([] | [_]) ->
// Call LanguagePrimitives.GenericOne
let info = makeOtherIntrinsicValRef (fslib_MFLanguagePrimitives_nleref, "GenericOne", None, None, [vara], ([], varaTy))
let tyargs = [aty]
diff --git a/src/Compiler/xlf/FSComp.txt.cs.xlf b/src/Compiler/xlf/FSComp.txt.cs.xlf
index a0bc2e214c7..7ad080d2aaf 100644
--- a/src/Compiler/xlf/FSComp.txt.cs.xlf
+++ b/src/Compiler/xlf/FSComp.txt.cs.xlf
@@ -177,6 +177,11 @@
literál float32 bez tečky
+
+ Raises errors for non-virtual members overrides
+ Raises errors for non-virtual members overrides
+
+ give error on deprecated access of construct with RequireQualifiedAccess attributechyba při zastaralém přístupu konstruktoru s atributem RequireQualifiedAccess
@@ -5657,26 +5662,6 @@
generovaný typ
-
- Found by AssemblyFolders registry key
- Nalezené klíčem registru AssemblyFolders
-
-
-
- Found by AssemblyFoldersEx registry key
- Nalezené klíčem registru AssemblyFoldersEx
-
-
-
- .NET Framework
- .NET Framework
-
-
-
- Global Assembly Cache
- Globální mezipaměť sestavení
-
- Recursive class hierarchy in type '{0}'Rekurzivní hierarchie tříd u typu {0}
diff --git a/src/Compiler/xlf/FSComp.txt.de.xlf b/src/Compiler/xlf/FSComp.txt.de.xlf
index 42a106317c2..fbb0a7bfb34 100644
--- a/src/Compiler/xlf/FSComp.txt.de.xlf
+++ b/src/Compiler/xlf/FSComp.txt.de.xlf
@@ -177,6 +177,11 @@
punktloses float32-Literal
+
+ Raises errors for non-virtual members overrides
+ Raises errors for non-virtual members overrides
+
+ give error on deprecated access of construct with RequireQualifiedAccess attributeBeim veralteten Zugriff auf das Konstrukt mit dem RequireQualifiedAccess-Attribut wird ein Fehler ausgegeben.
@@ -5657,26 +5662,6 @@
Generierter Typ
-
- Found by AssemblyFolders registry key
- Von AssemblyFolders-Registrierungsschlüssel gefunden
-
-
-
- Found by AssemblyFoldersEx registry key
- Von AssemblyFoldersEx-Registrierungsschlüssel gefunden
-
-
-
- .NET Framework
- .NET Framework
-
-
-
- Global Assembly Cache
- Globaler Assemblycache
-
- Recursive class hierarchy in type '{0}'Rekursive Klassenhierarchie in Typ "{0}".
diff --git a/src/Compiler/xlf/FSComp.txt.es.xlf b/src/Compiler/xlf/FSComp.txt.es.xlf
index 932afaea4ff..7d8aca4e042 100644
--- a/src/Compiler/xlf/FSComp.txt.es.xlf
+++ b/src/Compiler/xlf/FSComp.txt.es.xlf
@@ -177,6 +177,11 @@
literal float32 sin punto
+
+ Raises errors for non-virtual members overrides
+ Raises errors for non-virtual members overrides
+
+ give error on deprecated access of construct with RequireQualifiedAccess attributeerror en el acceso en desuso de la construcción con el atributo RequireQualifiedAccess
@@ -5657,26 +5662,6 @@
tipo generado
-
- Found by AssemblyFolders registry key
- Encontrado por la clave del Registro AssemblyFolders.
-
-
-
- Found by AssemblyFoldersEx registry key
- Encontrado por la clave del Registro AssemblyFoldersEx.
-
-
-
- .NET Framework
- .NET Framework
-
-
-
- Global Assembly Cache
- Caché global de ensamblados
-
- Recursive class hierarchy in type '{0}'Jerarquía de clases recursiva en el tipo '{0}'.
diff --git a/src/Compiler/xlf/FSComp.txt.fr.xlf b/src/Compiler/xlf/FSComp.txt.fr.xlf
index 01b2db7f5c4..bb507ae5dd8 100644
--- a/src/Compiler/xlf/FSComp.txt.fr.xlf
+++ b/src/Compiler/xlf/FSComp.txt.fr.xlf
@@ -177,6 +177,11 @@
littéral float32 sans point
+
+ Raises errors for non-virtual members overrides
+ Raises errors for non-virtual members overrides
+
+ give error on deprecated access of construct with RequireQualifiedAccess attributedonner une erreur sur l’accès déconseillé de la construction avec l’attribut RequireQualifiedAccess
@@ -5657,26 +5662,6 @@
type généré
-
- Found by AssemblyFolders registry key
- Trouvée par la clé de Registre AssemblyFolders
-
-
-
- Found by AssemblyFoldersEx registry key
- Trouvée par la clé de Registre AssemblyFoldersEx
-
-
-
- .NET Framework
- .NET Framework
-
-
-
- Global Assembly Cache
- Global Assembly Cache
-
- Recursive class hierarchy in type '{0}'Hiérarchie de classes récursive dans le type '{0}'
diff --git a/src/Compiler/xlf/FSComp.txt.it.xlf b/src/Compiler/xlf/FSComp.txt.it.xlf
index 9e47f7b017f..e07ab4a3b59 100644
--- a/src/Compiler/xlf/FSComp.txt.it.xlf
+++ b/src/Compiler/xlf/FSComp.txt.it.xlf
@@ -177,6 +177,11 @@
valore letterale float32 senza punti
+
+ Raises errors for non-virtual members overrides
+ Raises errors for non-virtual members overrides
+
+ give error on deprecated access of construct with RequireQualifiedAccess attributeerrore durante l'accesso deprecato del costrutto con l'attributo RequireQualifiedAccess
@@ -5657,26 +5662,6 @@
tipo generato
-
- Found by AssemblyFolders registry key
- Trovata mediante la chiave del Registro di sistema AssemblyFolders
-
-
-
- Found by AssemblyFoldersEx registry key
- Trovata mediante chiave del Registro di sistema AssemblyFoldersEx
-
-
-
- .NET Framework
- .NET Framework
-
-
-
- Global Assembly Cache
- Global Assembly Cache
-
- Recursive class hierarchy in type '{0}'Gerarchia di classi ricorsiva nel tipo '{0}'
diff --git a/src/Compiler/xlf/FSComp.txt.ja.xlf b/src/Compiler/xlf/FSComp.txt.ja.xlf
index 5262c515b26..1f0084d7541 100644
--- a/src/Compiler/xlf/FSComp.txt.ja.xlf
+++ b/src/Compiler/xlf/FSComp.txt.ja.xlf
@@ -177,6 +177,11 @@
ドットなしの float32 リテラル
+
+ Raises errors for non-virtual members overrides
+ Raises errors for non-virtual members overrides
+
+ give error on deprecated access of construct with RequireQualifiedAccess attributeRequireQualifiedAccess 属性を持つコンストラクトの非推奨アクセスでエラーが発生しました
@@ -5657,26 +5662,6 @@
生成された型
-
- Found by AssemblyFolders registry key
- AssemblyFolders レジストリ キーによって検出されました
-
-
-
- Found by AssemblyFoldersEx registry key
- AssemblyFoldersEx レジストリ キーによって検出されました
-
-
-
- .NET Framework
- .NET Framework
-
-
-
- Global Assembly Cache
- グローバル アセンブリ キャッシュ
-
- Recursive class hierarchy in type '{0}'型 '{0}' の再帰的クラス階層
diff --git a/src/Compiler/xlf/FSComp.txt.ko.xlf b/src/Compiler/xlf/FSComp.txt.ko.xlf
index 232411cd146..42e39e8db3c 100644
--- a/src/Compiler/xlf/FSComp.txt.ko.xlf
+++ b/src/Compiler/xlf/FSComp.txt.ko.xlf
@@ -177,6 +177,11 @@
점이 없는 float32 리터럴
+
+ Raises errors for non-virtual members overrides
+ Raises errors for non-virtual members overrides
+
+ give error on deprecated access of construct with RequireQualifiedAccess attributeRequireQualifiedAccess 특성을 사용하여 사용되지 않는 구문 액세스에 대한 오류 제공
@@ -5657,26 +5662,6 @@
생성된 형식
-
- Found by AssemblyFolders registry key
- AssemblyFolders 레지스트리 키로 찾았습니다.
-
-
-
- Found by AssemblyFoldersEx registry key
- AssemblyFoldersEx 레지스트리 키로 찾았습니다.
-
-
-
- .NET Framework
- .NET Framework
-
-
-
- Global Assembly Cache
- 전역 어셈블리 캐시
-
- Recursive class hierarchy in type '{0}''{0}' 형식에 재귀적 클래스 계층 구조가 있습니다.
diff --git a/src/Compiler/xlf/FSComp.txt.pl.xlf b/src/Compiler/xlf/FSComp.txt.pl.xlf
index 0e97c468507..24ec9716810 100644
--- a/src/Compiler/xlf/FSComp.txt.pl.xlf
+++ b/src/Compiler/xlf/FSComp.txt.pl.xlf
@@ -177,6 +177,11 @@
bezkropkowy literał float32
+
+ Raises errors for non-virtual members overrides
+ Raises errors for non-virtual members overrides
+
+ give error on deprecated access of construct with RequireQualifiedAccess attributewskazywanie błędu w przypadku przestarzałego dostępu do konstrukcji z atrybutem RequireQualifiedAccess
@@ -5657,26 +5662,6 @@
wygenerowany typ
-
- Found by AssemblyFolders registry key
- Znalezione przez klucz rejestru AssemblyFolders
-
-
-
- Found by AssemblyFoldersEx registry key
- Znalezione przez klucz rejestru AssemblyFoldersEx
-
-
-
- .NET Framework
- .NET Framework
-
-
-
- Global Assembly Cache
- Globalna pamięć podręczna zestawów
-
- Recursive class hierarchy in type '{0}'Cykliczna hierarchia klas w typie „{0}”
diff --git a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf
index 3da17e5abaf..7bbd44e0748 100644
--- a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf
+++ b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf
@@ -177,6 +177,11 @@
literal float32 sem ponto
+
+ Raises errors for non-virtual members overrides
+ Raises errors for non-virtual members overrides
+
+ give error on deprecated access of construct with RequireQualifiedAccess attributefornecer erro no acesso preterido do constructo com o atributo RequireQualifiedAccess
@@ -5657,26 +5662,6 @@
tipo gerado
-
- Found by AssemblyFolders registry key
- Localizada pela chave de registro AssemblyFolders
-
-
-
- Found by AssemblyFoldersEx registry key
- Localizada pela chave de registro AssemblyFoldersEx
-
-
-
- .NET Framework
- .NET Framework
-
-
-
- Global Assembly Cache
- Cache de Assembly Global
-
- Recursive class hierarchy in type '{0}'Hierarquia de classe recursiva no tipo '{0}'
diff --git a/src/Compiler/xlf/FSComp.txt.ru.xlf b/src/Compiler/xlf/FSComp.txt.ru.xlf
index 0b55fec7ee5..dcec58500e5 100644
--- a/src/Compiler/xlf/FSComp.txt.ru.xlf
+++ b/src/Compiler/xlf/FSComp.txt.ru.xlf
@@ -177,6 +177,11 @@
литерал float32 без точки
+
+ Raises errors for non-virtual members overrides
+ Raises errors for non-virtual members overrides
+
+ give error on deprecated access of construct with RequireQualifiedAccess attributeвыдать ошибку при устаревшем доступе к конструкции с атрибутом RequireQualifiedAccess
@@ -5657,26 +5662,6 @@
созданный тип
-
- Found by AssemblyFolders registry key
- Найдено по разделу реестра AssemblyFolders
-
-
-
- Found by AssemblyFoldersEx registry key
- Найдено по разделу реестра AssemblyFoldersEx
-
-
-
- .NET Framework
- .NET Framework
-
-
-
- Global Assembly Cache
- Глобальный кэш сборок
-
- Recursive class hierarchy in type '{0}'Рекурсивная иерархия классов в типе "{0}"
diff --git a/src/Compiler/xlf/FSComp.txt.tr.xlf b/src/Compiler/xlf/FSComp.txt.tr.xlf
index 1643e114292..fe7389a0a37 100644
--- a/src/Compiler/xlf/FSComp.txt.tr.xlf
+++ b/src/Compiler/xlf/FSComp.txt.tr.xlf
@@ -177,6 +177,11 @@
noktasız float32 sabit değeri
+
+ Raises errors for non-virtual members overrides
+ Raises errors for non-virtual members overrides
+
+ give error on deprecated access of construct with RequireQualifiedAccess attributeRequireQualifiedAccess özniteliğine sahip yapının kullanım dışı erişiminde hata
@@ -5657,26 +5662,6 @@
oluşturulan tür
-
- Found by AssemblyFolders registry key
- AssemblyFolders kayıt defteri anahtarı ile bulunur
-
-
-
- Found by AssemblyFoldersEx registry key
- AssemblyFoldersEx kayıt defteri anahtarı ile bulunur
-
-
-
- .NET Framework
- .NET Framework
-
-
-
- Global Assembly Cache
- Genel Bütünleştirilmiş Kod Önbelleği
-
- Recursive class hierarchy in type '{0}''{0}' türünde özyinelemeli sınıf hiyerarşisi
diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf
index 9eccaa3a848..a1f490de899 100644
--- a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf
+++ b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf
@@ -177,6 +177,11 @@
无点 float32 文本
+
+ Raises errors for non-virtual members overrides
+ Raises errors for non-virtual members overrides
+
+ give error on deprecated access of construct with RequireQualifiedAccess attribute对具有 RequireQualifiedAccess 属性的构造进行弃用的访问时出错
@@ -5657,26 +5662,6 @@
生成的类型
-
- Found by AssemblyFolders registry key
- 已由 AssemblyFolders 注册表项找到
-
-
-
- Found by AssemblyFoldersEx registry key
- 已由 AssemblyFoldersEx 注册表项找到
-
-
-
- .NET Framework
- .NET Framework
-
-
-
- Global Assembly Cache
- 全局程序集缓存
-
- Recursive class hierarchy in type '{0}'类型“{0}”中的递归类层次结构
diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf
index 38bc273305f..00e26426d17 100644
--- a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf
+++ b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf
@@ -177,6 +177,11 @@
無點號的 float32 常值
+
+ Raises errors for non-virtual members overrides
+ Raises errors for non-virtual members overrides
+
+ give error on deprecated access of construct with RequireQualifiedAccess attribute對具有 RequireQualifiedAccess 屬性的建構的已取代存取發出錯誤
@@ -5657,26 +5662,6 @@
產生的類型
-
- Found by AssemblyFolders registry key
- 依 AssemblyFolders 登錄機碼找到
-
-
-
- Found by AssemblyFoldersEx registry key
- 依 AssemblyFoldersEx 登錄機碼找到
-
-
-
- .NET Framework
- .NET Framework
-
-
-
- Global Assembly Cache
- 全域組件快取
-
- Recursive class hierarchy in type '{0}'類型 '{0}' 中有遞迴的類別階層
diff --git a/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.Utilities.fs b/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.Utilities.fs
index 8a1b526837a..14f55dc6fb4 100644
--- a/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.Utilities.fs
+++ b/src/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.Utilities.fs
@@ -64,7 +64,6 @@ module internal Utilities =
|> Array.filter (fun r ->
not (String.IsNullOrEmpty(r.NugetPackageId) || String.IsNullOrEmpty(r.FullPath))
&& not (equals r.IsNotImplementationReference "true")
- && File.Exists(r.FullPath)
&& equals r.AssetType "runtime")
|> Array.map (fun r -> r.FullPath)
|> Array.distinct
@@ -260,7 +259,12 @@ module internal Utilities =
let resolutionsFile, resolutions, references, loads, includes =
if success && File.Exists(outputFile) then
let resolutions = getResolutionsFromFile outputFile
- let references = (findReferencesFromResolutions resolutions) |> Array.toList
+
+ let references =
+ (findReferencesFromResolutions resolutions)
+ |> Array.filter (File.Exists)
+ |> Array.toList
+
let loads = (findLoadsFromResolutions resolutions) |> Array.toList
let includes = (findIncludesFromResolutions resolutions) |> Array.toList
(Some outputFile), resolutions, references, loads, includes
diff --git a/src/LegacyMSBuildResolver/LegacyMSBuildReferenceResolver.fs b/src/LegacyMSBuildResolver/LegacyMSBuildReferenceResolver.fs
new file mode 100644
index 00000000000..977372d675a
--- /dev/null
+++ b/src/LegacyMSBuildResolver/LegacyMSBuildReferenceResolver.fs
@@ -0,0 +1,516 @@
+// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.
+
+module FSharp.Compiler.CodeAnalysis.LegacyMSBuildReferenceResolver
+
+open System
+open System.IO
+open System.Reflection
+open Internal.Utilities.Library
+open Microsoft.Build.Tasks
+open Microsoft.Build.Utilities
+open Microsoft.Build.Framework
+open FSharp.Compiler.IO
+
+// Reflection wrapper for properties
+type Object with
+
+ member this.GetPropertyValue(propName) =
+ this.GetType().GetProperty(propName, BindingFlags.Public).GetValue(this, null)
+
+/// Match on the nullness of an argument.
+let inline (|Null|NonNull|) (x: 'T) : Choice =
+ match x with
+ | null -> Null
+ | v -> NonNull v
+
+/// Get the Reference Assemblies directory for the .NET Framework on Window.
+let DotNetFrameworkReferenceAssembliesRootDirectory =
+ // ProgramFilesX86 is correct for both x86 and x64 architectures
+ // (the reference assemblies are always in the 32-bit location, which is PF(x86) on an x64 machine)
+ let PF =
+ match Environment.GetEnvironmentVariable("ProgramFiles(x86)") with
+ | Null -> Environment.GetEnvironmentVariable("ProgramFiles") // if PFx86 is null, then we are 32-bit and just get PF
+ | NonNull s -> s
+
+ PF + @"\Reference Assemblies\Microsoft\Framework\.NETFramework"
+
+/// When targeting .NET 2.0-3.5 on Windows, we expand the {WindowsFramework} and {ReferenceAssemblies} paths manually
+let internal ReplaceVariablesForLegacyFxOnWindows (dirs: string list) =
+ let windowsFramework =
+ Environment.GetEnvironmentVariable("windir") + @"\Microsoft.NET\Framework"
+
+ let referenceAssemblies = DotNetFrameworkReferenceAssembliesRootDirectory
+
+ dirs
+ |> List.map (fun d ->
+ d
+ .Replace("{WindowsFramework}", windowsFramework)
+ .Replace("{ReferenceAssemblies}", referenceAssemblies))
+
+// ATTENTION!: the following code needs to be updated every time we are switching to the new MSBuild version because new .NET framework version was released
+// 1. List of frameworks
+// 2. DeriveTargetFrameworkDirectoriesFor45Plus
+// 3. HighestInstalledRefAssembliesOrDotNETFramework
+// 4. GetPathToDotNetFrameworkImlpementationAssemblies
+[]
+let private Net45 = "v4.5"
+
+[]
+let private Net451 = "v4.5.1"
+
+[]
+let private Net452 = "v4.5.2" // not available in Dev15 MSBuild version
+
+[]
+let private Net46 = "v4.6"
+
+[]
+let private Net461 = "v4.6.1"
+
+[]
+let private Net462 = "v4.6.2"
+
+[]
+let private Net47 = "v4.7"
+
+[]
+let private Net471 = "v4.7.1"
+
+[]
+let private Net472 = "v4.7.2"
+
+[]
+let private Net48 = "v4.8"
+
+let SupportedDesktopFrameworkVersions =
+ [ Net48; Net472; Net471; Net47; Net462; Net461; Net46; Net452; Net451; Net45 ]
+
+/// Get the path to the .NET Framework implementation assemblies by using ToolLocationHelper.GetPathToDotNetFramework
+/// This is only used to specify the "last resort" path for assembly resolution.
+let GetPathToDotNetFrameworkImlpementationAssemblies v : string list =
+ let v =
+ match v with
+ | Net45 -> Some TargetDotNetFrameworkVersion.Version45
+ | Net451 -> Some TargetDotNetFrameworkVersion.Version451
+ | Net452 -> Some TargetDotNetFrameworkVersion.Version452
+ | Net46 -> Some TargetDotNetFrameworkVersion.Version46
+ | Net461 -> Some TargetDotNetFrameworkVersion.Version461
+ | Net462 -> Some TargetDotNetFrameworkVersion.Version462
+ | Net47 -> Some TargetDotNetFrameworkVersion.Version47
+ | Net471 -> Some TargetDotNetFrameworkVersion.Version471
+ | Net472 -> Some TargetDotNetFrameworkVersion.Version472
+ | Net48 -> Some TargetDotNetFrameworkVersion.Version48
+ | _ ->
+ assert false
+ None
+
+ match v with
+ | Some v ->
+ match ToolLocationHelper.GetPathToDotNetFramework v with
+ | Null -> []
+ | NonNull x -> [ x ]
+ | _ -> []
+
+let GetPathToDotNetFrameworkReferenceAssemblies version =
+#if NETSTANDARD
+ ignore version
+ let r: string list = []
+ r
+#else
+ match Microsoft.Build.Utilities.ToolLocationHelper.GetPathToStandardLibraries(".NETFramework", version, "") with
+ | Null
+ | "" -> []
+ | NonNull x -> [ x ]
+#endif
+
+/// Use MSBuild to determine the version of the highest installed set of reference assemblies, failing that grab the highest installed framework version
+let HighestInstalledRefAssembliesOrDotNETFramework () =
+ let getHighestInstalledDotNETFramework () =
+ try
+ if
+ box (ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version48))
+ <> null
+ then
+ Net48
+ elif
+ box (ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version472))
+ <> null
+ then
+ Net472
+ elif
+ box (ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version471))
+ <> null
+ then
+ Net471
+ elif
+ box (ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version47))
+ <> null
+ then
+ Net47
+ elif
+ box (ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version462))
+ <> null
+ then
+ Net462
+ elif
+ box (ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version461))
+ <> null
+ then
+ Net461
+ elif
+ box (ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version461))
+ <> null
+ then
+ Net461
+ elif
+ box (ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version46))
+ <> null
+ then
+ Net46
+ elif
+ box (ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version452))
+ <> null
+ then
+ Net452
+ elif
+ box (ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version451))
+ <> null
+ then
+ Net451
+ elif
+ box (ToolLocationHelper.GetPathToDotNetFramework(TargetDotNetFrameworkVersion.Version45))
+ <> null
+ then
+ Net45
+ else
+ Net45 // version is 4.5 assumed since this code is running.
+ with _ ->
+ Net45
+
+ // 1. First look to see if we can find the highest installed set of dotnet reference assemblies, if yes then select that framework
+ // 2. Otherwise ask msbuild for the highestinstalled framework
+ let checkFrameworkForReferenceAssemblies (dotNetVersion: string) =
+ if not (String.IsNullOrEmpty(dotNetVersion)) then
+ try
+ let v =
+ if dotNetVersion.StartsWith("v") then
+ dotNetVersion.Substring(1)
+ else
+ dotNetVersion
+
+ let frameworkName =
+ System.Runtime.Versioning.FrameworkName(".NETFramework", Version(v))
+
+ match ToolLocationHelper.GetPathToReferenceAssemblies(frameworkName) |> Seq.tryHead with
+ | Some p -> FileSystem.DirectoryExistsShim(p)
+ | None -> false
+ with _ ->
+ false
+ else
+ false
+
+ match
+ SupportedDesktopFrameworkVersions
+ |> Seq.tryFind (fun v -> checkFrameworkForReferenceAssemblies v)
+ with
+ | Some v -> v
+ | None -> getHighestInstalledDotNETFramework ()
+
+/// Derive the target framework directories.
+let DeriveTargetFrameworkDirectories (targetFrameworkVersion: string, logMessage) =
+
+ let targetFrameworkVersion =
+ if not (targetFrameworkVersion.StartsWith("v", StringComparison.Ordinal)) then
+ "v" + targetFrameworkVersion
+ else
+ targetFrameworkVersion
+
+ let result =
+ GetPathToDotNetFrameworkReferenceAssemblies(targetFrameworkVersion)
+ |> Array.ofList
+
+ logMessage (sprintf "Derived target framework directories for version %s are: %s" targetFrameworkVersion (String.Join(",", result)))
+ result
+
+/// Describes the location where the reference was found, used only for debug and tooltip output
+type ResolvedFrom =
+ | AssemblyFolders
+ | AssemblyFoldersEx
+ | TargetFrameworkDirectory
+ | RawFileName
+ | GlobalAssemblyCache
+ | Path of string
+ | Unknown
+
+/// Decode the ResolvedFrom code from MSBuild.
+let DecodeResolvedFrom (resolvedFrom: string) : ResolvedFrom =
+ match resolvedFrom with
+ | "{RawFileName}" -> RawFileName
+ | "{GAC}" -> GlobalAssemblyCache
+ | "{TargetFrameworkDirectory}" -> TargetFrameworkDirectory
+ | "{AssemblyFolders}" -> AssemblyFolders
+ | r when r.Length >= 10 && "{Registry:" = r.Substring(0, 10) -> AssemblyFoldersEx
+ | r -> ResolvedFrom.Path r
+
+let TooltipForResolvedFrom (resolvedFrom, fusionName, redist) =
+ fun (originalReference, resolvedPath) ->
+ let originalReferenceName = originalReference
+
+ let resolvedPath = // Don't show the resolved path if it is identical to what was referenced.
+ if originalReferenceName = resolvedPath then
+ String.Empty
+ else
+ resolvedPath
+
+ let lineIfExists text =
+ if String.IsNullOrEmpty text then
+ ""
+ else
+ text.Trim(' ') + "\n"
+
+ match resolvedFrom with
+ | AssemblyFolders ->
+ lineIfExists resolvedPath
+ + lineIfExists fusionName
+ + LegacyResolver.SR.assemblyResolutionFoundByAssemblyFoldersKey ()
+ | AssemblyFoldersEx ->
+ lineIfExists resolvedPath
+ + lineIfExists fusionName
+ + LegacyResolver.SR.assemblyResolutionFoundByAssemblyFoldersExKey ()
+ | TargetFrameworkDirectory ->
+ lineIfExists resolvedPath
+ + lineIfExists fusionName
+ + LegacyResolver.SR.assemblyResolutionNetFramework ()
+ | Unknown ->
+ // Unknown when resolved by plain directory search without help from MSBuild resolver.
+ lineIfExists resolvedPath + lineIfExists fusionName
+ | RawFileName -> lineIfExists fusionName
+ | GlobalAssemblyCache ->
+ lineIfExists fusionName
+ + lineIfExists (LegacyResolver.SR.assemblyResolutionGAC ())
+ + lineIfExists redist
+ | Path _ -> lineIfExists resolvedPath + lineIfExists fusionName
+
+/// Perform assembly resolution by instantiating the ResolveAssembly task directly from the MSBuild SDK.
+let ResolveCore
+ (
+ resolutionEnvironment: LegacyResolutionEnvironment,
+ references: (string * string)[],
+ targetFrameworkVersion: string,
+ targetFrameworkDirectories: string list,
+ targetProcessorArchitecture: string,
+ fsharpCoreDir: string,
+ explicitIncludeDirs: string list,
+ implicitIncludeDir: string,
+ allowRawFileName: bool,
+ logMessage: string -> unit,
+ logDiagnostic: bool -> string -> string -> unit
+ ) =
+
+ let frameworkRegistryBase, assemblyFoldersSuffix, assemblyFoldersConditions =
+ "Software\Microsoft\.NetFramework", "AssemblyFoldersEx", ""
+
+ if Array.isEmpty references then
+ [||]
+ else
+
+ let mutable backgroundException = false
+
+ let protect f =
+ if not backgroundException then
+ try
+ f ()
+ with _ ->
+ backgroundException <- true
+
+ let engine =
+ { new IBuildEngine with
+ member _.BuildProjectFile(projectFileName, targetNames, globalProperties, targetOutputs) = true
+
+ member _.LogCustomEvent(e) =
+ protect (fun () -> logMessage e.Message)
+
+ member _.LogErrorEvent(e) =
+ protect (fun () -> logDiagnostic true e.Code e.Message)
+
+ member _.LogMessageEvent(e) =
+ protect (fun () -> logMessage e.Message)
+
+ member _.LogWarningEvent(e) =
+ protect (fun () -> logDiagnostic false e.Code e.Message)
+
+ member _.ColumnNumberOfTaskNode = 1
+ member _.LineNumberOfTaskNode = 1
+ member _.ContinueOnError = true
+ member _.ProjectFileOfTaskNode = ""
+ }
+
+ // Derive the target framework directory if none was supplied.
+ let targetFrameworkDirectories =
+ if targetFrameworkDirectories = [] then
+ DeriveTargetFrameworkDirectories(targetFrameworkVersion, logMessage)
+ else
+ targetFrameworkDirectories |> Array.ofList
+
+ // Filter for null and zero length
+ let references = references |> Array.filter (fst >> String.IsNullOrEmpty >> not)
+
+ // Determine the set of search paths for the resolution
+ let searchPaths =
+
+ let explicitIncludeDirs =
+ explicitIncludeDirs |> List.filter (String.IsNullOrEmpty >> not)
+
+ let registry =
+ sprintf "{Registry:%s,%s,%s%s}" frameworkRegistryBase targetFrameworkVersion assemblyFoldersSuffix assemblyFoldersConditions
+
+ [| // When compiling scripts using fsc.exe, for some reason we have always historically put TargetFrameworkDirectory first
+ // It is unclear why. This is the only place we look at the 'isdifference between ResolutionEnvironment.EditingOrCompilation and ResolutionEnvironment.EditingTime.
+ match resolutionEnvironment with
+ | LegacyResolutionEnvironment.EditingOrCompilation false -> yield "{TargetFrameworkDirectory}"
+ | LegacyResolutionEnvironment.EditingOrCompilation true
+ | LegacyResolutionEnvironment.CompilationAndEvaluation -> ()
+
+ // Quick-resolve straight to file name first
+ if allowRawFileName then
+ yield "{RawFileName}"
+ yield! explicitIncludeDirs // From -I, #I
+ yield fsharpCoreDir // Location of explicit reference to FSharp.Core, otherwise location of fsc.exe
+ yield implicitIncludeDir // Usually the project directory
+
+ match resolutionEnvironment with
+ | LegacyResolutionEnvironment.EditingOrCompilation true
+ | LegacyResolutionEnvironment.CompilationAndEvaluation -> yield "{TargetFrameworkDirectory}"
+ | LegacyResolutionEnvironment.EditingOrCompilation false -> ()
+
+ yield registry
+ yield "{AssemblyFolders}"
+ yield "{GAC}"
+ // use path to implementation assemblies as the last resort
+ yield! GetPathToDotNetFrameworkImlpementationAssemblies targetFrameworkVersion
+ |]
+
+ let assemblies =
+ [|
+ for referenceName, baggage in references ->
+ let item = TaskItem(referenceName) :> ITaskItem
+ item.SetMetadata("Baggage", baggage)
+ item
+ |]
+
+ let rar =
+ ResolveAssemblyReference(
+ BuildEngine = engine,
+ TargetFrameworkDirectories = targetFrameworkDirectories,
+ FindRelatedFiles = false,
+ FindDependencies = false,
+ FindSatellites = false,
+ FindSerializationAssemblies = false,
+ Assemblies = assemblies,
+ SearchPaths = searchPaths,
+ AllowedAssemblyExtensions = [| ".dll"; ".exe" |]
+ )
+
+ rar.TargetProcessorArchitecture <- targetProcessorArchitecture
+ let targetedRuntimeVersionValue = typeof.Assembly.ImageRuntimeVersion
+ rar.TargetedRuntimeVersion <- targetedRuntimeVersionValue
+ rar.CopyLocalDependenciesWhenParentReferenceInGac <- true
+
+ let succeeded = rar.Execute()
+
+ if not succeeded then
+ raise LegacyResolutionFailure
+
+ [|
+ for p in rar.ResolvedFiles ->
+ let resolvedFrom = DecodeResolvedFrom(p.GetMetadata("ResolvedFrom"))
+ let fusionName = p.GetMetadata("FusionName")
+ let redist = p.GetMetadata("Redist")
+
+ {
+ itemSpec = p.ItemSpec
+ prepareToolTip = TooltipForResolvedFrom(resolvedFrom, fusionName, redist)
+ baggage = p.GetMetadata("Baggage")
+ }
+ |]
+
+let getResolver () =
+ { new ILegacyReferenceResolver with
+ member _.HighestInstalledNetFrameworkVersion() =
+ HighestInstalledRefAssembliesOrDotNETFramework()
+
+ member _.DotNetFrameworkReferenceAssembliesRootDirectory =
+ DotNetFrameworkReferenceAssembliesRootDirectory
+
+ /// Perform the resolution on rooted and unrooted paths, and then combine the results.
+ member _.Resolve
+ (
+ resolutionEnvironment,
+ references,
+ targetFrameworkVersion,
+ targetFrameworkDirectories,
+ targetProcessorArchitecture,
+ fsharpCoreDir,
+ explicitIncludeDirs,
+ implicitIncludeDir,
+ logMessage,
+ logDiagnostic
+ ) =
+
+ // The {RawFileName} target is 'dangerous', in the sense that is uses Directory.GetCurrentDirectory() to resolve unrooted file paths.
+ // It is unreliable to use this mutable global state inside Visual Studio. As a result, we partition all references into a "rooted" set
+ // (which contains e.g. C:\MyDir\MyAssem.dll) and "unrooted" (everything else). We only allow "rooted" to use {RawFileName}. Note that
+ // unrooted may still find 'local' assemblies by virtue of the fact that "implicitIncludeDir" is one of the places searched during
+ // assembly resolution.
+ let references =
+ [|
+ for fileName, baggage as data in references ->
+ // However, MSBuild will not resolve 'relative' paths, even when e.g. implicitIncludeDir is part of the search. As a result,
+ // if we have an unrooted path + file name, we'll assume this is relative to the project directory and root it.
+ if FileSystem.IsPathRootedShim(fileName) then
+ data // fine, e.g. "C:\Dir\foo.dll"
+ elif not (fileName.Contains("\\") || fileName.Contains("/")) then
+ data // fine, e.g. "System.Transactions.dll"
+ else
+ // We have a 'relative path', e.g. "bin/Debug/foo.exe" or "..\Yadda\bar.dll"
+ // turn it into an absolute path based at implicitIncludeDir
+ (Path.Combine(implicitIncludeDir, fileName), baggage)
+ |]
+
+ let rooted, unrooted =
+ references |> Array.partition (fst >> FileSystem.IsPathRootedShim)
+
+ let rootedResults =
+ ResolveCore(
+ resolutionEnvironment,
+ rooted,
+ targetFrameworkVersion,
+ targetFrameworkDirectories,
+ targetProcessorArchitecture,
+ fsharpCoreDir,
+ explicitIncludeDirs,
+ implicitIncludeDir,
+ true,
+ logMessage,
+ logDiagnostic
+ )
+
+ let unrootedResults =
+ ResolveCore(
+ resolutionEnvironment,
+ unrooted,
+ targetFrameworkVersion,
+ targetFrameworkDirectories,
+ targetProcessorArchitecture,
+ fsharpCoreDir,
+ explicitIncludeDirs,
+ implicitIncludeDir,
+ false,
+ logMessage,
+ logDiagnostic
+ )
+
+ // now unify the two sets of results
+ Array.concat [| rootedResults; unrootedResults |]
+ }
+ |> LegacyReferenceResolver
diff --git a/src/Compiler/Legacy/LegacyMSBuildReferenceResolver.fsi b/src/LegacyMSBuildResolver/LegacyMSBuildReferenceResolver.fsi
similarity index 100%
rename from src/Compiler/Legacy/LegacyMSBuildReferenceResolver.fsi
rename to src/LegacyMSBuildResolver/LegacyMSBuildReferenceResolver.fsi
diff --git a/src/LegacyMSBuildResolver/LegacyResolver.txt b/src/LegacyMSBuildResolver/LegacyResolver.txt
new file mode 100644
index 00000000000..1aac6347541
--- /dev/null
+++ b/src/LegacyMSBuildResolver/LegacyResolver.txt
@@ -0,0 +1,7 @@
+# -------------------------------------------------------------------------------
+# use a completely new error number and keep messages in their surrounding groups
+# -------------------------------------------------------------------------------
+assemblyResolutionFoundByAssemblyFoldersKey,"Found by AssemblyFolders registry key"
+assemblyResolutionFoundByAssemblyFoldersExKey,"Found by AssemblyFoldersEx registry key"
+assemblyResolutionNetFramework,".NET Framework"
+assemblyResolutionGAC,"Global Assembly Cache"
\ No newline at end of file
diff --git a/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.cs.xlf b/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.cs.xlf
new file mode 100644
index 00000000000..fe16dc84f65
--- /dev/null
+++ b/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.cs.xlf
@@ -0,0 +1,27 @@
+
+
+
+
+
+ Found by AssemblyFoldersEx registry key
+ Found by AssemblyFoldersEx registry key
+
+
+
+ Found by AssemblyFolders registry key
+ Found by AssemblyFolders registry key
+
+
+
+ Global Assembly Cache
+ Global Assembly Cache
+
+
+
+ .NET Framework
+ .NET Framework
+
+
+
+
+
\ No newline at end of file
diff --git a/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.de.xlf b/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.de.xlf
new file mode 100644
index 00000000000..0980cec838a
--- /dev/null
+++ b/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.de.xlf
@@ -0,0 +1,27 @@
+
+
+
+
+
+ Found by AssemblyFoldersEx registry key
+ Found by AssemblyFoldersEx registry key
+
+
+
+ Found by AssemblyFolders registry key
+ Found by AssemblyFolders registry key
+
+
+
+ Global Assembly Cache
+ Global Assembly Cache
+
+
+
+ .NET Framework
+ .NET Framework
+
+
+
+
+
\ No newline at end of file
diff --git a/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.es.xlf b/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.es.xlf
new file mode 100644
index 00000000000..ae938d2cacd
--- /dev/null
+++ b/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.es.xlf
@@ -0,0 +1,27 @@
+
+
+
+
+
+ Found by AssemblyFoldersEx registry key
+ Found by AssemblyFoldersEx registry key
+
+
+
+ Found by AssemblyFolders registry key
+ Found by AssemblyFolders registry key
+
+
+
+ Global Assembly Cache
+ Global Assembly Cache
+
+
+
+ .NET Framework
+ .NET Framework
+
+
+
+
+
\ No newline at end of file
diff --git a/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.fr.xlf b/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.fr.xlf
new file mode 100644
index 00000000000..7fe41477230
--- /dev/null
+++ b/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.fr.xlf
@@ -0,0 +1,27 @@
+
+
+
+
+
+ Found by AssemblyFoldersEx registry key
+ Found by AssemblyFoldersEx registry key
+
+
+
+ Found by AssemblyFolders registry key
+ Found by AssemblyFolders registry key
+
+
+
+ Global Assembly Cache
+ Global Assembly Cache
+
+
+
+ .NET Framework
+ .NET Framework
+
+
+
+
+
\ No newline at end of file
diff --git a/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.it.xlf b/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.it.xlf
new file mode 100644
index 00000000000..d20390cc87e
--- /dev/null
+++ b/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.it.xlf
@@ -0,0 +1,27 @@
+
+
+
+
+
+ Found by AssemblyFoldersEx registry key
+ Found by AssemblyFoldersEx registry key
+
+
+
+ Found by AssemblyFolders registry key
+ Found by AssemblyFolders registry key
+
+
+
+ Global Assembly Cache
+ Global Assembly Cache
+
+
+
+ .NET Framework
+ .NET Framework
+
+
+
+
+
\ No newline at end of file
diff --git a/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.ja.xlf b/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.ja.xlf
new file mode 100644
index 00000000000..2f2fbca84a3
--- /dev/null
+++ b/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.ja.xlf
@@ -0,0 +1,27 @@
+
+
+
+
+
+ Found by AssemblyFoldersEx registry key
+ Found by AssemblyFoldersEx registry key
+
+
+
+ Found by AssemblyFolders registry key
+ Found by AssemblyFolders registry key
+
+
+
+ Global Assembly Cache
+ Global Assembly Cache
+
+
+
+ .NET Framework
+ .NET Framework
+
+
+
+
+
\ No newline at end of file
diff --git a/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.ko.xlf b/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.ko.xlf
new file mode 100644
index 00000000000..a57ff6c0dc3
--- /dev/null
+++ b/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.ko.xlf
@@ -0,0 +1,27 @@
+
+
+
+
+
+ Found by AssemblyFoldersEx registry key
+ Found by AssemblyFoldersEx registry key
+
+
+
+ Found by AssemblyFolders registry key
+ Found by AssemblyFolders registry key
+
+
+
+ Global Assembly Cache
+ Global Assembly Cache
+
+
+
+ .NET Framework
+ .NET Framework
+
+
+
+
+
\ No newline at end of file
diff --git a/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.pl.xlf b/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.pl.xlf
new file mode 100644
index 00000000000..49133a8479c
--- /dev/null
+++ b/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.pl.xlf
@@ -0,0 +1,27 @@
+
+
+
+
+
+ Found by AssemblyFoldersEx registry key
+ Found by AssemblyFoldersEx registry key
+
+
+
+ Found by AssemblyFolders registry key
+ Found by AssemblyFolders registry key
+
+
+
+ Global Assembly Cache
+ Global Assembly Cache
+
+
+
+ .NET Framework
+ .NET Framework
+
+
+
+
+
\ No newline at end of file
diff --git a/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.pt-BR.xlf b/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.pt-BR.xlf
new file mode 100644
index 00000000000..fbfa95dbf16
--- /dev/null
+++ b/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.pt-BR.xlf
@@ -0,0 +1,27 @@
+
+
+
+
+
+ Found by AssemblyFoldersEx registry key
+ Found by AssemblyFoldersEx registry key
+
+
+
+ Found by AssemblyFolders registry key
+ Found by AssemblyFolders registry key
+
+
+
+ Global Assembly Cache
+ Global Assembly Cache
+
+
+
+ .NET Framework
+ .NET Framework
+
+
+
+
+
\ No newline at end of file
diff --git a/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.ru.xlf b/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.ru.xlf
new file mode 100644
index 00000000000..c01f76a7296
--- /dev/null
+++ b/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.ru.xlf
@@ -0,0 +1,27 @@
+
+
+
+
+
+ Found by AssemblyFoldersEx registry key
+ Found by AssemblyFoldersEx registry key
+
+
+
+ Found by AssemblyFolders registry key
+ Found by AssemblyFolders registry key
+
+
+
+ Global Assembly Cache
+ Global Assembly Cache
+
+
+
+ .NET Framework
+ .NET Framework
+
+
+
+
+
\ No newline at end of file
diff --git a/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.tr.xlf b/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.tr.xlf
new file mode 100644
index 00000000000..3131d7674af
--- /dev/null
+++ b/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.tr.xlf
@@ -0,0 +1,27 @@
+
+
+
+
+
+ Found by AssemblyFoldersEx registry key
+ Found by AssemblyFoldersEx registry key
+
+
+
+ Found by AssemblyFolders registry key
+ Found by AssemblyFolders registry key
+
+
+
+ Global Assembly Cache
+ Global Assembly Cache
+
+
+
+ .NET Framework
+ .NET Framework
+
+
+
+
+
\ No newline at end of file
diff --git a/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.zh-Hans.xlf b/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.zh-Hans.xlf
new file mode 100644
index 00000000000..7791accdff9
--- /dev/null
+++ b/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.zh-Hans.xlf
@@ -0,0 +1,27 @@
+
+
+
+
+
+ Found by AssemblyFoldersEx registry key
+ Found by AssemblyFoldersEx registry key
+
+
+
+ Found by AssemblyFolders registry key
+ Found by AssemblyFolders registry key
+
+
+
+ Global Assembly Cache
+ Global Assembly Cache
+
+
+
+ .NET Framework
+ .NET Framework
+
+
+
+
+
\ No newline at end of file
diff --git a/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.zh-Hant.xlf b/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.zh-Hant.xlf
new file mode 100644
index 00000000000..52a305821cf
--- /dev/null
+++ b/src/LegacyMSBuildResolver/xlf/LegacyResolver.txt.zh-Hant.xlf
@@ -0,0 +1,27 @@
+
+
+
+
+
+ Found by AssemblyFoldersEx registry key
+ Found by AssemblyFoldersEx registry key
+
+
+
+ Found by AssemblyFolders registry key
+ Found by AssemblyFolders registry key
+
+
+
+ Global Assembly Cache
+ Global Assembly Cache
+
+
+
+ .NET Framework
+ .NET Framework
+
+
+
+
+
\ No newline at end of file
diff --git a/src/fsc/fsc.targets b/src/fsc/fsc.targets
index af1998e9bbe..6dccff1eae3 100644
--- a/src/fsc/fsc.targets
+++ b/src/fsc/fsc.targets
@@ -28,6 +28,11 @@
+
+ LegacyResolver.txt
+
+
+ {{FSCoreVersion}}
@@ -46,6 +51,9 @@
+
+
+
diff --git a/src/fsi/fsi.targets b/src/fsi/fsi.targets
index 23ee6e76bfc..e553c55cf1c 100644
--- a/src/fsi/fsi.targets
+++ b/src/fsi/fsi.targets
@@ -32,6 +32,11 @@
+
+ LegacyResolver.txt
+
+
+
@@ -54,4 +59,10 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/FSharp.Compiler.ComponentTests/CompilerOptions/fsc/debug.fs b/tests/FSharp.Compiler.ComponentTests/CompilerOptions/fsc/debug.fs
new file mode 100644
index 00000000000..335566ef175
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/CompilerOptions/fsc/debug.fs
@@ -0,0 +1,42 @@
+// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.
+
+namespace FSharp.Compiler.ComponentTests.CompilerOptions
+
+open Xunit
+open FSharp.Test
+open FSharp.Test.Compiler
+
+module debug =
+
+ []
+ let ``fsc debug``() =
+ FSharp """
+printfn "Hello, World"
+ """
+ |> asExe
+ |> withOptions ["--debug"]
+ |> compile
+ |> shouldSucceed
+ |> verifyHasPdb
+
+ []
+ let ``fsc debug plus``() =
+ FSharp """
+printfn "Hello, World"
+ """
+ |> asExe
+ |> withOptions ["--debug+"]
+ |> compile
+ |> shouldSucceed
+ |> verifyHasPdb
+
+ []
+ let ``fsc debug minus``() =
+ FSharp """
+printfn "Hello, World"
+ """
+ |> asExe
+ |> withOptions ["--debug-"]
+ |> compile
+ |> shouldSucceed
+ |> verifyNoPdb
diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/TypesAndTypeConstraints/IWSAMsAndSRTPs/IWSAMsAndSRTPsTests.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/TypesAndTypeConstraints/IWSAMsAndSRTPs/IWSAMsAndSRTPsTests.fs
index 9abba91ca2f..a328c5f3df2 100644
--- a/tests/FSharp.Compiler.ComponentTests/Conformance/TypesAndTypeConstraints/IWSAMsAndSRTPs/IWSAMsAndSRTPsTests.fs
+++ b/tests/FSharp.Compiler.ComponentTests/Conformance/TypesAndTypeConstraints/IWSAMsAndSRTPs/IWSAMsAndSRTPsTests.fs
@@ -19,6 +19,38 @@ let setupCompilation compilation =
|> withReferences [typesModule]
+[]
+let ``Srtp call Zero property returns valid result`` () =
+ Fsx """
+let inline zero<'T when 'T: (static member Zero: 'T)> = 'T.Zero
+let result = zero
+if result <> 0 then failwith $"Something's wrong: {result}"
+ """
+ |> runFsi
+ |> shouldSucceed
+
+[]
+let ``Srtp call to custom property returns valid result`` () =
+ FSharp """
+module Foo
+type Foo =
+ static member Bar = 1
+
+type HasBar<'T when 'T: (static member Bar: int)> = 'T
+
+let inline bar<'T when HasBar<'T>> =
+ 'T.Bar
+
+[]
+let main _ =
+ let result = bar
+ if result <> 0 then
+ failwith $"Unexpected result: {result}"
+ 0
+ """
+ |> asExe
+ |> compileAndRun
+
#if !NETCOREAPP
[]
#else
@@ -775,7 +807,11 @@ module ``Active patterns`` =
module ``Suppression of System Numerics interfaces on unitized types`` =
- []
+#if !NETCOREAPP
+ []
+#else
+ []
+#endif
let Baseline () =
Fsx """
open System.Numerics
@@ -785,16 +821,19 @@ module ``Suppression of System Numerics interfaces on unitized types`` =
|> compile
|> shouldSucceed
- []
+#if !NETCOREAPP
+ []
+#else
+ []
[]
[]
[]
[]
[]
- []
+ []
[]
[]
- []
+ []
[]
[]
[]
@@ -814,6 +853,7 @@ module ``Suppression of System Numerics interfaces on unitized types`` =
[]
[]
[]
+#endif
let ``Unitized type shouldn't be compatible with System.Numerics.I*`` name paramCount =
let typeParams = Seq.replicate paramCount "'T" |> String.concat ","
let genericType = $"{name}<{typeParams}>"
diff --git a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/ClassesTests.fs b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/ClassesTests.fs
index 621307f4e66..eeb3ab1d371 100644
--- a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/ClassesTests.fs
+++ b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/ClassesTests.fs
@@ -120,4 +120,426 @@ type X() =
|> withDiagnostics [
(Error 531, Line 4, Col 5, Line 4, Col 12, "Accessibility modifiers should come immediately prior to the identifier naming a construct")
(Error 512, Line 4, Col 13, Line 4, Col 18, "Accessibility modifiers are not permitted on 'do' bindings, but 'Private' was given.")
- (Error 222, Line 2, Col 1, Line 3, Col 1, "Files in libraries or multiple-file applications must begin with a namespace or module declaration, e.g. 'namespace SomeNamespace.SubNamespace' or 'module SomeNamespace.SomeModule'. Only the last source file of an application may omit such a declaration.")]
+ (Error 222, Line 2, Col 1, Line 3, Col 1, "Files in libraries or multiple-file applications must begin with a namespace or module declaration, e.g. 'namespace SomeNamespace.SubNamespace' or 'module SomeNamespace.SomeModule'. Only the last source file of an application may omit such a declaration.")
+ ]
+
+ []
+ let ``No abstract or interface member was found that corresponds to this override with lang preview``() =
+ Fsx """
+type A =
+ abstract member M1: unit -> unit
+ abstract member M2: unit -> unit
+ abstract member M3: unit -> unit
+ abstract member M4: unit -> unit
+
+type B() =
+ interface A with
+ override this.M1() = ()
+ override this.M2() = () // error is expected
+ override this.M3() = () // error is expected
+ override this.M4() = ()
+
+type C() =
+ inherit B()
+ override this.M1() = ()
+ override this.M2() = ()
+ override this.M3() = ()
+ override this.M4() = ()
+ member this.M5() = ()
+ """
+ |> withLangVersionPreview
+ |> compile
+ |> shouldFail
+ |> withDiagnostics [
+ (Error 855, Line 17, Col 19, Line 17, Col 21, "No abstract or interface member was found that corresponds to this override")
+ (Error 855, Line 18, Col 19, Line 18, Col 21, "No abstract or interface member was found that corresponds to this override")
+ (Error 855, Line 19, Col 19, Line 19, Col 21, "No abstract or interface member was found that corresponds to this override")
+ (Error 855, Line 20, Col 19, Line 20, Col 21, "No abstract or interface member was found that corresponds to this override")
+ ]
+
+ []
+ let ``No abstract or interface member was found that corresponds to this override with lang version70``() =
+ Fsx """
+type A =
+ abstract member M1: unit -> unit
+ abstract member M2: unit -> unit
+ abstract member M3: unit -> unit
+ abstract member M4: unit -> unit
+
+type B() =
+ interface A with
+ override this.M1() = ()
+ override this.M2() = () // error is expected
+ override this.M3() = () // error is expected
+ override this.M4() = ()
+
+type C() =
+ inherit B()
+ override this.M1() = ()
+ override this.M2() = ()
+ override this.M3() = ()
+ override this.M4() = ()
+ member this.M5() = ()
+ """
+ |> withLangVersion70
+ |> compile
+ |> shouldFail
+ |> withDiagnostics [
+ (Error 855, Line 17, Col 19, Line 17, Col 21, "No abstract or interface member was found that corresponds to this override")
+ (Error 855, Line 18, Col 19, Line 18, Col 21, "No abstract or interface member was found that corresponds to this override")
+ (Error 855, Line 19, Col 19, Line 19, Col 21, "No abstract or interface member was found that corresponds to this override")
+ (Error 855, Line 20, Col 19, Line 20, Col 21, "No abstract or interface member was found that corresponds to this override")
+ ]
+
+ []
+ let ``Virtual member was found that corresponds to this override with lang version70`` () =
+ let CSLib =
+ CSharp """
+public class A
+{
+ public virtual void M1() { }
+ public virtual void M2() { }
+ public virtual void M3() { }
+ public virtual void M4() { }
+}
+ """ |> withName "CSLib"
+
+ let app =
+ FSharp """
+module ClassTests
+type B() =
+ inherit A()
+ override this.M1() = ()
+ override this.M2() = ()
+ override this.M3() = ()
+ override this.M4() = ()
+ member this.M5() = ()
+ """ |> withReferences [CSLib]
+ app
+ |> withLangVersion70
+ |> compile
+ |> shouldSucceed
+
+ []
+ let ``Virtual member was found that corresponds to this override with lang preview`` () =
+ let CSLib =
+ CSharp """
+public class A
+{
+ public virtual void M1() { }
+ public virtual void M2() { }
+ public virtual void M3() { }
+ public virtual void M4() { }
+}
+ """ |> withName "CSLib"
+
+ let app =
+ FSharp """
+module ClassTests
+type B() =
+ inherit A()
+ override this.M1() = ()
+ override this.M2() = ()
+ override this.M3() = ()
+ override this.M4() = ()
+ member this.M5() = ()
+ """ |> withReferences [CSLib]
+ app
+ |> withLangVersionPreview
+ |> compile
+ |> shouldSucceed
+
+
+ []
+ let ``Virtual member was not found that corresponds to this override simple base class with lang version preview`` () =
+ let CSLib =
+ CSharp """
+public class A
+{
+ public virtual void M1() { }
+ public void M2() { }
+ public virtual void M3() { }
+}
+ """ |> withName "CSLib"
+
+ let app =
+ FSharp """
+module ClassTests
+type B() =
+ inherit A()
+
+ override this.M1() = ()
+ override this.M2() = () // error expected
+ override this.M3() = ()
+ member this.M4() = ()
+ """ |> withReferences [CSLib]
+ app
+ |> withLangVersionPreview
+ |> compile
+ |> shouldFail
+ |> withDiagnostics [
+ (Error 855, Line 7, Col 19, Line 7, Col 21, "No abstract or interface member was found that corresponds to this override")
+ ]
+
+ []
+ let ``Virtual member was not found that corresponds to this override simple base class with lang version70`` () =
+ let CSLib =
+ CSharp """
+public class A
+{
+ public virtual void M1() { }
+ public void M2() { }
+ public virtual void M3() { }
+}
+ """ |> withName "CSLib"
+
+ let app =
+ FSharp """
+module ClassTests
+type B() =
+ inherit A()
+
+ override this.M1() = ()
+ override this.M2() = ()
+ override this.M3() = ()
+ member this.M4() = ()
+ """ |> withReferences [CSLib]
+ app
+ |> withLangVersion70
+ |> compile
+ |> shouldFail
+ |> withDiagnostics [
+ (Error 855, Line 7, Col 19, Line 7, Col 21, "No abstract or interface member was found that corresponds to this override")
+ ]
+
+ []
+ let ``Virtual member was not found that corresponds to this override nested base class with lang version preview`` () =
+ let CSLib =
+ CSharp """
+public class A
+{
+ public virtual void M1() { }
+ public virtual void M2() { }
+ public virtual void M3() { }
+ public virtual void M4() { }
+}
+
+public class B : A
+{
+ public override void M1() { }
+ public void M2() { }
+ public new void M3() { }
+ public new virtual void M4() { }
+}
+ """ |> withName "CSLib"
+
+ let app =
+ FSharp """
+module ClassTests
+type C() =
+ inherit B()
+
+ override this.M1() = ()
+ override this.M2() = () // error expected
+ override this.M3() = () // error expected
+ override this.M4() = ()
+ member this.M5() = ()
+ """ |> withReferences [CSLib]
+ app
+ |> withLangVersionPreview
+ |> compile
+ |> shouldFail
+ |> withDiagnostics [
+ (Error 855, Line 7, Col 19, Line 7, Col 21, "No abstract or interface member was found that corresponds to this override")
+ (Error 855, Line 8, Col 19, Line 8, Col 21, "No abstract or interface member was found that corresponds to this override")
+ ]
+
+ []
+ let ``Virtual member was not found that corresponds to this override nested base class with lang version70`` () =
+ let CSLib =
+ CSharp """
+public class A
+{
+ public virtual void M1() { }
+ public virtual void M2() { }
+ public virtual void M3() { }
+ public virtual void M4() { }
+}
+
+public class B : A
+{
+ public override void M1() { }
+ public void M2() { }
+ public new void M3() { }
+ public new virtual void M4() { }
+}
+ """ |> withName "CSLib"
+
+ let app =
+ FSharp """
+module ClassTests
+type C() =
+ inherit B()
+
+ override this.M1() = ()
+ override this.M2() = () // error expected
+ override this.M3() = () // error expected
+ override this.M4() = ()
+ member this.M5() = ()
+ """ |> withReferences [CSLib]
+ app
+ |> withLangVersion70
+ |> compile
+ |> shouldSucceed
+
+ []
+ let ``Virtual member was not found that corresponds to this override nested 2 base class with lang preview`` () =
+ let CSLib =
+ CSharp """
+public class A
+{
+ public virtual void M1() { }
+ public virtual void M2() { }
+ public virtual void M3() { }
+ public virtual void M4() { }
+}
+
+public class B : A
+{
+ public void M2() { }
+ public new void M3() { }
+}
+ """ |> withName "CSLib"
+
+ let app =
+ FSharp """
+module ClassTests
+type C() =
+ inherit B()
+
+ override this.M1() = ()
+ override this.M2() = () // error is expected
+ override this.M3() = () // error is expected
+ override this.M4() = ()
+ member this.M5() = ()
+ """ |> withReferences [CSLib]
+ app
+ |> withLangVersionPreview
+ |> compile
+ |> shouldFail
+ |> withDiagnostics [
+ (Error 855, Line 7, Col 19, Line 7, Col 21, "No abstract or interface member was found that corresponds to this override")
+ (Error 855, Line 8, Col 19, Line 8, Col 21, "No abstract or interface member was found that corresponds to this override")
+ ]
+
+ []
+ let ``Virtual member was not found that corresponds to this override nested 2 base classes with lang version70`` () =
+ let CSLib =
+ CSharp """
+public class A
+{
+ public virtual void M1() { }
+ public virtual void M2() { }
+ public virtual void M3() { }
+ public virtual void M4() { }
+}
+
+public class B : A
+{
+ public void M2() { }
+ public new void M3() { }
+}
+ """ |> withName "CSLib"
+
+ let app =
+ FSharp """
+module ClassTests
+type C() =
+ inherit B()
+
+ override this.M1() = ()
+ override this.M2() = () // error is expected
+ override this.M3() = () // error is expected
+ override this.M4() = ()
+ member this.M5() = ()
+ """ |> withReferences [CSLib]
+ app
+ |> withLangVersion70
+ |> compile
+ |> shouldSucceed
+
+ []
+ let ``Virtual member was not found that corresponds to this override nested 2 base classes and mixed methods with lang preview`` () =
+ let CSLib =
+ CSharp """
+public class A
+{
+ public virtual void M1() { }
+ public void M2() { }
+}
+
+public class B : A
+{
+ public virtual void M3() { }
+ public new void M4() { }
+}
+ """ |> withName "CSLib"
+
+ let app =
+ FSharp """
+module ClassTests
+type C() =
+ inherit B()
+
+ override this.M1() = ()
+ override this.M2() = () // error is expected
+ override this.M3() = ()
+ override this.M4() = () // error is expected
+ member this.M5() = ()
+ """ |> withReferences [CSLib]
+ app
+ |> withLangVersionPreview
+ |> compile
+ |> shouldFail
+ |> withDiagnostics [
+ (Error 855, Line 7, Col 19, Line 7, Col 21, "No abstract or interface member was found that corresponds to this override")
+ (Error 855, Line 9, Col 19, Line 9, Col 21, "No abstract or interface member was found that corresponds to this override")
+ ]
+
+ []
+ let ``Virtual member was not found that corresponds to this override nested 2 base classes and mixed methods with lang version70`` () =
+ let CSLib =
+ CSharp """
+public class A
+{
+ public virtual void M1() { }
+ public void M2() { }
+}
+
+public class B : A
+{
+ public virtual void M3() { }
+ public new void M4() { }
+}
+ """ |> withName "CSLib"
+
+ let app =
+ FSharp """
+module ClassTests
+type C() =
+ inherit B()
+
+ override this.M1() = ()
+ override this.M2() = () // error is expected
+ override this.M3() = ()
+ override this.M4() = () // error is expected
+ member this.M5() = ()
+ """ |> withReferences [CSLib]
+ app
+ |> withLangVersion70
+ |> compile
+ |> shouldFail
+ |> withDiagnostics [
+ (Error 855, Line 7, Col 19, Line 7, Col 21, "No abstract or interface member was found that corresponds to this override")
+ (Error 855, Line 9, Col 19, Line 9, Col 21, "No abstract or interface member was found that corresponds to this override")
+ ]
\ No newline at end of file
diff --git a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj
index 240cf851b92..85239d5a3c0 100644
--- a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj
+++ b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj
@@ -187,6 +187,7 @@
+
@@ -206,6 +207,7 @@
+
@@ -222,6 +224,7 @@
+
diff --git a/tests/FSharp.Compiler.ComponentTests/Interop/RequiredAndInitOnlyProperties.fs b/tests/FSharp.Compiler.ComponentTests/Interop/RequiredAndInitOnlyProperties.fs
index a3e6b6b6ed7..0b2d4cc37ab 100644
--- a/tests/FSharp.Compiler.ComponentTests/Interop/RequiredAndInitOnlyProperties.fs
+++ b/tests/FSharp.Compiler.ComponentTests/Interop/RequiredAndInitOnlyProperties.fs
@@ -8,6 +8,14 @@ open System
module ``Required and init-only properties`` =
+ let csharpRecord =
+ CSharp """
+ namespace RequiredAndInitOnlyProperties
+ {
+ public record Recd();
+
+ }""" |> withCSharpLanguageVersion CSharpLanguageVersion.Preview |> withName "csLib"
+
let csharpBaseClass =
CSharp """
namespace RequiredAndInitOnlyProperties
@@ -228,7 +236,7 @@ let main _ =
Error 810, Line 9, Col 5, Line 9, Col 21, "Cannot call 'set_GetInit' - a setter for init-only property, please use object initialization instead. See https://aka.ms/fsharp-assigning-values-to-properties-at-initialization"
]
- #if !NETCOREAPP
+#if !NETCOREAPP
[]
#else
[]
@@ -259,6 +267,63 @@ let main _ =
Error 810, Line 9, Col 38, Line 9, Col 40, "Init-only property 'GetInit' cannot be set outside the initialization code. See https://aka.ms/fsharp-assigning-values-to-properties-at-initialization"
]
+#if !NETCOREAPP
+ []
+#else
+ []
+#endif
+ let ``F# can change init-only property via SRTP`` () =
+
+ let csharpLib = csharpBaseClass
+
+ let fsharpSource =
+ """
+open System
+open RequiredAndInitOnlyProperties
+
+let inline setGetInit<'T when 'T : (member set_GetInit: int -> unit)> (a: 'T) (x: int) = a.set_GetInit(x)
+
+[]
+let main _ =
+ let raio = RAIO()
+ setGetInit raio 111
+ 0
+"""
+ FSharp fsharpSource
+ |> asExe
+ |> withLangVersion70
+ |> withReferences [csharpLib]
+ |> compile
+ |> shouldSucceed
+
+ #if !NETCOREAPP
+ []
+#else
+ []
+#endif
+ let ``F# can call special-named methods via SRTP`` () =
+
+ let csharpLib = csharpRecord
+
+ let fsharpSource =
+ """
+open System
+open RequiredAndInitOnlyProperties
+
+let inline clone<'T when 'T : (member ``$``: unit -> 'T)> (a: 'T) = a.``$``()
+
+[]
+let main _ =
+ let recd = Recd()
+ let _ = clone recd
+ 0
+"""
+ FSharp fsharpSource
+ |> asExe
+ |> withLangVersion70
+ |> withReferences [csharpLib]
+ |> compile
+ |> shouldSucceed
#if !NETCOREAPP
[]
diff --git a/tests/FSharp.Compiler.ComponentTests/Signatures/SigGenerationRoundTripTests.fs b/tests/FSharp.Compiler.ComponentTests/Signatures/SigGenerationRoundTripTests.fs
new file mode 100644
index 00000000000..0b4be741d50
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/Signatures/SigGenerationRoundTripTests.fs
@@ -0,0 +1,34 @@
+module FSharp.Compiler.ComponentTests.Signatures.SigGenerationRoundTripTests
+
+open Xunit
+open FSharp.Test
+open FSharp.Test.Compiler
+open System.IO
+
+let testCasesDir = Path.Combine(__SOURCE_DIRECTORY__,"TestCasesForGenerationRoundTrip")
+let allTestCases =
+ Directory.EnumerateFiles(testCasesDir)
+ |> Seq.toArray
+ |> Array.map Path.GetFileName
+ |> Array.map (fun f -> [|f :> obj|])
+
+[]
+[]
+let ``Generate and compile`` implFileName =
+ let implContents = File.ReadAllText (Path.Combine(testCasesDir,implFileName))
+
+ let generatedSignature =
+ Fs implContents
+ |> withLangVersionPreview
+ |> withDefines ["TESTS_AS_APP";"COMPILED"]
+ |> printSignatures
+
+ Fsi generatedSignature
+ |> withAdditionalSourceFile (FsSource implContents)
+ |> withLangVersionPreview
+ |> withDefines ["TESTS_AS_APP";"COMPILED"]
+ |> ignoreWarnings
+ |> asExe
+ |> compile
+ |> shouldSucceed
+
diff --git a/tests/FSharp.Compiler.ComponentTests/Signatures/TestCasesForGenerationRoundTrip/access-minimal-repro.fsx b/tests/FSharp.Compiler.ComponentTests/Signatures/TestCasesForGenerationRoundTrip/access-minimal-repro.fsx
new file mode 100644
index 00000000000..830c81fb47d
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/Signatures/TestCasesForGenerationRoundTrip/access-minimal-repro.fsx
@@ -0,0 +1,8 @@
+module Core_access
+
+[]
+type MyClassPropertyGetters =
+ member internal x.InstInternal = 12
+ member private x.InstPrivate = 12
+ member public x.InstPublic = 12
+ member x.InstDefault = 12
diff --git a/tests/FSharp.Compiler.ComponentTests/Signatures/TestCasesForGenerationRoundTrip/access.fsx b/tests/FSharp.Compiler.ComponentTests/Signatures/TestCasesForGenerationRoundTrip/access.fsx
new file mode 100644
index 00000000000..6c067a82125
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/Signatures/TestCasesForGenerationRoundTrip/access.fsx
@@ -0,0 +1,287 @@
+module Core_access
+
+#light
+let failures = ref []
+
+let report_failure (s : string) =
+ stderr.Write" NO: "
+ stderr.WriteLine s
+ failures.Value <- failures.Value @ [s]
+
+let test (s : string) b =
+ stderr.Write(s)
+ if b then stderr.WriteLine " OK"
+ else report_failure (s)
+
+(*--------------------*)
+
+// Test cases for bug://1562
+// Checking that generated signature can be compiled against the file.
+
+type internal typInternal = | AAA1
+type private typPrivate = | AAA2
+type public typPublic = | AAA3
+type typDefault = | AAA4
+type internal rrr = | AAA
+
+let internal ValInternal = 1212
+let private ValPrivate = 1212
+let public ValPublic = 1212
+let ValDefault = 1212
+
+[]
+type MyClassFields =
+ val internal fieldInternal : int
+ val private fieldPrivate : int
+ val public fieldPublic : int
+
+[]
+type MyClassMutableFields =
+ val mutable internal mfieldInternal : int
+ val mutable private mfieldPrivate : int
+ val mutable public mfieldPublic : int
+
+[]
+type MyClassStaticMembers =
+ static member internal SInternal = 12
+ static member private SPrivate = 12
+ static member public SPublic = 12
+ static member SDefault = 12
+ static member internal SMInternal() = 12
+ static member private SMPrivate() = 12
+ static member public SMPublic() = 12
+ static member SMDefault() = 12
+
+[]
+type MyClassPropertiyGetters =
+ member internal x.InstInternal = 12
+ member private x.InstPrivate = 12
+ member public x.InstPublic = 12
+ member x.InstDefault = 12
+
+type MyClassExplicitCtors =
+ val v : int
+ internal new(x) = { v = x }
+ private new(x,y) = { v = x + y}
+ public new(x,y,z) = { v = x + y + z}
+
+type MyClassExplicitCtors2 =
+ new() = {}
+ internal new(x) = let v : int = x in {}
+ private new(x,y) = let v : int = x + y in {}
+ public new(x,y,z) = let v : int = x + y + z in {}
+
+[]
+type MyClassPropertyGetSetterMatrix =
+ //--
+ member obj.PropGetSetInternalInternal
+ with internal get() = 1
+ and internal set(x:int) = ()
+ member obj.PropGetSetInternalPrivate
+ with internal get() = 1
+ and private set(x:int) = ()
+ member obj.PropGetSetInternalPublic
+ with internal get() = 1
+ and public set(x:int) = ()
+ //--
+ member obj.PropGetSetPrivateInternal
+ with private get() = 1
+ and internal set(x:int) = ()
+ member obj.PropGetSetPrivatePrivate
+ with private get() = 1
+ and private set(x:int) = ()
+ member obj.PropGetSetPrivatePublic
+ with private get() = 1
+ and public set(x:int) = ()
+ //--
+ member obj.PropGetSetPublicInternal
+ with public get() = 1
+ and internal set(x:int) = ()
+ member obj.PropGetSetPublicPrivate
+ with public get() = 1
+ and private set(x:int) = ()
+ member obj.PropGetSetPublicPublic
+ with public get() = 1
+ and public set(x:int) = ()
+
+[]
+type MyClassImplicitCtorInternal internal() =
+ member obj.Res = 12
+
+[]
+type MyClassImplicitCtorPrivate private() =
+ member obj.Res = 12
+
+module internal ModInternal = begin end
+module private ModPrivate = begin end
+module public ModPublic = begin end
+
+type recordRepInternal = internal { rfA1 : int }
+type recordRepPrivate = private { rfA2 : int }
+type recordRepPublic = public { rfA3 : int }
+
+type dtypeRepInternal = internal | AA1 | BB1
+type dtypeRepPrivate = private | AA2 | BB2
+type dtypeRepPublic = public | AA3 | BB3
+
+type internal dtypeRepPublic2 = private | AA3 | BB3
+type private dtypeRepPublic3 = internal | AA3 | BB3
+
+type internal dtypeRepPublic4 =
+ private
+ | AA3
+ | BB3
+
+module internal M =
+ module private PP =
+ type dtypeRepPublic5 =
+ | AA3
+ | BB3
+
+module private M2 =
+ module internal P =
+ let vv = 12
+
+
+module RestrictedRecordsAndUnionsUsingPrivateAndInternalTypes =
+
+ module public Test1 =
+
+ type internal Data =
+ {
+ Datum: int
+ }
+
+ type public Datum =
+ internal
+ {
+ Thing: Data
+ }
+
+ type public Datum2 =
+ internal | A of Data * Data | B of Data
+
+ module public Test2 =
+
+ type internal Data =
+ {
+ Datum: int
+ }
+
+ type internal Datum =
+ {
+ Thing: Data
+ }
+
+ type internal Datum2 =
+ | A of Data * Data | B of Data
+
+ module public Test3 =
+
+ type public Data =
+ internal
+ {
+ Datum: int
+ }
+
+ type internal Datum =
+ {
+ Thing: Data
+ }
+
+ type internal Datum2 =
+ internal | A of Data * Data | B of Data
+
+
+ module public Test4 =
+
+ type internal Data =
+ {
+ Datum: int
+ }
+
+ type public Datum =
+ internal
+ {
+ Thing: Data
+ }
+
+ type public Datum2 =
+ internal | A of Data * Data | B of Data
+
+
+ module public Test5 =
+
+ type private Data =
+ {
+ Datum: int
+ }
+
+ type public Datum =
+ private
+ {
+ Thing: Data
+ }
+
+ type public Datum2 =
+ private | A of Data * Data | B of Data
+
+
+ module Test6 =
+ module internal HelperModule =
+
+ type public Data =
+ private
+ {
+ Datum: int
+ }
+
+ let internal handle (data:Data): int = data.Datum
+
+ module public Module =
+
+ type public Data =
+ private
+ {
+ Thing: HelperModule.Data
+ }
+
+ let public getInt (data:Data): int = HelperModule.handle data.Thing
+
+ module Test7 =
+ module internal HelperModule =
+
+ type Data =
+ {
+ Datum: int
+ }
+
+ let handle (data:Data): int = data.Datum
+
+ module Module =
+
+ type Data =
+ internal
+ {
+ Thing: HelperModule.Data
+ }
+
+ let getInt (data:Data): int = HelperModule.handle data.Thing
+
+
+ (*--------------------*)
+
+#if TESTS_AS_APP
+let RUN() = failures.Value
+#else
+let aa =
+ match failures.Value with
+ | [] ->
+ stdout.WriteLine "Test Passed"
+ System.IO.File.WriteAllText("test.ok","ok")
+ exit 0
+ | _ ->
+ stdout.WriteLine "Test Failed"
+ exit 1
+#endif
+
diff --git a/tests/FSharp.Compiler.ComponentTests/Signatures/TestCasesForGenerationRoundTrip/array.fsx b/tests/FSharp.Compiler.ComponentTests/Signatures/TestCasesForGenerationRoundTrip/array.fsx
new file mode 100644
index 00000000000..82914ce60f6
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/Signatures/TestCasesForGenerationRoundTrip/array.fsx
@@ -0,0 +1,1151 @@
+// #Conformance #Arrays #Stress #Structs #Mutable #ControlFlow #LetBindings
+#if TESTS_AS_APP
+module Core_array
+#endif
+
+let mutable failures = []
+let report_failure (s) =
+ stderr.WriteLine " NO"; failures <- s :: failures
+let test s b = if not b then (stderr.Write(s:string); report_failure(s) )
+let check s b1 b2 = test s (b1 = b2)
+
+
+(* TEST SUITE FOR Array *)
+
+let test_make_get_set_length () =
+ let arr = Array.create 3 0 in
+ test "fewoih" (Array.get arr 0 = 0);
+ test "vvrew0" (Array.get arr 2 = 0);
+ ignore (Array.set arr 0 4);
+ test "vsdiuvs" (Array.get arr 0 = 4);
+ test "vropivrwe" (Array.length arr = 3)
+
+let test_const () =
+ let arr = [| 4;3;2 |] in
+ test "sdvjk2" (Array.get arr 0 = 4);
+ test "cedkj" (Array.get arr 2 = 2);
+ ignore (Array.set arr 0 4);
+ test "ds9023" (Array.get arr 0 = 4);
+ test "sdio2" (Array.length arr = 3)
+
+let test_const_empty () =
+ let arr = [| |] in
+ test "sdio2" (Array.length arr = 0)
+
+let test_map () =
+ let arr = Array.map (fun x -> x + 1) ( [| 4;3;2 |]) in
+ test "test2927: sdvjk2" (Array.get arr 0 = 5);
+ test "test2927: cedkj" (Array.get arr 2 = 3)
+
+let test_iter () =
+ Array.iter (fun x -> test "fuo" (x <= 4)) ( [| 4;3;2 |])
+
+let test_iteri () =
+ let arr = [| 4;3;2 |] in
+ Array.iteri (fun i x -> test "fuo" (arr.[i] = x)) arr
+
+let test_mapi () =
+ let arr = [| 4;3;2 |] in
+ let arr2 = Array.mapi (fun i x -> test "dwqfuo" (arr.[i] = x); i + x) arr in
+ test "test2927: sdvjk2" (Array.get arr2 0 = 4);
+ test "test2927: cedkj" (Array.get arr2 2 = 4)
+
+let test_isEmpty () =
+ test "isEmpty a" (Array.isEmpty [||])
+ test "isEmpty b" (Array.isEmpty <| Array.create 0 42)
+ test "isEmpty c" <| not (Array.isEmpty <| [| 1 |])
+ test "isEmpty d" (Array.isEmpty <| Array.empty)
+
+let test_create () =
+ let arr = Array.create 10 10
+ for i in 0 .. 9 do
+ test "test_create" (arr.[i] = 10)
+
+let test_concat () =
+ let make n = [| for i in n .. n + 9 -> i |]
+ let arr = [| for i in 0..+10..50 -> make i|]
+ test "concat a" (Array.concat arr = [|0..59|])
+
+ let arr2 = [| for i in 0..50 -> [||] |]
+ test "concat b" (Array.concat arr2 = [| |])
+
+ let arr3 = [| [||]; [||]; [|1; 2|]; [||] |]
+ test "concat c" (Array.concat arr3 = [|1; 2|])
+
+let test_sub () =
+ test "sub a" (Array.sub [|0..100|] 10 20 = [|10..29|])
+ test "sub b" (Array.sub [|0..100|] 0 101 = [|0..100|])
+ test "sub c" (Array.sub [|0..100|] 0 1 = [|0|])
+ test "sub d" (Array.sub [|0..100|] 0 0 = [||])
+
+let test_fold2 () =
+ test "fold2 a"
+ (Array.fold2 (fun i j k -> i+j+k) 100 [|1;2;3|] [|1;2;3|] = 112)
+
+ test "fold2_b"
+ (Array.fold2 (fun i j k -> i-j-k) 100 [|1;2;3|] [|1;2;3|] = 100-12)
+
+let test_foldBack2 () =
+ test "foldBack2 a"
+ (Array.foldBack2 (fun i j k -> i+j+k) [|1;2;3|] [|1;2;3|] 100 = 112)
+
+ test "foldBack2_b"
+ (Array.foldBack2 (fun i j k -> k-i-j) [|1;2;3|] [|1;2;3|] 100 = 100-12)
+
+let test_scan () =
+ test "scan"
+ (Array.scan (+) 0 [|1..5|] = [|0; 1; 3; 6; 10; 15|])
+
+ test "scanBack"
+ (Array.scanBack (+) [|1..5|] 0 = [|15; 14; 12; 9; 5; 0|])
+
+let test_iter2 () =
+ let c = ref -1
+ Array.iter2 (fun x y -> c.Value <- c.Value + 1; test "iter2" (c.Value = x && c.Value = y)) [|0..100|] [|0..100|]
+ test "iter2" (c.Value = 100)
+
+let test_iteri2 () =
+ let c = ref 0
+ Array.iteri2 (fun i j k -> c.Value <- c.Value+i+j+k) [|1;2;3|] [|10;20;30|]
+ test "iteri2" (c.Value = 6+60+3)
+
+let test_map2 () =
+ test "map2"
+ (Array.map2 (+) [|0..100|] [|0..100|] = [|0..+2..200|])
+
+let test_mapi2 () =
+ test "mapi2 a"
+ (Array.mapi2 (fun i j k -> i+j+k) [|1..10|] [|1..10|] = [|2..+3..29|])
+
+ test "mapi2_b"
+ (try Array.mapi2 (fun i j k -> i+j+k) [||] [|1..10|] |> ignore; false
+ with _ -> true)
+
+let test_exists () =
+ test "exists a"
+ ([|1..100|] |> Array.exists ((=) 50))
+
+ test "exists b" <| not
+ ([|1..100|] |> Array.exists ((=) 150))
+
+let test_forall () =
+ test "forall a"
+ ([|1..100|] |> Array.forall (fun x -> x < 150))
+
+ test "forall b" <| not
+ ([|1..100|] |> Array.forall (fun x -> x < 80))
+
+let test_exists2 () =
+ test "exists2 a" <| Array.exists2 (=)
+ [|1; 2; 3; 4; 5; 6|]
+ [|2; 3; 4; 5; 6; 6|]
+
+ test "exists2 b" <| not (Array.exists2 (=)
+ [|1; 2; 3; 4; 5; 6|]
+ [|2; 3; 4; 5; 6; 7|])
+
+let test_forall2 () =
+ test "forall2 a"
+ (Array.forall2 (=) [|1..10|] [|1..10|])
+
+ test "forall2_b" <| not
+ (Array.forall2 (=) [|1;2;3;4;5|] [|1;2;3;0;5|])
+
+let test_filter () =
+ test "filter a"
+ (Array.filter (fun x -> x % 2 = 0) [|0..100|] = [|0..+2..100|])
+
+ test "filter b"
+ (Array.filter (fun x -> false) [|0..100|] = [||])
+
+ test "filter c"
+ (Array.filter (fun x -> true) [|0..100|] = [|0..100|])
+
+
+let test_partition () =
+ let p1, p2 = Array.partition (fun x -> x % 2 = 0) [|0..100|]
+ test "partition"
+ (p1 = [|0..+2..100|] && p2 = [|1..+2..100|])
+
+let test_choose () =
+ test "choose"
+ (Array.choose (fun x -> if x % 2 = 0 then Some (x/2) else None) [|0..100|] = [|0..50|])
+
+let test_find () =
+ test "find a"
+ ([|1..100|] |> Array.find (fun x -> x > 50) = 51)
+
+ test "find b"
+ (try [|1..100|] |> Array.find (fun x -> x > 180) |> ignore; false
+ with _ -> true)
+
+module Array =
+ let findIndexi f (array : array<_>) =
+ let len = array.Length
+ let rec go n =
+ if n >= len then
+ failwith "fail"
+ elif f n array.[n] then
+ n
+ else
+ go (n+1)
+ go 0
+
+ let tryFindIndexi f (array : array<_>) =
+ let len = array.Length
+ let rec go n = if n >= len then None elif f n array.[n] then Some n else go (n+1)
+ go 0
+
+let test_findIndex () =
+ test "findIndex a"
+ (Array.findIndex (fun i -> i >= 4) [|0..10|] = 4)
+
+ test "findIndex b"
+ (try Array.findIndex (fun i -> i >= 20) [|0..10|] |> ignore; false
+ with _ -> true)
+
+ test "findIndexi a"
+ (Array.findIndexi (=) [|1; 2; 3; 3; 2; 1|] = 3)
+
+ test "findIndexi b"
+ (try Array.findIndexi (=) [|1..10|] |> ignore; false
+ with _ -> true)
+
+let test_tryfind () =
+ test "tryFind"
+ ([|1..100|] |> Array.tryFind (fun x -> x > 50) = Some 51)
+
+ test "tryFind b"
+ ([|1..100|] |> Array.tryFind (fun x -> x > 180) = None)
+
+ test "tryfind_index a"
+ (Array.tryFindIndex (fun x -> x = 4) [|0..10|] = Some 4)
+
+ test "tryfind_index b"
+ (Array.tryFindIndex (fun x -> x = 42) [|0..10|] = None)
+
+ test "tryFindIndexi a"
+ (Array.tryFindIndexi (=) [|1;2;3;4;4;3;2;1|] = Some 4)
+
+ test "tryFindIndexi b"
+ (Array.tryFindIndexi (=) [|1..10|] = None)
+
+let test_first () =
+ test "first a"
+ ([|1..100|] |> Array.tryPick (fun x -> if x > 50 then Some (x*x) else None) = Some (51*51))
+
+ test "first b"
+ ([|1..100|] |> Array.tryPick (fun x -> None) = None)
+
+ test "first c"
+ ([||] |> Array.tryPick (fun _ -> Some 42) = None)
+
+let test_sort () =
+
+ test "sort a" (Array.sort [||] = [||])
+ test "sort b" (Array.sort [|1|] = [|1|])
+ test "sort c" (Array.sort [|1;2|] = [|1;2|])
+ test "sort d" (Array.sort [|2;1|] = [|1;2|])
+ test "sort e" (Array.sort [|1..1000|] = [|1..1000|])
+ test "sort f" (Array.sort [|1000..-1..1|] = [|1..1000|])
+
+let test_sort_by () =
+
+ test "Array.sortBy a" (Array.sortBy int [||] = [||])
+ test "Array.sortBy b" (Array.sortBy int [|1|] = [|1|])
+ test "Array.sortBy c" (Array.sortBy int [|1;2|] = [|1;2|])
+ test "Array.sortBy d" (Array.sortBy int [|2;1|] = [|1;2|])
+ test "Array.sortBy e" (Array.sortBy int [|1..1000|] = [|1..1000|])
+ test "Array.sortBy f" (Array.sortBy int [|1000..-1..1|] = [|1..1000|])
+
+ let testGen s f =
+ test ("Array.sortBy a "+s) (Array.sortBy f [||] = [||])
+ test ("Array.sortBy b "+s) (Array.sortBy f [|1|] = [|1|])
+ test ("Array.sortBy c "+s) (Array.sortBy f [|1;2|] = [|1;2|])
+ test ("Array.sortBy d "+s) (Array.sortBy f [|2;1|] = [|1;2|])
+ test ("Array.sortBy e "+s) (Array.sortBy f [|1..1000|] = [|1..1000|])
+ test ("Array.sortBy f "+s) (Array.sortBy f [|1000..-1..1|] = [|1..1000|])
+
+ // All these projects from integers preserve the expected key ordering for the tests in 'testGen()'
+ testGen "int" int
+ testGen "uint32" uint32
+ testGen "int16" int16
+ testGen "uint16" uint16
+ testGen "int64" int64
+ testGen "uint64" uint64
+ testGen "nativeint" nativeint
+ testGen "unativeint" unativeint
+ testGen "float" float
+ testGen "float32" float32
+ testGen "decimal" decimal
+
+ test "Array.sortBy g" (Array.sortBy int [|"4";"2";"3";"1";"5"|] = [|"1";"2";"3";"4";"5"|])
+ test "Array.sortBy h" (Array.sortBy abs [|1;-2;5;-4;0;-6;3|] = [|0;1;-2;3;-4;5;-6|])
+ test "Array.sortBy i" (Array.sortBy String.length [|"a";"abcd";"ab";"";"abc"|] = [|"";"a";"ab";"abc";"abcd"|])
+
+
+let test_list_stableSortBy() =
+ for lo in 0 .. 100 do
+ for hi in lo .. 100 do
+ test (sprintf "vre9u0rejkn, lo = %d, hi = %d" lo hi) (List.sortBy snd [ for i in lo .. hi -> (i, i % 17) ] = [ for key in 0 .. 16 do for i in lo .. hi do if i % 17 = key then yield (i, i % 17) ])
+
+test_list_stableSortBy()
+
+
+[]
+type Key =
+ | Key of int * int
+ interface System.IComparable with
+ member x.CompareTo(yobj:obj) =
+ match yobj with
+ | :? Key as y ->
+ let (Key(y1,y2)) = y in
+ let (Key(x1,x2)) = x in
+ compare x2 y2
+ | _ -> failwith "failure"
+
+ override x.Equals(yobj) =
+ match yobj with
+ | :? Key as y ->
+ let (Key(y1,y2)) = y in
+ let (Key(x1,x2)) = x in
+ x2 = y2
+ | _ -> false
+
+ override x.GetHashCode() =
+ let (Key(x1,x2)) = x in
+ hash x2
+
+let test_list_stableSort() =
+ for lo in 0 .. 100 do
+ for hi in lo .. 100 do
+ test (sprintf "vre9u0rejkn, lo = %d, hi = %d" lo hi) (List.sort [ for i in lo .. hi -> Key(i, i % 17) ] = [ for key in 0 .. 16 do for i in lo .. hi do if i % 17 = key then yield Key(i, i % 17) ])
+
+test_list_stableSort()
+
+let test_list_stableSortByNonIntegerKey() =
+ for lo in 0 .. 100 do
+ for hi in lo .. 100 do
+ test (sprintf "vre9u0rejkn, lo = %d, hi = %d" lo hi) (List.sortBy (fun (Key(a,b)) -> Key(0,b)) [ for i in lo .. hi -> Key(i, i % 17) ] = [ for key in 0 .. 16 do for i in lo .. hi do if i % 17 = key then yield Key(i, i % 17) ])
+
+test_list_stableSortByNonIntegerKey()
+
+
+let test_zip () =
+ test "zip"
+ (Array.zip [|1..10|] [|1..10|] = [|for i in 1..10 -> i, i|])
+
+ let unzip1, unzip2 = Array.unzip <| [|for i in 1..10 -> i, i+1|]
+ test "unzip" (unzip1 = [|1..10|] && unzip2 = [|2..11|])
+
+let test_zip3 () =
+ test "zip3"
+ (Array.zip3 [|1..10|] [|1..10|] [|1..10|] = [|for i in 1..10 -> i, i, i|])
+
+ let unzip1, unzip2, unzip3 = Array.unzip3 <| [|for i in 1..10 -> i, i+1, i+2|]
+ test "unzip3" (unzip1 = [|1..10|] && unzip2 = [|2..11|] && unzip3 = [|3..12|])
+
+
+let test_rev () =
+ test "rev a"
+ (Array.rev [|0..100|] = [|100..-1 ..0|])
+
+ test "rev b"
+ (Array.rev [|1|] = [|1|])
+
+ test "rev c"
+ (Array.rev [||] = [||])
+
+ test "rev d"
+ (Array.rev [|1; 2|] = [|2; 1|])
+
+let test_sum () =
+ test "sum a" (Array.sum [||] = 0)
+ test "sum b" (Array.sum [|42|] = 42)
+ test "sum c" (Array.sum [|42;-21|] = 21)
+ test "sum d" (Array.sum [|1..1000|] = (1000*1001) / 2)
+ test "sum e" (Array.sum [|1.;2.;3.|] = 6.)
+ test "sum f" (Array.sum [|1.;2.;infinity;3.|] = infinity)
+
+let test_sum_by () =
+ test "sum_by a" (Array.sumBy int [||] = 0)
+ test "sum_by b" (Array.sumBy int [|42|] = 42)
+ test "sum_by c" (Array.sumBy int [|42;-21|] = 21)
+ test "sum_by d" (Array.sumBy int [|1..1000|] = (1000*1001) / 2)
+ test "sum_by e" (Array.sumBy float [|1.;2.;3.|] = 6.)
+ test "sum_by f" (Array.sumBy float [|1.;2.;infinity;3.|] = infinity)
+ test "sum_by g" (Array.sumBy abs [|1; -2; 3; -4|] = 10)
+ test "sum_by h" (Array.sumBy String.length [|"abcd";"efg";"hi";"j";""|] = 10)
+
+let test_average () =
+ test "average a1" (try Array.average ([||]: float array) |> ignore; false with :? System.ArgumentException -> true)
+ test "average a2" (try Array.average ([||]: float32 array) |> ignore; false with :? System.ArgumentException -> true)
+ test "average a3" (try Array.average ([||]: decimal array) |> ignore; false with :? System.ArgumentException -> true)
+ test "average a4" (Array.average [|0.|] = 0.)
+ test "average b" (Array.average [|4.|] = 4.)
+ test "average c" (Array.average [|4.;6.|] = 5.)
+
+ test "average_by a1" (try Array.averageBy id ([||]: float array) |> ignore; false with :? System.ArgumentException -> true)
+ test "average_by a2" (try Array.averageBy id ([||]: float32 array) |> ignore; false with :? System.ArgumentException -> true)
+ test "average_by a3" (try Array.averageBy id ([||]: decimal array) |> ignore; false with :? System.ArgumentException -> true)
+ test "average_by a4" (Array.averageBy float [|0..1000|] = 500.)
+ test "average_by b" (Array.averageBy (String.length >> float) [|"ab";"cdef"|] = 3.)
+
+let test_min () =
+ test "min a" (Array.min [|42|] = 42)
+ test "min b" (Array.min [|42;21|] = 21)
+ test "min c" (Array.min [|'a';'b'|] = 'a')
+
+ test "max a" (Array.max [|42|] = 42)
+ test "max b" (Array.max [|42;21|] = 42)
+ test "max c" (Array.max [|'a';'b'|] = 'b')
+
+let test_min_by () =
+ test "min_by a" (Array.minBy int [|42|] = 42)
+ test "min_by b" (Array.minBy abs [|-42;-21|] = -21)
+ test "min_by c" (Array.minBy int [|'a';'b'|] = 'a')
+
+ test "max_by a" (Array.maxBy int [|42|] = 42)
+ test "max_by b" (Array.maxBy abs [|-42;-21|] = -42)
+ test "max_by c" (Array.maxBy int [|'a';'b'|] = 'b')
+
+let test_seq () =
+ test "to_seq" (Array.ofSeq [1..100] = [|1..100|])
+ test "to_seq" ([|1..100|] |> Array.toSeq |> Array.ofSeq = [|1..100|])
+
+
+let test_zero_create () =
+ let arr = Array.zeroCreate 3 in
+ ignore (Array.set arr 0 4);
+ ignore (Array.set arr 1 3);
+ ignore (Array.set arr 2 2);
+ test "fewoih" (Array.get arr 0 = 4);
+ test "vvrew0" (Array.get arr 1 = 3);
+ test "vvrew0" (Array.get arr 2 = 2)
+
+let test_zero_create_2 () =
+ let arr = Array.zeroCreate 0 in
+ test "sdio2" (Array.length arr = 0)
+
+let test_init () =
+ let arr = Array.init 4 (fun x -> x + 1) in
+ test "test2927: sdvjk2" (Array.get arr 0 = 1);
+ test "test2927: cedkj" (Array.get arr 2 = 3)
+
+let test_init_empty () =
+ let arr = Array.init 0 (fun x -> x + 1) in
+ test "test2927: sdvjk2" (Array.length arr = 0)
+
+let test_append () =
+ let arr = Array.append ( [| "4";"3" |]) ( [| "2" |]) in
+ test "test2928: sdvjk2" (Array.get arr 0 = "4");
+ test "test2928: cedkj" (Array.get arr 2 = "2");
+ test "test2928: cedkj" (Array.length arr = 3)
+
+let test_append_empty () =
+ let arr = Array.append ( [| |]) ( [| |]) in
+ test "test2928: cedkj" (Array.length arr = 0)
+
+let test_fill () =
+ let arr = [| "4";"3";"2" |] in
+ Array.fill arr 1 2 "1";
+ test "test2929: sdvjk2" (Array.get arr 0 = "4");
+ test "test2929: cedkj" (Array.get arr 2 = "1")
+
+let test_copy () =
+ let arr = [| "4";"3";"2" |] in
+ let arr2 = Array.copy arr in
+ test "test2929: sdvjk2" (Array.get arr2 0 = "4");
+ test "test2929: cedkj" (Array.get arr2 2 = "2");
+ test "feio" (not (LanguagePrimitives.PhysicalEquality arr arr2))
+
+let test_blit () =
+ let arr = [| "4";"3";"2";"0" |] in
+ let arr2 = [| "4";"3";"-1"; "-1" |] in
+ Array.blit arr 1 arr2 2 2;
+ test "test2930: sdvjk2" (Array.get arr2 0 = "4");
+ test "test2930: cedkj" (Array.get arr2 1 = "3");
+ test "test2930: ceddwkj" (Array.get arr2 2 = "3");
+ test "test2930: ceqwddkj" (Array.get arr2 3 = "2")
+
+let test_of_list () =
+ let arr = Array.ofList [ "4";"3";"2";"0" ] in
+ test "test2931: sdvjk2" (Array.get arr 0 = "4");
+ test "test2931: cedkj" (Array.get arr 1 = "3");
+ test "test2931: ceddwkj" (Array.get arr 2 = "2");
+ test "test2931: ceqwddkj" (Array.get arr 3 = "0")
+
+let test_to_list () =
+ test "test2932" (Array.toList ( [| "4";"3";"2";"0" |]) = [ "4";"3";"2";"0" ])
+
+let test_to_list_of_list () =
+ test "test2933" (Array.toList (Array.ofList [ "4";"3";"2";"0" ]) = [ "4";"3";"2";"0" ])
+
+let test_fold_left () =
+ let arr = Array.ofList [ 4;3;2;1 ] in
+ test "test2931: sdvjk2few" (Array.fold (fun x y -> x/y) (5*4*3*2*1) arr = 5)
+
+let test_fold_right () =
+ let arr = Array.ofList [ 4;3;2;1 ] in
+ test "test2931: sdvjk2ew" (Array.foldBack (fun y x -> x/y) arr (6*4*3*2*1) = 6)
+
+let test_reduce_left () =
+ test "test2931: array.reduce" (Array.reduce (fun x y -> x/y) [|5*4*3*2; 4;3;2;1|] = 5)
+
+let test_reduce_right () =
+ let arr = Array.ofList [ 4;3;2;1;5 ] in
+ test "test2931: array.reduceBack" (Array.reduceBack (fun y x -> x/y) [|4;3;2;1; 5*4*3*2|] = 5)
+
+
+let _ = test_make_get_set_length ()
+let _ = test_const ()
+let _ = test_const_empty ()
+let _ = test_map ()
+let _ = test_mapi ()
+let _ = test_iter ()
+let _ = test_iteri ()
+let _ = test_mapi ()
+let _ = test_isEmpty ()
+let _ = test_create ()
+let _ = test_concat ()
+let _ = test_sub ()
+let _ = test_fold2 ()
+let _ = test_foldBack2 ()
+let _ = test_scan ()
+let _ = test_iter2 ()
+let _ = test_iteri2 ()
+let _ = test_iter ()
+let _ = test_map2 ()
+let _ = test_mapi2 ()
+let _ = test_exists ()
+let _ = test_forall ()
+let _ = test_iter ()
+let _ = test_exists2 ()
+let _ = test_forall2 ()
+let _ = test_filter ()
+let _ = test_partition ()
+let _ = test_choose ()
+let _ = test_find ()
+let _ = test_findIndex ()
+let _ = test_tryfind ()
+let _ = test_first ()
+let _ = test_sort ()
+let _ = test_sort_by ()
+let _ = test_zip ()
+let _ = test_zip3 ()
+let _ = test_rev ()
+let _ = test_sum ()
+let _ = test_sum_by ()
+let _ = test_average ()
+let _ = test_min ()
+let _ = test_min_by ()
+let _ = test_seq ()
+let _ = test_zero_create ()
+let _ = test_zero_create_2 ()
+let _ = test_append ()
+let _ = test_append_empty ()
+let _ = test_init ()
+let _ = test_init_empty ()
+let _ = test_fill ()
+let _ = test_blit ()
+let _ = test_of_list ()
+let _ = test_to_list ()
+let _ = test_to_list_of_list ()
+let _ = test_copy ()
+let _ = test_iter ()
+let _ = test_iteri ()
+let _ = test_fold_left ()
+let _ = test_fold_right ()
+let _ = test_reduce_left ()
+let _ = test_reduce_right ()
+
+module Array2Tests = begin
+
+ let test_make_get_set_length () =
+ let arr = Array2D.create 3 4 0 in
+ test "fewoih1" (Array2D.get arr 0 0 = 0);
+ test "fewoih2" (Array2D.get arr 0 1 = 0);
+ test "vvrew03" (Array2D.get arr 2 2 = 0);
+ test "vvrew04" (Array2D.get arr 2 3 = 0);
+
+ ignore (Array2D.set arr 0 2 4);
+ test "vsdiuvs5" (Array2D.get arr 0 2 = 4);
+ arr.[0,2] <- 2;
+
+ test "vsdiuvs6" (arr.[0,2] = 2);
+ test "vropivrwe7" (Array2D.length1 arr = 3);
+ test "vropivrwe8" (Array2D.length2 arr = 4)
+
+ let a = Array2D.init 10 10 (fun i j -> i,j)
+ let b = Array2D.init 2 2 (fun i j -> i+1,j+1)
+ //test "a2_sub"
+ // (Array2D.sub a 1 1 2 2 = b)
+
+
+ Array2D.blit b 0 0 a 0 0 2 2
+ //test "a2_blit"
+ // (Array2D.sub a 0 0 2 2 = b)
+
+ let _ = test_make_get_set_length ()
+
+
+end
+
+module ArrayNonZeroBasedTestsSlice =
+ let runTest () =
+ let arr = (Array2D.initBased 5 4 3 2 (fun i j -> (i,j)))
+ test "fewoih1" (arr.[6,*] = [|(6, 4); (6, 5)|])
+ test "fewoih2" (arr.[*,*].[1,*] = [|(6, 4); (6, 5)|])
+ test "fewoih3" (arr.[*,5] = [|(5, 5); (6, 5); (7, 5)|])
+ test "fewoih4" (arr.[*,*].[*,1] = [|(5, 5); (6, 5); (7, 5)|])
+ test "fewoih5" (arr.GetLowerBound(0) = 5)
+ test "fewoih6" (arr.GetLowerBound(1) = 4)
+ test "fewoih7" (arr.[*,*].GetLowerBound(0) = 0)
+ test "fewoih8" (arr.[*,*].GetLowerBound(1) = 0)
+ test "fewoih9" (arr.[*,*].[0..,1] = [|(5, 5); (6, 5); (7, 5)|])
+ test "fewoih10" (arr.[*,*].[1..,1] = [|(6, 5); (7, 5)|])
+ let arr2d =
+ let arr = Array2D.zeroCreateBased 5 4 3 2
+ for i in 5..7 do for j in 4..5 do arr.[i,j] <- (i,j)
+ arr
+ let arr2d2 =
+ let arr = Array2D.zeroCreate 3 2
+ for i in 0..2 do for j in 0..1 do arr.[i,j] <- (j,i)
+ arr
+ test "fewoih11" (arr2d.[6..6,5] = [|(6, 5)|])
+ test "fewoih11" (arr2d.[..6,5] = [|(5, 5); (6, 5)|])
+ test "fewoih11" (arr2d.[6..,5] = [|(6, 5); (7, 5)|])
+ test "fewoih12" (arr2d.[*,*].[1..,1] = [|(6, 5); (7, 5)|])
+ arr2d.[*,*] <- arr2d2
+ test "fewoih13" (arr2d.[*,*].[0..0,1] = [|(1, 0)|])
+ test "fewoih13" (arr2d.[*,*].[1..,1] = [|(1, 1); (1, 2)|])
+ test "fewoih13" (arr2d.[*,*].[1,1..] = [|(1, 1)|])
+ test "fewoih13" (arr2d.[*,*].[1,0..0] = [|(0, 1)|])
+ let arr3d =
+ let arr = System.Array.CreateInstance(typeof, [| 3;2;1 |], [|5;4;3|]) :?> (int*int*int)[,,]
+ for i in 5..7 do for j in 4..5 do for k in 3..3 do arr.[i,j,k] <- (i,j,k)
+ arr
+ let arr3d2 =
+ let arr = System.Array.CreateInstance(typeof, [| 3;2;1 |]) :?> (int*int*int)[,,]
+ for i in 0..2 do for j in 0..1 do for k in 0..0 do arr.[i,j,k] <- (k,j,i)
+ arr
+
+ test "fewoih14" (arr3d.[5,4,3] = (5,4,3))
+ test "fewoih15" (arr3d.[*,*,*].[0,0,0] = (5,4,3))
+ arr3d.[*,*,*] <- arr3d2
+ test "fewoih16" (arr3d.[5,4,3] = (0,0,0))
+ test "fewoih16" (arr3d.[5,5,3] = (0,1,0))
+ test "fewoih16" (arr3d.[6,5,3] = (0,1,1))
+ let _ = runTest()
+
+module Array3Tests = begin
+
+ let test_make_get_set_length () =
+ let arr = Array3D.create 3 4 5 0 in
+ test "fewoih1" (Array3D.get arr 0 0 0 = 0);
+ test "fewoih2" (Array3D.get arr 0 1 0 = 0);
+ test "vvrew03" (Array3D.get arr 2 2 2 = 0);
+ test "vvrew04" (Array3D.get arr 2 3 4 = 0);
+ ignore (Array3D.set arr 0 2 3 4);
+ test "vsdiuvs5" (Array3D.get arr 0 2 3 = 4);
+ arr.[0,2,3] <- 2;
+ test "vsdiuvs6" (arr.[0,2,3] = 2);
+ arr.[0,2,3] <- 3;
+ test "vsdiuvs" (arr.[0,2,3] = 3);
+ test "vropivrwe7" (Array3D.length1 arr = 3);
+ test "vropivrwe8" (Array3D.length2 arr = 4);
+ test "vropivrwe9" (Array3D.length3 arr = 5)
+
+ let _ = test_make_get_set_length ()
+
+end
+
+module Array4Tests = begin
+
+ let test_make_get_set_length () =
+ let arr = Array4D.create 3 4 5 6 0 in
+ arr.[0,2,3,4] <- 2;
+ test "vsdiuvsq" (arr.[0,2,3,4] = 2);
+ arr.[0,2,3,4] <- 3;
+ test "vsdiuvsw" (arr.[0,2,3,4] = 3);
+ test "vsdiuvsw" (Array4D.get arr 0 2 3 4 = 3);
+ Array4D.set arr 0 2 3 4 5;
+ test "vsdiuvsw" (Array4D.get arr 0 2 3 4 = 5);
+ test "vropivrwee" (Array4D.length1 arr = 3);
+ test "vropivrwer" (Array4D.length2 arr = 4);
+ test "vropivrwet" (Array4D.length3 arr = 5)
+ test "vropivrwey" (Array4D.length4 arr = 6)
+
+ let test_init () =
+ let arr = Array4D.init 3 4 5 6 (fun i j k m -> i+j+k+m) in
+ test "vsdiuvs1" (arr.[0,2,3,4] = 9);
+ test "vsdiuvs2" (arr.[0,2,3,3] = 8);
+ test "vsdiuvs3" (arr.[0,0,0,0] = 0);
+ arr.[0,2,3,4] <- 2;
+ test "vsdiuvs4" (arr.[0,2,3,4] = 2);
+ arr.[0,2,3,4] <- 3;
+ test "vsdiuvs5" (arr.[0,2,3,4] = 3);
+ test "vropivrwe1" (Array4D.length1 arr = 3);
+ test "vropivrwe2" (Array4D.length2 arr = 4);
+ test "vropivrwe3" (Array4D.length3 arr = 5)
+ test "vropivrwe4" (Array4D.length4 arr = 6)
+
+ let _ = test_make_get_set_length ()
+ let _ = test_init ()
+
+end
+
+// nb. PERF TESTING ONLY WITH v2.0 (GENERICS)
+#if PERF
+let test_map_perf () =
+ let arr1 = [| 4;3;2 |] in
+ let res = ref (Array.map (fun x -> x + 1) arr1) in
+ for i = 1 to 20000000 do
+ res := Array.map (fun x -> x + 1) arr1
+ done;
+ test "test2927: sdvjk2" (Array.get !res 0 = 5)
+
+let _ = test_map_perf()
+#endif
+
+module SeqCacheAllTest =
+ let s2 =
+ let count = ref 0
+ let s = Seq.cache (seq { for i in 0 .. 10 -> (count.Value <- count.Value + 1; i) }) :> seq<_>
+ let test0 = (count.Value = 0)
+ let e1 = s.GetEnumerator()
+ let test1 = (count.Value = 0)
+ printf "test1 = %b\n" test1;
+ for i = 1 to 1 do (e1.MoveNext() |> ignore; e1.Current |> ignore)
+ let test2 = (count.Value = 1)
+ printf "test2 = %b\n" test2;
+ let e2 = s.GetEnumerator()
+ for i = 1 to 5 do (e2.MoveNext() |> ignore; e2.Current |> ignore)
+ let test3 = (count.Value = 5)
+ printf "test3 = %b\n" test3;
+ let e3 = s.GetEnumerator()
+ for i = 1 to 5 do (e3.MoveNext() |> ignore; e3.Current |> ignore)
+ let test4 = (count.Value = 5)
+ printf "test4 = %b\n" test4;
+ let e4 = s.GetEnumerator()
+ for i = 1 to 3 do (e4.MoveNext() |> ignore; e4.Current |> ignore)
+ let test5 = (count.Value = 5)
+ printf "test5 = %b\n" test5;
+
+ let test6 = [ for x in s -> x ] = [ 0 .. 10 ]
+ printf "test6 = %b\n" test6;
+ for x in s do ()
+ let test7 = (count.Value = 11)
+ let test8 = [ for x in s -> x ] = [ 0 .. 10 ]
+ let test9 = count.Value = 11
+ test "test0" test0
+ test "test1" test1
+ test "test2" test2
+ test "test3" test3
+ test "test4" test4
+ test "test5" test5
+ test "test6" test6
+ test "test7" test7
+ test "test8" test8
+ test "test9" test9
+
+
+module ArrayStructMutation =
+ module Array1D =
+ module Test1 =
+ []
+ type T =
+ val mutable i : int
+ let a = Array.create 10 Unchecked.defaultof
+ a.[0].i <- 27
+ check "wekvw0301" 27 a.[0].i
+
+
+ module Test2 =
+
+ []
+ type T =
+ val mutable public i : int
+ member public this.Set i = this.i <- i
+ let a = Array.create 10 Unchecked.defaultof
+ a.[0].Set 27
+ a.[2].Set 27
+ check "wekvw0302" 27 a.[0].i
+ check "wekvw0303" 27 a.[2].i
+
+ module Array2D =
+ module Test1 =
+ []
+ type T =
+ val mutable i : int
+ let a = Array2D.create 10 10 Unchecked.defaultof
+ a.[0,0].i <- 27
+ check "wekvw0304" 27 a.[0,0].i
+
+
+ module Test2 =
+
+ []
+ type T =
+ val mutable public i : int
+ member public this.Set i = this.i <- i
+ let a = Array2D.create 10 10 Unchecked.defaultof
+ a.[0,0].Set 27
+ a.[0,2].Set 27
+ check "wekvw0305" 27 a.[0,0].i
+ check "wekvw0306" 27 a.[0,2].i
+
+
+ module Array3D =
+ module Test1 =
+ []
+ type T =
+ val mutable i : int
+ let a = Array3D.create 10 10 10 Unchecked.defaultof
+ a.[0,0,0].i <- 27
+ a.[0,2,3].i <- 27
+ check "wekvw0307" 27 a.[0,0,0].i
+ check "wekvw0308" 27 a.[0,2,3].i
+
+
+ module Test2 =
+
+ []
+ type T =
+ val mutable public i : int
+ member public this.Set i = this.i <- i
+ let a = Array3D.create 10 10 10 Unchecked.defaultof
+ a.[0,0,0].Set 27
+ a.[0,2,3].Set 27
+ check "wekvw0309" 27 a.[0,0,0].i
+ check "wekvw030q" 27 a.[0,2,3].i
+
+ module Array4D =
+ module Test1 =
+ []
+ type T =
+ val mutable i : int
+ let a = Array4D.create 10 10 10 10 Unchecked.defaultof
+ a.[0,0,0,0].i <- 27
+ a.[0,2,3,4].i <- 27
+ check "wekvw030w" 27 a.[0,0,0,0].i
+ check "wekvw030e" 27 a.[0,2,3,4].i
+
+
+ module Test2 =
+
+ []
+ type T =
+ val mutable public i : int
+ member public this.Set i = this.i <- i
+ let a = Array4D.create 10 10 10 10 Unchecked.defaultof
+ a.[0,0,0,0].Set 27
+ a.[0,2,3,4].Set 27
+ check "wekvw030r" 27 a.[0,0,0,0].i
+ check "wekvw030t" 27 a.[0,2,3,4].i
+
+module LoopTests =
+ let loop3 a N =
+ let mutable x = 0 in
+ // In this loop, the types of 'a' and 'N' are not known prior to the loop
+ for i in (min a a) .. N do
+ x <- x + 1
+ done;
+ check (sprintf "clkrerev90-%A" (a,N)) x (if N < a then 0 else N - a + 1)
+
+
+ do loop3 0 10
+ do loop3 0 0
+ do loop3 0 -1
+ do loop3 10 9
+
+ let loop4 a N =
+ let mutable x = 0 in
+ for i in OperatorIntrinsics.RangeInt32 a 1 N do
+ x <- x + 1
+ done;
+ check (sprintf "clkrerev91-%A" (a,N)) x (if N < a then 0 else N - a + 1)
+
+ do loop4 0 10
+ do loop4 0 0
+ do loop4 0 -1
+ do loop4 10 9
+
+ let loop5 a N =
+ let mutable x = 0 in
+ // In this loop, the types of 'a' and 'N' are not known prior to the loop
+ for i in (min a a) .. 2 .. (min N N) do
+ x <- x + 1
+ done;
+ check (sprintf "clkrerev92-%A" (a,N)) x ((if N < a then 0 else N - a + 2) / 2)
+
+ do loop5 0 10
+ do loop5 0 0
+ do loop5 0 -1
+ do loop5 10 9
+
+
+ let loop6 a N =
+ let mutable x = 0 in
+ // In this loop, the types of 'a' and 'N' are not known prior to the loop
+ for i in (min a a) .. 200 .. (min N N) do
+ x <- x + 1
+ done;
+ check (sprintf "clkrerev93-%A" (a,N)) x ((if N < a then 0 else N - a + 200) / 200)
+
+ do loop6 0 10
+ do loop6 0 0
+ do loop6 0 -1
+ do loop6 10 9
+
+
+ let loop7 a step N =
+ let mutable x = 0 in
+ // In this loop, the types of 'a' and 'N' are not known prior to the loop
+ for i in (min a a) .. step .. (min N N) do
+ x <- x + 1
+ done;
+ check (sprintf "clkrerev95-%A" (a,step,N)) x (if step < 0 then (if a < N then 0 else (a - N + abs step) / abs step) else (if N < a then 0 else N - a + step) / step)
+
+ do loop7 0 1 10
+ do loop7 0 -1 0
+ do loop7 0 2 -1
+ do loop7 10 -2 9
+
+ let loop8 a N =
+ let mutable x = 0 in
+ // In this loop, the types of 'a' and 'N' are not known prior to the loop
+ for i in (min a a) .. -1 .. (min N N) do
+ x <- x + 1
+ done;
+ check (sprintf "clkrerev96-%A" (a,N)) x (abs (if a < N then 0 else (a - N + 1) / 1))
+
+ do loop8 0 10
+ do loop8 0 0
+ do loop8 0 -1
+ do loop8 10 9
+
+// Some more adhoc testing - the use of 'min' gives rise to a let binding in optimized code
+module MoreLoopTestsWithLetBindings =
+ let loop3 a N =
+ let mutable x = 0 in
+ // In this loop, the types of 'a' and 'N' are not known prior to the loop
+ for i in (min a a) .. (min N N) do
+ x <- x + 1
+ done;
+ check (sprintf "ffclkrerev90-%A" (a,N)) x (if N < a then 0 else N - a + 1)
+
+
+ do loop3 0 10
+ do loop3 0 0
+ do loop3 0 -1
+ do loop3 10 9
+ do for start in -3 .. 3 do for finish in -3 .. 3 do loop3 start finish
+
+ let loop4 a N =
+ let mutable x = 0 in
+ for i in OperatorIntrinsics.RangeInt32 a 1 N do
+ x <- x + 1
+ done;
+ check (sprintf "ffclkrerev91-%A" (a,N)) x (if N < a then 0 else N - a + 1)
+
+ do loop4 0 10
+ do loop4 0 0
+ do loop4 0 -1
+ do loop4 10 9
+ do for start in -3 .. 3 do for finish in -3 .. 3 do loop4 start finish
+
+ let loop5 a N =
+ let mutable x = 0 in
+ // In this loop, the types of 'a' and 'N' are not known prior to the loop
+ for i in (min a a) .. 2 .. (min N N) do
+ x <- x + 1
+ done;
+ check (sprintf "ffclkrerev92-%A" (a,N)) x ((if N < a then 0 else N - a + 2) / 2)
+
+ do loop5 0 10
+ do loop5 0 0
+ do loop5 0 -1
+ do loop5 10 9
+ do for start in -3 .. 3 do for finish in -3 .. 3 do loop5 start finish
+
+
+ let loop6 a N =
+ let mutable x = 0 in
+ // In this loop, the types of 'a' and 'N' are not known prior to the loop
+ for i in (min a a) .. 200 .. (min N N) do
+ x <- x + 1
+ done;
+ check (sprintf "ffclkrerev93-%A" (a,N)) x ((if N < a then 0 else N - a + 200) / 200)
+
+ do loop6 0 10
+ do loop6 0 0
+ do loop6 0 -1
+ do loop6 10 9
+ do for start in -3 .. 3 do for finish in -3 .. 3 do loop6 start finish
+
+
+ let loop7 a step N =
+ let mutable x = 0 in
+ // In this loop, the types of 'a' and 'N' are not known prior to the loop
+ for i in (min a a) .. step .. (min N N) do
+ x <- x + 1
+ done;
+ check (sprintf "ffclkrerev95-%A" (a,step,N)) x (if step < 0 then (if a < N then 0 else (a - N + abs step) / abs step) else (if N < a then 0 else N - a + step) / step)
+
+ do loop7 0 1 10
+ do loop7 0 -1 0
+ do loop7 0 2 -1
+ do loop7 10 -2 9
+ do for start in -3 .. 3 do for finish in -3 .. 3 do for step in [-2; -1; 1; 2] do loop7 start step finish
+
+ let loop8 a N =
+ let mutable x = 0 in
+ // In this loop, the types of 'a' and 'N' are not known prior to the loop
+ for i in (min a a) .. -1 .. (min N N) do
+ x <- x + 1
+ done;
+ check (sprintf "ffclkrerev96-%A" (a,N)) x (abs (if a < N then 0 else (a - N + 1) / 1))
+
+ do loop8 0 10
+ do loop8 0 0
+ do loop8 0 -1
+ do loop8 10 9
+ do for start in -3 .. 3 do for finish in -3 .. 3 do loop8 start finish
+
+module bug872632 =
+ type MarkerStyle =
+ | None = 0
+ | Square = 1
+ | Circle = 2
+ | Diamond = 3
+ | Triangle = 4
+ | Triangle1 = 10
+ | Cross = 5
+ | Star4 = 6
+ | Star5 = 7
+ | Star6 = 8
+ | Star10 = 9
+
+
+
+ module Foo =
+ let x = [|
+ MarkerStyle.Circle
+ MarkerStyle.Cross
+ MarkerStyle.Star6
+ MarkerStyle.Diamond
+ MarkerStyle.Square
+ MarkerStyle.Star10
+ MarkerStyle.Triangle
+ MarkerStyle.Triangle1
+ |]
+
+ do check "bug872632" Foo.x.Length 8
+
+module CheckUnionTypesAreSealed =
+ open System
+#if NETCOREAPP
+ open System.Reflection
+ type System.Type with
+ member this.IsSealed
+ with get () = this.GetTypeInfo().IsSealed
+#endif
+
+ do check "vwllfewlkefw1" (typedefof>.IsSealed) true
+ do check "vwllfewlkefw2" (typedefof