未验证 提交 f7633a7c 编写于 作者: D dotnet bot 提交者: GitHub

Merge pull request #13056 from dotnet/merges/main-to-release/dev17.3

Merge main to release/dev17.3
......@@ -132,19 +132,26 @@ This only works on Windows/.NETStandard framework, so changing this from any oth
## Updating baselines in tests
Some tests use "baseline" files. There is sometimes a way to update these baselines en-masse in your local build,
useful when some change affects many baselines. For example, in the 'fsharpqa' tests the baselines
useful when some change affects many baselines. For example, in the `fsharpqa` and `FSharp.Compiler.ComponentTests` tests the baselines
are updated using scripts or utilities that allow the following environment variable to be set:
```
Windows:
```shell
set TEST_UPDATE_BSL=1
```
Linux/macOS:
```shell
export TEST_UPDATE_BSL=1
```
## Developing the F# tools for Visual Studio
As you would expect, doing this requires both Windows and Visual Studio are installed.
See (DEVGUIDE.md#Developing on Windows) for instructions to install what is needed; it's the same prerequisites.
See [Developing on Windows](#Developing-on-Windows) for instructions to install what is needed; it's the same prerequisites.
### Quickly see your changes locally
......@@ -158,7 +165,7 @@ Alternatively, you can do this entirely via the command line if you prefer that:
devenv.exe /rootsuffix RoslynDev
```
### Install your changes into a current Visual Studio installation
### Deploy your changes into a current Visual Studio installation
If you'd like to "run with your changes", you can produce a VSIX and install it into your current Visual Studio instance:
......@@ -169,10 +176,6 @@ VSIXInstaller.exe artifacts\VSSetup\Release\VisualFSharpDebug.vsix
It's important to use `Release` if you want to see if your changes have had a noticeable performance impact.
### Performance and debugging
Use the `Debug` configuration to test your changes locally. It is the default. Do not use the `Release` configuration! Local development and testing of Visual Studio tooling is not designed for the `Release` configuration.
### Troubleshooting a failed build of the tools
You may run into an issue with a somewhat difficult or cryptic error message, like:
......@@ -188,6 +191,165 @@ To fix this, delete these folders:
Where `<version>` corresponds to the latest Visual Studio version on your machine.
## Performance and debugging
Use the `Debug` configuration to test your changes locally. It is the default. Do not use the `Release` configuration! Local development and testing of Visual Studio tooling is not designed for the `Release` configuration.
### Writing and running benchmarks
Existing compiler benchmarks can be found in `tests\benchmarks\`.
### Benchmarking and profiling the compiler
**NOTE:** When running benchmarks or profiling compiler, and comparing results with upstream version, make sure:
* Always build both versions of compiler/FCS from source and not use pre-built binaries from SDK (SDK binaries are crossgen'd, which can affect performance).
* To run `Release` build of compiler/FCS.
### Example benchmark setup using [BenchmarkDotNet](https://github.com/dotnet/BenchmarkDotNet)
1. Perform a clean build of the compiler and FCS from source (as described in this document, build can be done with `-noVisualStudio` in case if FCS/FSharp.Core is being benchmarked/profiled).
2. Create a benchmark project (in this example, the project will be created in `tests\benchmarks\`).
```shell
cd tests\benchmarks
dotnet new console -o FcsBench --name FcsBench -lang F#
```
3. Add needed packages and project references.
```shell
cd FcsBench
dotnet add package BenchmarkDotNet
dotnet add reference ..\..\..\src\fsharp\FSharp.Compiler.Service\FSharp.Compiler.Service.fsproj
```
4. Additionally, if you want to test changes to the FSharp.Core
```shell
dotnet add reference ..\..\..\src\fsharp\FSharp.Core\FSharp.Core.fsproj
```
> as well as the following property have to be added to `FcsBench.fsproj`:
```xml
<PropertyGroup>
<DisableImplicitFSharpCoreReference>true</DisableImplicitFSharpCoreReference>
</PropertyGroup>
```
5. Add a new benchmark for FCS/FSharp.Core by editing `Program.fs`.
```fsharp
open System.IO
open FSharp.Compiler.CodeAnalysis
open FSharp.Compiler.Diagnostics
open FSharp.Compiler.Text
open BenchmarkDotNet.Attributes
open BenchmarkDotNet.Running
[<MemoryDiagnoser>]
type CompilerService() =
let mutable checkerOpt = None
let mutable sourceOpt = None
let parsingOptions =
{
SourceFiles = [|"CheckExpressions.fs"|]
ConditionalDefines = []
ErrorSeverityOptions = FSharpDiagnosticOptions.Default
LangVersionText = "default"
IsInteractive = false
LightSyntax = None
CompilingFsLib = false
IsExe = false
}
[<GlobalSetup>]
member _.Setup() =
match checkerOpt with
| None ->
checkerOpt <- Some(FSharpChecker.Create(projectCacheSize = 200))
| _ -> ()
match sourceOpt with
| None ->
sourceOpt <- Some <| SourceText.ofString(File.ReadAllText("""C:\Users\vlza\code\fsharp\src\fsharp\CheckExpressions.fs"""))
| _ -> ()
[<Benchmark>]
member _.ParsingTypeCheckerFs() =
match checkerOpt, sourceOpt with
| None, _ -> failwith "no checker"
| _, None -> failwith "no source"
| Some(checker), Some(source) ->
let results = checker.ParseFile("CheckExpressions.fs", source, parsingOptions) |> Async.RunSynchronously
if results.ParseHadErrors then failwithf "parse had errors: %A" results.Diagnostics
[<IterationCleanup(Target = "ParsingTypeCheckerFs")>]
member _.ParsingTypeCheckerFsSetup() =
match checkerOpt with
| None -> failwith "no checker"
| Some(checker) ->
checker.InvalidateAll()
checker.ClearLanguageServiceRootCachesAndCollectAndFinalizeAllTransients()
checker.ParseFile("dummy.fs", SourceText.ofString "dummy", parsingOptions) |> Async.RunSynchronously |> ignore
[<EntryPoint>]
let main _ =
BenchmarkRunner.Run<CompilerService>() |> ignore
0
```
> For more detailed information about available BenchmarkDotNet options, please refer to [BenchmarkDotNet Documentation](https://benchmarkdotnet.org/articles/overview.html).
6. Build and run the benchmark.
```shell
dotnet build -c Release
dotnet run -c Release
```
7. You can find results in `.\BenchmarkDotNet.Artifacts\results\` in the current benchmark project directory.
```shell
> ls .\BenchmarkDotNet.Artifacts\results\
Directory: C:\Users\vlza\code\fsharp\tests\benchmarks\FcsBench\BenchmarkDotNet.Artifacts\results
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 4/25/2022 1:42 PM 638 Program.CompilerService-report-github.md
-a--- 4/25/2022 1:42 PM 1050 Program.CompilerService-report.csv
-a--- 4/25/2022 1:42 PM 1169 Program.CompilerService-report.html
```
> *-report-github.md can be used to post benchmark results to GitHub issue/PR/discussion or RFC.
>
>*-report.csv can be used for comparison purposes.
**Example output:**
``` ini
BenchmarkDotNet=v0.13.1, OS=Windows 10.0.25102
Intel Core i7-8750H CPU 2.20GHz (Coffee Lake), 1 CPU, 12 logical and 6 physical cores
.NET SDK=6.0.200
[Host] : .NET 6.0.3 (6.0.322.12309), X64 RyuJIT DEBUG
Job-GDIBXX : .NET 6.0.3 (6.0.322.12309), X64 RyuJIT
InvocationCount=1 UnrollFactor=1
```
| Method | Mean | Error | StdDev | Median | Gen 0 | Gen 1 | Allocated |
|--------------------- |---------:|--------:|--------:|---------:|----------:|----------:|----------:|
| ParsingTypeCheckerFs | 199.4 ms | 3.84 ms | 9.78 ms | 195.5 ms | 4000.0000 | 1000.0000 | 28 MB |
8. Repeat for any number of changes you would like to test.
9. **Optionally:** benchmark code and results can be included as part of the PR for future reference.
## Additional resources
The primary technical guide to the core compiler code is [The F# Compiler Technical Guide](https://github.com/dotnet/fsharp/blob/main/docs/index.md). Please read and contribute to that guide.
......
......@@ -8,9 +8,9 @@
</Dependency>
</ProductDependencies>
<ToolsetDependencies>
<Dependency Name="Microsoft.DotNet.Arcade.Sdk" Version="7.0.0-beta.22222.4">
<Dependency Name="Microsoft.DotNet.Arcade.Sdk" Version="7.0.0-beta.22225.6">
<Uri>https://github.com/dotnet/arcade</Uri>
<Sha>5f04b602a86b74f6cdd12f48aca2d1868e6425f3</Sha>
<Sha>5145e86df0c491e082b589aa31d69eea300adc02</Sha>
<SourceBuild RepoName="arcade" ManagedOnly="true" />
</Dependency>
</ToolsetDependencies>
......
......@@ -64,7 +64,7 @@ try {
$GlobalJson.tools | Add-Member -Name "vs" -Value (ConvertFrom-Json "{ `"version`": `"16.5`" }") -MemberType NoteProperty
}
if( -not ($GlobalJson.tools.PSObject.Properties.Name -match "xcopy-msbuild" )) {
$GlobalJson.tools | Add-Member -Name "xcopy-msbuild" -Value "16.10.0-preview2" -MemberType NoteProperty
$GlobalJson.tools | Add-Member -Name "xcopy-msbuild" -Value "17.1.0" -MemberType NoteProperty
}
if ($GlobalJson.tools."xcopy-msbuild".Trim() -ine "none") {
$xcopyMSBuildToolsFolder = InitializeXCopyMSBuild $GlobalJson.tools."xcopy-msbuild" -install $true
......
......@@ -365,8 +365,8 @@ function InitializeVisualStudioMSBuild([bool]$install, [object]$vsRequirements =
# If the version of msbuild is going to be xcopied,
# use this version. Version matches a package here:
# https://dev.azure.com/dnceng/public/_packaging?_a=package&feed=dotnet-eng&package=RoslynTools.MSBuild&protocolType=NuGet&version=16.10.0-preview2&view=overview
$defaultXCopyMSBuildVersion = '16.10.0-preview2'
# https://dev.azure.com/dnceng/public/_packaging?_a=package&feed=dotnet-eng&package=RoslynTools.MSBuild&protocolType=NuGet&version=17.1.0&view=overview
$defaultXCopyMSBuildVersion = '17.1.0'
if (!$vsRequirements) { $vsRequirements = $GlobalJson.tools.vs }
$vsMinVersionStr = if ($vsRequirements.version) { $vsRequirements.version } else { $vsMinVersionReqdStr }
......
......@@ -17,7 +17,7 @@
"perl": "5.32.1.1"
},
"msbuild-sdks": {
"Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.22222.4",
"Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.22225.6",
"Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19069.2"
}
}
......@@ -3,5 +3,3 @@
//<Expects id="FS0534" status="error" span="(5,1)">A module abbreviation must be a simple name, not a path</Expects>
module MS.FS.Co.L = Microsoft.FSharp.Collections.List
exit 1
......@@ -11,6 +11,4 @@ let ListMod x = [x]
module ListMod = Microsoft.FSharp.Collections.List
// Error: function wins due to name resolution rules
if ListMod.sum [1; 2; 3] <> 6 then exit 1
exit 1
if ListMod.sum [1; 2; 3] <> 6 then failwith "Failed: 1"
// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.
namespace FSharp.Compiler.ComponentTests.Conformance.DeclarationElements
open Xunit
open FSharp.Test
open FSharp.Test.Compiler
module ModuleAbbreviations =
let verifyCompile compilation =
compilation
|> asExe
|> withOptions ["--nowarn:988"]
|> compile
let verifyCompileAndRun compilation =
compilation
|> asExe
|> withOptions ["--nowarn:988"]
|> compileAndRun
// SOURCE=E_AbbreviationOnNamespace01.fs SCFLAGS="--test:ErrorRanges" # E_AbbreviationOnNamespace01.fs
[<Theory; Directory(__SOURCE_DIRECTORY__, Includes=[|"E_AbbreviationOnNamespace01.fs"|])>]
let ``E_AbbreviationOnNamespace01_fs`` compilation =
compilation
|> verifyCompile
|> shouldFail
|> withDiagnostics [
(Error 965, Line 11, Col 1, Line 11, Col 22, "The path 'System.IO' is a namespace. A module abbreviation may not abbreviate a namespace.")
(Error 39, Line 13, Col 15, Line 13, Col 17, "The value, namespace, type or module 'IO' is not defined.")
(Error 965, Line 16, Col 1, Line 16, Col 43, "The path 'System.Text.RegularExpressions' is a namespace. A module abbreviation may not abbreviate a namespace.")
(Error 39, Line 18, Col 19, Line 18, Col 21, "The namespace or module 'rx' is not defined.")
(Error 72, Line 21, Col 4, Line 21, Col 19, "Lookup on object of indeterminate type based on information prior to this program point. A type annotation may be needed prior to this program point to constrain the type of the object. This may allow the lookup to be resolved.")
]
// SOURCE=E_InvalidAbbrevName01.fs SCFLAGS="--test:ErrorRanges" # E_InvalidAbbrevName01.fs
[<Theory; Directory(__SOURCE_DIRECTORY__, Includes=[|"E_InvalidAbbrevName01.fs"|])>]
let ``E_InvalidAbbrevName01_fs`` compilation =
compilation
|> verifyCompile
|> shouldFail
|> withDiagnostics [
(Error 10, Line 5, Col 11, Line 5, Col 12, "Unexpected symbol '$' in definition. Expected incomplete structured construct at or before this point or other token.")
]
// SOURCE=E_InvalidAbbrevName02.fs # E_InvalidAbbrevName02.fs
[<Theory; Directory(__SOURCE_DIRECTORY__, Includes=[|"E_InvalidAbbrevName02.fs"|])>]
let ``E_InvalidAbbrevName02_fs`` compilation =
compilation
|> verifyCompile
|> shouldFail
|> withDiagnostics [
(Error 534, Line 5, Col 1, Line 5, Col 18, "A module abbreviation must be a simple name, not a path")
]
// SOURCE=E_NameConflict01.fs # E_NameConflict01.fs
[<Theory; Directory(__SOURCE_DIRECTORY__, Includes=[|"E_NameConflict01.fs"|])>]
let ``E_NameConflict01_fs`` compilation =
compilation
|> verifyCompile
|> shouldFail
|> withDiagnostics [
(Error 39, Line 14, Col 12, Line 14, Col 15, "The field, constructor or member 'sum' is not defined.")
]
// SOURCE=E_UseInsideFunc.fs SCFLAGS="--test:ErrorRanges" # E_UseInsideFunc.fs
[<Theory; Directory(__SOURCE_DIRECTORY__, Includes=[|"E_UseInsideFunc.fs"|])>]
let ``E_UseInsideFunc_fs`` compilation =
compilation
|> verifyCompile
|> shouldFail
|> withDiagnostics [
(Error 10, Line 7, Col 5, Line 7, Col 11, "Incomplete structured construct at or before this point in binding")
]
// SOURCE=SanityCheck.fs # SanityCheck.fs
[<Theory; Directory(__SOURCE_DIRECTORY__, Includes=[|"SanityCheck.fs"|])>]
let ``SanityCheck_fs`` compilation =
compilation
|> verifyCompileAndRun
|> shouldSucceed
// SOURCE=SanityCheck02.fs # SanityCheck02.fs
[<Theory; Directory(__SOURCE_DIRECTORY__, Includes=[|"SanityCheck02.fs"|])>]
let ``SanityCheck02_fs`` compilation =
compilation
|> withNoWarn 1104
|> verifyCompileAndRun
|> shouldSucceed
// SOURCE=useInsideModuleDef.fs # useInsideModuleDef.fs
[<Theory; Directory(__SOURCE_DIRECTORY__, Includes=[|"useInsideModuleDef.fs"|])>]
let ``useInsideModuleDef_fs`` compilation =
compilation
|> verifyCompileAndRun
|> shouldSucceed
// SOURCE=useInsideNamespaceDef.fs COMPILE_ONLY=1 # useInsideNamespaceDef.fs
[<Theory; Directory(__SOURCE_DIRECTORY__, Includes=[|"useInsideNamespaceDef.fs"|])>]
let ``useInsideNamespaceDef_fs`` compilation =
compilation
|> verifyCompileAndRun
|> shouldSucceed
// NoMT SOURCE=useInsideNamespaceDefExternal.fs PRECMD="\$FSC_PIPE -a useInsideNamespaceDefExternal_DLL.fs" SCFLAGS="-r:useInsideNamespaceDefExternal_DLL.dll" # useInsideNamespaceDefExternal.fs
[<Theory; Directory(__SOURCE_DIRECTORY__, Includes=[|"useInsideNamespaceDefExternal.fs"|])>]
let ``useInsideNamespaceDefExternal_fs`` compilation =
let useInsideNamespaceDefExternal_DLL =
FsFromPath(__SOURCE_DIRECTORY__ ++ "useInsideNamespaceDefExternal_DLL.fs")
|> asLibrary
|> withName "useInsideNamespaceDefExternal_DLL"
compilation
|> withReferences [useInsideNamespaceDefExternal_DLL]
|> verifyCompileAndRun
|> shouldSucceed
......@@ -17,4 +17,4 @@ module Abbreviated_A_B_C = A.B.C
let blue = int Abbreviated_A_B_C.X.Blue
let red = int Abbreviated_A_B.C.X.Red
if (blue = 2) && (red = 1) then 0 else 1
if (blue = 2) && (red = 1) then () else failwith "Failed: 1"
......@@ -6,6 +6,4 @@ module ``Some Crazy Identifier !@#`` = Microsoft.FSharp.Collections.List
let result = ``Some Crazy Identifier !@#``.sum [1; 2; 3]
if result <> 6 then exit 1
exit 0
if result <> 6 then failwith "Failed: 1"
......@@ -18,6 +18,4 @@ module TestModule1 =
let dsc = ABC.DirectorySeparatorChar
printfn "Current directory seperator char is %c" dsc
// If this compiles ok, then we are good to go
exit 0
......@@ -56,6 +56,7 @@
<Compile Include="Conformance\DeclarationElements\MemberDefinitions\OptionalArguments\OptionalArguments.fs" />
<Compile Include="Conformance\DeclarationElements\MemberDefinitions\OptionalDefaultParamArgs\OptionalDefaultParamArgs.fs" />
<Compile Include="Conformance\DeclarationElements\MemberDefinitions\OverloadingMembers\OverloadingMembers.fs" />
<Compile Include="Conformance\DeclarationElements\ModuleAbbreviations\ModuleAbbreviations.fs" />
<Compile Include="Conformance\DeclarationElements\UseBindings\UseBindings.fs" />
<Compile Include="Conformance\Expressions\ApplicationExpressions\BasicApplication\BasicApplication.fs" />
<Compile Include="Conformance\Expressions\BindingExpressions\BindingExpressions.fs" />
......
......@@ -169,6 +169,15 @@ module rec Compiler =
| Success of CompilationOutput
| Failure of CompilationOutput
type ExecutionPlatform =
| Anycpu = 0
| AnyCpu32bitPreferred = 1
| X86 = 2
| Itanium = 3
| X64 = 4
| Arm = 5
| Arm64 = 6
let private defaultOptions : string list = []
// Not very safe version of reading stuff from file, but we want to fail fast for now if anything goes wrong.
......@@ -427,6 +436,23 @@ module rec Compiler =
| FS fs -> FS { fs with OutputType = CompileOutput.Exe }
| _ -> failwith "TODO: Implement where applicable."
let withPlatform (platform:ExecutionPlatform) (cUnit: CompilationUnit) : CompilationUnit =
match cUnit with
| FS _ ->
let p =
match platform with
| ExecutionPlatform.Anycpu -> "anycpu"
| ExecutionPlatform.AnyCpu32bitPreferred -> "anycpu32bitpreferred"
| ExecutionPlatform.Itanium -> "itanium"
| ExecutionPlatform.X64 -> "x64"
| ExecutionPlatform.X86 -> "x86"
| ExecutionPlatform.Arm -> "arm"
| ExecutionPlatform.Arm64 -> "arm64"
| _ -> failwith $"Unknown value for ExecutionPlatform: {platform}"
withOptionsHelper [ $"--platform:{p}" ] "withPlatform is only supported for F#" cUnit
| _ -> failwith "TODO: Implement ignorewarnings for the rest."
let ignoreWarnings (cUnit: CompilationUnit) : CompilationUnit =
match cUnit with
| FS fs -> FS { fs with IgnoreWarnings = true }
......
SOURCE=SanityCheck.fs # SanityCheck.fs
SOURCE=SanityCheck02.fs # SanityCheck02.fs
SOURCE=useInsideModuleDef.fs # useInsideModuleDef.fs
SOURCE=useInsideNamespaceDef.fs COMPILE_ONLY=1 # useInsideNamespaceDef.fs
SOURCE=W_AbbreviationOnNamespace01.fs SCFLAGS="--test:ErrorRanges" # W_AbbreviationOnNamespace01.fs
NoMT SOURCE=useInsideNamespaceDefExternal.fs PRECMD="\$FSC_PIPE -a useInsideNamespaceDefExternal_DLL.fs" SCFLAGS="-r:useInsideNamespaceDefExternal_DLL.dll" # useInsideNamespaceDefExternal.fs
SOURCE=E_UseInsideFunc.fs SCFLAGS="--test:ErrorRanges" # E_UseInsideFunc.fs
SOURCE=E_NameConflict01.fs # E_NameConflict01.fs
SOURCE=E_InvalidAbbrevName01.fs SCFLAGS="--test:ErrorRanges" # E_InvalidAbbrevName01.fs
SOURCE=E_InvalidAbbrevName02.fs # E_InvalidAbbrevName02.fs
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册