Skip to content

Commit daad9c4

Browse files
authored
Merge pull request #16653 from dotnet/merges/main-to-release/dev17.10
Merge main to release/dev17.10
2 parents 052d113 + bed8ee9 commit daad9c4

File tree

53 files changed

+814
-355
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+814
-355
lines changed

DEVGUIDE.md

Lines changed: 18 additions & 147 deletions
Original file line numberDiff line numberDiff line change
@@ -275,9 +275,25 @@ Where `<version>` corresponds to the latest Visual Studio version on your machin
275275

276276
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.
277277

278-
### Writing and running benchmarks
278+
### Benchmarking
279279

280-
Existing compiler benchmarks can be found in `tests\benchmarks\`.
280+
Existing compiler benchmarks can be found in `tests\benchmarks\`. The folder contains READMEs describing specific benchmark projects as well as guidelines for creating new benchmarks. There is also `FSharp.Benchmarks.sln` solution containing all the benchmark project and their dependencies.
281+
282+
To exercise the benchmarking infrastructure locally, run:
283+
284+
(Windows)
285+
```cmd
286+
build.cmd -configuration Release -testBenchmarks
287+
```
288+
289+
(Linux/Mac)
290+
```shell
291+
./build.sh --configuration Release --testBenchmarks
292+
```
293+
294+
This is executed in CI as well. It does the following:
295+
- builds all the benchmarking projects
296+
- does smoke testing for fast benchmarks (executes them once to check they don't fail in the runtime)
281297

282298
### Benchmarking and profiling the compiler
283299

@@ -286,151 +302,6 @@ Existing compiler benchmarks can be found in `tests\benchmarks\`.
286302
* 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).
287303
* To run `Release` build of compiler/FCS.
288304

289-
### Example benchmark setup using [BenchmarkDotNet](https://github.com/dotnet/BenchmarkDotNet)
290-
291-
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).
292-
293-
2. Create a benchmark project (in this example, the project will be created in `tests\benchmarks\FCSBenchmarks`).
294-
295-
```shell
296-
cd tests\benchmarks\FCSBenchmarks
297-
dotnet new console -o FcsBench --name FcsBench -lang F#
298-
```
299-
300-
3. Add needed packages and project references.
301-
302-
```shell
303-
cd FcsBench
304-
dotnet add package BenchmarkDotNet
305-
dotnet add reference ..\..\..\src\Compiler\FSharp.Compiler.Service.fsproj
306-
```
307-
308-
4. Additionally, if you want to test changes to the FSharp.Core (note that the relative path can be different)
309-
310-
```shell
311-
dotnet add reference ..\..\..\src\FSharp.Core\FSharp.Core.fsproj
312-
```
313-
314-
> as well as the following property have to be added to `FcsBench.fsproj`:
315-
316-
```xml
317-
<PropertyGroup>
318-
<DisableImplicitFSharpCoreReference>true</DisableImplicitFSharpCoreReference>
319-
</PropertyGroup>
320-
```
321-
322-
5. Add a new benchmark for FCS/FSharp.Core by editing `Program.fs`.
323-
324-
```fsharp
325-
open System.IO
326-
open FSharp.Compiler.CodeAnalysis
327-
open FSharp.Compiler.Diagnostics
328-
open FSharp.Compiler.Text
329-
open BenchmarkDotNet.Attributes
330-
open BenchmarkDotNet.Running
331-
332-
[<MemoryDiagnoser>]
333-
type CompilerService() =
334-
let mutable checkerOpt = None
335-
let mutable sourceOpt = None
336-
337-
let parsingOptions =
338-
{
339-
SourceFiles = [|"CheckExpressions.fs"|]
340-
ConditionalDefines = []
341-
DiagnosticOptions = FSharpDiagnosticOptions.Default
342-
LangVersionText = "default"
343-
IsInteractive = false
344-
LightSyntax = None
345-
CompilingFsLib = false
346-
IsExe = false
347-
}
348-
349-
[<GlobalSetup>]
350-
member _.Setup() =
351-
match checkerOpt with
352-
| None ->
353-
checkerOpt <- Some(FSharpChecker.Create(projectCacheSize = 200))
354-
| _ -> ()
355-
356-
match sourceOpt with
357-
| None ->
358-
sourceOpt <- Some <| SourceText.ofString(File.ReadAllText("""C:\Users\vlza\code\fsharp\src\Compiler\Checking\CheckExpressions.fs"""))
359-
| _ -> ()
360-
361-
362-
[<Benchmark>]
363-
member _.ParsingTypeCheckerFs() =
364-
match checkerOpt, sourceOpt with
365-
| None, _ -> failwith "no checker"
366-
| _, None -> failwith "no source"
367-
| Some(checker), Some(source) ->
368-
let results = checker.ParseFile("CheckExpressions.fs", source, parsingOptions) |> Async.RunSynchronously
369-
if results.ParseHadErrors then failwithf "parse had errors: %A" results.Diagnostics
370-
371-
[<IterationCleanup(Target = "ParsingTypeCheckerFs")>]
372-
member _.ParsingTypeCheckerFsSetup() =
373-
match checkerOpt with
374-
| None -> failwith "no checker"
375-
| Some(checker) ->
376-
checker.InvalidateAll()
377-
checker.ClearLanguageServiceRootCachesAndCollectAndFinalizeAllTransients()
378-
checker.ParseFile("dummy.fs", SourceText.ofString "dummy", parsingOptions) |> Async.RunSynchronously |> ignore
379-
380-
[<EntryPoint>]
381-
let main _ =
382-
BenchmarkRunner.Run<CompilerService>() |> ignore
383-
0
384-
```
385-
386-
> For more detailed information about available BenchmarkDotNet options, please refer to [BenchmarkDotNet Documentation](https://benchmarkdotnet.org/articles/overview.html).
387-
388-
6. Build and run the benchmark.
389-
390-
```shell
391-
dotnet build -c Release
392-
dotnet run -c Release
393-
```
394-
395-
7. You can find results in `.\BenchmarkDotNet.Artifacts\results\` in the current benchmark project directory.
396-
397-
```shell
398-
> ls .\BenchmarkDotNet.Artifacts\results\
399-
400-
Directory: C:\Users\vlza\code\fsharp\tests\benchmarks\FCSBenchmarks\FcsBench\BenchmarkDotNet.Artifacts\results
401-
402-
Mode LastWriteTime Length Name
403-
---- ------------- ------ ----
404-
-a--- 4/25/2022 1:42 PM 638 Program.CompilerService-report-github.md
405-
-a--- 4/25/2022 1:42 PM 1050 Program.CompilerService-report.csv
406-
-a--- 4/25/2022 1:42 PM 1169 Program.CompilerService-report.html
407-
```
408-
409-
> *-report-github.md can be used to post benchmark results to GitHub issue/PR/discussion or RFC.
410-
>
411-
>*-report.csv can be used for comparison purposes.
412-
413-
**Example output:**
414-
415-
``` ini
416-
417-
BenchmarkDotNet=v0.13.1, OS=Windows 10.0.25102
418-
Intel Core i7-8750H CPU 2.20GHz (Coffee Lake), 1 CPU, 12 logical and 6 physical cores
419-
.NET SDK=6.0.200
420-
[Host] : .NET 6.0.3 (6.0.322.12309), X64 RyuJIT DEBUG
421-
Job-GDIBXX : .NET 6.0.3 (6.0.322.12309), X64 RyuJIT
422-
423-
InvocationCount=1 UnrollFactor=1
424-
425-
```
426-
427-
| Method | Mean | Error | StdDev | Median | Gen 0 | Gen 1 | Allocated |
428-
|--------------------- |---------:|--------:|--------:|---------:|----------:|----------:|----------:|
429-
| ParsingTypeCheckerFs | 199.4 ms | 3.84 ms | 9.78 ms | 195.5 ms | 4000.0000 | 1000.0000 | 28 MB |
430-
431-
8. Repeat for any number of changes you would like to test.
432-
9. **Optionally:** benchmark code and results can be included as part of the PR for future reference.
433-
434305
## Additional resources
435306

436307
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.

docs/release-notes/.FSharp.Compiler.Service/8.0.300.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
* Code generated files with > 64K methods and generated symbols crash when loaded. Use infered sequence points for debugging. ([Issue #16399](https://github.com/dotnet/fsharp/issues/16399), [#PR 16514](https://github.com/dotnet/fsharp/pull/16514))
44
* `nameof Module` expressions and patterns are processed to link files in `--test:GraphBasedChecking`. ([PR #16550](https://github.com/dotnet/fsharp/pull/16550))
5-
* Graph Based Checking doesn't throw on invalid parsed input so it can be used for IDE scenarios ([PR #16575](https://github.com/dotnet/fsharp/pull/16575), [PR #16588](https://github.com/dotnet/fsharp/pull/16588))
5+
* Graph Based Checking doesn't throw on invalid parsed input so it can be used for IDE scenarios ([PR #16575](https://github.com/dotnet/fsharp/pull/16575), [PR #16588](https://github.com/dotnet/fsharp/pull/16588), [PR #16643](https://github.com/dotnet/fsharp/pull/16643))
66
* Keep parens for problematic exprs (`if`, `match`, etc.) in `$"{(…):N0}"`, `$"{(…),-3}"`, etc. ([PR #16578](https://github.com/dotnet/fsharp/pull/16578))
77
* Fix crash in DOTNET_SYSTEM_GLOBALIZATION_INVARIANT mode [#PR 16471](https://github.com/dotnet/fsharp/pull/16471))
88

@@ -13,6 +13,7 @@
1313
* Parser recovers on complex primary constructor patterns, better tree representation for primary constructor patterns. ([PR #16425](https://github.com/dotnet/fsharp/pull/16425))
1414
* Name resolution: keep type vars in subsequent checks ([PR #16456](https://github.com/dotnet/fsharp/pull/16456))
1515
* Higher-order-function-based API for working with the untyped abstract syntax tree. ([PR #16462](https://github.com/dotnet/fsharp/pull/16462))
16+
* Allow returning bool instead of unit option for partial active patterns. ([Language suggestion #1041](https://github.com/fsharp/fslang-suggestions/issues/1041), [PR #16473](https://github.com/dotnet/fsharp/pull/16473))
1617

1718
### Changed
1819

docs/release-notes/.Language/preview.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* Better generic unmanaged structs handling. ([Language suggestion #692](https://github.com/fsharp/fslang-suggestions/issues/692), [PR #12154](https://github.com/dotnet/fsharp/pull/12154))
44
* Bidirectional F#/C# interop for 'unmanaged' constraint. ([PR #12154](https://github.com/dotnet/fsharp/pull/12154))
55
* Make `.Is*` discriminated union properties visible. ([Language suggestion #222](https://github.com/fsharp/fslang-suggestions/issues/222), [PR #16341](https://github.com/dotnet/fsharp/pull/16341))
6+
* Allow returning bool instead of unit option for partial active patterns. ([Language suggestion #1041](https://github.com/fsharp/fslang-suggestions/issues/1041), [PR #16473](https://github.com/dotnet/fsharp/pull/16473))
67

78
### Fixed
89

eng/Version.Details.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<Dependencies>
33
<ProductDependencies>
4+
<!-- Intermediate is necessary for source build. -->
45
<Dependency Name="Microsoft.SourceBuild.Intermediate.source-build-reference-packages" Version="9.0.0-alpha.1.24073.1">
56
<Uri>https://github.com/dotnet/source-build-reference-packages</Uri>
67
<Sha>412264fd6c04712d1d31ff05d37c6919101ef4f4</Sha>
78
<SourceBuild RepoName="source-build-reference-packages" ManagedOnly="true" />
89
</Dependency>
10+
<!-- Intermediate is necessary for source build. -->
911
<Dependency Name="Microsoft.SourceBuild.Intermediate.msbuild" Version="17.7.0-preview-23217-02">
1012
<Uri>https://github.com/dotnet/msbuild</Uri>
1113
<Sha>2cbc8b6aef648cf21c6a68a0dab7fe09a614e475</Sha>
@@ -37,6 +39,11 @@
3739
<Dependency Name="Microsoft.DotNet.XliffTasks" Version="1.0.0-beta.23475.1" CoherentParentDependency="Microsoft.DotNet.Arcade.Sdk">
3840
<Uri>https://github.com/dotnet/xliff-tasks</Uri>
3941
<Sha>73f0850939d96131c28cf6ea6ee5aacb4da0083a</Sha>
42+
</Dependency>
43+
<!-- Intermediate is necessary for source build. -->
44+
<Dependency Name="Microsoft.SourceBuild.Intermediate.xliff-tasks" Version="1.0.0-beta.23475.1" CoherentParentDependency="Microsoft.DotNet.Arcade.Sdk">
45+
<Uri>https://github.com/dotnet/xliff-tasks</Uri>
46+
<Sha>73f0850939d96131c28cf6ea6ee5aacb4da0083a</Sha>
4047
<SourceBuild RepoName="xliff-tasks" ManagedOnly="true" />
4148
</Dependency>
4249
<Dependency Name="optimization.windows_nt-x64.MIBC.Runtime" Version="1.0.0-prerelease.23614.4">

eng/build-utils.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ function Get-PackageDir([string]$name, [string]$version = "") {
179179
}
180180

181181
function Run-MSBuild([string]$projectFilePath, [string]$buildArgs = "", [string]$logFileName = "", [switch]$parallel = $true, [switch]$summary = $true, [switch]$warnAsError = $true, [string]$configuration = $script:configuration, [string]$verbosity = $script:verbosity) {
182-
# Because we override the C#/VB toolset to build against our LKG package, it is important
182+
# Because we override the C#/VB toolset to build against our LKG (Last Known Good) package, it is important
183183
# that we do not reuse MSBuild nodes from other jobs/builds on the machine. Otherwise,
184184
# we'll run into issues such as https://github.com/dotnet/roslyn/issues/6211.
185185
# MSBuildAdditionalCommandLineArgs=

eng/build.sh

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ usage()
2525
echo "Test actions:"
2626
echo " --testcoreclr Run unit tests on .NET Core (short: --test, -t)"
2727
echo " --testCompilerComponentTests Run FSharp.Compiler.ComponentTests on .NET Core"
28+
echo " --testBenchmarks Build and Run Benchmark suite"
2829
echo ""
2930
echo "Advanced settings:"
3031
echo " --ci Building in CI"
@@ -56,6 +57,7 @@ pack=false
5657
publish=false
5758
test_core_clr=false
5859
test_compilercomponent_tests=false
60+
test_benchmarks=false
5961
configuration="Debug"
6062
verbosity='minimal'
6163
binary_log=false
@@ -126,6 +128,9 @@ while [[ $# > 0 ]]; do
126128
--testcompilercomponenttests)
127129
test_compilercomponent_tests=true
128130
;;
131+
--testbenchmarks)
132+
test_benchmarks=true
133+
;;
129134
--ci)
130135
ci=true
131136
;;
@@ -330,4 +335,10 @@ if [[ "$test_compilercomponent_tests" == true ]]; then
330335
TestUsingNUnit --testproject "$repo_root/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj" --targetframework $coreclrtestframework --notestfilter
331336
fi
332337

338+
if [[ "$test_benchmarks" == true ]]; then
339+
pushd "$repo_root/tests/benchmarks"
340+
./SmokeTestBenchmarks.sh
341+
popd
342+
fi
343+
333344
ExitWithExitCode 0

src/Compiler/Checking/CheckExpressions.fs

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5093,7 +5093,11 @@ and TcPatLongIdentActivePatternCase warnOnUpper (cenv: cenv) (env: TcEnv) vFlags
50935093

50945094
if dtys.Length = args.Length + 1 &&
50955095
((isOptionTy g retTy && isUnitTy g (destOptionTy g retTy)) ||
5096-
(isValueOptionTy g retTy && isUnitTy g (destValueOptionTy g retTy))) then
5096+
(isValueOptionTy g retTy && isUnitTy g (destValueOptionTy g retTy))) ||
5097+
// `bool` partial AP always be treated as `unit option`
5098+
// For `val (|P|_|) : _ -> bool`, only allow `match x with | P -> ...`
5099+
// For `val (|P|_|) : _ -> _ -> bool`, only allow `match x with | P parameter -> ...`
5100+
(not apinfo.IsTotal && isBoolTy g retTy) then
50975101
args, SynPat.Const(SynConst.Unit, m)
50985102
else
50995103
List.frontAndBack args
@@ -10752,14 +10756,25 @@ and TcNormalizedBinding declKind (cenv: cenv) env tpenv overallTy safeThisValOpt
1075210756
| Some (apinfo, apOverallTy, _) ->
1075310757
let activePatResTys = NewInferenceTypes g apinfo.ActiveTags
1075410758
let _, apReturnTy = stripFunTy g apOverallTy
10755-
10756-
if isStructRetTy && apinfo.IsTotal then
10757-
errorR(Error(FSComp.SR.tcInvalidStructReturn(), mBinding))
10758-
10759-
if isStructRetTy then
10759+
let apRetTy =
10760+
if apinfo.IsTotal then
10761+
if isStructRetTy then errorR(Error(FSComp.SR.tcInvalidStructReturn(), mBinding))
10762+
ActivePatternReturnKind.RefTypeWrapper
10763+
else
10764+
if isStructRetTy || isValueOptionTy cenv.g apReturnTy then ActivePatternReturnKind.StructTypeWrapper
10765+
elif isBoolTy cenv.g apReturnTy then ActivePatternReturnKind.Boolean
10766+
else ActivePatternReturnKind.RefTypeWrapper
10767+
10768+
match apRetTy with
10769+
| ActivePatternReturnKind.Boolean ->
10770+
checkLanguageFeatureError g.langVersion LanguageFeature.BooleanReturningAndReturnTypeDirectedPartialActivePattern mBinding
10771+
| ActivePatternReturnKind.StructTypeWrapper when not isStructRetTy ->
10772+
checkLanguageFeatureError g.langVersion LanguageFeature.BooleanReturningAndReturnTypeDirectedPartialActivePattern mBinding
10773+
| ActivePatternReturnKind.StructTypeWrapper ->
1076010774
checkLanguageFeatureError g.langVersion LanguageFeature.StructActivePattern mBinding
10775+
| ActivePatternReturnKind.RefTypeWrapper -> ()
1076110776

10762-
UnifyTypes cenv env mBinding (apinfo.ResultType g rhsExpr.Range activePatResTys isStructRetTy) apReturnTy
10777+
UnifyTypes cenv env mBinding (apinfo.ResultType g rhsExpr.Range activePatResTys apRetTy) apReturnTy
1076310778

1076410779
| None ->
1076510780
if isStructRetTy then

src/Compiler/Checking/NameResolution.fs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,18 +87,20 @@ let ActivePatternElemsOfValRef g (vref: ValRef) =
8787
match TryGetActivePatternInfo vref with
8888
| Some apinfo ->
8989

90-
let isStructRetTy =
90+
let retKind =
9191
if apinfo.IsTotal then
92-
false
92+
ActivePatternReturnKind.RefTypeWrapper
9393
else
9494
let _, apReturnTy = stripFunTy g vref.TauType
9595
let hasStructAttribute() =
9696
vref.Attribs
9797
|> List.exists (function
9898
| Attrib(targetsOpt = Some(System.AttributeTargets.ReturnValue)) as a -> IsMatchingFSharpAttribute g g.attrib_StructAttribute a
9999
| _ -> false)
100-
isStructTy g apReturnTy || hasStructAttribute()
101-
apinfo.ActiveTags |> List.mapi (fun i _ -> APElemRef(apinfo, vref, i, isStructRetTy))
100+
if isValueOptionTy g apReturnTy || hasStructAttribute() then ActivePatternReturnKind.StructTypeWrapper
101+
elif isBoolTy g apReturnTy then ActivePatternReturnKind.Boolean
102+
else ActivePatternReturnKind.RefTypeWrapper
103+
apinfo.ActiveTags |> List.mapi (fun i _ -> APElemRef(apinfo, vref, i, retKind))
102104
| None -> []
103105

104106
/// Try to make a reference to a value in a module.

0 commit comments

Comments
 (0)