From ef0949cc1eabd5bccb195d121d7ffa92a159cfbe Mon Sep 17 00:00:00 2001 From: JC Aguilera Date: Wed, 10 Jul 2019 17:16:08 -0700 Subject: [PATCH 01/46] Copy sources from Versions.props to NuGet.config (#7191) --- NuGet.config | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/NuGet.config b/NuGet.config index 8f21de1b15b..a8664a73c57 100644 --- a/NuGet.config +++ b/NuGet.config @@ -8,6 +8,20 @@ + + + + + + + + + + + + + + From 0c9ccae80518c26a6a3869380fbc125ec1fc18c9 Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Thu, 11 Jul 2019 03:11:56 +0200 Subject: [PATCH 02/46] Only check distinct errors (#7140) --- tests/fsharp/Compiler/CompilerAssert.fs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tests/fsharp/Compiler/CompilerAssert.fs b/tests/fsharp/Compiler/CompilerAssert.fs index c83947d331f..40da516c515 100644 --- a/tests/fsharp/Compiler/CompilerAssert.fs +++ b/tests/fsharp/Compiler/CompilerAssert.fs @@ -121,8 +121,12 @@ module CompilerAssert = | FSharpCheckFileAnswer.Aborted _ -> Assert.Fail("Type Checker Aborted") | FSharpCheckFileAnswer.Succeeded(typeCheckResults) -> - Assert.AreEqual(1, typeCheckResults.Errors.Length, sprintf "Expected one type check error: %A" typeCheckResults.Errors) - typeCheckResults.Errors + let errors = + typeCheckResults.Errors + |> Array.distinctBy (fun e -> e.Severity, e.ErrorNumber, e.StartLineAlternate, e.StartColumn, e.EndLineAlternate, e.EndColumn, e.Message) + + Assert.AreEqual(1, errors.Length, sprintf "Expected one type check error: %A" typeCheckResults.Errors) + errors |> Array.iter (fun info -> Assert.AreEqual(FSharpErrorSeverity.Error, info.Severity) Assert.AreEqual(expectedErrorNumber, info.ErrorNumber, "expectedErrorNumber") @@ -203,4 +207,4 @@ module CompilerAssert = ||> Seq.iter2 (fun expectedErrorMessage errorMessage -> Assert.AreEqual(expectedErrorMessage, errorMessage) ) - \ No newline at end of file + From 598db3e138453fa19e4dda988ace1c0e5a29b95a Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Thu, 11 Jul 2019 10:12:51 +0200 Subject: [PATCH 03/46] Use 1-based column numbers in tests (#7141) * Use 1-based column numbers in tests * Helper that can check for multiple type errors --- tests/fsharp/Compiler/CompilerAssert.fs | 18 ++++++++++++------ .../Compiler/Language/AnonRecordTests.fs | 9 ++++++--- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/tests/fsharp/Compiler/CompilerAssert.fs b/tests/fsharp/Compiler/CompilerAssert.fs index 40da516c515..9c748455498 100644 --- a/tests/fsharp/Compiler/CompilerAssert.fs +++ b/tests/fsharp/Compiler/CompilerAssert.fs @@ -111,7 +111,8 @@ module CompilerAssert = Assert.IsEmpty(typeCheckResults.Errors, sprintf "Type Check errors: %A" typeCheckResults.Errors) - let TypeCheckSingleError (source: string) (expectedErrorNumber: int) (expectedErrorRange: int * int * int * int) (expectedErrorMsg: string) = + + let TypeCheckWithErrors (source: string) expectedTypeErrors = lock gate <| fun () -> let parseResults, fileAnswer = checker.ParseAndCheckFileInProject("test.fs", 0, SourceText.ofString source, defaultProjectOptions) |> Async.RunSynchronously @@ -125,15 +126,20 @@ module CompilerAssert = typeCheckResults.Errors |> Array.distinctBy (fun e -> e.Severity, e.ErrorNumber, e.StartLineAlternate, e.StartColumn, e.EndLineAlternate, e.EndColumn, e.Message) - Assert.AreEqual(1, errors.Length, sprintf "Expected one type check error: %A" typeCheckResults.Errors) - errors - |> Array.iter (fun info -> - Assert.AreEqual(FSharpErrorSeverity.Error, info.Severity) + Assert.AreEqual(Array.length expectedTypeErrors, errors.Length, sprintf "Type check errors: %A" typeCheckResults.Errors) + + Array.zip errors expectedTypeErrors + |> Array.iter (fun (info, expectedError) -> + let (expectedServerity: FSharpErrorSeverity, expectedErrorNumber: int, expectedErrorRange: int * int * int * int, expectedErrorMsg: string) = expectedError + Assert.AreEqual(expectedServerity, info.Severity) Assert.AreEqual(expectedErrorNumber, info.ErrorNumber, "expectedErrorNumber") - Assert.AreEqual(expectedErrorRange, (info.StartLineAlternate, info.StartColumn, info.EndLineAlternate, info.EndColumn), "expectedErrorRange") + Assert.AreEqual(expectedErrorRange, (info.StartLineAlternate, info.StartColumn + 1, info.EndLineAlternate, info.EndColumn + 1), "expectedErrorRange") Assert.AreEqual(expectedErrorMsg, info.Message, "expectedErrorMsg") ) + let TypeCheckSingleError (source: string) (expectedServerity: FSharpErrorSeverity) (expectedErrorNumber: int) (expectedErrorRange: int * int * int * int) (expectedErrorMsg: string) = + TypeCheckWithErrors (source: string) [| expectedServerity, expectedErrorNumber, expectedErrorRange, expectedErrorMsg |] + let CompileExe (source: string) = compile true source (fun (errors, _) -> if errors.Length > 0 then diff --git a/tests/fsharp/Compiler/Language/AnonRecordTests.fs b/tests/fsharp/Compiler/Language/AnonRecordTests.fs index 7182e359b19..0a4d1c18d9f 100644 --- a/tests/fsharp/Compiler/Language/AnonRecordTests.fs +++ b/tests/fsharp/Compiler/Language/AnonRecordTests.fs @@ -3,6 +3,7 @@ namespace FSharp.Compiler.UnitTests open NUnit.Framework +open FSharp.Compiler.SourceCodeServices [] module AnonRecordsTests = @@ -30,8 +31,9 @@ let sAnon = StructClass() type RefClass<'a when 'a : not struct>() = class end let rAnon = RefClass() """ + FSharpErrorSeverity.Error 1 - (3, 12, 3, 41) + (3, 13, 3, 42) "A generic construct requires that the type 'struct {|R : int|}' have reference semantics, but it does not, i.e. it is a struct" [] @@ -40,7 +42,8 @@ let rAnon = RefClass() """ type StructClass<'a when 'a : struct>() = class end let sAnon = StructClass<{| S: int |}>() - """ + """ + FSharpErrorSeverity.Error 1 - (3, 12, 3, 37) + (3, 13, 3, 38) "A generic construct requires that the type '{|S : int|}' is a CLI or F# struct type" \ No newline at end of file From bf1055cd70b50d2f7b22c4d433606dece27cd10b Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Thu, 11 Jul 2019 11:42:21 -0700 Subject: [PATCH 04/46] Update dependencies from https://github.com/dotnet/arcade build 20190710.8 (#7200) - Microsoft.DotNet.Arcade.Sdk - 1.0.0-beta.19360.8 --- eng/Version.Details.xml | 4 +- eng/common/SigningValidation.proj | 2 +- eng/common/performance/perfhelixpublish.proj | 77 ++++++++ eng/common/performance/performance-setup.ps1 | 91 +++++++++ eng/common/performance/performance-setup.sh | 176 ++++++++++++++++++ eng/common/pipeline-logging-functions.ps1 | 7 +- .../post-build/trigger-subscriptions.ps1 | 6 +- eng/common/templates/job/performance.yml | 93 +++++++++ .../channels/internal-servicing.yml | 8 +- .../channels/public-dev-release.yml | 1 + .../post-build/channels/public-release.yml | 8 +- .../channels/public-validation-release.yml | 1 + .../templates/post-build/common-variables.yml | 3 + .../templates/steps/perf-send-to-helix.yml | 66 +++++++ eng/common/tools.ps1 | 4 +- global.json | 2 +- 16 files changed, 529 insertions(+), 20 deletions(-) create mode 100644 eng/common/performance/perfhelixpublish.proj create mode 100644 eng/common/performance/performance-setup.ps1 create mode 100644 eng/common/performance/performance-setup.sh create mode 100644 eng/common/templates/job/performance.yml create mode 100644 eng/common/templates/steps/perf-send-to-helix.yml diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 0c5078f9f9c..bfb72eca155 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -3,9 +3,9 @@ - + https://github.com/dotnet/arcade - 0f5dd7680174620f31c9a00cdb2ac0b0e70e631f + a6ae1b637ed236354529992729af875f6c8a180a diff --git a/eng/common/SigningValidation.proj b/eng/common/SigningValidation.proj index 7045fb6fb9d..3d0ac80af3f 100644 --- a/eng/common/SigningValidation.proj +++ b/eng/common/SigningValidation.proj @@ -3,7 +3,7 @@ + + + $(WorkItemDirectory) + $(WorkItemCommand) --bdn-arguments="--anyCategories $(BDNCategories) $(ExtraBenchmarkDotNetArguments) $(CoreRunArgument) --artifacts $(ArtifactsDirectory) --partition-count $(PartitionCount) --partition-index %(HelixWorkItem.Index)" + 4:00 + + + + + $(WorkItemDirectory) + $(WorkItemCommand) --bdn-arguments="--anyCategories $(BDNCategories) $(ExtraBenchmarkDotNetArguments) $(CoreRunArgument) --artifacts $(ArtifactsDirectory)" + 4:00 + + + \ No newline at end of file diff --git a/eng/common/performance/performance-setup.ps1 b/eng/common/performance/performance-setup.ps1 new file mode 100644 index 00000000000..7e5441f7974 --- /dev/null +++ b/eng/common/performance/performance-setup.ps1 @@ -0,0 +1,91 @@ +Param( + [string] $SourceDirectory=$env:BUILD_SOURCESDIRECTORY, + [string] $CoreRootDirectory, + [string] $Architecture="x64", + [string] $Framework="netcoreapp3.0", + [string] $CompilationMode="Tiered", + [string] $Repository=$env:BUILD_REPOSITORY_NAME, + [string] $Branch=$env:BUILD_SOURCEBRANCH, + [string] $CommitSha=$env:BUILD_SOURCEVERSION, + [string] $BuildNumber=$env:BUILD_BUILDNUMBER, + [string] $RunCategories="coreclr corefx", + [string] $Csproj="src\benchmarks\micro\MicroBenchmarks.csproj", + [string] $Kind="micro", + [switch] $Internal, + [string] $Configurations="CompilationMode=$CompilationMode" +) + +$RunFromPerformanceRepo = ($Repository -eq "dotnet/performance") +$UseCoreRun = ($CoreRootDirectory -ne [string]::Empty) + +$PayloadDirectory = (Join-Path $SourceDirectory "Payload") +$PerformanceDirectory = (Join-Path $PayloadDirectory "performance") +$WorkItemDirectory = (Join-Path $SourceDirectory "workitem") +$ExtraBenchmarkDotNetArguments = "--iterationCount 1 --warmupCount 0 --invocationCount 1 --unrollFactor 1 --strategy ColdStart --stopOnFirstError true" +$Creator = $env:BUILD_DEFINITIONNAME +$PerfLabArguments = "" +$HelixSourcePrefix = "pr" + +$Queue = "Windows.10.Amd64.ClientRS4.DevEx.15.8.Open" + +if ($Framework.StartsWith("netcoreapp")) { + $Queue = "Windows.10.Amd64.ClientRS4.Open" +} + +if ($Internal) { + $Queue = "Windows.10.Amd64.ClientRS5.Perf" + $PerfLabArguments = "--upload-to-perflab-container" + $ExtraBenchmarkDotNetArguments = "" + $Creator = "" + $HelixSourcePrefix = "official" +} + +$CommonSetupArguments="--frameworks $Framework --queue $Queue --build-number $BuildNumber --build-configs $Configurations" +$SetupArguments = "--repository https://github.com/$Repository --branch $Branch --get-perf-hash --commit-sha $CommitSha $CommonSetupArguments" + +if ($RunFromPerformanceRepo) { + $SetupArguments = "--perf-hash $CommitSha $CommonSetupArguments" + + robocopy $SourceDirectory $PerformanceDirectory /E /XD $PayloadDirectory $SourceDirectory\artifacts $SourceDirectory\.git +} +else { + git clone --branch master --depth 1 --quiet https://github.com/dotnet/performance $PerformanceDirectory +} + +if ($UseCoreRun) { + $NewCoreRoot = (Join-Path $PayloadDirectory "Core_Root") + Move-Item -Path $CoreRootDirectory -Destination $NewCoreRoot +} + +$DocsDir = (Join-Path $PerformanceDirectory "docs") +robocopy $DocsDir $WorkItemDirectory + +# Set variables that we will need to have in future steps +$ci = $true + +. "$PSScriptRoot\..\pipeline-logging-functions.ps1" + +# Directories +Write-PipelineSetVariable -Name 'PayloadDirectory' -Value "$PayloadDirectory" -IsMultiJobVariable $false +Write-PipelineSetVariable -Name 'PerformanceDirectory' -Value "$PerformanceDirectory" -IsMultiJobVariable $false +Write-PipelineSetVariable -Name 'WorkItemDirectory' -Value "$WorkItemDirectory" -IsMultiJobVariable $false + +# Script Arguments +Write-PipelineSetVariable -Name 'Python' -Value "py -3" -IsMultiJobVariable $false +Write-PipelineSetVariable -Name 'ExtraBenchmarkDotNetArguments' -Value "$ExtraBenchmarkDotNetArguments" -IsMultiJobVariable $false +Write-PipelineSetVariable -Name 'SetupArguments' -Value "$SetupArguments" -IsMultiJobVariable $false +Write-PipelineSetVariable -Name 'PerfLabArguments' -Value "$PerfLabArguments" -IsMultiJobVariable $false +Write-PipelineSetVariable -Name 'BDNCategories' -Value "$RunCategories" -IsMultiJobVariable $false +Write-PipelineSetVariable -Name 'TargetCsproj' -Value "$Csproj" -IsMultiJobVariable $false +Write-PipelineSetVariable -Name 'Kind' -Value "$Kind" -IsMultiJobVariable $false +Write-PipelineSetVariable -Name 'Architecture' -Value "$Architecture" -IsMultiJobVariable $false +Write-PipelineSetVariable -Name 'UseCoreRun' -Value "$UseCoreRun" -IsMultiJobVariable $false +Write-PipelineSetVariable -Name 'RunFromPerfRepo' -Value "$RunFromPerformanceRepo" -IsMultiJobVariable $false + +# Helix Arguments +Write-PipelineSetVariable -Name 'Creator' -Value "$Creator" -IsMultiJobVariable $false +Write-PipelineSetVariable -Name 'Queue' -Value "$Queue" -IsMultiJobVariable $false +Write-PipelineSetVariable -Name 'HelixSourcePrefix' -Value "$HelixSourcePrefix" -IsMultiJobVariable $false +Write-PipelineSetVariable -Name '_BuildConfig' -Value "$Architecture.$Kind.$Framework" -IsMultiJobVariable $false + +exit 0 \ No newline at end of file diff --git a/eng/common/performance/performance-setup.sh b/eng/common/performance/performance-setup.sh new file mode 100644 index 00000000000..126da5f76d4 --- /dev/null +++ b/eng/common/performance/performance-setup.sh @@ -0,0 +1,176 @@ +#!/usr/bin/env bash + +source_directory=$BUILD_SOURCESDIRECTORY +core_root_directory= +architecture=x64 +framework=netcoreapp3.0 +compilation_mode=tiered +repository=$BUILD_REPOSITORY_NAME +branch=$BUILD_SOURCEBRANCH +commit_sha=$BUILD_SOURCEVERSION +build_number=$BUILD_BUILDNUMBER +internal=false +kind="micro" +run_categories="coreclr corefx" +csproj="src\benchmarks\micro\MicroBenchmarks.csproj" +configurations= +run_from_perf_repo=false +use_core_run=true + +while (($# > 0)); do + lowerI="$(echo $1 | awk '{print tolower($0)}')" + case $lowerI in + --sourcedirectory) + source_directory=$2 + shift 2 + ;; + --corerootdirectory) + core_root_directory=$2 + shift 2 + ;; + --architecture) + architecture=$2 + shift 2 + ;; + --framework) + framework=$2 + shift 2 + ;; + --compilationmode) + compilation_mode=$2 + shift 2 + ;; + --repository) + repository=$2 + shift 2 + ;; + --branch) + branch=$2 + shift 2 + ;; + --commitsha) + commit_sha=$2 + shift 2 + ;; + --buildnumber) + build_number=$2 + shift 2 + ;; + --kind) + kind=$2 + shift 2 + ;; + --runcategories) + run_categories=$2 + shift 2 + ;; + --csproj) + csproj=$2 + shift 2 + ;; + --internal) + internal=true + shift 1 + ;; + --configurations) + configurations=$2 + shift 2 + ;; + --help) + echo "Common settings:" + echo " --corerootdirectory Directory where Core_Root exists, if running perf testing with --corerun" + echo " --architecture Architecture of the testing being run" + echo " --configurations List of key=value pairs that will be passed to perf testing infrastructure." + echo " ex: --configurations \"CompilationMode=Tiered OptimzationLevel=PGO\"" + echo " --help Print help and exit" + echo "" + echo "Advanced settings:" + echo " --framework The framework to run, if not running in master" + echo " --compliationmode The compilation mode if not passing --configurations" + echo " --sourcedirectory The directory of the sources. Defaults to env:BUILD_SOURCESDIRECTORY" + echo " --repository The name of the repository in the / format. Defaults to env:BUILD_REPOSITORY_NAME" + echo " --branch The name of the branch. Defaults to env:BUILD_SOURCEBRANCH" + echo " --commitsha The commit sha1 to run against. Defaults to env:BUILD_SOURCEVERSION" + echo " --buildnumber The build number currently running. Defaults to env:BUILD_BUILDNUMBER" + echo " --csproj The relative path to the benchmark csproj whose tests should be run. Defaults to src\benchmarks\micro\MicroBenchmarks.csproj" + echo " --kind Related to csproj. The kind of benchmarks that should be run. Defaults to micro" + echo " --runcategories Related to csproj. Categories of benchmarks to run. Defaults to \"coreclr corefx\"" + echo " --internal If the benchmarks are running as an official job." + echo "" + exit 0 + ;; + esac +done + +if [[ "$repository" == "dotnet/performance" ]]; then + run_from_perf_repo=true +fi + +if [ -z "$configurations" ]; then + configurations="CompliationMode=$compilation_mode" +fi + +if [ -z "$core_root_directory" ]; then + use_core_run=false +fi + +payload_directory=$source_directory/Payload +performance_directory=$payload_directory/performance +workitem_directory=$source_directory/workitem +extra_benchmark_dotnet_arguments="--iterationCount 1 --warmupCount 0 --invocationCount 1 --unrollFactor 1 --strategy ColdStart --stopOnFirstError true" +perflab_arguments= +queue=Ubuntu.1804.Amd64.Open +creator=$BUILD_DEFINITIONNAME +helix_source_prefix="pr" + +if [[ "$internal" == true ]]; then + perflab_arguments="--upload-to-perflab-container" + helix_source_prefix="official" + creator= + extra_benchmark_dotnet_arguments= + + if [[ "$architecture" = "arm64" ]]; then + queue=Ubuntu.1804.Arm64.Perf + else + queue=Ubuntu.1804.Amd64.Perf + fi +fi + +common_setup_arguments="--frameworks $framework --queue $queue --build-number $build_number --build-configs $configurations" +setup_arguments="--repository https://github.com/$repository --branch $branch --get-perf-hash --commit-sha $commit_sha $common_setup_arguments" + +if [[ "$run_from_perf_repo" = true ]]; then + payload_directory= + workitem_directory=$source_directory + performance_directory=$workitem_directory + setup_arguments="--perf-hash $commit_sha $common_setup_arguments" +else + git clone --branch master --depth 1 --quiet https://github.com/dotnet/performance $performance_directory + + docs_directory=$performance_directory/docs + mv $docs_directory $workitem_directory +fi + +if [[ "$use_core_run" = true ]]; then + new_core_root=$payload_directory/Core_Root + mv $core_root_directory $new_core_root +fi + +# Make sure all of our variables are available for future steps +echo "##vso[task.setvariable variable=UseCoreRun]$use_core_run" +echo "##vso[task.setvariable variable=Architecture]$architecture" +echo "##vso[task.setvariable variable=PayloadDirectory]$payload_directory" +echo "##vso[task.setvariable variable=PerformanceDirectory]$performance_directory" +echo "##vso[task.setvariable variable=WorkItemDirectory]$workitem_directory" +echo "##vso[task.setvariable variable=Queue]$queue" +echo "##vso[task.setvariable variable=SetupArguments]$setup_arguments" +echo "##vso[task.setvariable variable=Python]python3" +echo "##vso[task.setvariable variable=PerfLabArguments]$perflab_arguments" +echo "##vso[task.setvariable variable=ExtraBenchmarkDotNetArguments]$extra_benchmark_dotnet_arguments" +echo "##vso[task.setvariable variable=BDNCategories]$run_categories" +echo "##vso[task.setvariable variable=TargetCsproj]$csproj" +echo "##vso[task.setvariable variable=RunFromPerfRepo]$run_from_perf_repo" +echo "##vso[task.setvariable variable=Creator]$creator" +echo "##vso[task.setvariable variable=HelixSourcePrefix]$helix_source_prefix" +echo "##vso[task.setvariable variable=Kind]$kind" +echo "##vso[task.setvariable variable=_BuildConfig]$architecture.$kind.$framework" \ No newline at end of file diff --git a/eng/common/pipeline-logging-functions.ps1 b/eng/common/pipeline-logging-functions.ps1 index 7b61376f8aa..af5f48aaceb 100644 --- a/eng/common/pipeline-logging-functions.ps1 +++ b/eng/common/pipeline-logging-functions.ps1 @@ -77,13 +77,14 @@ function Write-PipelineTaskError { [string]$Name, [string]$Value, [switch]$Secret, - [switch]$AsOutput) - + [switch]$AsOutput, + [bool]$IsMultiJobVariable=$true) + if($ci) { Write-LoggingCommand -Area 'task' -Event 'setvariable' -Data $Value -Properties @{ 'variable' = $Name 'isSecret' = $Secret - 'isOutput' = 'true' + 'isOutput' = $IsMultiJobVariable } -AsOutput:$AsOutput } } diff --git a/eng/common/post-build/trigger-subscriptions.ps1 b/eng/common/post-build/trigger-subscriptions.ps1 index db8a839457a..1a91dab0371 100644 --- a/eng/common/post-build/trigger-subscriptions.ps1 +++ b/eng/common/post-build/trigger-subscriptions.ps1 @@ -19,14 +19,14 @@ function Get-Headers([string]$accept, [string]$barToken) { } # Get all the $SourceRepo subscriptions -$normalizedSurceRepo = $SourceRepo.Replace('dnceng@', '') -$getSubscriptionsApiEndpoint = "$maestroEndpoint/api/subscriptions?sourceRepository=$normalizedSurceRepo&api-version=$apiVersion" +$normalizedSourceRepo = $SourceRepo.Replace('dnceng@', '') +$getSubscriptionsApiEndpoint = "$maestroEndpoint/api/subscriptions?sourceRepository=$normalizedSourceRepo&api-version=$apiVersion" $headers = Get-Headers 'application/json' $barToken $subscriptions = Invoke-WebRequest -Uri $getSubscriptionsApiEndpoint -Headers $headers | ConvertFrom-Json if (!$subscriptions) { - Write-Host "No subscriptions found for source repo '$normalizedSurceRepo' in channel '$ChannelId'" + Write-Host "No subscriptions found for source repo '$normalizedSourceRepo' in channel '$ChannelId'" return } diff --git a/eng/common/templates/job/performance.yml b/eng/common/templates/job/performance.yml new file mode 100644 index 00000000000..ef809253d1a --- /dev/null +++ b/eng/common/templates/job/performance.yml @@ -0,0 +1,93 @@ +parameters: + steps: [] # optional -- any additional steps that need to happen before pulling down the performance repo and sending the performance benchmarks to helix (ie building your repo) + variables: [] # optional -- list of additional variables to send to the template + jobName: '' # required -- job name + displayName: '' # optional -- display name for the job. Will use jobName if not passed + pool: '' # required -- name of the Build pool + container: '' # required -- name of the container + extraSetupParameters: '' # optional -- extra arguments to pass to the setup script + frameworks: ['netcoreapp3.0'] # optional -- list of frameworks to run against + continueOnError: 'false' # optional -- determines whether to continue the build if the step errors + dependsOn: '' # optional -- dependencies of the job + timeoutInMinutes: 320 # optional -- timeout for the job + enableTelemetry: false # optional -- enable for telemetry + +jobs: +- template: ../jobs/jobs.yml + parameters: + dependsOn: ${{ parameters.dependsOn }} + enableTelemetry: ${{ parameters.enableTelemetry }} + enablePublishBuildArtifacts: true + continueOnError: ${{ parameters.continueOnError }} + + jobs: + - job: '${{ parameters.jobName }}' + + ${{ if ne(parameters.displayName, '') }}: + displayName: '${{ parameters.displayName }}' + ${{ if eq(parameters.displayName, '') }}: + displayName: '${{ parameters.jobName }}' + + timeoutInMinutes: ${{ parameters.timeoutInMinutes }} + + variables: + + - ${{ each variable in parameters.variables }}: + - ${{ if ne(variable.name, '') }}: + - name: ${{ variable.name }} + value: ${{ variable.value }} + - ${{ if ne(variable.group, '') }}: + - group: ${{ variable.group }} + + - IsInternal: '' + - HelixApiAccessToken: '' + - HelixPreCommand: '' + + - ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: + - ${{ if eq(variables['Agent.Os'], 'Windows_NT') }}: + - HelixPreCommand: 'set "PERFLAB_UPLOAD_TOKEN=$(PerfCommandUploadToken)"' + - IsInternal: -Internal + - ${{ if ne(variables['Agent.Os'], 'Windows_NT') }}: + - HelixPreCommand: 'export PERFLAB_UPLOAD_TOKEN="$(PerfCommandUploadTokenLinux)"' + - IsInternal: --internal + - group: DotNet-HelixApi-Access + - group: dotnet-benchview + + workspace: + clean: all + pool: + ${{ parameters.pool }} + container: ${{ parameters.container }} + strategy: + matrix: + ${{ each framework in parameters.frameworks }}: + ${{ framework }}: + _Framework: ${{ framework }} + steps: + - checkout: self + clean: true + # Run all of the steps to setup repo + - ${{ each step in parameters.steps }}: + - ${{ step }} + - powershell: $(Build.SourcesDirectory)\eng\common\performance\performance-setup.ps1 $(IsInternal) -Framework $(_Framework) ${{ parameters.extraSetupParameters }} + displayName: Performance Setup (Windows) + condition: and(succeeded(), eq(variables['Agent.Os'], 'Windows_NT')) + continueOnError: ${{ parameters.continueOnError }} + - script: $(Build.SourcesDirectory)/eng/common/performance/performance-setup.sh $(IsInternal) --framework $(_Framework) ${{ parameters.extraSetupParameters }} + displayName: Performance Setup (Unix) + condition: and(succeeded(), ne(variables['Agent.Os'], 'Windows_NT')) + continueOnError: ${{ parameters.continueOnError }} + - script: $(Python) $(PerformanceDirectory)/scripts/ci_setup.py $(SetupArguments) + displayName: Run ci setup script + # Run perf testing in helix + - template: /eng/common/templates/steps/perf-send-to-helix.yml + parameters: + HelixSource: '$(HelixSourcePrefix)/$(Build.Repository.Name)/$(Build.SourceBranch)' # sources must start with pr/, official/, prodcon/, or agent/ + HelixType: 'test/performance/$(Kind)/$(_Framework)/$(Architecture)' + HelixAccessToken: $(HelixApiAccessToken) + HelixTargetQueues: $(Queue) + HelixPreCommands: $(HelixPreCommand) + Creator: $(Creator) + WorkItemTimeout: 4:00 # 4 hours + WorkItemDirectory: '$(WorkItemDirectory)' # WorkItemDirectory can not be empty, so we send it some docs to keep it happy + CorrelationPayloadDirectory: '$(PayloadDirectory)' # it gets checked out to a folder with shorter path than WorkItemDirectory so we can avoid file name too long exceptions \ No newline at end of file diff --git a/eng/common/templates/post-build/channels/internal-servicing.yml b/eng/common/templates/post-build/channels/internal-servicing.yml index 808d46b17f2..50ad724fc0c 100644 --- a/eng/common/templates/post-build/channels/internal-servicing.yml +++ b/eng/common/templates/post-build/channels/internal-servicing.yml @@ -81,10 +81,10 @@ stages: /p:IsInternalBuild=$(IsInternalBuild) /p:RepositoryName=$(Build.Repository.Name) /p:CommitSha=$(Build.SourceVersion) + /p:AzureStorageAccountName=$(ProxyBackedFeedsAccountName) + /p:AzureStorageAccountKey=$(dotnetfeed-storage-access-key-1) + /p:AzureDevOpsFeedsBaseUrl=$(dotnetfeed-internal-private-feed-url) /p:NugetPath=$(Agent.BuildDirectory)\Nuget\NuGet.exe - /p:AzdoTargetFeedPAT='$(dn-bot-dnceng-unviersal-packages-rw)' - /p:TargetFeedPAT='$(dn-bot-dnceng-unviersal-packages-rw)' - /p:AzureStorageTargetFeedPAT='$(dotnetfeed-storage-access-key-1)' /p:BARBuildId=$(BARBuildId) /p:MaestroApiEndpoint='https://maestro-prod.westus2.cloudapp.azure.com' /p:BuildAssetRegistryToken='$(MaestroAccessToken)' @@ -167,4 +167,4 @@ stages: - template: ../promote-build.yml parameters: - ChannelId: ${{ variables.InternalServicing_30_Channel_Id }} \ No newline at end of file + ChannelId: ${{ variables.InternalServicing_30_Channel_Id }} diff --git a/eng/common/templates/post-build/channels/public-dev-release.yml b/eng/common/templates/post-build/channels/public-dev-release.yml index 79c6822db72..bdc631016b6 100644 --- a/eng/common/templates/post-build/channels/public-dev-release.yml +++ b/eng/common/templates/post-build/channels/public-dev-release.yml @@ -77,6 +77,7 @@ stages: filePath: eng\common\sdk-task.ps1 arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet /p:ChannelId=$(PublicDevRelease_30_Channel_Id) + /p:ArtifactsCategory=.NetCore /p:IsStableBuild=$(IsStableBuild) /p:IsInternalBuild=$(IsInternalBuild) /p:RepositoryName=$(Build.Repository.Name) diff --git a/eng/common/templates/post-build/channels/public-release.yml b/eng/common/templates/post-build/channels/public-release.yml index 25923020df8..574cb1c2b92 100644 --- a/eng/common/templates/post-build/channels/public-release.yml +++ b/eng/common/templates/post-build/channels/public-release.yml @@ -81,10 +81,10 @@ stages: /p:IsInternalBuild=$(IsInternalBuild) /p:RepositoryName=$(Build.Repository.Name) /p:CommitSha=$(Build.SourceVersion) - /p:NugetPath=$(Agent.BuildDirectory)/Nuget/NuGet.exe - /p:AzdoTargetFeedPAT='$(dn-bot-dnceng-unviersal-packages-rw)' - /p:TargetFeedPAT='$(dn-bot-dnceng-unviersal-packages-rw)' - /p:AzureStorageTargetFeedPAT='$(dotnetfeed-storage-access-key-1)' + /p:AzureStorageAccountName=$(ProxyBackedFeedsAccountName) + /p:AzureStorageAccountKey=$(dotnetfeed-storage-access-key-1) + /p:AzureDevOpsFeedsBaseUrl=$(dotnetfeed-internal-private-feed-url) + /p:NugetPath=$(Agent.BuildDirectory)\Nuget\NuGet.exe /p:BARBuildId=$(BARBuildId) /p:MaestroApiEndpoint='https://maestro-prod.westus2.cloudapp.azure.com' /p:BuildAssetRegistryToken='$(MaestroAccessToken)' diff --git a/eng/common/templates/post-build/channels/public-validation-release.yml b/eng/common/templates/post-build/channels/public-validation-release.yml index 114477d3adb..f12f402ad9a 100644 --- a/eng/common/templates/post-build/channels/public-validation-release.yml +++ b/eng/common/templates/post-build/channels/public-validation-release.yml @@ -48,6 +48,7 @@ stages: filePath: eng\common\sdk-task.ps1 arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet /p:ChannelId=$(PublicValidationRelease_30_Channel_Id) + /p:ArtifactsCategory=.NetCoreValidation /p:IsStableBuild=$(IsStableBuild) /p:IsInternalBuild=$(IsInternalBuild) /p:RepositoryName=$(Build.Repository.Name) diff --git a/eng/common/templates/post-build/common-variables.yml b/eng/common/templates/post-build/common-variables.yml index 82834673520..42df4ae77e3 100644 --- a/eng/common/templates/post-build/common-variables.yml +++ b/eng/common/templates/post-build/common-variables.yml @@ -14,5 +14,8 @@ variables: # Whether the build is internal or not IsInternalBuild: ${{ and(ne(variables['System.TeamProject'], 'public'), contains(variables['Build.SourceBranch'], 'internal')) }} + # Storage account name for proxy-backed feeds + ProxyBackedFeedsAccountName: dotnetfeed + SourceLinkCLIVersion: 3.0.0 SymbolToolVersion: 1.0.1 diff --git a/eng/common/templates/steps/perf-send-to-helix.yml b/eng/common/templates/steps/perf-send-to-helix.yml new file mode 100644 index 00000000000..b3ea9acf1f1 --- /dev/null +++ b/eng/common/templates/steps/perf-send-to-helix.yml @@ -0,0 +1,66 @@ +# Please remember to update the documentation if you make changes to these parameters! +parameters: + HelixSource: 'pr/default' # required -- sources must start with pr/, official/, prodcon/, or agent/ + HelixType: 'tests/default/' # required -- Helix telemetry which identifies what type of data this is; should include "test" for clarity and must end in '/' + HelixBuild: $(Build.BuildNumber) # required -- the build number Helix will use to identify this -- automatically set to the AzDO build number + HelixTargetQueues: '' # required -- semicolon delimited list of Helix queues to test on; see https://helix.dot.net/ for a list of queues + HelixAccessToken: '' # required -- access token to make Helix API requests; should be provided by the appropriate variable group + HelixPreCommands: '' # optional -- commands to run before Helix work item execution + HelixPostCommands: '' # optional -- commands to run after Helix work item execution + WorkItemDirectory: '' # optional -- a payload directory to zip up and send to Helix; requires WorkItemCommand; incompatible with XUnitProjects + CorrelationPayloadDirectory: '' # optional -- a directory to zip up and send to Helix as a correlation payload + IncludeDotNetCli: false # optional -- true will download a version of the .NET CLI onto the Helix machine as a correlation payload; requires DotNetCliPackageType and DotNetCliVersion + DotNetCliPackageType: '' # optional -- either 'sdk' or 'runtime'; determines whether the sdk or runtime will be sent to Helix; see https://raw.githubusercontent.com/dotnet/core/master/release-notes/releases.json + DotNetCliVersion: '' # optional -- version of the CLI to send to Helix; based on this: https://raw.githubusercontent.com/dotnet/core/master/release-notes/releases.json + EnableXUnitReporter: false # optional -- true enables XUnit result reporting to Mission Control + WaitForWorkItemCompletion: true # optional -- true will make the task wait until work items have been completed and fail the build if work items fail. False is "fire and forget." + Creator: '' # optional -- if the build is external, use this to specify who is sending the job + DisplayNamePrefix: 'Send job to Helix' # optional -- rename the beginning of the displayName of the steps in AzDO + condition: succeeded() # optional -- condition for step to execute; defaults to succeeded() + continueOnError: false # optional -- determines whether to continue the build if the step errors; defaults to false + +steps: + - powershell: $(Build.SourcesDirectory)\eng\common\msbuild.ps1 $(Build.SourcesDirectory)\eng\common\performance\perfhelixpublish.proj /restore /t:Test /bl:$(Build.SourcesDirectory)\artifacts\log\$env:BuildConfig\SendToHelix.binlog + displayName: ${{ parameters.DisplayNamePrefix }} (Windows) + env: + BuildConfig: $(_BuildConfig) + HelixSource: ${{ parameters.HelixSource }} + HelixType: ${{ parameters.HelixType }} + HelixBuild: ${{ parameters.HelixBuild }} + HelixTargetQueues: ${{ parameters.HelixTargetQueues }} + HelixAccessToken: ${{ parameters.HelixAccessToken }} + HelixPreCommands: ${{ parameters.HelixPreCommands }} + HelixPostCommands: ${{ parameters.HelixPostCommands }} + WorkItemDirectory: ${{ parameters.WorkItemDirectory }} + CorrelationPayloadDirectory: ${{ parameters.CorrelationPayloadDirectory }} + IncludeDotNetCli: ${{ parameters.IncludeDotNetCli }} + DotNetCliPackageType: ${{ parameters.DotNetCliPackageType }} + DotNetCliVersion: ${{ parameters.DotNetCliVersion }} + EnableXUnitReporter: ${{ parameters.EnableXUnitReporter }} + WaitForWorkItemCompletion: ${{ parameters.WaitForWorkItemCompletion }} + Creator: ${{ parameters.Creator }} + SYSTEM_ACCESSTOKEN: $(System.AccessToken) + condition: and(${{ parameters.condition }}, eq(variables['Agent.Os'], 'Windows_NT')) + continueOnError: ${{ parameters.continueOnError }} + - script: $BUILD_SOURCESDIRECTORY/eng/common/msbuild.sh $BUILD_SOURCESDIRECTORY/eng/common/performance/perfhelixpublish.proj /restore /t:Test /bl:$BUILD_SOURCESDIRECTORY/artifacts/log/$BuildConfig/SendToHelix.binlog + displayName: ${{ parameters.DisplayNamePrefix }} (Unix) + env: + BuildConfig: $(_BuildConfig) + HelixSource: ${{ parameters.HelixSource }} + HelixType: ${{ parameters.HelixType }} + HelixBuild: ${{ parameters.HelixBuild }} + HelixTargetQueues: ${{ parameters.HelixTargetQueues }} + HelixAccessToken: ${{ parameters.HelixAccessToken }} + HelixPreCommands: ${{ parameters.HelixPreCommands }} + HelixPostCommands: ${{ parameters.HelixPostCommands }} + WorkItemDirectory: ${{ parameters.WorkItemDirectory }} + CorrelationPayloadDirectory: ${{ parameters.CorrelationPayloadDirectory }} + IncludeDotNetCli: ${{ parameters.IncludeDotNetCli }} + DotNetCliPackageType: ${{ parameters.DotNetCliPackageType }} + DotNetCliVersion: ${{ parameters.DotNetCliVersion }} + EnableXUnitReporter: ${{ parameters.EnableXUnitReporter }} + WaitForWorkItemCompletion: ${{ parameters.WaitForWorkItemCompletion }} + Creator: ${{ parameters.Creator }} + SYSTEM_ACCESSTOKEN: $(System.AccessToken) + condition: and(${{ parameters.condition }}, ne(variables['Agent.Os'], 'Windows_NT')) + continueOnError: ${{ parameters.continueOnError }} diff --git a/eng/common/tools.ps1 b/eng/common/tools.ps1 index 60741f03901..9abaac015fb 100644 --- a/eng/common/tools.ps1 +++ b/eng/common/tools.ps1 @@ -84,7 +84,7 @@ function Exec-Process([string]$command, [string]$commandArgs) { return $global:LASTEXITCODE = $process.ExitCode } finally { - # If we didn't finish then an error occured or the user hit ctrl-c. Either + # If we didn't finish then an error occurred or the user hit ctrl-c. Either # way kill the process if (-not $finished) { $process.Kill() @@ -147,7 +147,7 @@ function InitializeDotNetCli([bool]$install) { # It also ensures that VS msbuild will use the downloaded sdk targets. $env:PATH = "$dotnetRoot;$env:PATH" - # Make Sure that our bootstrapped dotnet cli is avaliable in future steps of the Azure Pipelines build + # Make Sure that our bootstrapped dotnet cli is available in future steps of the Azure Pipelines build Write-PipelinePrependPath -Path $dotnetRoot Write-PipelineSetVariable -Name 'DOTNET_MULTILEVEL_LOOKUP' -Value '0' Write-PipelineSetVariable -Name 'DOTNET_SKIP_FIRST_TIME_EXPERIENCE' -Value '1' diff --git a/global.json b/global.json index 4c66387e58e..60dbe5efe92 100644 --- a/global.json +++ b/global.json @@ -10,7 +10,7 @@ } }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19359.6", + "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19360.8", "Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19069.2" } } From da432e1188ac1f461ec733e78a0a7c9c53a8d4d7 Mon Sep 17 00:00:00 2001 From: Phillip Carter Date: Thu, 11 Jul 2019 20:14:51 -0700 Subject: [PATCH 05/46] Better record and value formatting in tools (#7021) * Remove semicolons from record tooltips * Update to put a space between braces * Update formatting as best I can, plus some tests I guess * More baseline updates * Anonymous records * Update anon records tests * Add vsbsl lol * Update baselines and reduce a simple filter * Update baselines maybe last time * Update fsharpqa test * make tests pass * Add formatting for values * Update tests * Update test * Update fsharpqa tests * tryit * lol * get yote * shlerp * Update tests again I guess * more update * mother of pearl * this is a real turd --- src/fsharp/NicePrint.fs | 22 +- src/utils/sformat.fs | 20 +- .../Compiler/Language/AnonRecordTests.fs | 4 +- tests/fsharp/core/anon/lib.fs | 4 +- tests/fsharp/core/anon/test.fsx | 6 +- tests/fsharp/core/members/basics/test.fs | 4 +- .../printing/z.output.test.1000.stdout.bsl | 268 +-- .../printing/z.output.test.200.stdout.bsl | 124 +- .../printing/z.output.test.default.stdout.bsl | 1444 ++++++++--------- .../printing/z.output.test.off.stdout.bsl | 56 +- tests/fsharp/typecheck/sigs/neg113.bsl | 12 +- tests/fsharp/typecheck/sigs/neg113.vsbsl | 12 +- tests/fsharp/typecheck/sigs/neg_anon_1.bsl | 12 +- .../Source/Printing/BindingsWithValues01.fsx | 6 +- .../Source/Printing/CustomExceptions01.fs | 2 +- .../Tests.LanguageService.QuickInfo.fs | 2 +- .../tests/UnitTests/QuickInfoTests.fs | 6 +- 17 files changed, 1003 insertions(+), 1001 deletions(-) diff --git a/src/fsharp/NicePrint.fs b/src/fsharp/NicePrint.fs index 5d56543e992..2d9ea197db4 100644 --- a/src/fsharp/NicePrint.fs +++ b/src/fsharp/NicePrint.fs @@ -32,8 +32,8 @@ module internal PrintUtilities = let bracketIfL x lyt = if x then bracketL lyt else lyt let squareAngleL x = LeftL.leftBracketAngle ^^ x ^^ RightL.rightBracketAngle let angleL x = sepL Literals.leftAngle ^^ x ^^ rightL Literals.rightAngle - let braceL x = leftL Literals.leftBrace ^^ x ^^ rightL Literals.rightBrace - let braceBarL x = leftL Literals.leftBraceBar ^^ x ^^ rightL Literals.rightBraceBar + let braceL x = wordL Literals.leftBrace ^^ x ^^ wordL Literals.rightBrace + let braceBarL x = wordL Literals.leftBraceBar ^^ x ^^ wordL Literals.rightBraceBar let comment str = wordL (tagText (sprintf "(* %s *)" str)) @@ -942,7 +942,7 @@ module private PrintTypes = // Layout a tuple type | TType_anon (anonInfo, tys) -> - let core = sepListL (wordL (tagPunctuation ";")) (List.map2 (fun nm ty -> wordL (tagField nm) ^^ wordL (tagPunctuation ":") ^^ layoutTypeWithInfoAndPrec denv env prec ty) (Array.toList anonInfo.SortedNames) tys) + let core = sepListL (rightL (tagPunctuation ";")) (List.map2 (fun nm ty -> wordL (tagField nm) ^^ rightL (tagPunctuation ":") ^^ layoutTypeWithInfoAndPrec denv env prec ty) (Array.toList anonInfo.SortedNames) tys) if evalAnonInfoIsStruct anonInfo then WordL.keywordStruct --- braceBarL core else @@ -1457,7 +1457,7 @@ module private TastDefinitionPrinting = let lhs = tagRecordField fld.Name |> mkNav fld.DefinitionRange - |> wordL + |> wordL let lhs = (if addAccess then layoutAccessibility denv fld.Accessibility lhs else lhs) let lhs = if fld.IsMutable then wordL (tagKeyword "mutable") --- lhs else lhs (lhs ^^ RightL.colon) --- layoutType denv fld.FormalType @@ -1738,8 +1738,15 @@ module private TastDefinitionPrinting = let denv = denv.AddAccessibility tycon.TypeReprAccessibility match repr with | TRecdRepr _ -> - let recdFieldRefL fld = layoutRecdField false denv fld ^^ rightL (tagPunctuation ";") - let recdL = tycon.TrueFieldsAsList |> List.map recdFieldRefL |> applyMaxMembers denv.maxMembers |> aboveListL |> braceL + let recdFieldRefL fld = layoutRecdField false denv fld + + let recdL = + tycon.TrueFieldsAsList + |> List.map recdFieldRefL + |> applyMaxMembers denv.maxMembers + |> aboveListL + |> braceL + Some (addMembersAsWithEnd (addReprAccessL recdL)) | TFSharpObjectRepr r -> @@ -1771,8 +1778,7 @@ module private TastDefinitionPrinting = | _ -> [] let vsprs = tycon.MembersOfFSharpTyconSorted - |> List.filter (fun v -> isNil (Option.get v.MemberInfo).ImplementedSlotSigs) - |> List.filter (fun v -> v.IsDispatchSlot) + |> List.filter (fun v -> isNil (Option.get v.MemberInfo).ImplementedSlotSigs && v.IsDispatchSlot) |> List.map (fun vref -> PrintTastMemberOrVals.prettyLayoutOfValOrMemberNoInst denv vref.Deref) let staticValsLs = tycon.TrueFieldsAsList diff --git a/src/utils/sformat.fs b/src/utils/sformat.fs index b490283f674..228f4aba399 100644 --- a/src/utils/sformat.fs +++ b/src/utils/sformat.fs @@ -759,18 +759,14 @@ namespace Microsoft.FSharp.Text.StructuredPrintfImpl // pprinter: attributes // -------------------------------------------------------------------- - let makeRecordVerticalL nameXs = - let itemL (name,xL) = let labelL = wordL name in ((labelL ^^ wordL Literals.equals)) -- (xL ^^ (rightL Literals.semicolon)) - let braceL xs = (leftL Literals.leftBrace) ^^ xs ^^ (rightL Literals.rightBrace) - braceL (aboveListL (List.map itemL nameXs)) - - // This is a more compact rendering of records - and is more like tuples - let makeRecordHorizontalL nameXs = - let itemL (name,xL) = let labelL = wordL name in ((labelL ^^ wordL Literals.equals)) -- xL - let braceL xs = (leftL Literals.leftBrace) ^^ xs ^^ (rightL Literals.rightBrace) - braceL (sepListL (rightL Literals.semicolon) (List.map itemL nameXs)) - - let makeRecordL nameXs = makeRecordVerticalL nameXs + let makeRecordL nameXs = + let itemL (name,xL) = wordL name ^^ wordL Literals.equals -- xL + let braceL xs = (wordL Literals.leftBrace) ^^ xs ^^ (wordL Literals.rightBrace) + + nameXs + |> List.map itemL + |> aboveListL + |> braceL let makePropertiesL nameXs = let itemL (name,v) = diff --git a/tests/fsharp/Compiler/Language/AnonRecordTests.fs b/tests/fsharp/Compiler/Language/AnonRecordTests.fs index 0a4d1c18d9f..befa39f2bfc 100644 --- a/tests/fsharp/Compiler/Language/AnonRecordTests.fs +++ b/tests/fsharp/Compiler/Language/AnonRecordTests.fs @@ -34,7 +34,7 @@ let rAnon = RefClass() FSharpErrorSeverity.Error 1 (3, 13, 3, 42) - "A generic construct requires that the type 'struct {|R : int|}' have reference semantics, but it does not, i.e. it is a struct" + "A generic construct requires that the type 'struct {| R: int |}' have reference semantics, but it does not, i.e. it is a struct" [] let StructConstraintFail() = @@ -46,4 +46,4 @@ let sAnon = StructClass<{| S: int |}>() FSharpErrorSeverity.Error 1 (3, 13, 3, 38) - "A generic construct requires that the type '{|S : int|}' is a CLI or F# struct type" \ No newline at end of file + "A generic construct requires that the type '{| S: int |}' is a CLI or F# struct type" diff --git a/tests/fsharp/core/anon/lib.fs b/tests/fsharp/core/anon/lib.fs index 9fc219e1cb1..cc3f7de7043 100644 --- a/tests/fsharp/core/anon/lib.fs +++ b/tests/fsharp/core/anon/lib.fs @@ -52,8 +52,8 @@ module KindB1 = check "coijoiwcnkwle1" {| a = 1 |} {| a = 1 |} check "coijoiwcnkwle2" {| a = 2 |} {| a = 2 |} - check "coijoiwcnkwle3" (sprintf "%A" {| X = 10 |}) "{X = 10;}" - check "coijoiwcnkwle4" (sprintf "%A" {| X = 10; Y = 1 |} |> fun s -> s.Replace("\n","").Replace("\r","")) ("{X = 10; Y = 1;}".Replace("\n","").Replace("\r","")) + check "coijoiwcnkwle3" (sprintf "%A" {| X = 10 |}) "{ X = 10 }" + check "coijoiwcnkwle4" (sprintf "%A" {| X = 10; Y = 1 |}) "{ X = 10\n Y = 1 }" check "clekoiew09" (f2 {| X = {| X = 10 |} |}) 10 check "cewkew0oijew" (f2 {| X = {| X = 20 |} |}) 20 diff --git a/tests/fsharp/core/anon/test.fsx b/tests/fsharp/core/anon/test.fsx index 092a8977143..580772b3446 100644 --- a/tests/fsharp/core/anon/test.fsx +++ b/tests/fsharp/core/anon/test.fsx @@ -25,13 +25,13 @@ module Test = let testAccess = (KindB1.data1.X, KindB1.data3.X) - check "coijoiwcnkwle2" (sprintf "%A" KindB1.data1) "{X = 1;}" + check "coijoiwcnkwle2" (sprintf "%A" KindB1.data1) "{ X = 1 }" module Tests2 = let testAccess = (KindB2.data1.X, KindB2.data3.X, KindB2.data3.Y) - check "coijoiwcnkwle3" (sprintf "%A" KindB2.data1) "{X = 1;}" + check "coijoiwcnkwle3" (sprintf "%A" KindB2.data1) "{ X = 1 }" let _ = (KindB2.data1 = KindB2.data1) @@ -49,7 +49,7 @@ module CrossAssemblyTest = check "vrknvio1" (SampleAPI.SampleFunction {| A=1; B = "abc" |}) 4 // note, this is creating an instance of an anonymous record from another assembly. check "vrknvio2" (SampleAPI.SampleFunctionAcceptingList [ {| A=1; B = "abc" |}; {| A=2; B = "def" |} ]) [4; 5] // note, this is creating an instance of an anonymous record from another assembly. check "vrknvio3" (let d = SampleAPI.SampleFunctionReturningAnonRecd() in d.A + d.B.Length) 4 - check "vrknvio4" (let d = SampleAPIStruct.SampleFunctionReturningAnonRecd() in d.ToString().Replace("\n","").Replace("\r","")) """{A = 1; B = "abc";}""" + check "vrknvio4" (let d = SampleAPIStruct.SampleFunctionReturningAnonRecd() in d.ToString()) ("{ A = 1\n " + """B = "abc" }""") tests() module CrossAssemblyTestStruct = diff --git a/tests/fsharp/core/members/basics/test.fs b/tests/fsharp/core/members/basics/test.fs index 27c9e6c3a40..a5da244c0a6 100644 --- a/tests/fsharp/core/members/basics/test.fs +++ b/tests/fsharp/core/members/basics/test.fs @@ -1178,8 +1178,8 @@ module ToStringOnRecordTest = begin let a1 = {A = "201"; B = 7} let c1 = {C = "20"; D = 17} - let expected1 = "{A = \"201\";\n B = 7;}" - let expected2 = "{C = \"20\";\n D = 17;}" + let expected1 = "{ A = \"201\"\n B = 7 }" + let expected2 = "{ C = \"20\"\n D = 17 }" do test "record-tostring-def" (a1.ToString() = expected1) do test "record-sprintfO-def" ((sprintf "%O" a1) = expected1) diff --git a/tests/fsharp/core/printing/z.output.test.1000.stdout.bsl b/tests/fsharp/core/printing/z.output.test.1000.stdout.bsl index 1f9224b67b7..52c96dd7598 100644 --- a/tests/fsharp/core/printing/z.output.test.1000.stdout.bsl +++ b/tests/fsharp/core/printing/z.output.test.1000.stdout.bsl @@ -226,7 +226,7 @@ type T = end val f_as_method : x:int -> int val f_as_thunk : (int -> int) -val refCell : string ref = {contents = "value";} +val refCell : string ref = { contents = "value" } module D1 = begin val words : System.Collections.Generic.IDictionary val words2000 : System.Collections.Generic.IDictionary @@ -1134,7 +1134,7 @@ end | B > type internal T2 = - {x: int;} + { x: int } > type internal T3 @@ -1148,28 +1148,28 @@ end | B > type T2 = - internal {x: int;} + internal { x: int } > type private T1 = | A | B > type private T2 = - {x: int;} + { x: int } > type T1 = private | A | B > type T2 = - private {x: int;} + private { x: int } > type internal T1 = private | A | B > type internal T2 = - private {x: int;} + private { x: int } > type private T3 @@ -1233,121 +1233,121 @@ type 'a T1Pre with member E : IEvent > type r = - {f0: int; - f1: int; - f2: int; - f3: int; - f4: int; - f5: int; - f6: int; - f7: int; - f8: int; - f9: int;} -val r10 : r = {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;} + { f0: int + f1: int + f2: int + f3: int + f4: int + f5: int + f6: int + f7: int + f8: int + f9: int } +val r10 : r = { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 } val r10s : r [] = - [|{f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; ...|] + [|{ f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; ...|] val r10s' : string * r [] = ("one extra node", - [|{f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = ...;}; ...|]) + [|{ f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = ... }; ...|]) > val x1564_A1 : int = 1 @@ -1398,7 +1398,7 @@ val x1564_A3 : int = 3 | A | B type T2 = - {x: int;} + { x: int } type T3 type T4 = class @@ -1408,22 +1408,22 @@ val x1564_A3 : int = 3 | A | B type T6 = - {x: int;} + { x: int } type private T7 = | A | B type private T8 = - {x: int;} + { x: int } type T9 = private | A | B type T10 = - private {x: int;} + private { x: int } type T11 = private | A | B type T12 = - private {x: int;} + private { x: int } type private T13 type private T14 = class @@ -1446,7 +1446,7 @@ module internal PrivateM = begin | A | B type T2 = - {x: int;} + { x: int } type T3 type T4 = class @@ -1456,22 +1456,22 @@ module internal PrivateM = begin | A | B type T6 = - {x: int;} + { x: int } type private T7 = | A | B type private T8 = - {x: int;} + { x: int } type T9 = private | A | B type T10 = - private {x: int;} + private { x: int } type T11 = private | A | B type T12 = - private {x: int;} + private { x: int } type private T13 type private T14 = class @@ -1806,9 +1806,9 @@ module Regression1019_long = begin val single_infinity : float32 = infinityf end -> val it : int ref = {contents = 1;} +> val it : int ref = { contents = 1 } -> val x : int ref = {contents = 1;} +> val x : int ref = { contents = 1 } val f : (unit -> int) > val it : int = 1 @@ -2732,11 +2732,11 @@ val namedEx1 : exn = MyNamedException1 (5,"") val namedEx2 : exn = MyNamedException7 25 > type optionRecord = - {x: int option;} -val x : optionRecord = {x = None;} + { x: int option } +val x : optionRecord = { x = None } > type optionRecord = - {x: obj;} -val x : optionRecord = {x = null;} + { x: obj } +val x : optionRecord = { x = null } > > > diff --git a/tests/fsharp/core/printing/z.output.test.200.stdout.bsl b/tests/fsharp/core/printing/z.output.test.200.stdout.bsl index 0877fcb8002..249743e0cff 100644 --- a/tests/fsharp/core/printing/z.output.test.200.stdout.bsl +++ b/tests/fsharp/core/printing/z.output.test.200.stdout.bsl @@ -121,7 +121,7 @@ type T = end val f_as_method : x:int -> int val f_as_thunk : (int -> int) -val refCell : string ref = {contents = "value";} +val refCell : string ref = { contents = "value" } module D1 = begin val words : System.Collections.Generic.IDictionary val words2000 : System.Collections.Generic.IDictionary @@ -458,7 +458,7 @@ end | B > type internal T2 = - {x: int;} + { x: int } > type internal T3 @@ -472,28 +472,28 @@ end | B > type T2 = - internal {x: int;} + internal { x: int } > type private T1 = | A | B > type private T2 = - {x: int;} + { x: int } > type T1 = private | A | B > type T2 = - private {x: int;} + private { x: int } > type internal T1 = private | A | B > type internal T2 = - private {x: int;} + private { x: int } > type private T3 @@ -557,46 +557,46 @@ type 'a T1Pre with member E : IEvent > type r = - {f0: int; - f1: int; - f2: int; - f3: int; - f4: int; - f5: int; - f6: int; - f7: int; - f8: int; - f9: int;} -val r10 : r = {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;} -val r10s : r [] = [|{f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; ...|] -val r10s' : string * r [] = ("one extra node", [|{f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = ...;}; ...|]) + { f0: int + f1: int + f2: int + f3: int + f4: int + f5: int + f6: int + f7: int + f8: int + f9: int } +val r10 : r = { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 } +val r10s : r [] = [|{ f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; ...|] +val r10s' : string * r [] = ("one extra node", [|{ f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = ... }; ...|]) > val x1564_A1 : int = 1 @@ -647,7 +647,7 @@ val x1564_A3 : int = 3 | A | B type T2 = - {x: int;} + { x: int } type T3 type T4 = class @@ -657,22 +657,22 @@ val x1564_A3 : int = 3 | A | B type T6 = - {x: int;} + { x: int } type private T7 = | A | B type private T8 = - {x: int;} + { x: int } type T9 = private | A | B type T10 = - private {x: int;} + private { x: int } type T11 = private | A | B type T12 = - private {x: int;} + private { x: int } type private T13 type private T14 = class @@ -695,7 +695,7 @@ module internal PrivateM = begin | A | B type T2 = - {x: int;} + { x: int } type T3 type T4 = class @@ -705,22 +705,22 @@ module internal PrivateM = begin | A | B type T6 = - {x: int;} + { x: int } type private T7 = | A | B type private T8 = - {x: int;} + { x: int } type T9 = private | A | B type T10 = - private {x: int;} + private { x: int } type T11 = private | A | B type T12 = - private {x: int;} + private { x: int } type private T13 type private T14 = class @@ -1055,9 +1055,9 @@ module Regression1019_long = begin val single_infinity : float32 = infinityf end -> val it : int ref = {contents = 1;} +> val it : int ref = { contents = 1 } -> val x : int ref = {contents = 1;} +> val x : int ref = { contents = 1 } val f : (unit -> int) > val it : int = 1 @@ -1981,11 +1981,11 @@ val namedEx1 : exn = MyNamedException1 (5,"") val namedEx2 : exn = MyNamedException7 25 > type optionRecord = - {x: int option;} -val x : optionRecord = {x = None;} + { x: int option } +val x : optionRecord = { x = None } > type optionRecord = - {x: obj;} -val x : optionRecord = {x = null;} + { x: obj } +val x : optionRecord = { x = null } > > > diff --git a/tests/fsharp/core/printing/z.output.test.default.stdout.bsl b/tests/fsharp/core/printing/z.output.test.default.stdout.bsl index fab8d8dbaa8..f861d11fef2 100644 --- a/tests/fsharp/core/printing/z.output.test.default.stdout.bsl +++ b/tests/fsharp/core/printing/z.output.test.default.stdout.bsl @@ -241,7 +241,7 @@ type T = end val f_as_method : x:int -> int val f_as_thunk : (int -> int) -val refCell : string ref = {contents = "value";} +val refCell : string ref = { contents = "value" } module D1 = begin val words : System.Collections.Generic.IDictionary val words2000 : System.Collections.Generic.IDictionary @@ -4072,7 +4072,7 @@ end | B > type internal T2 = - {x: int;} + { x: int } > type internal T3 @@ -4086,28 +4086,28 @@ end | B > type T2 = - internal {x: int;} + internal { x: int } > type private T1 = | A | B > type private T2 = - {x: int;} + { x: int } > type T1 = private | A | B > type T2 = - private {x: int;} + private { x: int } > type internal T1 = private | A | B > type internal T2 = - private {x: int;} + private { x: int } > type private T3 @@ -4171,709 +4171,709 @@ type 'a T1Pre with member E : IEvent > type r = - {f0: int; - f1: int; - f2: int; - f3: int; - f4: int; - f5: int; - f6: int; - f7: int; - f8: int; - f9: int;} -val r10 : r = {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;} + { f0: int + f1: int + f2: int + f3: int + f4: int + f5: int + f6: int + f7: int + f8: int + f9: int } +val r10 : r = { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 } val r10s : r [] = - [|{f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; - {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; - {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; - {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; - {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; - {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; - {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}|] + [|{ f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; + { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; + { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; + { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; + { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; + { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; + { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }|] val r10s' : string * r [] = ("one extra node", - [|{f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; - {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; - {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; - {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; - {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; - {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}; - {f0 = 0; - f1 = 1; - f2 = 2; - f3 = 3; - f4 = 4; - f5 = 5; - f6 = 6; - f7 = 7; - f8 = 8; - f9 = 9;}|]) + [|{ f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; + { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; + { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; + { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; + { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; + { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }; + { f0 = 0 + f1 = 1 + f2 = 2 + f3 = 3 + f4 = 4 + f5 = 5 + f6 = 6 + f7 = 7 + f8 = 8 + f9 = 9 }|]) > val x1564_A1 : int = 1 @@ -4924,7 +4924,7 @@ val x1564_A3 : int = 3 | A | B type T2 = - {x: int;} + { x: int } type T3 type T4 = class @@ -4934,22 +4934,22 @@ val x1564_A3 : int = 3 | A | B type T6 = - {x: int;} + { x: int } type private T7 = | A | B type private T8 = - {x: int;} + { x: int } type T9 = private | A | B type T10 = - private {x: int;} + private { x: int } type T11 = private | A | B type T12 = - private {x: int;} + private { x: int } type private T13 type private T14 = class @@ -4972,7 +4972,7 @@ module internal PrivateM = begin | A | B type T2 = - {x: int;} + { x: int } type T3 type T4 = class @@ -4982,22 +4982,22 @@ module internal PrivateM = begin | A | B type T6 = - {x: int;} + { x: int } type private T7 = | A | B type private T8 = - {x: int;} + { x: int } type T9 = private | A | B type T10 = - private {x: int;} + private { x: int } type T11 = private | A | B type T12 = - private {x: int;} + private { x: int } type private T13 type private T14 = class @@ -5332,9 +5332,9 @@ module Regression1019_long = begin val single_infinity : float32 = infinityf end -> val it : int ref = {contents = 1;} +> val it : int ref = { contents = 1 } -> val x : int ref = {contents = 1;} +> val x : int ref = { contents = 1 } val f : (unit -> int) > val it : int = 1 @@ -6258,11 +6258,11 @@ val namedEx1 : exn = MyNamedException1 (5,"") val namedEx2 : exn = MyNamedException7 25 > type optionRecord = - {x: int option;} -val x : optionRecord = {x = None;} + { x: int option } +val x : optionRecord = { x = None } > type optionRecord = - {x: obj;} -val x : optionRecord = {x = null;} + { x: obj } +val x : optionRecord = { x = null } > > > diff --git a/tests/fsharp/core/printing/z.output.test.off.stdout.bsl b/tests/fsharp/core/printing/z.output.test.off.stdout.bsl index 2b0d6ca9877..9c90f3e2fac 100644 --- a/tests/fsharp/core/printing/z.output.test.off.stdout.bsl +++ b/tests/fsharp/core/printing/z.output.test.off.stdout.bsl @@ -289,7 +289,7 @@ end | B > type internal T2 = - {x: int;} + { x: int } > type internal T3 @@ -303,28 +303,28 @@ end | B > type T2 = - internal {x: int;} + internal { x: int } > type private T1 = | A | B > type private T2 = - {x: int;} + { x: int } > type T1 = private | A | B > type T2 = - private {x: int;} + private { x: int } > type internal T1 = private | A | B > type internal T2 = - private {x: int;} + private { x: int } > type private T3 @@ -388,16 +388,16 @@ type 'a T1Pre with member E : IEvent > type r = - {f0: int; - f1: int; - f2: int; - f3: int; - f4: int; - f5: int; - f6: int; - f7: int; - f8: int; - f9: int;} + { f0: int + f1: int + f2: int + f3: int + f4: int + f5: int + f6: int + f7: int + f8: int + f9: int } val r10 : r val r10s : r [] val r10s' : string * r [] @@ -451,7 +451,7 @@ val x1564_A3 : int | A | B type T2 = - {x: int;} + { x: int } type T3 type T4 = class @@ -461,22 +461,22 @@ val x1564_A3 : int | A | B type T6 = - {x: int;} + { x: int } type private T7 = | A | B type private T8 = - {x: int;} + { x: int } type T9 = private | A | B type T10 = - private {x: int;} + private { x: int } type T11 = private | A | B type T12 = - private {x: int;} + private { x: int } type private T13 type private T14 = class @@ -499,7 +499,7 @@ module internal PrivateM = begin | A | B type T2 = - {x: int;} + { x: int } type T3 type T4 = class @@ -509,22 +509,22 @@ module internal PrivateM = begin | A | B type T6 = - {x: int;} + { x: int } type private T7 = | A | B type private T8 = - {x: int;} + { x: int } type T9 = private | A | B type T10 = - private {x: int;} + private { x: int } type T11 = private | A | B type T12 = - private {x: int;} + private { x: int } type private T13 type private T14 = class @@ -831,7 +831,7 @@ module Regression1019_long = begin val single_infinity : float32 end -> val it : int ref = {contents = 1;} +> val it : int ref = { contents = 1 } > val x : int ref val f : (unit -> int) @@ -1755,11 +1755,11 @@ val namedEx1 : exn val namedEx2 : exn > type optionRecord = - {x: int option;} + { x: int option } val x : optionRecord > type optionRecord = - {x: obj;} + { x: obj } val x : optionRecord > > > diff --git a/tests/fsharp/typecheck/sigs/neg113.bsl b/tests/fsharp/typecheck/sigs/neg113.bsl index 211ba670f91..b9f0190c63b 100644 --- a/tests/fsharp/typecheck/sigs/neg113.bsl +++ b/tests/fsharp/typecheck/sigs/neg113.bsl @@ -3,20 +3,20 @@ neg113.fs(5,50,5,61): typecheck error FS0001: Two anonymous record types have mi neg113.fs(7,41,7,52): typecheck error FS0001: Two anonymous record types have mismatched sets of field names '["b"]' and '["a"]' -neg113.fs(10,27,10,55): typecheck error FS0059: The type '{|a : int|}' does not have any proper subtypes and need not be used as the target of a static coercion +neg113.fs(10,27,10,55): typecheck error FS0059: The type '{| a: int |}' does not have any proper subtypes and need not be used as the target of a static coercion neg113.fs(10,27,10,55): typecheck error FS0193: Type constraint mismatch. The type - '{|b : int|}' + '{| b: int |}' is not compatible with type - '{|a : int|}' + '{| a: int |}' -neg113.fs(13,27,13,62): typecheck error FS0059: The type '{|a : int|}' does not have any proper subtypes and need not be used as the target of a static coercion +neg113.fs(13,27,13,62): typecheck error FS0059: The type '{| a: int |}' does not have any proper subtypes and need not be used as the target of a static coercion neg113.fs(13,27,13,62): typecheck error FS0193: Type constraint mismatch. The type - '{|a : int ; b : int|}' + '{| a: int; b: int |}' is not compatible with type - '{|a : int|}' + '{| a: int |}' neg113.fs(18,34,18,36): typecheck error FS0001: The type '('a -> 'a)' does not support the 'comparison' constraint. For example, it does not support the 'System.IComparable' interface diff --git a/tests/fsharp/typecheck/sigs/neg113.vsbsl b/tests/fsharp/typecheck/sigs/neg113.vsbsl index 211ba670f91..b9f0190c63b 100644 --- a/tests/fsharp/typecheck/sigs/neg113.vsbsl +++ b/tests/fsharp/typecheck/sigs/neg113.vsbsl @@ -3,20 +3,20 @@ neg113.fs(5,50,5,61): typecheck error FS0001: Two anonymous record types have mi neg113.fs(7,41,7,52): typecheck error FS0001: Two anonymous record types have mismatched sets of field names '["b"]' and '["a"]' -neg113.fs(10,27,10,55): typecheck error FS0059: The type '{|a : int|}' does not have any proper subtypes and need not be used as the target of a static coercion +neg113.fs(10,27,10,55): typecheck error FS0059: The type '{| a: int |}' does not have any proper subtypes and need not be used as the target of a static coercion neg113.fs(10,27,10,55): typecheck error FS0193: Type constraint mismatch. The type - '{|b : int|}' + '{| b: int |}' is not compatible with type - '{|a : int|}' + '{| a: int |}' -neg113.fs(13,27,13,62): typecheck error FS0059: The type '{|a : int|}' does not have any proper subtypes and need not be used as the target of a static coercion +neg113.fs(13,27,13,62): typecheck error FS0059: The type '{| a: int |}' does not have any proper subtypes and need not be used as the target of a static coercion neg113.fs(13,27,13,62): typecheck error FS0193: Type constraint mismatch. The type - '{|a : int ; b : int|}' + '{| a: int; b: int |}' is not compatible with type - '{|a : int|}' + '{| a: int |}' neg113.fs(18,34,18,36): typecheck error FS0001: The type '('a -> 'a)' does not support the 'comparison' constraint. For example, it does not support the 'System.IComparable' interface diff --git a/tests/fsharp/typecheck/sigs/neg_anon_1.bsl b/tests/fsharp/typecheck/sigs/neg_anon_1.bsl index d7aaaecd939..3e75d81144c 100644 --- a/tests/fsharp/typecheck/sigs/neg_anon_1.bsl +++ b/tests/fsharp/typecheck/sigs/neg_anon_1.bsl @@ -3,20 +3,20 @@ neg_anon_1.fs(5,50,5,61): typecheck error FS0001: Two anonymous record types hav neg_anon_1.fs(7,41,7,52): typecheck error FS0001: Two anonymous record types have mismatched sets of field names '["b"]' and '["a"]' -neg_anon_1.fs(10,27,10,55): typecheck error FS0059: The type '{|a : int|}' does not have any proper subtypes and need not be used as the target of a static coercion +neg_anon_1.fs(10,27,10,55): typecheck error FS0059: The type '{| a: int |}' does not have any proper subtypes and need not be used as the target of a static coercion neg_anon_1.fs(10,27,10,55): typecheck error FS0193: Type constraint mismatch. The type - '{|b : int|}' + '{| b: int |}' is not compatible with type - '{|a : int|}' + '{| a: int |}' -neg_anon_1.fs(13,27,13,62): typecheck error FS0059: The type '{|a : int|}' does not have any proper subtypes and need not be used as the target of a static coercion +neg_anon_1.fs(13,27,13,62): typecheck error FS0059: The type '{| a: int |}' does not have any proper subtypes and need not be used as the target of a static coercion neg_anon_1.fs(13,27,13,62): typecheck error FS0193: Type constraint mismatch. The type - '{|a : int ; b : int|}' + '{| a: int; b: int |}' is not compatible with type - '{|a : int|}' + '{| a: int |}' neg_anon_1.fs(18,34,18,36): typecheck error FS0001: The type '('a -> 'a)' does not support the 'comparison' constraint. For example, it does not support the 'System.IComparable' interface diff --git a/tests/fsharpqa/Source/Printing/BindingsWithValues01.fsx b/tests/fsharpqa/Source/Printing/BindingsWithValues01.fsx index 052100c05f6..30b453b9fc6 100644 --- a/tests/fsharpqa/Source/Printing/BindingsWithValues01.fsx +++ b/tests/fsharpqa/Source/Printing/BindingsWithValues01.fsx @@ -4,14 +4,14 @@ // Test for FSharp1.0:2581 - FSI should display bound values, not just evaluated expressions (was: FSI should print the value of the last declared value is there is no last expression) //type RecT = -// {Name: string;} +// { Name: string } //type Bldg = // \| House // \| Museum // \| Office //val a : int = 1 //val B : string = "Hello" -//val c' : RecT = {Name = "F#";} +//val c' : RecT = { Name = "F#" } //val _d : Bldg = Office //val e : seq //val F'F : int list = \[3; 2; 1] @@ -19,7 +19,7 @@ //val g' : Set<'a> //val getPointF : x:float32 \* y:float32 -> System\.Drawing\.PointF //val h : System\.Drawing\.PointF = {X=.+, Y=.+} -//val i : int \* RecT \* Bldg = \(1, {Name = "F#";}, Office\) +//val i : int \* RecT \* Bldg = \(1, { Name = "F#" }, Office\) //val J_ : int \[\] = \[\|1; 2; 3\|] //val j_' : float \[\] = \[\|1\.0; 1\.0\|] //val j_'_ : RecT \[\] = \[\|\|] diff --git a/tests/fsharpqa/Source/Printing/CustomExceptions01.fs b/tests/fsharpqa/Source/Printing/CustomExceptions01.fs index 6f33bff2e19..7a2949be917 100644 --- a/tests/fsharpqa/Source/Printing/CustomExceptions01.fs +++ b/tests/fsharpqa/Source/Printing/CustomExceptions01.fs @@ -16,7 +16,7 @@ exception WeekendEx of WeekendDay if sprintf "%A" (Foo) <> "Foo" || sprintf "%A" (Bar 10) <> "Bar 10" || sprintf "%A" (FooBaz System.DateTime.Today) <> ("FooBaz " + System.DateTime.Today.ToString()) - || sprintf "%A" (MarkupEx {Body = ""}) <> "MarkupEx {Body = \"\";}" + || sprintf "%A" (MarkupEx {Body = ""}) <> "MarkupEx { Body = \"\" }" || sprintf "%A" (WeekendEx Saturday) <> "WeekendEx Saturday" then exit 1 diff --git a/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.QuickInfo.fs b/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.QuickInfo.fs index 16d2f34a4e8..09f358678df 100644 --- a/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.QuickInfo.fs +++ b/vsintegration/tests/UnitTests/LegacyLanguageService/Tests.LanguageService.QuickInfo.fs @@ -762,7 +762,7 @@ Full name: Microsoft.FSharp.Control.Async""".TrimStart().Replace("\r\n", "\n") let fileContents = """namespace NS type Re(*MarkerRecord*) = { X : int } """ - let expectedQuickinfoTypeRecored = "type Re = {X: int;}" + let expectedQuickinfoTypeRecored = "type Re = { X: int }" this.InfoInDeclarationTestQuickInfoImplWithTrim fileContents "Re(*MarkerRecord*)" expectedQuickinfoTypeRecored diff --git a/vsintegration/tests/UnitTests/QuickInfoTests.fs b/vsintegration/tests/UnitTests/QuickInfoTests.fs index bfa6c7df729..415079942e7 100644 --- a/vsintegration/tests/UnitTests/QuickInfoTests.fs +++ b/vsintegration/tests/UnitTests/QuickInfoTests.fs @@ -154,9 +154,9 @@ module Test = let quickInfo = GetQuickInfoTextFromCode code let expected = expectedLines [ "type MyEmployee =" - " {mutable Name: string;" - " mutable Age: int;" - " mutable IsFTE: bool;}" + " { mutable Name: string" + " mutable Age: int" + " mutable IsFTE: bool }" "Full name: FsTest.MyEmployee" ] Assert.AreEqual(expected, quickInfo) () From 660a5457ca46d337df61aae49fe681eb7cbdbc4d Mon Sep 17 00:00:00 2001 From: Don Syme Date: Fri, 12 Jul 2019 06:04:23 +0100 Subject: [PATCH 06/46] fix portable PDBs for anon records (#7099) --- src/absil/ilwritepdb.fs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/absil/ilwritepdb.fs b/src/absil/ilwritepdb.fs index 260ccbe238e..2a992ed4855 100644 --- a/src/absil/ilwritepdb.fs +++ b/src/absil/ilwritepdb.fs @@ -403,12 +403,17 @@ let generatePortablePdb (embedAllSource: bool) (embedSourceList: string list) (s if i < 1 || offsetDelta > 0 then builder.WriteCompressedInteger offsetDelta - // Hidden-sequence-point-record - if startLine = 0xfeefee || endLine = 0xfeefee || (startColumn = 0 && endColumn = 0) + // Check for hidden-sequence-point-record + if startLine = 0xfeefee || + endLine = 0xfeefee || + (startColumn = 0 && endColumn = 0) || + ((endLine - startLine) = 0 && (endColumn - startColumn) = 0) then + // Hidden-sequence-point-record builder.WriteCompressedInteger 0 builder.WriteCompressedInteger 0 - else // Non-hidden-sequence-point-record + else + // Non-hidden-sequence-point-record let deltaLines = endLine - startLine // lines builder.WriteCompressedInteger deltaLines From 9dc9d0e6d0e07ed8efe2ea83e6f8532e87c5c237 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Fri, 12 Jul 2019 06:04:23 +0100 Subject: [PATCH 07/46] fix portable PDBs for anon records (#7099) --- src/absil/ilwritepdb.fs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/absil/ilwritepdb.fs b/src/absil/ilwritepdb.fs index 260ccbe238e..2a992ed4855 100644 --- a/src/absil/ilwritepdb.fs +++ b/src/absil/ilwritepdb.fs @@ -403,12 +403,17 @@ let generatePortablePdb (embedAllSource: bool) (embedSourceList: string list) (s if i < 1 || offsetDelta > 0 then builder.WriteCompressedInteger offsetDelta - // Hidden-sequence-point-record - if startLine = 0xfeefee || endLine = 0xfeefee || (startColumn = 0 && endColumn = 0) + // Check for hidden-sequence-point-record + if startLine = 0xfeefee || + endLine = 0xfeefee || + (startColumn = 0 && endColumn = 0) || + ((endLine - startLine) = 0 && (endColumn - startColumn) = 0) then + // Hidden-sequence-point-record builder.WriteCompressedInteger 0 builder.WriteCompressedInteger 0 - else // Non-hidden-sequence-point-record + else + // Non-hidden-sequence-point-record let deltaLines = endLine - startLine // lines builder.WriteCompressedInteger deltaLines From 60c915afd59740184da73e34ae0146622feae582 Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Fri, 12 Jul 2019 07:50:38 +0200 Subject: [PATCH 08/46] Moving ElseBranchHasWrongTypeTests over to NUnit (#7104) --- .../ElseBranchHasWrongTypeTests.fs | 176 ++++++++++++++++++ tests/fsharp/FSharpSuite.Tests.fsproj | 3 +- .../ElseBranchContextDoesntPropagateInAppl.fs | 11 -- ...ElseBranchContextDoesntPropagateInAppl2.fs | 12 -- ...seBranchContextDoesntPropagateInForLoop.fs | 14 -- ...extDoesntPropagateToLinesBeforeLastLine.fs | 13 -- .../Warnings/ElseBranchHasWrongContextType.fs | 9 - .../Source/Warnings/ElseBranchHasWrongType.fs | 9 - .../Warnings/ElseBranchHasWrongType2.fs | 10 - .../Warnings/ElseBranchHasWrongType3.fs | 13 -- .../Warnings/ElseBranchHasWrongType4.fs | 15 -- .../Warnings/NestedElseBranchHasWrongType.fs | 10 - tests/fsharpqa/Source/Warnings/env.lst | 10 - 13 files changed, 178 insertions(+), 127 deletions(-) create mode 100644 tests/fsharp/Compiler/ErrorMessages/ElseBranchHasWrongTypeTests.fs delete mode 100644 tests/fsharpqa/Source/Warnings/ElseBranchContextDoesntPropagateInAppl.fs delete mode 100644 tests/fsharpqa/Source/Warnings/ElseBranchContextDoesntPropagateInAppl2.fs delete mode 100644 tests/fsharpqa/Source/Warnings/ElseBranchContextDoesntPropagateInForLoop.fs delete mode 100644 tests/fsharpqa/Source/Warnings/ElseBranchContextDoesntPropagateToLinesBeforeLastLine.fs delete mode 100644 tests/fsharpqa/Source/Warnings/ElseBranchHasWrongContextType.fs delete mode 100644 tests/fsharpqa/Source/Warnings/ElseBranchHasWrongType.fs delete mode 100644 tests/fsharpqa/Source/Warnings/ElseBranchHasWrongType2.fs delete mode 100644 tests/fsharpqa/Source/Warnings/ElseBranchHasWrongType3.fs delete mode 100644 tests/fsharpqa/Source/Warnings/ElseBranchHasWrongType4.fs delete mode 100644 tests/fsharpqa/Source/Warnings/NestedElseBranchHasWrongType.fs diff --git a/tests/fsharp/Compiler/ErrorMessages/ElseBranchHasWrongTypeTests.fs b/tests/fsharp/Compiler/ErrorMessages/ElseBranchHasWrongTypeTests.fs new file mode 100644 index 00000000000..21c7bb29269 --- /dev/null +++ b/tests/fsharp/Compiler/ErrorMessages/ElseBranchHasWrongTypeTests.fs @@ -0,0 +1,176 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace FSharp.Compiler.UnitTests + +open NUnit.Framework +open FSharp.Compiler.SourceCodeServices + +[] +module ``Else branch has wrong type`` = + + [] + let ``Else branch is int while if branch is string``() = + CompilerAssert.TypeCheckSingleError + """ +let test = 100 +let y = + if test > 10 then "test" + else 123 + """ + FSharpErrorSeverity.Error + 1 + (5, 10, 5, 13) + "All branches of an 'if' expression must return values of the same type as the first branch, which here is 'string'. This branch returns a value of type 'int'." + + [] + let ``Else branch is a function that returns int while if branch is string``() = + CompilerAssert.TypeCheckSingleError + """ +let test = 100 +let f x = test +let y = + if test > 10 then "test" + else f 10 + """ + FSharpErrorSeverity.Error + 1 + (6, 10, 6, 14) + "All branches of an 'if' expression must return values of the same type as the first branch, which here is 'string'. This branch returns a value of type 'int'." + + + [] + let ``Else branch is a sequence of expressions that returns int while if branch is string``() = + CompilerAssert.TypeCheckSingleError + """ +let f x = x + 4 + +let y = + if true then + "" + else + "" |> ignore + (f 5) + """ + FSharpErrorSeverity.Error + 1 + (9, 10, 9, 13) + "All branches of an 'if' expression must return values of the same type as the first branch, which here is 'string'. This branch returns a value of type 'int'." + + + [] + let ``Else branch is a longer sequence of expressions that returns int while if branch is string``() = + CompilerAssert.TypeCheckSingleError + """ +let f x = x + 4 + +let y = + if true then + "" + else + "" |> ignore + let z = f 4 + let a = 3 * z + (f a) + """ + FSharpErrorSeverity.Error + 1 + (11, 10, 11, 13) + "All branches of an 'if' expression must return values of the same type as the first branch, which here is 'string'. This branch returns a value of type 'int'." + + + [] + let ``Else branch context doesn't propagate into function application``() = + CompilerAssert.TypeCheckSingleError + """ +let test = 100 +let f x : string = x +let y = + if test > 10 then "test" + else + f 123 + """ + FSharpErrorSeverity.Error + 1 + (7, 11, 7, 14) + "This expression was expected to have type\n 'string' \nbut here has type\n 'int' " + + [] + let ``Else branch context doesn't propagate into function application even if not last expr``() = + CompilerAssert.TypeCheckSingleError + """ +let test = 100 +let f x = printfn "%s" x +let y = + if test > 10 then "test" + else + f 123 + "test" + """ + FSharpErrorSeverity.Error + 1 + (7, 11, 7, 14) + "This expression was expected to have type\n 'string' \nbut here has type\n 'int' " + + [] + let ``Else branch context doesn't propagate into for loop``() = + CompilerAssert.TypeCheckSingleError + """ +let test = 100 +let list = [1..10] +let y = + if test > 10 then "test" + else + for (x:string) in list do + printfn "%s" x + + "test" + """ + FSharpErrorSeverity.Error + 1 + (7, 14, 7, 22) + "This expression was expected to have type\n 'int' \nbut here has type\n 'string' " + + [] + let ``Else branch context doesn't propagate to lines before last line``() = + CompilerAssert.TypeCheckSingleError + """ +let test = 100 +let list = [1..10] +let y = + if test > 10 then "test" + else + printfn "%s" 1 + + "test" + """ + FSharpErrorSeverity.Error + 1 + (7, 22, 7, 23) + "This expression was expected to have type\n 'string' \nbut here has type\n 'int' " + + [] + let ``Else branch should not have wrong context type``() = + CompilerAssert.TypeCheckWithErrors + """ +let x = 1 +let y : bool = + if x = 2 then "A" + else "B" + """ + [| FSharpErrorSeverity.Error, 1, (4, 19, 4, 22), "The 'if' expression needs to have type 'bool' to satisfy context type requirements. It currently has type 'string'." + FSharpErrorSeverity.Error, 1, (5, 10, 5, 13), "All branches of an 'if' expression must return values of the same type as the first branch, which here is 'bool'. This branch returns a value of type 'string'." |] + + + [] + let ``Else branch has wrong type in nested if``() = + CompilerAssert.TypeCheckWithErrors + """ +let x = 1 +if x = 1 then true +else + if x = 2 then "A" + else "B" + """ + [| FSharpErrorSeverity.Error, 1, (5, 19, 5, 22), "All branches of an 'if' expression must return values of the same type as the first branch, which here is 'bool'. This branch returns a value of type 'string'." + FSharpErrorSeverity.Error, 1, (6, 10, 6, 13), "All branches of an 'if' expression must return values of the same type as the first branch, which here is 'bool'. This branch returns a value of type 'string'." + FSharpErrorSeverity.Warning, 20, (3, 1, 6, 13), "The result of this expression has type 'bool' and is implicitly ignored. Consider using 'ignore' to discard this value explicitly, e.g. 'expr |> ignore', or 'let' to bind the result to a name, e.g. 'let result = expr'." |] diff --git a/tests/fsharp/FSharpSuite.Tests.fsproj b/tests/fsharp/FSharpSuite.Tests.fsproj index 10e1f4733ac..6335b5172cd 100644 --- a/tests/fsharp/FSharpSuite.Tests.fsproj +++ b/tests/fsharp/FSharpSuite.Tests.fsproj @@ -1,4 +1,4 @@ - + @@ -32,6 +32,7 @@ + diff --git a/tests/fsharpqa/Source/Warnings/ElseBranchContextDoesntPropagateInAppl.fs b/tests/fsharpqa/Source/Warnings/ElseBranchContextDoesntPropagateInAppl.fs deleted file mode 100644 index 79152abb78a..00000000000 --- a/tests/fsharpqa/Source/Warnings/ElseBranchContextDoesntPropagateInAppl.fs +++ /dev/null @@ -1,11 +0,0 @@ -// #Warnings -//This expression was expected to have - -let test = 100 -let f x : string = x -let y = - if test > 10 then "test" - else - f 123 - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/ElseBranchContextDoesntPropagateInAppl2.fs b/tests/fsharpqa/Source/Warnings/ElseBranchContextDoesntPropagateInAppl2.fs deleted file mode 100644 index 5478d8b09d3..00000000000 --- a/tests/fsharpqa/Source/Warnings/ElseBranchContextDoesntPropagateInAppl2.fs +++ /dev/null @@ -1,12 +0,0 @@ -// #Warnings -//This expression was expected to have - -let test = 100 -let f x = printfn "%s" x -let y = - if test > 10 then "test" - else - f 123 - "test" - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/ElseBranchContextDoesntPropagateInForLoop.fs b/tests/fsharpqa/Source/Warnings/ElseBranchContextDoesntPropagateInForLoop.fs deleted file mode 100644 index bfd5a18dd17..00000000000 --- a/tests/fsharpqa/Source/Warnings/ElseBranchContextDoesntPropagateInForLoop.fs +++ /dev/null @@ -1,14 +0,0 @@ -// #Warnings -//This expression was expected to have - -let test = 100 -let list = [1..10] -let y = - if test > 10 then "test" - else - for (x:string) in list do - printfn "%s" x - - "test" - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/ElseBranchContextDoesntPropagateToLinesBeforeLastLine.fs b/tests/fsharpqa/Source/Warnings/ElseBranchContextDoesntPropagateToLinesBeforeLastLine.fs deleted file mode 100644 index 9facc603ff6..00000000000 --- a/tests/fsharpqa/Source/Warnings/ElseBranchContextDoesntPropagateToLinesBeforeLastLine.fs +++ /dev/null @@ -1,13 +0,0 @@ -// #Warnings -//This expression was expected to have type - -let test = 100 -let list = [1..10] -let y = - if test > 10 then "test" - else - printfn "%s" 1 - - "test" - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/ElseBranchHasWrongContextType.fs b/tests/fsharpqa/Source/Warnings/ElseBranchHasWrongContextType.fs deleted file mode 100644 index 895881ac7be..00000000000 --- a/tests/fsharpqa/Source/Warnings/ElseBranchHasWrongContextType.fs +++ /dev/null @@ -1,9 +0,0 @@ -// #Warnings -//The 'if' expression needs to have type 'bool' - -let x = 1 -let y : bool = - if x = 2 then "A" - else "B" - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/ElseBranchHasWrongType.fs b/tests/fsharpqa/Source/Warnings/ElseBranchHasWrongType.fs deleted file mode 100644 index b14b495304e..00000000000 --- a/tests/fsharpqa/Source/Warnings/ElseBranchHasWrongType.fs +++ /dev/null @@ -1,9 +0,0 @@ -// #Warnings -//All branches of an 'if' expression must return values of the same type as the first branch, which here is 'string'. This branch returns a value of type 'int'. - -let test = 100 -let y = - if test > 10 then "test" - else 123 - -exit 0 diff --git a/tests/fsharpqa/Source/Warnings/ElseBranchHasWrongType2.fs b/tests/fsharpqa/Source/Warnings/ElseBranchHasWrongType2.fs deleted file mode 100644 index 06d83f76aa0..00000000000 --- a/tests/fsharpqa/Source/Warnings/ElseBranchHasWrongType2.fs +++ /dev/null @@ -1,10 +0,0 @@ -// #Warnings -//All branches of an 'if' expression must return values of the same type as the first branch, which here is 'string'. This branch returns a value of type 'int'. - -let test = 100 -let f x = test -let y = - if test > 10 then "test" - else f 10 - -exit 0 diff --git a/tests/fsharpqa/Source/Warnings/ElseBranchHasWrongType3.fs b/tests/fsharpqa/Source/Warnings/ElseBranchHasWrongType3.fs deleted file mode 100644 index 1306c794759..00000000000 --- a/tests/fsharpqa/Source/Warnings/ElseBranchHasWrongType3.fs +++ /dev/null @@ -1,13 +0,0 @@ -// #Warnings -//All branches of an 'if' expression must return values of the same type as the first branch, which here is 'string'. This branch returns a value of type 'int'. - -let f x = x + 4 - -let y = - if true then - "" - else - "" |> ignore - (f 5) - -exit 0 diff --git a/tests/fsharpqa/Source/Warnings/ElseBranchHasWrongType4.fs b/tests/fsharpqa/Source/Warnings/ElseBranchHasWrongType4.fs deleted file mode 100644 index 8339a930d30..00000000000 --- a/tests/fsharpqa/Source/Warnings/ElseBranchHasWrongType4.fs +++ /dev/null @@ -1,15 +0,0 @@ -// #Warnings -//All branches of an 'if' expression must return values of the same type as the first branch, which here is 'string'. This branch returns a value of type 'int'. - -let f x = x + 4 - -let y = - if true then - "" - else - "" |> ignore - let z = f 4 - let a = 3 * z - (f a) - -exit 0 diff --git a/tests/fsharpqa/Source/Warnings/NestedElseBranchHasWrongType.fs b/tests/fsharpqa/Source/Warnings/NestedElseBranchHasWrongType.fs deleted file mode 100644 index a8e63cee65a..00000000000 --- a/tests/fsharpqa/Source/Warnings/NestedElseBranchHasWrongType.fs +++ /dev/null @@ -1,10 +0,0 @@ -// #Warnings -//All branches of an 'if' expression must return values of the same type as the first branch, which here is 'bool'. This branch returns a value of type 'string'. - -let x = 1 -if x = 1 then true -else - if x = 2 then "A" - else "B" - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/env.lst b/tests/fsharpqa/Source/Warnings/env.lst index 383c291e906..127d78a21c5 100644 --- a/tests/fsharpqa/Source/Warnings/env.lst +++ b/tests/fsharpqa/Source/Warnings/env.lst @@ -45,16 +45,6 @@ SOURCE=SuggestDoubleBacktickIdentifiers.fs SCFLAGS="--vserrors" # SuggestDoubleBacktickIdentifiers.fs SOURCE=SuggestDoubleBacktickUnions.fs SCFLAGS="--vserrors" # SuggestDoubleBacktickUnions.fs SOURCE=GuardHasWrongType.fs # GuardHasWrongType.fs - SOURCE=ElseBranchHasWrongType.fs # ElseBranchHasWrongType.fs - SOURCE=ElseBranchHasWrongType2.fs # ElseBranchHasWrongType2.fs - SOURCE=ElseBranchHasWrongType3.fs # ElseBranchHasWrongType3.fs - SOURCE=ElseBranchHasWrongType4.fs # ElseBranchHasWrongType4.fs - SOURCE=NestedElseBranchHasWrongType.fs # NestedElseBranchHasWrongType.fs - SOURCE=ElseBranchHasWrongContextType.fs # ElseBranchHasWrongContextType.fs - SOURCE=ElseBranchContextDoesntPropagateInAppl.fs # ElseBranchContextDoesntPropagateInAppl.fs - SOURCE=ElseBranchContextDoesntPropagateInAppl2.fs # ElseBranchContextDoesntPropagateInAppl2.fs - SOURCE=ElseBranchContextDoesntPropagateInForLoop.fs # ElseBranchContextDoesntPropagateInForLoop.fs - SOURCE=ElseBranchContextDoesntPropagateToLinesBeforeLastLine.fs # ElseBranchContextDoesntPropagateToLinesBeforeLastLine.fs SOURCE=MatchingMethodWithSameNameIsNotAbstract.fs # MatchingMethodWithSameNameIsNotAbstract.fs SOURCE=NoMatchingAbstractMethodWithSameName.fs # NoMatchingAbstractMethodWithSameName.fs SOURCE=MissingExpressionAfterLet.fs # MissingExpressionAfterLet.fs From 869c2bb395f18d5970f8f1bd4827d8449285bddf Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Fri, 12 Jul 2019 20:26:14 +0200 Subject: [PATCH 09/46] Port tests for missing else branch to NUnit (#7209) --- .../ErrorMessages/MissingElseBranch.fs | 50 +++++++++++++++++++ tests/fsharp/FSharpSuite.Tests.fsproj | 3 +- .../Warnings/WarnIfMissingElseBranch.fs | 8 --- .../Warnings/WarnIfMissingElseBranch2.fs | 10 ---- .../Warnings/WarnIfMissingElseBranch3.fs | 8 --- tests/fsharpqa/Source/Warnings/env.lst | 3 -- 6 files changed, 52 insertions(+), 30 deletions(-) create mode 100644 tests/fsharp/Compiler/ErrorMessages/MissingElseBranch.fs delete mode 100644 tests/fsharpqa/Source/Warnings/WarnIfMissingElseBranch.fs delete mode 100644 tests/fsharpqa/Source/Warnings/WarnIfMissingElseBranch2.fs delete mode 100644 tests/fsharpqa/Source/Warnings/WarnIfMissingElseBranch3.fs diff --git a/tests/fsharp/Compiler/ErrorMessages/MissingElseBranch.fs b/tests/fsharp/Compiler/ErrorMessages/MissingElseBranch.fs new file mode 100644 index 00000000000..06f9cb160d9 --- /dev/null +++ b/tests/fsharp/Compiler/ErrorMessages/MissingElseBranch.fs @@ -0,0 +1,50 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace FSharp.Compiler.UnitTests + +open NUnit.Framework +open FSharp.Compiler.SourceCodeServices + +[] +module ``Else branch is missing`` = + + [] + let ``Fail if else branch is missing``() = + CompilerAssert.TypeCheckSingleError + """ +let x = 10 +let y = + if x > 10 then "test" + """ + FSharpErrorSeverity.Error + 1 + (4, 19, 4, 25) + "This 'if' expression is missing an 'else' branch. Because 'if' is an expression, and not a statement, add an 'else' branch which also returns a value of type 'string'." + + [] + let ``Fail on type error in condition``() = + CompilerAssert.TypeCheckSingleError + """ +let x = 10 +let y = + if x > 10 then + if x <> "test" then printfn "test" + () + """ + FSharpErrorSeverity.Error + 1 + (5, 14, 5, 20) + "This expression was expected to have type\n 'int' \nbut here has type\n 'string' " + + [] + let ``Fail if else branch is missing in nesting``() = + CompilerAssert.TypeCheckSingleError + """ +let x = 10 +let y = + if x > 10 then ("test") + """ + FSharpErrorSeverity.Error + 1 + (4, 20, 4, 26) + "This 'if' expression is missing an 'else' branch. Because 'if' is an expression, and not a statement, add an 'else' branch which also returns a value of type 'string'." diff --git a/tests/fsharp/FSharpSuite.Tests.fsproj b/tests/fsharp/FSharpSuite.Tests.fsproj index 6335b5172cd..8f450a1b3a8 100644 --- a/tests/fsharp/FSharpSuite.Tests.fsproj +++ b/tests/fsharp/FSharpSuite.Tests.fsproj @@ -1,4 +1,4 @@ - + @@ -33,6 +33,7 @@ + diff --git a/tests/fsharpqa/Source/Warnings/WarnIfMissingElseBranch.fs b/tests/fsharpqa/Source/Warnings/WarnIfMissingElseBranch.fs deleted file mode 100644 index 9e6e9d7efe9..00000000000 --- a/tests/fsharpqa/Source/Warnings/WarnIfMissingElseBranch.fs +++ /dev/null @@ -1,8 +0,0 @@ -// #Warnings -//This 'if' expression is missing an 'else' branch. Because 'if' is an expression, and not a statement, add an 'else' branch which also returns a value of type 'string'. - -let x = 10 -let y = - if x > 10 then "test" - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/WarnIfMissingElseBranch2.fs b/tests/fsharpqa/Source/Warnings/WarnIfMissingElseBranch2.fs deleted file mode 100644 index a8b98922a0e..00000000000 --- a/tests/fsharpqa/Source/Warnings/WarnIfMissingElseBranch2.fs +++ /dev/null @@ -1,10 +0,0 @@ -// #Warnings -//This expression was expected to have type - -let x = 10 -let y = - if x > 10 then - if x <> "test" then printfn "test" - () - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/WarnIfMissingElseBranch3.fs b/tests/fsharpqa/Source/Warnings/WarnIfMissingElseBranch3.fs deleted file mode 100644 index cbf7d5acf16..00000000000 --- a/tests/fsharpqa/Source/Warnings/WarnIfMissingElseBranch3.fs +++ /dev/null @@ -1,8 +0,0 @@ -// #Warnings -//This 'if' expression is missing an 'else' branch. Because 'if' is an expression, and not a statement, add an 'else' branch which also returns a value of type 'string'. - -let x = 10 -let y = - if x > 10 then ("test") - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/env.lst b/tests/fsharpqa/Source/Warnings/env.lst index 127d78a21c5..f711b79a377 100644 --- a/tests/fsharpqa/Source/Warnings/env.lst +++ b/tests/fsharpqa/Source/Warnings/env.lst @@ -1,7 +1,4 @@ SOURCE=WrongNumericLiteral.fs # WrongNumericLiteral.fs - SOURCE=WarnIfMissingElseBranch.fs # WarnIfMissingElseBranch.fs - SOURCE=WarnIfMissingElseBranch2.fs # WarnIfMissingElseBranch2.fs - SOURCE=WarnIfMissingElseBranch3.fs # WarnIfMissingElseBranch3.fs SOURCE=ReturnInsteadOfReturnBang.fs # ReturnInsteadOfReturnBang.fs SOURCE=YieldInsteadOfYieldBang.fs # YieldInsteadOfYieldBang.fs SOURCE=TupleInAbstractMethod.fs # TupleInAbstractMethod.fs From 59bfc836efc4cd2ba8df60871b0ae4c4dad06963 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Fri, 12 Jul 2019 12:49:41 -0700 Subject: [PATCH 10/46] Update dependencies from https://github.com/dotnet/arcade build 20190711.7 (#7216) - Microsoft.DotNet.Arcade.Sdk - 1.0.0-beta.19361.7 --- eng/Version.Details.xml | 4 ++-- global.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index bfb72eca155..e2195f4bc58 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -3,9 +3,9 @@ - + https://github.com/dotnet/arcade - a6ae1b637ed236354529992729af875f6c8a180a + f1b09644408f45f43f5835786b3e4bdfd2e78141 diff --git a/global.json b/global.json index 60dbe5efe92..ca0cec66a73 100644 --- a/global.json +++ b/global.json @@ -10,7 +10,7 @@ } }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19360.8", + "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19361.7", "Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19069.2" } } From 8ab272af8e62b6aaa527de6db8bedb22399fcb52 Mon Sep 17 00:00:00 2001 From: dotnet-maestro <@dotnet-maestro> Date: Sat, 13 Jul 2019 12:47:20 +0000 Subject: [PATCH 11/46] Update dependencies from https://github.com/dotnet/arcade build 20190712.5 - Microsoft.DotNet.Arcade.Sdk - 1.0.0-beta.19362.5 --- eng/Version.Details.xml | 4 ++-- global.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index e2195f4bc58..55da8d6499d 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -3,9 +3,9 @@ - + https://github.com/dotnet/arcade - f1b09644408f45f43f5835786b3e4bdfd2e78141 + 15f50ca6a9d0b441c9927421657fb9dc91206cc9 diff --git a/global.json b/global.json index ca0cec66a73..a6d76946ba1 100644 --- a/global.json +++ b/global.json @@ -10,7 +10,7 @@ } }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19361.7", + "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19362.5", "Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19069.2" } } From 7780cab8dcaaa042c31b0588deed3d408af0d210 Mon Sep 17 00:00:00 2001 From: Solomon Rutzky Date: Sat, 13 Jul 2019 14:59:46 -0400 Subject: [PATCH 12/46] Fix Supplementary Character / Surrogate Pair info (no code changes) (#7221) Terminology and info regarding Supplementary Characters / Surrogate Pairs is either incorrect, or at least incomplete (which then leads to incorrect statements and/or code). 1. Introduce the term "Supplementary Character" since that is often what we are dealing with, not "surrogate pairs" since that is an encoding-specific concept (UTF-16 only). 2. Add comment re: Supplementary Character code point range, which helps to explain the `elif high > 0x10 then Invalid` condition (line 173). 3. Fix URI for Unicode Standard PDF, Chapter 3, and specify the name of the section (i.e. "Surrogates") instead of the section number (i.e. 3.8) since the section number was 3.7 but is now 3.8 (line 174). 4. Add comment for definition of a valid "surrogate pair" because why make the reader guess or have to go look it up when it will never change? (line 175) 5. Correct and expand comment with example long Unicode escape sequence (line 64): `"\UDEADBEEF"` is _not_ a valid escape sequence. Usage of the `\U` escape has been misstated from the very beginning, both in this documentation as well as the C# Specification documentation, and the language references for "String" for both F# and C#: 1. `\U` is used to specify a Unicode code point (or UTF-32 code unit, which maps 1:1 with all Unicode code points, hence they are synonymous), not surrogate pairs. Hence the valid range is `00000000` - `0010FFFF`, hence the first two digits are static `0`s, and the third digit can only ever be a `0` or `1`. This escape sequence can specify either a BMP character or a Supplementary character. Supplementary characters are then encoded as a surrogate pair in UTF-16 only, not in UTF-8 or UTF-32. If you want to specify an actual surrogate pair, then use the `\u` escape, e.g. `\uD83D\uDC7D` == `\U0001F47D`. 2. Even if you could specify a surrogate pair using `\U`, "DEADBEEF" is not valid. U+DEAD is a valid surrogate, _but_ it's a low surrogate code point and cannot be specified first in the pair (meaning, at best one could use `\UxxxxDEAD`). Also, U+BEEF is _not_ a valid surrogate code point, high or low. Surrogate code points are in the range of U+D800 to U+DFFF. For more info, please see: https://sqlquantumleap.com/2019/06/26/unicode-escape-sequences-across-various-languages-and-platforms-including-supplementary-characters/#fsharp --- src/fsharp/lexhelp.fs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/fsharp/lexhelp.fs b/src/fsharp/lexhelp.fs index e966678486e..fb66ac5f85a 100644 --- a/src/fsharp/lexhelp.fs +++ b/src/fsharp/lexhelp.fs @@ -60,7 +60,8 @@ type lexargs = applyLineDirectives: bool pathMap: PathMap } -/// possible results of lexing a long unicode escape sequence in a string literal, e.g. "\UDEADBEEF" +/// possible results of lexing a long Unicode escape sequence in a string literal, e.g. "\U0001F47D", +/// "\U000000E7", or "\UDEADBEEF" returning SurrogatePair, SingleChar, or Invalid, respectively type LongUnicodeLexResult = | SurrogatePair of uint16 * uint16 | SingleChar of uint16 @@ -169,7 +170,9 @@ let unicodeGraphLong (s:string) = if high = 0 then SingleChar(uint16 low) // invalid encoding elif high > 0x10 then Invalid - // valid surrogate pair - see http://www.unicode.org/unicode/uni2book/ch03.pdf, section 3.7 *) + // valid supplementary character: code points U+10000 to U+10FFFF + // valid surrogate pair: see http://www.unicode.org/versions/latest/ch03.pdf , "Surrogates" section + // high-surrogate code point (U+D800 to U+DBFF) followed by low-surrogate code point (U+DC00 to U+DFFF) else let codepoint = high * 0x10000 + low let hiSurr = uint16 (0xD800 + ((codepoint - 0x10000) / 0x400)) From f9a8e2a200d863d0bbb81f55bce214097f4cf8d0 Mon Sep 17 00:00:00 2001 From: Will Smith Date: Sat, 13 Jul 2019 18:47:41 -0700 Subject: [PATCH 13/46] Update IlxGen.fs (#7227) --- src/fsharp/IlxGen.fs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/fsharp/IlxGen.fs b/src/fsharp/IlxGen.fs index 74d633b9f9c..b77d06e508a 100644 --- a/src/fsharp/IlxGen.fs +++ b/src/fsharp/IlxGen.fs @@ -2533,7 +2533,8 @@ and GenAllocUnionCase cenv cgbuf eenv (c,tyargs,args,m) sequel = GenSequel cenv eenv.cloc cgbuf sequel and GenLinearExpr cenv cgbuf eenv sp expr sequel canProcessSequencePoint (contf: FakeUnit -> FakeUnit) = - match stripExpr expr with + let expr = stripExpr expr + match expr with | LinearOpExpr (TOp.UnionCase c, tyargs, argsFront, argLast, m) -> GenExprs cenv cgbuf eenv argsFront GenLinearExpr cenv cgbuf eenv SPSuppress argLast Continue (* canProcessSequencePoint *) true (contf << (fun Fake -> From ec8a4249b74b678b7104b4188d09aae28ff48c02 Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Sun, 14 Jul 2019 03:52:03 +0200 Subject: [PATCH 14/46] Check for exit code in compiler tests (#7211) --- tests/fsharp/Compiler/CompilerAssert.fs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/fsharp/Compiler/CompilerAssert.fs b/tests/fsharp/Compiler/CompilerAssert.fs index 9c748455498..d5f93d7810e 100644 --- a/tests/fsharp/Compiler/CompilerAssert.fs +++ b/tests/fsharp/Compiler/CompilerAssert.fs @@ -168,6 +168,9 @@ module CompilerAssert = let errors = p.StandardError.ReadToEnd () if not (String.IsNullOrWhiteSpace errors) then Assert.Fail errors + + if p.ExitCode <> 0 then + Assert.Fail(sprintf "Program exited with exit code %d" p.ExitCode) ) let CompileLibraryAndVerifyIL (source: string) (f: ILVerifier -> unit) = From c4dba1f7b4f6c72f9d19b248b40431a563e948b2 Mon Sep 17 00:00:00 2001 From: Sergey Tihon Date: Sun, 14 Jul 2019 11:27:24 +0300 Subject: [PATCH 15/46] Moving AccessOfTypeAbbreviationTests over to NUnit (#7226) * Moving AccessOfTypeAbbreviationTests over to NUnit * ha! now I know what this `1` means =) * Error range updated and removed `exit 0` * Error message prefixed by "This construct is deprecated." * Error messages changed based on current state of FSI --- .../AccessOfTypeAbbreviationTests.fs | 75 +++++++++++++++++++ tests/fsharp/FSharpSuite.Tests.fsproj | 1 + .../Warnings/AccessOfTypeAbbreviation.fs | 8 -- .../Warnings/AccessOfTypeAbbreviation2.fs | 8 -- .../Warnings/AccessOfTypeAbbreviation3.fs | 8 -- .../Warnings/AccessOfTypeAbbreviation4.fs | 8 -- .../Warnings/AccessOfTypeAbbreviation5.fs | 8 -- .../Warnings/AccessOfTypeAbbreviation6.fs | 8 -- tests/fsharpqa/Source/Warnings/env.lst | 6 -- 9 files changed, 76 insertions(+), 54 deletions(-) create mode 100644 tests/fsharp/Compiler/ErrorMessages/AccessOfTypeAbbreviationTests.fs delete mode 100644 tests/fsharpqa/Source/Warnings/AccessOfTypeAbbreviation.fs delete mode 100644 tests/fsharpqa/Source/Warnings/AccessOfTypeAbbreviation2.fs delete mode 100644 tests/fsharpqa/Source/Warnings/AccessOfTypeAbbreviation3.fs delete mode 100644 tests/fsharpqa/Source/Warnings/AccessOfTypeAbbreviation4.fs delete mode 100644 tests/fsharpqa/Source/Warnings/AccessOfTypeAbbreviation5.fs delete mode 100644 tests/fsharpqa/Source/Warnings/AccessOfTypeAbbreviation6.fs diff --git a/tests/fsharp/Compiler/ErrorMessages/AccessOfTypeAbbreviationTests.fs b/tests/fsharp/Compiler/ErrorMessages/AccessOfTypeAbbreviationTests.fs new file mode 100644 index 00000000000..0143486a349 --- /dev/null +++ b/tests/fsharp/Compiler/ErrorMessages/AccessOfTypeAbbreviationTests.fs @@ -0,0 +1,75 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace FSharp.Compiler.UnitTests + +open NUnit.Framework +open FSharp.Compiler.SourceCodeServices + +[] +module ``Access Of Type Abbreviation`` = + + [] + let ``Test1``() = + CompilerAssert.TypeCheckSingleError + """ +module Library = + type private Hidden = Hidden of unit + type Exported = Hidden + """ + FSharpErrorSeverity.Warning + 44 + (4, 8, 4, 16) + "This construct is deprecated. The type 'Hidden' is less accessible than the value, member or type 'Exported' it is used in.\r\nAs of F# 4.1, the accessibility of type abbreviations is checked at compile-time. Consider changing the accessibility of the type abbreviation. Ignoring this warning might lead to runtime errors." + + [] + let ``Test2``() = + CompilerAssert.Pass + """ +module Library = + type internal Hidden = Hidden of unit + type internal Exported = Hidden + """ + + [] + let ``Test3``() = + CompilerAssert.TypeCheckSingleError + """ +module Library = + type internal Hidden = Hidden of unit + type Exported = Hidden + """ + FSharpErrorSeverity.Warning + 44 + (4, 8, 4, 16) + "This construct is deprecated. The type 'Hidden' is less accessible than the value, member or type 'Exported' it is used in.\r\nAs of F# 4.1, the accessibility of type abbreviations is checked at compile-time. Consider changing the accessibility of the type abbreviation. Ignoring this warning might lead to runtime errors." + + [] + let ``Test4``() = + CompilerAssert.TypeCheckSingleError + """ +module Library = + type private Hidden = Hidden of unit + type internal Exported = Hidden + """ + FSharpErrorSeverity.Warning + 44 + (4, 17, 4, 25) + "This construct is deprecated. The type 'Hidden' is less accessible than the value, member or type 'Exported' it is used in.\r\nAs of F# 4.1, the accessibility of type abbreviations is checked at compile-time. Consider changing the accessibility of the type abbreviation. Ignoring this warning might lead to runtime errors." + + [] + let ``Test5``() = + CompilerAssert.Pass + """ +module Library = + type private Hidden = Hidden of unit + type private Exported = Hidden + """ + + [] + let ``Test6``() = + CompilerAssert.Pass + """ +module Library = + type Hidden = Hidden of unit + type Exported = Hidden + """ \ No newline at end of file diff --git a/tests/fsharp/FSharpSuite.Tests.fsproj b/tests/fsharp/FSharpSuite.Tests.fsproj index 8f450a1b3a8..5976803c10e 100644 --- a/tests/fsharp/FSharpSuite.Tests.fsproj +++ b/tests/fsharp/FSharpSuite.Tests.fsproj @@ -32,6 +32,7 @@ + diff --git a/tests/fsharpqa/Source/Warnings/AccessOfTypeAbbreviation.fs b/tests/fsharpqa/Source/Warnings/AccessOfTypeAbbreviation.fs deleted file mode 100644 index b72fdb7baae..00000000000 --- a/tests/fsharpqa/Source/Warnings/AccessOfTypeAbbreviation.fs +++ /dev/null @@ -1,8 +0,0 @@ -// #Warnings -//The type 'Hidden' is less accessible than the value, member or type 'Exported' it is used in - -module Library = - type private Hidden = Hidden of unit - type Exported = Hidden - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/AccessOfTypeAbbreviation2.fs b/tests/fsharpqa/Source/Warnings/AccessOfTypeAbbreviation2.fs deleted file mode 100644 index 898e941523e..00000000000 --- a/tests/fsharpqa/Source/Warnings/AccessOfTypeAbbreviation2.fs +++ /dev/null @@ -1,8 +0,0 @@ -// #Warnings -// - -module Library = - type internal Hidden = Hidden of unit - type internal Exported = Hidden - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/AccessOfTypeAbbreviation3.fs b/tests/fsharpqa/Source/Warnings/AccessOfTypeAbbreviation3.fs deleted file mode 100644 index de1875bf576..00000000000 --- a/tests/fsharpqa/Source/Warnings/AccessOfTypeAbbreviation3.fs +++ /dev/null @@ -1,8 +0,0 @@ -// #Warnings -//The type 'Hidden' is less accessible than the value, member or type 'Exported' it is used in - -module Library = - type internal Hidden = Hidden of unit - type Exported = Hidden - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/AccessOfTypeAbbreviation4.fs b/tests/fsharpqa/Source/Warnings/AccessOfTypeAbbreviation4.fs deleted file mode 100644 index 728dc399bf2..00000000000 --- a/tests/fsharpqa/Source/Warnings/AccessOfTypeAbbreviation4.fs +++ /dev/null @@ -1,8 +0,0 @@ -// #Warnings -//The type 'Hidden' is less accessible than the value, member or type 'Exported' it is used in - -module Library = - type private Hidden = Hidden of unit - type internal Exported = Hidden - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/AccessOfTypeAbbreviation5.fs b/tests/fsharpqa/Source/Warnings/AccessOfTypeAbbreviation5.fs deleted file mode 100644 index d0d3b251008..00000000000 --- a/tests/fsharpqa/Source/Warnings/AccessOfTypeAbbreviation5.fs +++ /dev/null @@ -1,8 +0,0 @@ -// #Warnings -// - -module Library = - type private Hidden = Hidden of unit - type private Exported = Hidden - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/AccessOfTypeAbbreviation6.fs b/tests/fsharpqa/Source/Warnings/AccessOfTypeAbbreviation6.fs deleted file mode 100644 index d179e5f20e0..00000000000 --- a/tests/fsharpqa/Source/Warnings/AccessOfTypeAbbreviation6.fs +++ /dev/null @@ -1,8 +0,0 @@ -// #Warnings -// - -module Library = - type Hidden = Hidden of unit - type Exported = Hidden - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/env.lst b/tests/fsharpqa/Source/Warnings/env.lst index f711b79a377..14b61a4649a 100644 --- a/tests/fsharpqa/Source/Warnings/env.lst +++ b/tests/fsharpqa/Source/Warnings/env.lst @@ -13,12 +13,6 @@ SOURCE=WrongArity.fs # WrongArity.fs SOURCE=OverrideErrors.fs # OverrideErrors.fs SOURCE=MethodIsNotStatic.fs # MethodIsNotStatic.fs - SOURCE=AccessOfTypeAbbreviation.fs # AccessOfTypeAbbreviation.fs - SOURCE=AccessOfTypeAbbreviation2.fs # AccessOfTypeAbbreviation2.fs - SOURCE=AccessOfTypeAbbreviation3.fs # AccessOfTypeAbbreviation3.fs - SOURCE=AccessOfTypeAbbreviation4.fs # AccessOfTypeAbbreviation4.fs - SOURCE=AccessOfTypeAbbreviation5.fs # AccessOfTypeAbbreviation5.fs - SOURCE=AccessOfTypeAbbreviation6.fs # AccessOfTypeAbbreviation6.fs SOURCE=EqualsInsteadOfInInForLoop.fs # EqualsInsteadOfInInForLoop.fs SOURCE=DontWarnExternalFunctionAsUnused.fs SCFLAGS="--warnon:1182 --warnaserror+" # DontWarnExternalFunctionAsUnused.fs SOURCE=SuggestTypesInModule.fs # SuggestTypesInModule.fs From 75cef56a5bbba57b146c991db74791bddd41e211 Mon Sep 17 00:00:00 2001 From: Sergey Tihon Date: Mon, 15 Jul 2019 21:11:55 +0300 Subject: [PATCH 16/46] Moving ConstructorTests over to NUnit (#7236) --- .../ErrorMessages/ConstructorTests.fs | 115 ++++++++++++++++++ tests/fsharp/FSharpSuite.Tests.fsproj | 1 + .../Source/Warnings/CommaInRecCtor.fs | 12 -- .../Source/Warnings/ExtraArgumentInCtor.fs | 10 -- .../Source/Warnings/ExtraArgumentInCtor2.fs | 11 -- .../fsharpqa/Source/Warnings/InvalidRecord.fs | 9 -- .../Source/Warnings/MissingCommaInCtor.fs | 11 -- .../Source/Warnings/MissingCtorValue.fs | 11 -- .../Source/Warnings/ValidCommaInRecCtor.fs | 9 -- tests/fsharpqa/Source/Warnings/env.lst | 7 -- 10 files changed, 116 insertions(+), 80 deletions(-) create mode 100644 tests/fsharp/Compiler/ErrorMessages/ConstructorTests.fs delete mode 100644 tests/fsharpqa/Source/Warnings/CommaInRecCtor.fs delete mode 100644 tests/fsharpqa/Source/Warnings/ExtraArgumentInCtor.fs delete mode 100644 tests/fsharpqa/Source/Warnings/ExtraArgumentInCtor2.fs delete mode 100644 tests/fsharpqa/Source/Warnings/InvalidRecord.fs delete mode 100644 tests/fsharpqa/Source/Warnings/MissingCommaInCtor.fs delete mode 100644 tests/fsharpqa/Source/Warnings/MissingCtorValue.fs delete mode 100644 tests/fsharpqa/Source/Warnings/ValidCommaInRecCtor.fs diff --git a/tests/fsharp/Compiler/ErrorMessages/ConstructorTests.fs b/tests/fsharp/Compiler/ErrorMessages/ConstructorTests.fs new file mode 100644 index 00000000000..97aa66e60a4 --- /dev/null +++ b/tests/fsharp/Compiler/ErrorMessages/ConstructorTests.fs @@ -0,0 +1,115 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace FSharp.Compiler.UnitTests + +open NUnit.Framework +open FSharp.Compiler.SourceCodeServices + +[] +module ``Constructor`` = + + [] + let ``Invalid Record``() = + CompilerAssert.TypeCheckWithErrors + """ +type Record = {field1:int; field2:int} +let doSomething (xs) = List.map (fun {field1=x} -> x) xs + +doSomething {Record.field1=0; field2=0} + """ + [| + FSharpErrorSeverity.Error, 1, (5, 13, 5, 40), "This expression was expected to have type\n 'Record list' \nbut here has type\n 'Record' " + FSharpErrorSeverity.Warning, 20, (5, 1, 5, 40), "The result of this expression has type 'int list' and is implicitly ignored. Consider using 'ignore' to discard this value explicitly, e.g. 'expr |> ignore', or 'let' to bind the result to a name, e.g. 'let result = expr'." + |] + + [] + let ``Comma In Rec Ctor``() = + CompilerAssert.TypeCheckWithErrors + """ +type Person = { Name : string; Age : int; City : string } +let x = { Name = "Isaac", Age = 21, City = "London" } + """ + [| + FSharpErrorSeverity.Error, 1, (3, 18, 3, 52), "This expression was expected to have type\n 'string' \nbut here has type\n ''a * 'b * 'c' \r\nA ';' is used to separate field values in records. Consider replacing ',' with ';'." + FSharpErrorSeverity.Error, 764, (3, 9, 3, 54), "No assignment given for field 'Age' of type 'Test.Person'" + |] + + [] + let ``Missing Comma In Ctor``() = + CompilerAssert.TypeCheckWithErrors + """ +type Person() = + member val Name = "" with get,set + member val Age = 0 with get,set + +let p = + Person(Name = "Fred" + Age = 18) + """ + [| + FSharpErrorSeverity.Error, 39, (7, 12, 7, 16), "The value or constructor 'Name' is not defined." + FSharpErrorSeverity.Warning, 20, (7, 12, 7, 25), "The result of this equality expression has type 'bool' and is implicitly discarded. Consider using 'let' to bind the result to a name, e.g. 'let result = expression'." + FSharpErrorSeverity.Error, 39, (8, 12, 8, 15), "The value or constructor 'Age' is not defined." + FSharpErrorSeverity.Error, 501, (7, 5, 8, 21), "The object constructor 'Person' takes 0 argument(s) but is here given 1. The required signature is 'new : unit -> Person'. If some of the arguments are meant to assign values to properties, consider separating those arguments with a comma (',')." + |] + + [] + let ``Missing Ctor Value``() = + CompilerAssert.TypeCheckSingleError + """ +type Person(x:int) = + member val Name = "" with get,set + member val Age = x with get,set + +let p = + Person(Name = "Fred", + Age = 18) + """ + FSharpErrorSeverity.Error + 496 + (7, 5, 8, 21) + "The member or object constructor 'Person' requires 1 argument(s). The required signature is 'new : x:int -> Person'." + + [] + let ``Extra Argument In Ctor``() = + CompilerAssert.TypeCheckSingleError + """ +type Person() = + member val Name = "" with get,set + member val Age = 0 with get,set + +let p = + Person(1) + """ + FSharpErrorSeverity.Error + 501 + (7, 5, 7, 14) + "The object constructor 'Person' takes 0 argument(s) but is here given 1. The required signature is 'new : unit -> Person'." + + [] + let ``Extra Argument In Ctor2``() = + CompilerAssert.TypeCheckSingleError + """ +type Person() = + member val Name = "" with get,set + member val Age = 0 with get,set + +let b = 1 + +let p = + Person(1=b) + """ + FSharpErrorSeverity.Error + 501 + (9, 5, 9, 16) + "The object constructor 'Person' takes 0 argument(s) but is here given 1. The required signature is 'new : unit -> Person'." + + [] + let ``Valid Comma In Rec Ctor``() = + CompilerAssert.Pass + """ +type Person = { Name : string * bool * bool } +let Age = 22 +let City = "London" +let x = { Name = "Isaac", Age = 21, City = "London" } + """ diff --git a/tests/fsharp/FSharpSuite.Tests.fsproj b/tests/fsharp/FSharpSuite.Tests.fsproj index 5976803c10e..55fad20ad29 100644 --- a/tests/fsharp/FSharpSuite.Tests.fsproj +++ b/tests/fsharp/FSharpSuite.Tests.fsproj @@ -32,6 +32,7 @@ + diff --git a/tests/fsharpqa/Source/Warnings/CommaInRecCtor.fs b/tests/fsharpqa/Source/Warnings/CommaInRecCtor.fs deleted file mode 100644 index b14d6c6dc98..00000000000 --- a/tests/fsharpqa/Source/Warnings/CommaInRecCtor.fs +++ /dev/null @@ -1,12 +0,0 @@ -// #Warnings -//This expression was expected to have type -// 'string' -//but here has type -// ''a \* 'b \* 'c' -//A ';' is used to separate field values in records. Consider replacing ',' with ';'. - - -type Person = { Name : string; Age : int; City : string } -let x = { Name = "Isaac", Age = 21, City = "London" } - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/ExtraArgumentInCtor.fs b/tests/fsharpqa/Source/Warnings/ExtraArgumentInCtor.fs deleted file mode 100644 index 794245b450b..00000000000 --- a/tests/fsharpqa/Source/Warnings/ExtraArgumentInCtor.fs +++ /dev/null @@ -1,10 +0,0 @@ -// #Warnings -//The object constructor 'Person' takes 0 argument\(s\) but is here given 1. The required signature is 'new : unit -> Person'.$ - -type Person() = - member val Name = "" with get,set - member val Age = 0 with get,set - - -let p = - Person(1) \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/ExtraArgumentInCtor2.fs b/tests/fsharpqa/Source/Warnings/ExtraArgumentInCtor2.fs deleted file mode 100644 index c73f250c551..00000000000 --- a/tests/fsharpqa/Source/Warnings/ExtraArgumentInCtor2.fs +++ /dev/null @@ -1,11 +0,0 @@ -// #Warnings -//The object constructor 'Person' takes 0 argument\(s\) but is here given 1. The required signature is 'new : unit -> Person'.$ - -type Person() = - member val Name = "" with get,set - member val Age = 0 with get,set - -let b = 1 - -let p = - Person(1=b) \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/InvalidRecord.fs b/tests/fsharpqa/Source/Warnings/InvalidRecord.fs deleted file mode 100644 index f04f24e4576..00000000000 --- a/tests/fsharpqa/Source/Warnings/InvalidRecord.fs +++ /dev/null @@ -1,9 +0,0 @@ -// #Warnings -//This expression was expected to have type - -type Record = {field1:int; field2:int} -let doSomething (xs) = List.map (fun {field1=x} -> x) xs - -doSomething {Record.field1=0; field2=0} - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/MissingCommaInCtor.fs b/tests/fsharpqa/Source/Warnings/MissingCommaInCtor.fs deleted file mode 100644 index 6c407bc6c4e..00000000000 --- a/tests/fsharpqa/Source/Warnings/MissingCommaInCtor.fs +++ /dev/null @@ -1,11 +0,0 @@ -// #Warnings -//The object constructor 'Person' takes 0 argument\(s\) but is here given 1. The required signature is 'new : unit -> Person'. If some of the arguments are meant to assign values to properties, consider separating those arguments with a comma \(','\). - -type Person() = - member val Name = "" with get,set - member val Age = 0 with get,set - - -let p = - Person(Name = "Fred" - Age = 18) \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/MissingCtorValue.fs b/tests/fsharpqa/Source/Warnings/MissingCtorValue.fs deleted file mode 100644 index c90377be50b..00000000000 --- a/tests/fsharpqa/Source/Warnings/MissingCtorValue.fs +++ /dev/null @@ -1,11 +0,0 @@ -// #Warnings -//The member or object constructor 'Person' requires 1 argument\(s\). The required signature is 'new : x:int -> Person'. - -type Person(x:int) = - member val Name = "" with get,set - member val Age = x with get,set - - -let p = - Person(Name = "Fred", - Age = 18) \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/ValidCommaInRecCtor.fs b/tests/fsharpqa/Source/Warnings/ValidCommaInRecCtor.fs deleted file mode 100644 index 6cbee50f02c..00000000000 --- a/tests/fsharpqa/Source/Warnings/ValidCommaInRecCtor.fs +++ /dev/null @@ -1,9 +0,0 @@ -// #Warnings -// - -type Person = { Name : string * bool * bool } -let Age = 22 -let City = "London" -let x = { Name = "Isaac", Age = 21, City = "London" } - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/env.lst b/tests/fsharpqa/Source/Warnings/env.lst index 14b61a4649a..350dc92a0d9 100644 --- a/tests/fsharpqa/Source/Warnings/env.lst +++ b/tests/fsharpqa/Source/Warnings/env.lst @@ -2,13 +2,6 @@ SOURCE=ReturnInsteadOfReturnBang.fs # ReturnInsteadOfReturnBang.fs SOURCE=YieldInsteadOfYieldBang.fs # YieldInsteadOfYieldBang.fs SOURCE=TupleInAbstractMethod.fs # TupleInAbstractMethod.fs - SOURCE=InvalidRecord.fs # InvalidRecord.fs - SOURCE=CommaInRecCtor.fs # CommaInRecCtor.fs - SOURCE=MissingCommaInCtor.fs # MissingCommaInCtor.fs - SOURCE=MissingCtorValue.fs # MissingCtorValue.fs - SOURCE=ExtraArgumentInCtor.fs # ExtraArgumentInCtor.fs - SOURCE=ExtraArgumentInCtor2.fs # ExtraArgumentInCtor2.fs - SOURCE=ValidCommaInRecCtor.fs # ValidCommaInRecCtor.fs SOURCE=FS0988AtEndOfFile.fs # FS0988AtEndOfFile.fs SOURCE=WrongArity.fs # WrongArity.fs SOURCE=OverrideErrors.fs # OverrideErrors.fs From c7cd220ada1fd4bfe784f5a3aa7ad8178512d5c2 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Mon, 15 Jul 2019 11:12:26 -0700 Subject: [PATCH 17/46] [master] Update dependencies from dotnet/arcade (#7233) * Update dependencies from https://github.com/dotnet/arcade build 20190713.1 - Microsoft.DotNet.Arcade.Sdk - 1.0.0-beta.19363.1 * Update dependencies from https://github.com/dotnet/arcade build 20190714.1 - Microsoft.DotNet.Arcade.Sdk - 1.0.0-beta.19364.1 --- eng/Version.Details.xml | 4 ++-- global.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 55da8d6499d..119dfcd3a41 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -3,9 +3,9 @@ - + https://github.com/dotnet/arcade - 15f50ca6a9d0b441c9927421657fb9dc91206cc9 + 0c81c2bbdc49749e9940bc8858ebd16026d51277 diff --git a/global.json b/global.json index a6d76946ba1..81be3571adc 100644 --- a/global.json +++ b/global.json @@ -10,7 +10,7 @@ } }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19362.5", + "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19364.1", "Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19069.2" } } From 0f24b3ef42cae5d48cdafc0b80dee92de1db10b6 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Tue, 16 Jul 2019 10:23:25 -0700 Subject: [PATCH 18/46] Update dependencies from https://github.com/dotnet/arcade build 20190715.4 (#7240) - Microsoft.DotNet.Arcade.Sdk - 1.0.0-beta.19365.4 --- eng/Version.Details.xml | 4 ++-- global.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 119dfcd3a41..19eab0f3c7e 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -3,9 +3,9 @@ - + https://github.com/dotnet/arcade - 0c81c2bbdc49749e9940bc8858ebd16026d51277 + fb27fd4d8a2b67d4333e33d4b898c65171c9f3c1 diff --git a/global.json b/global.json index 81be3571adc..616ab02e470 100644 --- a/global.json +++ b/global.json @@ -10,7 +10,7 @@ } }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19364.1", + "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19365.4", "Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19069.2" } } From 863ec255f4345eb0622673414cdf3052494c5ab4 Mon Sep 17 00:00:00 2001 From: Sergey Tihon Date: Tue, 16 Jul 2019 20:31:30 +0300 Subject: [PATCH 19/46] Moving UpcastDowncastTests over to NUnit (#7229) * Moving UpcastDowncastTests over to NUnit * missing new line --- .../ErrorMessages/UpcastDowncastTests.fs | 51 +++++++++++++++++++ tests/fsharp/FSharpSuite.Tests.fsproj | 1 + .../Warnings/DowncastInsteadOfUpcast.fs | 9 ---- .../UpcastFunctionInsteadOfDowncast.fs | 9 ---- .../Warnings/UpcastInsteadOfDowncast.fs | 9 ---- tests/fsharpqa/Source/Warnings/env.lst | 3 -- 6 files changed, 52 insertions(+), 30 deletions(-) create mode 100644 tests/fsharp/Compiler/ErrorMessages/UpcastDowncastTests.fs delete mode 100644 tests/fsharpqa/Source/Warnings/DowncastInsteadOfUpcast.fs delete mode 100644 tests/fsharpqa/Source/Warnings/UpcastFunctionInsteadOfDowncast.fs delete mode 100644 tests/fsharpqa/Source/Warnings/UpcastInsteadOfDowncast.fs diff --git a/tests/fsharp/Compiler/ErrorMessages/UpcastDowncastTests.fs b/tests/fsharp/Compiler/ErrorMessages/UpcastDowncastTests.fs new file mode 100644 index 00000000000..739f841bfca --- /dev/null +++ b/tests/fsharp/Compiler/ErrorMessages/UpcastDowncastTests.fs @@ -0,0 +1,51 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace FSharp.Compiler.UnitTests + +open NUnit.Framework +open FSharp.Compiler.SourceCodeServices + +[] +module ``Upcast and Downcast`` = + + [] + let ``Downcast Instead Of Upcast``() = + CompilerAssert.TypeCheckSingleError + """ +open System.Collections.Generic + +let orig = Dictionary() :> IDictionary +let c = orig :> Dictionary + """ + FSharpErrorSeverity.Error + 193 + (5, 9, 5, 36) + "Type constraint mismatch. The type \n 'IDictionary' \nis not compatible with type\n 'Dictionary' \n" + + [] + let ``Upcast Instead Of Downcast``() = + CompilerAssert.TypeCheckWithErrors + """ +open System.Collections.Generic + +let orig = Dictionary() +let c = orig :?> IDictionary + """ + [| + FSharpErrorSeverity.Warning, 67, (5, 9, 5, 38), "This type test or downcast will always hold" + FSharpErrorSeverity.Error, 3198, (5, 9, 5, 38), "The conversion from Dictionary to IDictionary is a compile-time safe upcast, not a downcast. Consider using the :> (upcast) operator instead of the :?> (downcast) operator." + |] + + [] + let ``Upcast Function Instead Of Downcast``() = + CompilerAssert.TypeCheckWithErrors + """ +open System.Collections.Generic + +let orig = Dictionary() +let c : IDictionary = downcast orig + """ + [| + FSharpErrorSeverity.Warning, 67, (5, 32, 5, 45), "This type test or downcast will always hold" + FSharpErrorSeverity.Error, 3198, (5, 32, 5, 45), "The conversion from Dictionary to IDictionary is a compile-time safe upcast, not a downcast. Consider using 'upcast' instead of 'downcast'." + |] diff --git a/tests/fsharp/FSharpSuite.Tests.fsproj b/tests/fsharp/FSharpSuite.Tests.fsproj index 55fad20ad29..ec2a852b131 100644 --- a/tests/fsharp/FSharpSuite.Tests.fsproj +++ b/tests/fsharp/FSharpSuite.Tests.fsproj @@ -36,6 +36,7 @@ + diff --git a/tests/fsharpqa/Source/Warnings/DowncastInsteadOfUpcast.fs b/tests/fsharpqa/Source/Warnings/DowncastInsteadOfUpcast.fs deleted file mode 100644 index a815425e294..00000000000 --- a/tests/fsharpqa/Source/Warnings/DowncastInsteadOfUpcast.fs +++ /dev/null @@ -1,9 +0,0 @@ -// #Warnings -//Type constraint mismatch. The type - -open System.Collections.Generic - -let orig = Dictionary() :> IDictionary -let c = orig :> Dictionary - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/UpcastFunctionInsteadOfDowncast.fs b/tests/fsharpqa/Source/Warnings/UpcastFunctionInsteadOfDowncast.fs deleted file mode 100644 index 6bc8c54c124..00000000000 --- a/tests/fsharpqa/Source/Warnings/UpcastFunctionInsteadOfDowncast.fs +++ /dev/null @@ -1,9 +0,0 @@ -// #Warnings -//The conversion from Dictionary to IDictionary is a compile-time safe upcast, not a downcast. Consider using 'upcast' instead of 'downcast'. - -open System.Collections.Generic - -let orig = Dictionary() -let c : IDictionary = downcast orig - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/UpcastInsteadOfDowncast.fs b/tests/fsharpqa/Source/Warnings/UpcastInsteadOfDowncast.fs deleted file mode 100644 index 00962a1521b..00000000000 --- a/tests/fsharpqa/Source/Warnings/UpcastInsteadOfDowncast.fs +++ /dev/null @@ -1,9 +0,0 @@ -// #Warnings -//The conversion from Dictionary to IDictionary is a compile-time safe upcast, not a downcast. - -open System.Collections.Generic - -let orig = Dictionary() -let c = orig :?> IDictionary - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/env.lst b/tests/fsharpqa/Source/Warnings/env.lst index 350dc92a0d9..3a31070e079 100644 --- a/tests/fsharpqa/Source/Warnings/env.lst +++ b/tests/fsharpqa/Source/Warnings/env.lst @@ -38,9 +38,6 @@ SOURCE=SuggestToUseIndexer.fs # SuggestToUseIndexer.fs SOURCE=RefCellInsteadOfNot.fs # RefCellInsteadOfNot.fs SOURCE=RefCellInsteadOfNot2.fs # RefCellInsteadOfNot2.fs - SOURCE=UpcastInsteadOfDowncast.fs # UpcastInsteadOfDowncast.fs - SOURCE=UpcastFunctionInsteadOfDowncast.fs # UpcastFunctionInsteadOfDowncast.fs - SOURCE=DowncastInsteadOfUpcast.fs # DowncastInsteadOfUpcast.fs SOURCE=RuntimeTypeTestInPattern.fs # RuntimeTypeTestInPattern.fs SOURCE=RuntimeTypeTestInPattern2.fs # RuntimeTypeTestInPattern2.fs SOURCE=WarnIfExpressionResultUnused.fs # WarnIfExpressionResultUnused.fs From c8bac72813d88e048979dd7160d7edf82700d67a Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Wed, 17 Jul 2019 10:24:11 -0700 Subject: [PATCH 20/46] Update dependencies from https://github.com/dotnet/arcade build 20190716.4 (#7245) - Microsoft.DotNet.Arcade.Sdk - 1.0.0-beta.19366.4 --- eng/Version.Details.xml | 4 ++-- global.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 19eab0f3c7e..86d49308d4e 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -3,9 +3,9 @@ - + https://github.com/dotnet/arcade - fb27fd4d8a2b67d4333e33d4b898c65171c9f3c1 + 0dd5e2025f0049c133a8706f40e4463b193e5d17 diff --git a/global.json b/global.json index 616ab02e470..7d6048be9fe 100644 --- a/global.json +++ b/global.json @@ -10,7 +10,7 @@ } }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19365.4", + "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19366.4", "Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19069.2" } } From 69805873b502337e8e3d2b1346796cc8ce8b7981 Mon Sep 17 00:00:00 2001 From: Kevin Schneider Date: Wed, 17 Jul 2019 19:44:10 +0200 Subject: [PATCH 21/46] Move ErrorMessages/NameResolution Tests to NUnit (#7237) * Mark name resoltion error message tests for port to NUnit * Add Nunit tests for FieldNotInRecord, RecordFieldProposal, and GlobalQualifierAfterDot * Fix expected error message in FieldNotInRecord Compiler test * Change global Qualifier after dot test back to original fsharpqa version. Needs seperate assert function for parsing errors instead of typechecking * Remove unnecessary double ticks from NameResolution tests --- .../ErrorMessages/NameResolutionTests.fs | 45 +++++++++++++++++++ tests/fsharp/FSharpSuite.Tests.fsproj | 1 + .../NameResolution/E_FieldNotInRecord.fs | 13 ------ .../E_GlobalQualifierAfterDot.fs | 2 +- .../NameResolution/E_RecordFieldProposal.fs | 13 ------ .../ErrorMessages/NameResolution/env.lst | 4 +- 6 files changed, 48 insertions(+), 30 deletions(-) create mode 100644 tests/fsharp/Compiler/ErrorMessages/NameResolutionTests.fs delete mode 100644 tests/fsharpqa/Source/ErrorMessages/NameResolution/E_FieldNotInRecord.fs delete mode 100644 tests/fsharpqa/Source/ErrorMessages/NameResolution/E_RecordFieldProposal.fs diff --git a/tests/fsharp/Compiler/ErrorMessages/NameResolutionTests.fs b/tests/fsharp/Compiler/ErrorMessages/NameResolutionTests.fs new file mode 100644 index 00000000000..70def908d11 --- /dev/null +++ b/tests/fsharp/Compiler/ErrorMessages/NameResolutionTests.fs @@ -0,0 +1,45 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace FSharp.Compiler.UnitTests + +open NUnit.Framework +open FSharp.Compiler.SourceCodeServices + +[] +module NameResolutionTests = + + [] + let FieldNotInRecord () = + CompilerAssert.TypeCheckSingleError + """ +type A = { Hello:string; World:string } +type B = { Size:int; Height:int } +type C = { Wheels:int } +type D = { Size:int; Height:int; Walls:int } +type E = { Unknown:string } +type F = { Wallis:int; Size:int; Height:int; } + +let r:F = { Size=3; Height=4; Wall=1 } + """ + FSharpErrorSeverity.Error + 1129 + (9, 31, 9, 35) + "The record type 'F' does not contain a label 'Wall'." + + [] + let RecordFieldProposal () = + CompilerAssert.TypeCheckSingleError + """ +type A = { Hello:string; World:string } +type B = { Size:int; Height:int } +type C = { Wheels:int } +type D = { Size:int; Height:int; Walls:int } +type E = { Unknown:string } +type F = { Wallis:int; Size:int; Height:int; } + +let r = { Size=3; Height=4; Wall=1 } + """ + FSharpErrorSeverity.Error + 39 + (9, 29, 9, 33) + "The record label 'Wall' is not defined." \ No newline at end of file diff --git a/tests/fsharp/FSharpSuite.Tests.fsproj b/tests/fsharp/FSharpSuite.Tests.fsproj index ec2a852b131..fe3d1656a91 100644 --- a/tests/fsharp/FSharpSuite.Tests.fsproj +++ b/tests/fsharp/FSharpSuite.Tests.fsproj @@ -36,6 +36,7 @@ + diff --git a/tests/fsharpqa/Source/ErrorMessages/NameResolution/E_FieldNotInRecord.fs b/tests/fsharpqa/Source/ErrorMessages/NameResolution/E_FieldNotInRecord.fs deleted file mode 100644 index 4a5361f8f67..00000000000 --- a/tests/fsharpqa/Source/ErrorMessages/NameResolution/E_FieldNotInRecord.fs +++ /dev/null @@ -1,13 +0,0 @@ -// #ErrorMessages #NameResolution -//The record type 'F' does not contain a label 'Wall'\. - -type A = { Hello:string; World:string } -type B = { Size:int; Height:int } -type C = { Wheels:int } -type D = { Size:int; Height:int; Walls:int } -type E = { Unknown:string } -type F = { Wallis:int; Size:int; Height:int; } - -let r:F = { Size=3; Height=4; Wall=1 } - -exit 0 diff --git a/tests/fsharpqa/Source/ErrorMessages/NameResolution/E_GlobalQualifierAfterDot.fs b/tests/fsharpqa/Source/ErrorMessages/NameResolution/E_GlobalQualifierAfterDot.fs index b369ffad37f..9bde0edbc4f 100644 --- a/tests/fsharpqa/Source/ErrorMessages/NameResolution/E_GlobalQualifierAfterDot.fs +++ b/tests/fsharpqa/Source/ErrorMessages/NameResolution/E_GlobalQualifierAfterDot.fs @@ -3,4 +3,4 @@ let x = global.System.String.Empty.global.System.String.Empty -exit 0 +exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/ErrorMessages/NameResolution/E_RecordFieldProposal.fs b/tests/fsharpqa/Source/ErrorMessages/NameResolution/E_RecordFieldProposal.fs deleted file mode 100644 index ca73d5c1e54..00000000000 --- a/tests/fsharpqa/Source/ErrorMessages/NameResolution/E_RecordFieldProposal.fs +++ /dev/null @@ -1,13 +0,0 @@ -// #ErrorMessages #NameResolution -//The record label 'Wall' is not defined\. - -type A = { Hello:string; World:string } -type B = { Size:int; Height:int } -type C = { Wheels:int } -type D = { Size:int; Height:int; Walls:int } -type E = { Unknown:string } -type F = { Wallis:int; Size:int; Height:int; } - -let r = { Size=3; Height=4; Wall=1 } - -exit 0 diff --git a/tests/fsharpqa/Source/ErrorMessages/NameResolution/env.lst b/tests/fsharpqa/Source/ErrorMessages/NameResolution/env.lst index 42209ddd28e..71bc0eb3900 100644 --- a/tests/fsharpqa/Source/ErrorMessages/NameResolution/env.lst +++ b/tests/fsharpqa/Source/ErrorMessages/NameResolution/env.lst @@ -1,3 +1 @@ - SOURCE=E_RecordFieldProposal.fs # E_RecordFieldProposal - SOURCE=E_GlobalQualifierAfterDot.fs # E_GlobalQualifierAfterDot - SOURCE=E_FieldNotInRecord.fs # E_FieldNotInRecord \ No newline at end of file +SOURCE=E_GlobalQualifierAfterDot.fs # E_GlobalQualifierAfterDot \ No newline at end of file From 4cf7b5bc523d9701f7f0ca22711ed4165bf11afc Mon Sep 17 00:00:00 2001 From: Sergey Tihon Date: Wed, 17 Jul 2019 21:11:31 +0300 Subject: [PATCH 22/46] Moving WarnExpressionTests over to NUnit (#7232) --- .../ErrorMessages/WarnExpressionTests.fs | 208 ++++++++++++++++++ tests/fsharp/FSharpSuite.Tests.fsproj | 1 + .../DontWarnIfPropertyWithoutSetter.fs | 14 -- .../Source/Warnings/WarnIfDiscardedInList.fs | 14 -- .../Source/Warnings/WarnIfDiscardedInList2.fs | 19 -- .../Source/Warnings/WarnIfDiscardedInList3.fs | 19 -- .../Warnings/WarnIfExpressionResultUnused.fs | 5 - .../Warnings/WarnIfImplicitlyDiscarded.fs | 11 - .../Warnings/WarnIfPossibleAssignment.fs | 11 - .../WarnIfPossibleAssignmentToMutable.fs | 11 - .../WarnIfPossibleDotNetPropertySetter.fs | 13 -- .../Warnings/WarnIfPossiblePropertySetter.fs | 15 -- .../Warnings/WarnOnlyOnLastExpression.fs | 10 - tests/fsharpqa/Source/Warnings/env.lst | 11 - 14 files changed, 209 insertions(+), 153 deletions(-) create mode 100644 tests/fsharp/Compiler/ErrorMessages/WarnExpressionTests.fs delete mode 100644 tests/fsharpqa/Source/Warnings/DontWarnIfPropertyWithoutSetter.fs delete mode 100644 tests/fsharpqa/Source/Warnings/WarnIfDiscardedInList.fs delete mode 100644 tests/fsharpqa/Source/Warnings/WarnIfDiscardedInList2.fs delete mode 100644 tests/fsharpqa/Source/Warnings/WarnIfDiscardedInList3.fs delete mode 100644 tests/fsharpqa/Source/Warnings/WarnIfExpressionResultUnused.fs delete mode 100644 tests/fsharpqa/Source/Warnings/WarnIfImplicitlyDiscarded.fs delete mode 100644 tests/fsharpqa/Source/Warnings/WarnIfPossibleAssignment.fs delete mode 100644 tests/fsharpqa/Source/Warnings/WarnIfPossibleAssignmentToMutable.fs delete mode 100644 tests/fsharpqa/Source/Warnings/WarnIfPossibleDotNetPropertySetter.fs delete mode 100644 tests/fsharpqa/Source/Warnings/WarnIfPossiblePropertySetter.fs delete mode 100644 tests/fsharpqa/Source/Warnings/WarnOnlyOnLastExpression.fs diff --git a/tests/fsharp/Compiler/ErrorMessages/WarnExpressionTests.fs b/tests/fsharp/Compiler/ErrorMessages/WarnExpressionTests.fs new file mode 100644 index 00000000000..557aa81a4d4 --- /dev/null +++ b/tests/fsharp/Compiler/ErrorMessages/WarnExpressionTests.fs @@ -0,0 +1,208 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace FSharp.Compiler.UnitTests + +open NUnit.Framework +open FSharp.Compiler.SourceCodeServices + +[] +module ``Warn Expression`` = + + [] + let ``Warn If Expression Result Unused``() = + CompilerAssert.TypeCheckSingleError + """ +1 + 2 +printfn "%d" 3 + """ + FSharpErrorSeverity.Warning + 20 + (2, 1, 2, 6) + "The result of this expression has type 'int' and is implicitly ignored. Consider using 'ignore' to discard this value explicitly, e.g. 'expr |> ignore', or 'let' to bind the result to a name, e.g. 'let result = expr'." + + [] + let ``Warn If Possible Assignment``() = + CompilerAssert.TypeCheckSingleError + """ +let x = 10 +let y = "hello" + +let changeX() = + x = 20 + y = "test" + """ + FSharpErrorSeverity.Warning + 20 + (6, 5, 6, 11) + "The result of this equality expression has type 'bool' and is implicitly discarded. Consider using 'let' to bind the result to a name, e.g. 'let result = expression'. If you intended to mutate a value, then mark the value 'mutable' and use the '<-' operator e.g. 'x <- expression'." + + [] + let ``Warn If Possible Assignment To Mutable``() = + CompilerAssert.TypeCheckSingleError + """ +let mutable x = 10 +let y = "hello" + +let changeX() = + x = 20 + y = "test" + """ + FSharpErrorSeverity.Warning + 20 + (6, 5, 6, 11) + "The result of this equality expression has type 'bool' and is implicitly discarded. Consider using 'let' to bind the result to a name, e.g. 'let result = expression'. If you intended to mutate a value, then use the '<-' operator e.g. 'x <- expression'." + + [] + let ``Warn If Possible dotnet Property Setter``() = + CompilerAssert.TypeCheckWithErrors + """ +open System + +let z = System.Timers.Timer() +let y = "hello" + +let changeProperty() = + z.Enabled = true + y = "test" + """ + [| + FSharpErrorSeverity.Warning, 760, (4, 9, 4, 30), "It is recommended that objects supporting the IDisposable interface are created using the syntax 'new Type(args)', rather than 'Type(args)' or 'Type' as a function value representing the constructor, to indicate that resources may be owned by the generated value" + FSharpErrorSeverity.Warning, 20, (8, 5, 8, 21), "The result of this equality expression has type 'bool' and is implicitly discarded. Consider using 'let' to bind the result to a name, e.g. 'let result = expression'. If you intended to set a value to a property, then use the '<-' operator e.g. 'z.Enabled <- expression'." + |] + + [] + let ``Don't Warn If Property Without Setter``() = + CompilerAssert.TypeCheckSingleError + """ +type MyClass(property1 : int) = + member val Property2 = "" with get + +let x = MyClass(1) +let y = "hello" + +let changeProperty() = + x.Property2 = "22" + y = "test" + """ + FSharpErrorSeverity.Warning + 20 + (9, 5, 9, 23) + "The result of this equality expression has type 'bool' and is implicitly discarded. Consider using 'let' to bind the result to a name, e.g. 'let result = expression'." + + [] + let ``Warn If Implicitly Discarded``() = + CompilerAssert.TypeCheckSingleError + """ +let x = 10 +let y = 20 + +let changeX() = + y * x = 20 + y = 30 + """ + FSharpErrorSeverity.Warning + 20 + (6, 5, 6, 15) + "The result of this equality expression has type 'bool' and is implicitly discarded. Consider using 'let' to bind the result to a name, e.g. 'let result = expression'." + + [] + let ``Warn If Discarded In List``() = + CompilerAssert.TypeCheckSingleError + """ +let div _ _ = 1 +let subView _ _ = [1; 2] + +// elmish view +let view model dispatch = + [ + yield! subView model dispatch + div [] [] + ] + """ + FSharpErrorSeverity.Warning + 3221 + (9, 8, 9, 17) + "This expression returns a value of type 'int' but is implicitly discarded. Consider using 'let' to bind the result to a name, e.g. 'let result = expression'. If you intended to use the expression as a value in the sequence then use an explicit 'yield'." + + [] + let ``Warn If Discarded In List 2``() = + CompilerAssert.TypeCheckSingleError + """ +// stupid things to make the sample compile +let div _ _ = 1 +let subView _ _ = [1; 2] +let y = 1 + +// elmish view +let view model dispatch = + [ + div [] [ + match y with + | 1 -> yield! subView model dispatch + | _ -> subView model dispatch + ] + ] + """ + FSharpErrorSeverity.Warning + 3222 + (13, 19, 13, 41) + "This expression returns a value of type 'int list' but is implicitly discarded. Consider using 'let' to bind the result to a name, e.g. 'let result = expression'. If you intended to use the expression as a value in the sequence then use an explicit 'yield!'." + + [] + let ``Warn If Discarded In List 3``() = + CompilerAssert.TypeCheckSingleError + """ +// stupid things to make the sample compile +let div _ _ = 1 +let subView _ _ = true +let y = 1 + +// elmish view +let view model dispatch = + [ + div [] [ + match y with + | 1 -> () + | _ -> subView model dispatch + ] + ] + """ + FSharpErrorSeverity.Warning + 20 + (13, 19, 13, 41) + "The result of this expression has type 'bool' and is implicitly ignored. Consider using 'ignore' to discard this value explicitly, e.g. 'expr |> ignore', or 'let' to bind the result to a name, e.g. 'let result = expr'." + + [] + let ``Warn Only On Last Expression``() = + CompilerAssert.TypeCheckSingleError + """ +let mutable x = 0 +while x < 1 do + printfn "unneeded" + x <- x + 1 + true + """ + FSharpErrorSeverity.Warning + 20 + (6, 5, 6, 9) + "The result of this expression has type 'bool' and is implicitly ignored. Consider using 'ignore' to discard this value explicitly, e.g. 'expr |> ignore', or 'let' to bind the result to a name, e.g. 'let result = expr'." + + [] + let ``Warn If Possible Property Setter``() = + CompilerAssert.TypeCheckSingleError + """ +type MyClass(property1 : int) = + member val Property1 = property1 + member val Property2 = "" with get, set + +let x = MyClass(1) +let y = "hello" + +let changeProperty() = + x.Property2 = "20" + y = "test" + """ + FSharpErrorSeverity.Warning + 20 + (10, 5, 10, 23) + "The result of this equality expression has type 'bool' and is implicitly discarded. Consider using 'let' to bind the result to a name, e.g. 'let result = expression'. If you intended to set a value to a property, then use the '<-' operator e.g. 'x.Property2 <- expression'." diff --git a/tests/fsharp/FSharpSuite.Tests.fsproj b/tests/fsharp/FSharpSuite.Tests.fsproj index fe3d1656a91..b1bb4c1e33a 100644 --- a/tests/fsharp/FSharpSuite.Tests.fsproj +++ b/tests/fsharp/FSharpSuite.Tests.fsproj @@ -38,6 +38,7 @@ + diff --git a/tests/fsharpqa/Source/Warnings/DontWarnIfPropertyWithoutSetter.fs b/tests/fsharpqa/Source/Warnings/DontWarnIfPropertyWithoutSetter.fs deleted file mode 100644 index 4492e6338c6..00000000000 --- a/tests/fsharpqa/Source/Warnings/DontWarnIfPropertyWithoutSetter.fs +++ /dev/null @@ -1,14 +0,0 @@ -// #Warnings -//The result of this equality expression has type 'bool' and is implicitly discarded. Consider using 'let' to bind the result to a name, e.g. 'let result = expression'. - -type MyClass(property1 : int) = - member val Property2 = "" with get - -let x = MyClass(1) -let y = "hello" - -let changeProperty() = - x.Property2 = "22" - y = "test" - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/WarnIfDiscardedInList.fs b/tests/fsharpqa/Source/Warnings/WarnIfDiscardedInList.fs deleted file mode 100644 index d47a4c13769..00000000000 --- a/tests/fsharpqa/Source/Warnings/WarnIfDiscardedInList.fs +++ /dev/null @@ -1,14 +0,0 @@ -// #Warnings -// - -let div _ _ = 1 -let subView _ _ = [1; 2] - -// elmish view -let view model dispatch = - [ - yield! subView model dispatch - div [] [] - ] - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/WarnIfDiscardedInList2.fs b/tests/fsharpqa/Source/Warnings/WarnIfDiscardedInList2.fs deleted file mode 100644 index d360da4d666..00000000000 --- a/tests/fsharpqa/Source/Warnings/WarnIfDiscardedInList2.fs +++ /dev/null @@ -1,19 +0,0 @@ -// #Warnings -// - -// stupid things to make the sample compile -let div _ _ = 1 -let subView _ _ = [1; 2] -let y = 1 - -// elmish view -let view model dispatch = - [ - div [] [ - match y with - | 1 -> yield! subView model dispatch - | _ -> subView model dispatch - ] - ] - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/WarnIfDiscardedInList3.fs b/tests/fsharpqa/Source/Warnings/WarnIfDiscardedInList3.fs deleted file mode 100644 index 238d4388f9e..00000000000 --- a/tests/fsharpqa/Source/Warnings/WarnIfDiscardedInList3.fs +++ /dev/null @@ -1,19 +0,0 @@ -// #Warnings -// - -// stupid things to make the sample compile -let div _ _ = 1 -let subView _ _ = true -let y = 1 - -// elmish view -let view model dispatch = - [ - div [] [ - match y with - | 1 -> () - | _ -> subView model dispatch - ] - ] - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/WarnIfExpressionResultUnused.fs b/tests/fsharpqa/Source/Warnings/WarnIfExpressionResultUnused.fs deleted file mode 100644 index 9480f35b6b6..00000000000 --- a/tests/fsharpqa/Source/Warnings/WarnIfExpressionResultUnused.fs +++ /dev/null @@ -1,5 +0,0 @@ -// #Warnings -//The result of this expression has type 'int' and is implicitly ignored\. Consider using 'ignore' to discard this value explicitly, e\.g\. 'expr \|> ignore', or 'let' to bind the result to a name, e\.g\. 'let result = expr'.$ - -1 + 2 -printfn "%d" 3 diff --git a/tests/fsharpqa/Source/Warnings/WarnIfImplicitlyDiscarded.fs b/tests/fsharpqa/Source/Warnings/WarnIfImplicitlyDiscarded.fs deleted file mode 100644 index ad7f9deacdd..00000000000 --- a/tests/fsharpqa/Source/Warnings/WarnIfImplicitlyDiscarded.fs +++ /dev/null @@ -1,11 +0,0 @@ -// #Warnings -//The result of this equality expression has type 'bool' and is implicitly discarded. Consider using 'let' to bind the result to a name, e.g. 'let result = expression'. - -let x = 10 -let y = 20 - -let changeX() = - y * x = 20 - y = 30 - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/WarnIfPossibleAssignment.fs b/tests/fsharpqa/Source/Warnings/WarnIfPossibleAssignment.fs deleted file mode 100644 index b3fca3a0b92..00000000000 --- a/tests/fsharpqa/Source/Warnings/WarnIfPossibleAssignment.fs +++ /dev/null @@ -1,11 +0,0 @@ -// #Warnings -//If you intended to mutate a value, then mark the value 'mutable' and use the '<-' operator e.g. 'x <- expression'. - -let x = 10 -let y = "hello" - -let changeX() = - x = 20 - y = "test" - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/WarnIfPossibleAssignmentToMutable.fs b/tests/fsharpqa/Source/Warnings/WarnIfPossibleAssignmentToMutable.fs deleted file mode 100644 index bd827ec4adc..00000000000 --- a/tests/fsharpqa/Source/Warnings/WarnIfPossibleAssignmentToMutable.fs +++ /dev/null @@ -1,11 +0,0 @@ -// #Warnings -//If you intended to mutate a value, then use the '<-' operator e.g. 'x <- expression'. - -let mutable x = 10 -let y = "hello" - -let changeX() = - x = 20 - y = "test" - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/WarnIfPossibleDotNetPropertySetter.fs b/tests/fsharpqa/Source/Warnings/WarnIfPossibleDotNetPropertySetter.fs deleted file mode 100644 index 7c461349ec2..00000000000 --- a/tests/fsharpqa/Source/Warnings/WarnIfPossibleDotNetPropertySetter.fs +++ /dev/null @@ -1,13 +0,0 @@ -// #Warnings -//If you intended to set a value to a property, then use the '<-' operator e.g. 'z.Enabled <- expression' - -open System - -let z = System.Timers.Timer() -let y = "hello" - -let changeProperty() = - z.Enabled = true - y = "test" - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/WarnIfPossiblePropertySetter.fs b/tests/fsharpqa/Source/Warnings/WarnIfPossiblePropertySetter.fs deleted file mode 100644 index 7548d204685..00000000000 --- a/tests/fsharpqa/Source/Warnings/WarnIfPossiblePropertySetter.fs +++ /dev/null @@ -1,15 +0,0 @@ -// #Warnings -//If you intended to set a value to a property, then use the '<-' operator e.g. 'x.Property2 <- expression' - -type MyClass(property1 : int) = - member val Property1 = property1 - member val Property2 = "" with get, set - -let x = MyClass(1) -let y = "hello" - -let changeProperty() = - x.Property2 = "20" - y = "test" - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/WarnOnlyOnLastExpression.fs b/tests/fsharpqa/Source/Warnings/WarnOnlyOnLastExpression.fs deleted file mode 100644 index 7b0b968c23b..00000000000 --- a/tests/fsharpqa/Source/Warnings/WarnOnlyOnLastExpression.fs +++ /dev/null @@ -1,10 +0,0 @@ -// #Warnings -//The result of this expression has type 'bool' and is implicitly ignored - -let mutable x = 0 -while x < 1 do - printfn "unneeded" - x <- x + 1 - true - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/env.lst b/tests/fsharpqa/Source/Warnings/env.lst index 3a31070e079..9b5fbffaeba 100644 --- a/tests/fsharpqa/Source/Warnings/env.lst +++ b/tests/fsharpqa/Source/Warnings/env.lst @@ -40,19 +40,8 @@ SOURCE=RefCellInsteadOfNot2.fs # RefCellInsteadOfNot2.fs SOURCE=RuntimeTypeTestInPattern.fs # RuntimeTypeTestInPattern.fs SOURCE=RuntimeTypeTestInPattern2.fs # RuntimeTypeTestInPattern2.fs - SOURCE=WarnIfExpressionResultUnused.fs # WarnIfExpressionResultUnused.fs SOURCE=MemberHasMultiplePossibleDispatchSlots.fs # MemberHasMultiplePossibleDispatchSlots.fs SOURCE=Repro1548.fs SCFLAGS="-r:Repro1548.dll" # Repro1548.fs - SOURCE=WarnIfPossibleAssignment.fs - SOURCE=WarnIfPossibleAssignmentToMutable.fs - SOURCE=WarnIfPossibleDotNetPropertySetter.fs - SOURCE=DontWarnIfPropertyWithoutSetter.fs - SOURCE=WarnIfImplicitlyDiscarded.fs - SOURCE=WarnIfDiscardedInList.fs - SOURCE=WarnIfDiscardedInList2.fs - SOURCE=WarnIfDiscardedInList3.fs - SOURCE=WarnOnlyOnLastExpression.fs - SOURCE=WarnIfPossiblePropertySetter.fs SOURCE=DoCannotHaveVisibilityDeclarations.fs SOURCE=ModuleAbbreviationsArePrivate.fs SOURCE=DontSuggestIntentionallyUnusedVariables.fs SCFLAGS="--vserrors" # DontSuggestIntentionallyUnusedVariables.fs From 650805b36840bd9ded0d4472a31bc756a42e8243 Mon Sep 17 00:00:00 2001 From: Sean McLemon Date: Wed, 17 Jul 2019 23:01:51 +0200 Subject: [PATCH 23/46] move some error and warning tests to NUnit (#7244) * move some error and warning tests to NUnit * CompilerAssert.ParseWithErrors now uses ParseFile instead of ParseAndCheckFileInProject * merge conflicts --- tests/fsharp/Compiler/CompilerAssert.fs | 19 +++ .../ErrorMessages/AssignmentErrorTests.fs | 23 ++++ .../Warnings/AssignmentWarningTests.fs | 108 ++++++++++++++++++ tests/fsharp/FSharpSuite.Tests.fsproj | 2 + .../E_GlobalQualifierAfterDot.fs | 6 - .../ErrorMessages/NameResolution/env.lst | 1 - .../Source/Warnings/AssignmentOnImmutable.fs | 7 -- tests/fsharpqa/Source/Warnings/env.lst | 1 - tests/fsharpqa/Source/test.lst | 1 - 9 files changed, 152 insertions(+), 16 deletions(-) create mode 100644 tests/fsharp/Compiler/ErrorMessages/AssignmentErrorTests.fs create mode 100644 tests/fsharp/Compiler/Warnings/AssignmentWarningTests.fs delete mode 100644 tests/fsharpqa/Source/ErrorMessages/NameResolution/E_GlobalQualifierAfterDot.fs delete mode 100644 tests/fsharpqa/Source/ErrorMessages/NameResolution/env.lst delete mode 100644 tests/fsharpqa/Source/Warnings/AssignmentOnImmutable.fs diff --git a/tests/fsharp/Compiler/CompilerAssert.fs b/tests/fsharp/Compiler/CompilerAssert.fs index d5f93d7810e..ade3ca8e4a3 100644 --- a/tests/fsharp/Compiler/CompilerAssert.fs +++ b/tests/fsharp/Compiler/CompilerAssert.fs @@ -217,3 +217,22 @@ module CompilerAssert = Assert.AreEqual(expectedErrorMessage, errorMessage) ) + let ParseWithErrors (source: string) expectedParseErrors = + let parseResults = checker.ParseFile("test.fs", SourceText.ofString source, FSharpParsingOptions.Default) |> Async.RunSynchronously + + Assert.True(parseResults.ParseHadErrors) + + let errors = + parseResults.Errors + |> Array.distinctBy (fun e -> e.Severity, e.ErrorNumber, e.StartLineAlternate, e.StartColumn, e.EndLineAlternate, e.EndColumn, e.Message) + + Assert.AreEqual(Array.length expectedParseErrors, errors.Length, sprintf "Type check errors: %A" parseResults.Errors) + + Array.zip errors expectedParseErrors + |> Array.iter (fun (info, expectedError) -> + let (expectedServerity: FSharpErrorSeverity, expectedErrorNumber: int, expectedErrorRange: int * int * int * int, expectedErrorMsg: string) = expectedError + Assert.AreEqual(expectedServerity, info.Severity) + Assert.AreEqual(expectedErrorNumber, info.ErrorNumber, "expectedErrorNumber") + Assert.AreEqual(expectedErrorRange, (info.StartLineAlternate, info.StartColumn + 1, info.EndLineAlternate, info.EndColumn + 1), "expectedErrorRange") + Assert.AreEqual(expectedErrorMsg, info.Message, "expectedErrorMsg") + ) \ No newline at end of file diff --git a/tests/fsharp/Compiler/ErrorMessages/AssignmentErrorTests.fs b/tests/fsharp/Compiler/ErrorMessages/AssignmentErrorTests.fs new file mode 100644 index 00000000000..51b75dd87d7 --- /dev/null +++ b/tests/fsharp/Compiler/ErrorMessages/AssignmentErrorTests.fs @@ -0,0 +1,23 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace FSharp.Compiler.UnitTests + +open NUnit.Framework +open FSharp.Compiler.SourceCodeServices + +[] +module ``Errors assigning to mutable objects`` = + + [] + let ``Assign to immutable error``() = + CompilerAssert.TypeCheckSingleError + """ +let x = 10 +x <- 20 + +exit 0 + """ + FSharpErrorSeverity.Error + 27 + (3, 1, 3, 8) + "This value is not mutable. Consider using the mutable keyword, e.g. 'let mutable x = expression'." \ No newline at end of file diff --git a/tests/fsharp/Compiler/Warnings/AssignmentWarningTests.fs b/tests/fsharp/Compiler/Warnings/AssignmentWarningTests.fs new file mode 100644 index 00000000000..2a0d15d8f8b --- /dev/null +++ b/tests/fsharp/Compiler/Warnings/AssignmentWarningTests.fs @@ -0,0 +1,108 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace FSharp.Compiler.UnitTests + +open NUnit.Framework +open FSharp.Compiler.SourceCodeServices + +[] +module ``Warnings assigning to mutable and immutable objects`` = + + [] + let ``Unused compare with immutable when assignment might be intended``() = + CompilerAssert.TypeCheckSingleError + """ +let x = 10 +let y = "hello" + +let changeX() = + x = 20 + y = "test" + +exit 0 + """ + FSharpErrorSeverity.Warning + 20 + (6, 5, 6, 11) + "The result of this equality expression has type 'bool' and is implicitly discarded. Consider using 'let' to bind the result to a name, e.g. 'let result = expression'. If you intended to mutate a value, then mark the value 'mutable' and use the '<-' operator e.g. 'x <- expression'." + + [] + let ``Unused compare with mutable when assignment might be intended``() = + CompilerAssert.TypeCheckSingleError + """ +let mutable x = 10 +let y = "hello" + +let changeX() = + x = 20 + y = "test" + +exit 0 + """ + FSharpErrorSeverity.Warning + 20 + (6, 5, 6, 11) + "The result of this equality expression has type 'bool' and is implicitly discarded. Consider using 'let' to bind the result to a name, e.g. 'let result = expression'. If you intended to mutate a value, then use the '<-' operator e.g. 'x <- expression'." + + [] + let ``Unused comparison of property in dotnet object when assignment might be intended``() = + CompilerAssert.TypeCheckSingleError + """ +open System + +let z = new System.Timers.Timer() +let y = "hello" + +let changeProperty() = + z.Enabled = true + y = "test" + +exit 0 + """ + FSharpErrorSeverity.Warning + 20 + (8, 5, 8, 21) + "The result of this equality expression has type 'bool' and is implicitly discarded. Consider using 'let' to bind the result to a name, e.g. 'let result = expression'. If you intended to set a value to a property, then use the '<-' operator e.g. 'z.Enabled <- expression'." + + [] + let ``Unused comparison of property when assignment might be intended ``() = + CompilerAssert.TypeCheckSingleError + """ +type MyClass(property1 : int) = + member val Property1 = property1 + member val Property2 = "" with get, set + +let x = MyClass(1) +let y = "hello" + +let changeProperty() = + x.Property2 = "20" + y = "test" + +exit 0 + """ + FSharpErrorSeverity.Warning + 20 + (10, 5, 10, 23) + "The result of this equality expression has type 'bool' and is implicitly discarded. Consider using 'let' to bind the result to a name, e.g. 'let result = expression'. If you intended to set a value to a property, then use the '<-' operator e.g. 'x.Property2 <- expression'." + + [] + let ``Don't warn if assignment to property without setter ``() = + CompilerAssert.TypeCheckSingleError + """ +type MyClass(property1 : int) = + member val Property2 = "" with get + +let x = MyClass(1) +let y = "hello" + +let changeProperty() = + x.Property2 = "22" + y = "test" + +exit 0 + """ + FSharpErrorSeverity.Warning + 20 + (9, 5, 9, 23) + "The result of this equality expression has type 'bool' and is implicitly discarded. Consider using 'let' to bind the result to a name, e.g. 'let result = expression'." \ No newline at end of file diff --git a/tests/fsharp/FSharpSuite.Tests.fsproj b/tests/fsharp/FSharpSuite.Tests.fsproj index b1bb4c1e33a..50e3e4f2d47 100644 --- a/tests/fsharp/FSharpSuite.Tests.fsproj +++ b/tests/fsharp/FSharpSuite.Tests.fsproj @@ -38,6 +38,7 @@ + @@ -45,6 +46,7 @@ + diff --git a/tests/fsharpqa/Source/ErrorMessages/NameResolution/E_GlobalQualifierAfterDot.fs b/tests/fsharpqa/Source/ErrorMessages/NameResolution/E_GlobalQualifierAfterDot.fs deleted file mode 100644 index 9bde0edbc4f..00000000000 --- a/tests/fsharpqa/Source/ErrorMessages/NameResolution/E_GlobalQualifierAfterDot.fs +++ /dev/null @@ -1,6 +0,0 @@ -// #ErrorMessages #NameResolution -//'global' may only be used as the first name in a qualified path - -let x = global.System.String.Empty.global.System.String.Empty - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/ErrorMessages/NameResolution/env.lst b/tests/fsharpqa/Source/ErrorMessages/NameResolution/env.lst deleted file mode 100644 index 71bc0eb3900..00000000000 --- a/tests/fsharpqa/Source/ErrorMessages/NameResolution/env.lst +++ /dev/null @@ -1 +0,0 @@ -SOURCE=E_GlobalQualifierAfterDot.fs # E_GlobalQualifierAfterDot \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/AssignmentOnImmutable.fs b/tests/fsharpqa/Source/Warnings/AssignmentOnImmutable.fs deleted file mode 100644 index a2e35c78a90..00000000000 --- a/tests/fsharpqa/Source/Warnings/AssignmentOnImmutable.fs +++ /dev/null @@ -1,7 +0,0 @@ -// #Warnings -//This value is not mutable. Consider using the mutable keyword, e.g. 'let mutable x = expression'. - -let x = 10 -x <- 20 - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/env.lst b/tests/fsharpqa/Source/Warnings/env.lst index 9b5fbffaeba..a3d677bf0fc 100644 --- a/tests/fsharpqa/Source/Warnings/env.lst +++ b/tests/fsharpqa/Source/Warnings/env.lst @@ -32,7 +32,6 @@ SOURCE=MatchingMethodWithSameNameIsNotAbstract.fs # MatchingMethodWithSameNameIsNotAbstract.fs SOURCE=NoMatchingAbstractMethodWithSameName.fs # NoMatchingAbstractMethodWithSameName.fs SOURCE=MissingExpressionAfterLet.fs # MissingExpressionAfterLet.fs - SOURCE=AssignmentOnImmutable.fs # AssignmentOnImmutable.fs SOURCE=SuggestFieldsInCtor.fs # SuggestFieldsInCtor.fs SOURCE=FieldSuggestion.fs # FieldSuggestion.fs SOURCE=SuggestToUseIndexer.fs # SuggestToUseIndexer.fs diff --git a/tests/fsharpqa/Source/test.lst b/tests/fsharpqa/Source/test.lst index f3d79d7a03f..147475acc7f 100644 --- a/tests/fsharpqa/Source/test.lst +++ b/tests/fsharpqa/Source/test.lst @@ -264,7 +264,6 @@ Misc01 Libraries\Core\Operators Misc01 Libraries\Core\Reflection Misc01 Libraries\Core\Unchecked Misc01 Warnings -Misc01 ErrorMessages\NameResolution Misc01 ErrorMessages\UnitGenericAbstractType Misc01 ErrorMessages\ConfusingTypeName From 375fd7c63f29d74d18c30c285d726107d8af301f Mon Sep 17 00:00:00 2001 From: dotnet-maestro <@dotnet-maestro> Date: Thu, 18 Jul 2019 12:51:28 +0000 Subject: [PATCH 24/46] Update dependencies from https://github.com/dotnet/arcade build 20190717.8 - Microsoft.DotNet.Arcade.Sdk - 1.0.0-beta.19367.8 --- eng/Version.Details.xml | 4 ++-- eng/common/init-tools-native.sh | 2 +- .../templates/post-build/channels/internal-servicing.yml | 1 + eng/common/templates/post-build/channels/public-release.yml | 1 + eng/common/tools.ps1 | 2 +- global.json | 2 +- 6 files changed, 7 insertions(+), 5 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 86d49308d4e..35196ac2a5f 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -3,9 +3,9 @@ - + https://github.com/dotnet/arcade - 0dd5e2025f0049c133a8706f40e4463b193e5d17 + 2359dc4184133defa27c8f3072622270b71b4ecf diff --git a/eng/common/init-tools-native.sh b/eng/common/init-tools-native.sh index fc72d13948e..5f2e77f448b 100644 --- a/eng/common/init-tools-native.sh +++ b/eng/common/init-tools-native.sh @@ -71,7 +71,7 @@ function ReadGlobalJsonNativeTools { local native_tools_list=$(echo $native_tools_section | awk -F"[{}]" '{print $2}') native_tools_list=${native_tools_list//[\" ]/} native_tools_list=${native_tools_list//,/$'\n'} - native_tools_list="$(echo -e "${native_tools_list}" | tr -d '[:space:]')" + native_tools_list="$(echo -e "${native_tools_list}" | tr -d '[[:space:]]')" local old_IFS=$IFS while read -r line; do diff --git a/eng/common/templates/post-build/channels/internal-servicing.yml b/eng/common/templates/post-build/channels/internal-servicing.yml index 50ad724fc0c..648e854e0ed 100644 --- a/eng/common/templates/post-build/channels/internal-servicing.yml +++ b/eng/common/templates/post-build/channels/internal-servicing.yml @@ -84,6 +84,7 @@ stages: /p:AzureStorageAccountName=$(ProxyBackedFeedsAccountName) /p:AzureStorageAccountKey=$(dotnetfeed-storage-access-key-1) /p:AzureDevOpsFeedsBaseUrl=$(dotnetfeed-internal-private-feed-url) + /p:StaticInternalFeed=$(dotnetfeed-internal-nonstable-feed-url) /p:NugetPath=$(Agent.BuildDirectory)\Nuget\NuGet.exe /p:BARBuildId=$(BARBuildId) /p:MaestroApiEndpoint='https://maestro-prod.westus2.cloudapp.azure.com' diff --git a/eng/common/templates/post-build/channels/public-release.yml b/eng/common/templates/post-build/channels/public-release.yml index 574cb1c2b92..f6a7efdfe9d 100644 --- a/eng/common/templates/post-build/channels/public-release.yml +++ b/eng/common/templates/post-build/channels/public-release.yml @@ -84,6 +84,7 @@ stages: /p:AzureStorageAccountName=$(ProxyBackedFeedsAccountName) /p:AzureStorageAccountKey=$(dotnetfeed-storage-access-key-1) /p:AzureDevOpsFeedsBaseUrl=$(dotnetfeed-internal-private-feed-url) + /p:StaticInternalFeed=$(dotnetfeed-internal-nonstable-feed-url) /p:NugetPath=$(Agent.BuildDirectory)\Nuget\NuGet.exe /p:BARBuildId=$(BARBuildId) /p:MaestroApiEndpoint='https://maestro-prod.westus2.cloudapp.azure.com' diff --git a/eng/common/tools.ps1 b/eng/common/tools.ps1 index 9abaac015fb..8fe2b11ad21 100644 --- a/eng/common/tools.ps1 +++ b/eng/common/tools.ps1 @@ -169,7 +169,7 @@ function InstallDotNetSdk([string] $dotnetRoot, [string] $version, [string] $arc InstallDotNet $dotnetRoot $version $architecture } -function InstallDotNet([string] $dotnetRoot, [string] $version, [string] $architecture = "", [string] $runtime = "", [bool] $skipNonVersionedFiles = $false) { $installScript = GetDotNetInstallScript $dotnetRoot +function InstallDotNet([string] $dotnetRoot, [string] $version, [string] $architecture = "", [string] $runtime = "", [bool] $skipNonVersionedFiles = $false) { $installScript = GetDotNetInstallScript $dotnetRoot $installParameters = @{ Version = $version diff --git a/global.json b/global.json index 7d6048be9fe..b4297bf622c 100644 --- a/global.json +++ b/global.json @@ -10,7 +10,7 @@ } }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19366.4", + "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19367.8", "Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19069.2" } } From c423de9078db600cb0b95f48a518823417217b91 Mon Sep 17 00:00:00 2001 From: Faisal Alfaddaghi Date: Fri, 19 Jul 2019 20:36:19 +0300 Subject: [PATCH 25/46] Move UnitGenericAbstractType To Nunit (#7257) --- .../ErrorMessages/UnitGenericAbstactType.fs | 27 +++++++++++++++++++ tests/fsharp/FSharpSuite.Tests.fsproj | 1 + .../E_UnitGenericAbstractType1.fs | 9 ------- .../UnitGenericAbstractType/env.lst | 1 - 4 files changed, 28 insertions(+), 10 deletions(-) create mode 100644 tests/fsharp/Compiler/ErrorMessages/UnitGenericAbstactType.fs delete mode 100644 tests/fsharpqa/Source/ErrorMessages/UnitGenericAbstractType/E_UnitGenericAbstractType1.fs delete mode 100644 tests/fsharpqa/Source/ErrorMessages/UnitGenericAbstractType/env.lst diff --git a/tests/fsharp/Compiler/ErrorMessages/UnitGenericAbstactType.fs b/tests/fsharp/Compiler/ErrorMessages/UnitGenericAbstactType.fs new file mode 100644 index 00000000000..e9165a4cf6a --- /dev/null +++ b/tests/fsharp/Compiler/ErrorMessages/UnitGenericAbstactType.fs @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace FSharp.Compiler.UnitTests + +open NUnit.Framework +open FSharp.Compiler.SourceCodeServices + +[] +module ``Unit generic abstract Type`` = + + [] + let ``Unit can not be used as return type of abstract method paramete on return type``() = + CompilerAssert.TypeCheckSingleError + """ +type EDF<'S> = + abstract member Apply : int -> 'S +type SomeEDF () = + interface EDF with + member this.Apply d = + // [ERROR] The member 'Apply' does not have the correct type to override the corresponding abstract method. + () + """ + FSharpErrorSeverity.Error + 17 + (6, 21, 6, 26) + "The member 'Apply : int -> unit' is specialized with 'unit' but 'unit' can't be used as return type of an abstract method parameterized on return type." + diff --git a/tests/fsharp/FSharpSuite.Tests.fsproj b/tests/fsharp/FSharpSuite.Tests.fsproj index 50e3e4f2d47..0c9578f2192 100644 --- a/tests/fsharp/FSharpSuite.Tests.fsproj +++ b/tests/fsharp/FSharpSuite.Tests.fsproj @@ -36,6 +36,7 @@ + diff --git a/tests/fsharpqa/Source/ErrorMessages/UnitGenericAbstractType/E_UnitGenericAbstractType1.fs b/tests/fsharpqa/Source/ErrorMessages/UnitGenericAbstractType/E_UnitGenericAbstractType1.fs deleted file mode 100644 index 0b7f1d98a6d..00000000000 --- a/tests/fsharpqa/Source/ErrorMessages/UnitGenericAbstractType/E_UnitGenericAbstractType1.fs +++ /dev/null @@ -1,9 +0,0 @@ -// #ErrorMessages #UnitGenericAbstractType -//The member 'Apply : int -> unit' is specialized with 'unit' but 'unit' can't be used as return type of an abstract method parameterized on return type\. -type EDF<'S> = - abstract member Apply : int -> 'S -type SomeEDF () = - interface EDF with - member this.Apply d = - // [ERROR] The member 'Apply' does not have the correct type to override the corresponding abstract method. - () \ No newline at end of file diff --git a/tests/fsharpqa/Source/ErrorMessages/UnitGenericAbstractType/env.lst b/tests/fsharpqa/Source/ErrorMessages/UnitGenericAbstractType/env.lst deleted file mode 100644 index 26ae602bd6a..00000000000 --- a/tests/fsharpqa/Source/ErrorMessages/UnitGenericAbstractType/env.lst +++ /dev/null @@ -1 +0,0 @@ - SOURCE=E_UnitGenericAbstractType1.fs # E_UnitGenericAbstractType1 \ No newline at end of file From 4151eb23b521f74e3ec1292779c8ab47a9d8014a Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Fri, 19 Jul 2019 10:38:48 -0700 Subject: [PATCH 26/46] Update dependencies from https://github.com/dotnet/arcade build 20190718.7 (#7256) - Microsoft.DotNet.Arcade.Sdk - 1.0.0-beta.19368.7 --- eng/Version.Details.xml | 4 +- eng/common/pipeline-logging-functions.sh | 82 ++++++++++++++++++++++-- eng/common/tools.sh | 19 +++--- global.json | 2 +- 4 files changed, 87 insertions(+), 20 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 35196ac2a5f..7a60463a0fb 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -3,9 +3,9 @@ - + https://github.com/dotnet/arcade - 2359dc4184133defa27c8f3072622270b71b4ecf + eecde8a8751dbe7fdb17ba4dfbd032e26f4cae7d diff --git a/eng/common/pipeline-logging-functions.sh b/eng/common/pipeline-logging-functions.sh index 6098f9a5438..1c560a50613 100644 --- a/eng/common/pipeline-logging-functions.sh +++ b/eng/common/pipeline-logging-functions.sh @@ -39,11 +39,11 @@ function Write-PipelineTaskError { return fi - message_type="error" - sourcepath='' - linenumber='' - columnnumber='' - error_code='' + local message_type="error" + local sourcepath='' + local linenumber='' + local columnnumber='' + local error_code='' while [[ $# -gt 0 ]]; do opt="$(echo "${1/#--/-}" | awk '{print tolower($0)}')" @@ -76,7 +76,7 @@ function Write-PipelineTaskError { shift done - message="##vso[task.logissue" + local message="##vso[task.logissue" message="$message type=$message_type" @@ -100,3 +100,73 @@ function Write-PipelineTaskError { echo "$message" } +function Write-PipelineSetVariable { + if [[ "$ci" != true ]]; then + return + fi + + local name='' + local value='' + local secret=false + local as_output=false + local is_multi_job_variable=true + + while [[ $# -gt 0 ]]; do + opt="$(echo "${1/#--/-}" | awk '{print tolower($0)}')" + case "$opt" in + -name|-n) + name=$2 + shift + ;; + -value|-v) + value=$2 + shift + ;; + -secret|-s) + secret=true + ;; + -as_output|-a) + as_output=true + ;; + -is_multi_job_variable|-i) + is_multi_job_variable=$2 + shift + ;; + esac + shift + done + + value=${value/;/%3B} + value=${value/\\r/%0D} + value=${value/\\n/%0A} + value=${value/]/%5D} + + local message="##vso[task.setvariable variable=$name;isSecret=$secret;isOutput=$is_multi_job_variable]$value" + + if [[ "$as_output" == true ]]; then + $message + else + echo "$message" + fi +} + +function Write-PipelinePrependPath { + local prepend_path='' + + while [[ $# -gt 0 ]]; do + opt="$(echo "${1/#--/-}" | awk '{print tolower($0)}')" + case "$opt" in + -path|-p) + prepend_path=$2 + shift + ;; + esac + shift + done + + export PATH="$prepend_path:$PATH" + + if [[ "$ci" == true ]]; then + echo "##vso[task.prependpath]$prepend_path" + fi +} \ No newline at end of file diff --git a/eng/common/tools.sh b/eng/common/tools.sh index 70d92cf85aa..0deb01c480b 100644 --- a/eng/common/tools.sh +++ b/eng/common/tools.sh @@ -146,14 +146,10 @@ function InitializeDotNetCli { # Add dotnet to PATH. This prevents any bare invocation of dotnet in custom # build steps from using anything other than what we've downloaded. - export PATH="$dotnet_root:$PATH" + Write-PipelinePrependPath -path "$dotnet_root" - if [[ $ci == true ]]; then - # Make Sure that our bootstrapped dotnet cli is available in future steps of the Azure Pipelines build - echo "##vso[task.prependpath]$dotnet_root" - echo "##vso[task.setvariable variable=DOTNET_MULTILEVEL_LOOKUP]0" - echo "##vso[task.setvariable variable=DOTNET_SKIP_FIRST_TIME_EXPERIENCE]1" - fi + Write-PipelineSetVariable -name "DOTNET_MULTILEVEL_LOOKUP" -value "0" + Write-PipelineSetVariable -name "DOTNET_SKIP_FIRST_TIME_EXPERIENCE" -value "1" # return value _InitializeDotNetCli="$dotnet_root" @@ -387,7 +383,8 @@ mkdir -p "$toolset_dir" mkdir -p "$temp_dir" mkdir -p "$log_dir" -if [[ $ci == true ]]; then - export TEMP="$temp_dir" - export TMP="$temp_dir" -fi +Write-PipelineSetVariable -name "Artifacts" -value "$artifacts_dir" +Write-PipelineSetVariable -name "Artifacts.Toolset" -value "$toolset_dir" +Write-PipelineSetVariable -name "Artifacts.Log" -value "$log_dir" +Write-PipelineSetVariable -name "Temp" -value "$temp_dir" +Write-PipelineSetVariable -name "TMP" -value "$temp_dir" diff --git a/global.json b/global.json index b4297bf622c..78425fae2ed 100644 --- a/global.json +++ b/global.json @@ -10,7 +10,7 @@ } }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19367.8", + "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19368.7", "Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19069.2" } } From bdb2b79e06bcb1b515ba4243103a9ff3cfbb2ea2 Mon Sep 17 00:00:00 2001 From: Sergey Tihon Date: Fri, 19 Jul 2019 21:02:07 +0300 Subject: [PATCH 27/46] Moving TypeMismatchTests over to NUnit (#7250) * Moving TypeMismatchTests over to NUnit * ci restart --- .../ErrorMessages/TypeMismatchTests.fs | 135 ++++++++++++++++++ tests/fsharp/FSharpSuite.Tests.fsproj | 1 + .../Source/Warnings/GuardHasWrongType.fs | 9 -- .../Source/Warnings/OverrideErrors.fs | 22 --- .../Source/Warnings/RefCellInsteadOfNot.fs | 9 -- .../Source/Warnings/RefCellInsteadOfNot2.fs | 8 -- .../Warnings/ReturnInsteadOfReturnBang.fs | 10 -- .../Warnings/RuntimeTypeTestInPattern.fs | 13 -- .../Warnings/RuntimeTypeTestInPattern2.fs | 13 -- .../Warnings/YieldInsteadOfYieldBang.fs | 13 -- tests/fsharpqa/Source/Warnings/env.lst | 8 -- 11 files changed, 136 insertions(+), 105 deletions(-) create mode 100644 tests/fsharp/Compiler/ErrorMessages/TypeMismatchTests.fs delete mode 100644 tests/fsharpqa/Source/Warnings/GuardHasWrongType.fs delete mode 100644 tests/fsharpqa/Source/Warnings/OverrideErrors.fs delete mode 100644 tests/fsharpqa/Source/Warnings/RefCellInsteadOfNot.fs delete mode 100644 tests/fsharpqa/Source/Warnings/RefCellInsteadOfNot2.fs delete mode 100644 tests/fsharpqa/Source/Warnings/ReturnInsteadOfReturnBang.fs delete mode 100644 tests/fsharpqa/Source/Warnings/RuntimeTypeTestInPattern.fs delete mode 100644 tests/fsharpqa/Source/Warnings/RuntimeTypeTestInPattern2.fs delete mode 100644 tests/fsharpqa/Source/Warnings/YieldInsteadOfYieldBang.fs diff --git a/tests/fsharp/Compiler/ErrorMessages/TypeMismatchTests.fs b/tests/fsharp/Compiler/ErrorMessages/TypeMismatchTests.fs new file mode 100644 index 00000000000..652361045c9 --- /dev/null +++ b/tests/fsharp/Compiler/ErrorMessages/TypeMismatchTests.fs @@ -0,0 +1,135 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace FSharp.Compiler.UnitTests + +open NUnit.Framework +open FSharp.Compiler.SourceCodeServices + +[] +module ``Type Mismatch`` = + + [] + let ``return Instead Of return!``() = + CompilerAssert.TypeCheckSingleError + """ +let rec foo() = async { return foo() } + """ + FSharpErrorSeverity.Error + 1 + (2, 32, 2, 37) + "Type mismatch. Expecting a\n ''a' \nbut given a\n 'Async<'a>' \nThe types ''a' and 'Async<'a>' cannot be unified. Consider using 'return!' instead of 'return'." + + [] + let ``yield Instead Of yield!``() = + CompilerAssert.TypeCheckSingleError + """ +type Foo() = + member this.Yield(x) = [x] + +let rec f () = Foo() { yield f ()} + """ + FSharpErrorSeverity.Error + 1 + (5, 30, 5, 34) + "Type mismatch. Expecting a\n ''a' \nbut given a\n ''a list' \nThe types ''a' and ''a list' cannot be unified. Consider using 'yield!' instead of 'yield'." + + [] + let ``Ref Cell Instead Of Not``() = + CompilerAssert.TypeCheckSingleError + """ +let x = true +if !x then + printfn "hello" + """ + FSharpErrorSeverity.Error + 1 + (3, 5, 3, 6) + "This expression was expected to have type\n 'bool ref' \nbut here has type\n 'bool' \r\nThe '!' operator is used to dereference a ref cell. Consider using 'not expr' here." + + [] + let ``Ref Cell Instead Of Not 2``() = + CompilerAssert.TypeCheckSingleError + """ +let x = true +let y = !x + """ + FSharpErrorSeverity.Error + 1 + (3, 10, 3, 11) + "This expression was expected to have type\n ''a ref' \nbut here has type\n 'bool' \r\nThe '!' operator is used to dereference a ref cell. Consider using 'not expr' here." + + [] + let ``Guard Has Wrong Type``() = + CompilerAssert.TypeCheckWithErrors + """ +let x = 1 +match x with +| 1 when "s" -> true +| _ -> false + """ + [| + FSharpErrorSeverity.Error, 1, (4, 10, 4, 13), "A pattern match guard must be of type 'bool', but this 'when' expression is of type 'string'." + FSharpErrorSeverity.Warning, 20, (3, 1, 5, 13), "The result of this expression has type 'bool' and is implicitly ignored. Consider using 'ignore' to discard this value explicitly, e.g. 'expr |> ignore', or 'let' to bind the result to a name, e.g. 'let result = expr'." + |] + + [] + let ``Runtime Type Test In Pattern``() = + CompilerAssert.TypeCheckWithErrors + """ +open System.Collections.Generic + +let orig = Dictionary() + +let c = + match orig with + | :? IDictionary -> "yes" + | _ -> "no" + """ + [| + FSharpErrorSeverity.Warning, 67, (8, 5, 8, 28), "This type test or downcast will always hold" + FSharpErrorSeverity.Error, 193, (8, 5, 8, 28), "Type constraint mismatch. The type \n 'IDictionary' \nis not compatible with type\n 'Dictionary' \n" + |] + + [] + let ``Runtime Type Test In Pattern 2``() = + CompilerAssert.TypeCheckWithErrors + """ +open System.Collections.Generic + +let orig = Dictionary() + +let c = + match orig with + | :? IDictionary as y -> "yes" + y.ToString() + | _ -> "no" + """ + [| + FSharpErrorSeverity.Warning, 67, (8, 5, 8, 28), "This type test or downcast will always hold" + FSharpErrorSeverity.Error, 193, (8, 5, 8, 28), "Type constraint mismatch. The type \n 'IDictionary' \nis not compatible with type\n 'Dictionary' \n" + |] + + [] + let ``Override Errors``() = + CompilerAssert.TypeCheckWithErrors + """ +type Base() = + abstract member Member: int * string -> string + default x.Member (i, s) = s + +type Derived1() = + inherit Base() + override x.Member() = 5 + +type Derived2() = + inherit Base() + override x.Member (i : int) = "Hello" + +type Derived3() = + inherit Base() + override x.Member (s : string, i : int) = sprintf "Hello %s" s + """ + [| + FSharpErrorSeverity.Error, 856, (8, 16, 8, 22), "This override takes a different number of arguments to the corresponding abstract member. The following abstract members were found:\r\n abstract member Base.Member : int * string -> string" + FSharpErrorSeverity.Error, 856, (12, 16, 12, 22), "This override takes a different number of arguments to the corresponding abstract member. The following abstract members were found:\r\n abstract member Base.Member : int * string -> string" + FSharpErrorSeverity.Error, 1, (16, 24, 16, 34), "This expression was expected to have type\n 'int' \nbut here has type\n 'string' " + |] diff --git a/tests/fsharp/FSharpSuite.Tests.fsproj b/tests/fsharp/FSharpSuite.Tests.fsproj index 0c9578f2192..9d80400c401 100644 --- a/tests/fsharp/FSharpSuite.Tests.fsproj +++ b/tests/fsharp/FSharpSuite.Tests.fsproj @@ -38,6 +38,7 @@ + diff --git a/tests/fsharpqa/Source/Warnings/GuardHasWrongType.fs b/tests/fsharpqa/Source/Warnings/GuardHasWrongType.fs deleted file mode 100644 index ac0c3cb4f3c..00000000000 --- a/tests/fsharpqa/Source/Warnings/GuardHasWrongType.fs +++ /dev/null @@ -1,9 +0,0 @@ -// #Warnings -//A pattern match guard must be of type 'bool' - -let x = 1 -match x with -| 1 when "s" -> true -| _ -> false - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/OverrideErrors.fs b/tests/fsharpqa/Source/Warnings/OverrideErrors.fs deleted file mode 100644 index ff03ba6ed4e..00000000000 --- a/tests/fsharpqa/Source/Warnings/OverrideErrors.fs +++ /dev/null @@ -1,22 +0,0 @@ -// #Warnings -//This override takes a different number of arguments to the corresponding abstract member. The following abstract members were found: -//abstract member Base.Member : int * string -> string -//This expression was expected to have type - -type Base() = - abstract member Member: int * string -> string - default x.Member (i, s) = s - -type Derived1() = - inherit Base() - override x.Member() = 5 - -type Derived2() = - inherit Base() - override x.Member (i : int) = "Hello" - -type Derived3() = - inherit Base() - override x.Member (s : string, i : int) = sprintf "Hello %s" s - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/RefCellInsteadOfNot.fs b/tests/fsharpqa/Source/Warnings/RefCellInsteadOfNot.fs deleted file mode 100644 index 1c6987bfa63..00000000000 --- a/tests/fsharpqa/Source/Warnings/RefCellInsteadOfNot.fs +++ /dev/null @@ -1,9 +0,0 @@ -// #Warnings -//This expression was expected to have type -//The '!' operator is used to dereference a ref cell. Consider using 'not expr' here. - -let x = true -if !x then - printfn "hello" - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/RefCellInsteadOfNot2.fs b/tests/fsharpqa/Source/Warnings/RefCellInsteadOfNot2.fs deleted file mode 100644 index 090934d8f56..00000000000 --- a/tests/fsharpqa/Source/Warnings/RefCellInsteadOfNot2.fs +++ /dev/null @@ -1,8 +0,0 @@ -// #Warnings -//This expression was expected to have type -//The '!' operator is used to dereference a ref cell. Consider using 'not expr' here. - -let x = true -let y = !x - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/ReturnInsteadOfReturnBang.fs b/tests/fsharpqa/Source/Warnings/ReturnInsteadOfReturnBang.fs deleted file mode 100644 index d9f87c521bd..00000000000 --- a/tests/fsharpqa/Source/Warnings/ReturnInsteadOfReturnBang.fs +++ /dev/null @@ -1,10 +0,0 @@ -// #Warnings -//Type mismatch. Expecting a -//''a' -//but given a -//'Async<'a>' -//The types ''a' and 'Async<'a>' cannot be unified. Consider using 'return!' instead of 'return'. - -let rec foo() = async { return foo() } - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/RuntimeTypeTestInPattern.fs b/tests/fsharpqa/Source/Warnings/RuntimeTypeTestInPattern.fs deleted file mode 100644 index 67ae796376d..00000000000 --- a/tests/fsharpqa/Source/Warnings/RuntimeTypeTestInPattern.fs +++ /dev/null @@ -1,13 +0,0 @@ -// #Warnings -//Type constraint mismatch. The type - -open System.Collections.Generic - -let orig = Dictionary() - -let c = - match orig with - | :? IDictionary -> "yes" - | _ -> "no" - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/RuntimeTypeTestInPattern2.fs b/tests/fsharpqa/Source/Warnings/RuntimeTypeTestInPattern2.fs deleted file mode 100644 index 098969482c5..00000000000 --- a/tests/fsharpqa/Source/Warnings/RuntimeTypeTestInPattern2.fs +++ /dev/null @@ -1,13 +0,0 @@ -// #Warnings -//Type constraint mismatch. The type - -open System.Collections.Generic - -let orig = Dictionary() - -let c = - match orig with - | :? IDictionary as y -> "yes" + y.ToString() - | _ -> "no" - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/YieldInsteadOfYieldBang.fs b/tests/fsharpqa/Source/Warnings/YieldInsteadOfYieldBang.fs deleted file mode 100644 index bd547fa7b28..00000000000 --- a/tests/fsharpqa/Source/Warnings/YieldInsteadOfYieldBang.fs +++ /dev/null @@ -1,13 +0,0 @@ -// #Warnings -//Type mismatch. Expecting a -//''a' -//but given a -//''a list' -//The types ''a' and ''a list' cannot be unified. Consider using 'yield!' instead of 'yield'. - -type Foo() = - member this.Yield(x) = [x] - -let rec f () = Foo() { yield f ()} - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/env.lst b/tests/fsharpqa/Source/Warnings/env.lst index a3d677bf0fc..18ef811a2a5 100644 --- a/tests/fsharpqa/Source/Warnings/env.lst +++ b/tests/fsharpqa/Source/Warnings/env.lst @@ -1,10 +1,7 @@ SOURCE=WrongNumericLiteral.fs # WrongNumericLiteral.fs - SOURCE=ReturnInsteadOfReturnBang.fs # ReturnInsteadOfReturnBang.fs - SOURCE=YieldInsteadOfYieldBang.fs # YieldInsteadOfYieldBang.fs SOURCE=TupleInAbstractMethod.fs # TupleInAbstractMethod.fs SOURCE=FS0988AtEndOfFile.fs # FS0988AtEndOfFile.fs SOURCE=WrongArity.fs # WrongArity.fs - SOURCE=OverrideErrors.fs # OverrideErrors.fs SOURCE=MethodIsNotStatic.fs # MethodIsNotStatic.fs SOURCE=EqualsInsteadOfInInForLoop.fs # EqualsInsteadOfInInForLoop.fs SOURCE=DontWarnExternalFunctionAsUnused.fs SCFLAGS="--warnon:1182 --warnaserror+" # DontWarnExternalFunctionAsUnused.fs @@ -28,17 +25,12 @@ SOURCE=DontSuggestWhenThingsAreOpen.fs SCFLAGS="--vserrors" # DontSuggestWhenThingsAreOpen.fs SOURCE=SuggestDoubleBacktickIdentifiers.fs SCFLAGS="--vserrors" # SuggestDoubleBacktickIdentifiers.fs SOURCE=SuggestDoubleBacktickUnions.fs SCFLAGS="--vserrors" # SuggestDoubleBacktickUnions.fs - SOURCE=GuardHasWrongType.fs # GuardHasWrongType.fs SOURCE=MatchingMethodWithSameNameIsNotAbstract.fs # MatchingMethodWithSameNameIsNotAbstract.fs SOURCE=NoMatchingAbstractMethodWithSameName.fs # NoMatchingAbstractMethodWithSameName.fs SOURCE=MissingExpressionAfterLet.fs # MissingExpressionAfterLet.fs SOURCE=SuggestFieldsInCtor.fs # SuggestFieldsInCtor.fs SOURCE=FieldSuggestion.fs # FieldSuggestion.fs SOURCE=SuggestToUseIndexer.fs # SuggestToUseIndexer.fs - SOURCE=RefCellInsteadOfNot.fs # RefCellInsteadOfNot.fs - SOURCE=RefCellInsteadOfNot2.fs # RefCellInsteadOfNot2.fs - SOURCE=RuntimeTypeTestInPattern.fs # RuntimeTypeTestInPattern.fs - SOURCE=RuntimeTypeTestInPattern2.fs # RuntimeTypeTestInPattern2.fs SOURCE=MemberHasMultiplePossibleDispatchSlots.fs # MemberHasMultiplePossibleDispatchSlots.fs SOURCE=Repro1548.fs SCFLAGS="-r:Repro1548.dll" # Repro1548.fs SOURCE=DoCannotHaveVisibilityDeclarations.fs From b0e59263c73f5194c514ec36d48b861527e7d65b Mon Sep 17 00:00:00 2001 From: "Brett V. Forsgren" Date: Fri, 19 Jul 2019 14:44:36 -0700 Subject: [PATCH 28/46] publish pdbs in FSharp.Core.nupkg (#7255) Also publish native symbols so they can be archived later. --- .vsts-signed.yaml | 8 ++++++++ azure-pipelines.yml | 6 ++++++ src/fsharp/FSharp.Core.nuget/FSharp.Core.nuspec | 2 ++ 3 files changed, 16 insertions(+) diff --git a/.vsts-signed.yaml b/.vsts-signed.yaml index 3ec301bbe0c..ed30cb74ef2 100644 --- a/.vsts-signed.yaml +++ b/.vsts-signed.yaml @@ -105,6 +105,14 @@ jobs: continueOnError: true condition: succeeded() + # Publish native PDBs for archiving + - task: PublishBuildArtifacts@1 + displayName: Publish Artifact Symbols + inputs: + PathtoPublish: '$(Build.SourcesDirectory)/artifacts/SymStore/$(BuildConfiguration)' + ArtifactName: NativeSymbols + condition: succeeded() + # Execute cleanup tasks - task: ms-vseng.MicroBuildTasks.521a94ea-9e68-468a-8167-6dcf361ea776.MicroBuildCleanup@1 displayName: Execute cleanup tasks diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 2207a4792eb..87306e5c604 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -113,6 +113,12 @@ jobs: PathtoPublish: '$(Build.SourcesDirectory)\artifacts\VSSetup\$(_BuildConfig)\VisualFSharpFull.vsix' ArtifactName: 'Nightly' condition: succeeded() + - task: PublishBuildArtifacts@1 + displayName: Publish Artifact Symbols + inputs: + PathtoPublish: '$(Build.SourcesDirectory)\artifacts\SymStore\$(_BuildConfig)' + ArtifactName: 'NativeSymbols' + condition: succeeded() #---------------------------------------------------------------------------------------------------------------------# # PR builds # diff --git a/src/fsharp/FSharp.Core.nuget/FSharp.Core.nuspec b/src/fsharp/FSharp.Core.nuget/FSharp.Core.nuspec index ee7a88b29d6..750052c45db 100644 --- a/src/fsharp/FSharp.Core.nuget/FSharp.Core.nuspec +++ b/src/fsharp/FSharp.Core.nuget/FSharp.Core.nuspec @@ -38,11 +38,13 @@ + + From 3e7b66dcd0bb58c575eda182a0aee24819577942 Mon Sep 17 00:00:00 2001 From: "Kevin Ransom (msft)" Date: Fri, 19 Jul 2019 20:17:49 -0700 Subject: [PATCH 29/46] Enable hash algorithm selection (#7252) * Enable hash algorithm selection * Feedback * More feedback * Revert "Feedback" This reverts commit 6ab1b077b413712f552bad9b2562aeb63994ad4c. * feedback --- src/absil/ilwrite.fs | 127 ++++++++++------- src/absil/ilwrite.fsi | 10 +- src/absil/ilwritepdb.fs | 129 ++++++++++++------ src/absil/ilwritepdb.fsi | 12 +- src/fsharp/CompileOps.fs | 4 + src/fsharp/CompileOps.fsi | 3 + src/fsharp/CompileOptions.fs | 12 ++ src/fsharp/FSComp.txt | 2 + src/fsharp/FSharp.Build/Fsc.fs | 15 +- .../FSharp.Build/Microsoft.FSharp.Targets | 1 + .../FSharp.Compiler.Private.fsproj | 6 +- src/fsharp/fsc.fs | 1 + src/fsharp/xlf/FSComp.txt.cs.xlf | 10 ++ src/fsharp/xlf/FSComp.txt.de.xlf | 10 ++ src/fsharp/xlf/FSComp.txt.es.xlf | 10 ++ src/fsharp/xlf/FSComp.txt.fr.xlf | 10 ++ src/fsharp/xlf/FSComp.txt.it.xlf | 10 ++ src/fsharp/xlf/FSComp.txt.ja.xlf | 10 ++ src/fsharp/xlf/FSComp.txt.ko.xlf | 10 ++ src/fsharp/xlf/FSComp.txt.pl.xlf | 10 ++ src/fsharp/xlf/FSComp.txt.pt-BR.xlf | 10 ++ src/fsharp/xlf/FSComp.txt.ru.xlf | 10 ++ src/fsharp/xlf/FSComp.txt.tr.xlf | 10 ++ src/fsharp/xlf/FSComp.txt.zh-Hans.xlf | 10 ++ src/fsharp/xlf/FSComp.txt.zh-Hant.xlf | 10 ++ .../ProvidedTypes/ProvidedTypes.fs | 2 +- tests/fsharp/.gitignore | 3 +- .../fsc/dumpAllCommandLineOptions/dummy.fs | 1 + .../fsc/help/help40.437.1033.bsl | 4 + 29 files changed, 359 insertions(+), 103 deletions(-) diff --git a/src/absil/ilwrite.fs b/src/absil/ilwrite.fs index 5d6bfd3ee06..66d2dd9a667 100644 --- a/src/absil/ilwrite.fs +++ b/src/absil/ilwrite.fs @@ -3025,7 +3025,8 @@ let generateIL requiredDataFixups (desiredMetadataVersion, generatePdb, ilg : IL //===================================================================== // TABLES+BLOBS --> PHYSICAL METADATA+BLOBS //===================================================================== -let chunk sz next = ({addr=next; size=sz}, next + sz) +let chunk sz next = ({addr=next; size=sz}, next + sz) +let emptychunk next = ({addr=next; size=0}, next) let nochunk next = ({addr= 0x0;size= 0x0; }, next) let count f arr = @@ -3516,7 +3517,7 @@ let writeBytes (os: BinaryWriter) (chunk: byte[]) = os.Write(chunk, 0, chunk.Len let writeBinaryAndReportMappings (outfile, ilg: ILGlobals, pdbfile: string option, signer: ILStrongNameSigner option, portablePDB, embeddedPDB, - embedAllSource, embedSourceList, sourceLink, emitTailcalls, deterministic, showTimes, dumpDebugInfo, pathMap) + embedAllSource, embedSourceList, sourceLink, checksumAlgorithm, emitTailcalls, deterministic, showTimes, dumpDebugInfo, pathMap) modul normalizeAssemblyRefs = // Store the public key from the signer into the manifest. This means it will be written // to the binary and also acts as an indicator to leave space for delay sign @@ -3565,7 +3566,7 @@ let writeBinaryAndReportMappings (outfile, with e -> failwith ("Could not open file for writing (binary mode): " + outfile) - let pdbData, pdbOpt, debugDirectoryChunk, debugDataChunk, debugEmbeddedPdbChunk, textV2P, mappings = + let pdbData, pdbOpt, debugDirectoryChunk, debugDataChunk, debugChecksumPdbChunk, debugEmbeddedPdbChunk, debugDeterministicPdbChunk, textV2P, mappings = try let imageBaseReal = modul.ImageBase // FIXED CHOICE @@ -3670,42 +3671,61 @@ let writeBinaryAndReportMappings (outfile, let pdbOpt = match portablePDB with | true -> - let (uncompressedLength, contentId, stream) as pdbStream = - generatePortablePdb embedAllSource embedSourceList sourceLink showTimes pdbData deterministic pathMap + let (uncompressedLength, contentId, stream, algorithmName, checkSum) as pdbStream = + generatePortablePdb embedAllSource embedSourceList sourceLink checksumAlgorithm showTimes pdbData pathMap - if embeddedPDB then Some (compressPortablePdbStream uncompressedLength contentId stream) + if embeddedPDB then + let uncompressedLength, contentId, stream = compressPortablePdbStream uncompressedLength contentId stream + Some (uncompressedLength, contentId, stream, algorithmName, checkSum) else Some pdbStream | _ -> None - let debugDirectoryChunk, next = - chunk (if pdbfile = None then - 0x0 - else if embeddedPDB && portablePDB then - sizeof_IMAGE_DEBUG_DIRECTORY * 2 + let debugDirectoryChunk, next = + chunk (if pdbfile = None then + 0x0 else - sizeof_IMAGE_DEBUG_DIRECTORY + sizeof_IMAGE_DEBUG_DIRECTORY * 2 + + (if embeddedPDB then sizeof_IMAGE_DEBUG_DIRECTORY else 0) + + (if deterministic then sizeof_IMAGE_DEBUG_DIRECTORY else 0) ) next + // The debug data is given to us by the PDB writer and appears to // typically be the type of the data plus the PDB file name. We fill // this in after we've written the binary. We approximate the size according // to what PDB writers seem to require and leave extra space just in case... let debugDataJustInCase = 40 - let debugDataChunk, next = + let debugDataChunk, next = chunk (align 0x4 (match pdbfile with | None -> 0 | Some f -> (24 + System.Text.Encoding.Unicode.GetByteCount f // See bug 748444 + debugDataJustInCase))) next - let debugEmbeddedPdbChunk, next = - let streamLength = - match pdbOpt with - | Some (_, _, stream) -> int stream.Length - | None -> 0 - chunk (align 0x4 (match embeddedPDB with - | true -> 8 + streamLength - | _ -> 0 )) next + let debugChecksumPdbChunk, next = + chunk (align 0x4 (match pdbOpt with + | Some (_, _, _, algorithmName, checkSum) -> + let alg = System.Text.Encoding.UTF8.GetBytes(algorithmName) + let size = alg.Length + 1 + checkSum.Length + size + | None -> 0)) next + + let debugEmbeddedPdbChunk, next = + if embeddedPDB then + let streamLength = + match pdbOpt with + | Some (_, _, stream, _, _) -> int stream.Length + | None -> 0 + chunk (align 0x4 (match embeddedPDB with + | true -> 8 + streamLength + | _ -> 0 )) next + else + nochunk next + + let debugDeterministicPdbChunk, next = + if deterministic then emptychunk next + else nochunk next + let textSectionSize = next - textSectionAddr let nextPhys = align alignPhys (textSectionPhysLoc + textSectionSize) @@ -3804,35 +3824,39 @@ let writeBinaryAndReportMappings (outfile, if pCurrent <> pExpected then failwith ("warning: "+chunkName+" not where expected, pCurrent = "+string pCurrent+", p.addr = "+string pExpected) writeBytes os chunk - + let writePadding (os: BinaryWriter) _comment sz = if sz < 0 then failwith "writePadding: size < 0" for i = 0 to sz - 1 do os.Write 0uy - + // Now we've computed all the offsets, write the image - + write (Some msdosHeaderChunk.addr) os "msdos header" msdosHeader - + write (Some peSignatureChunk.addr) os "pe signature" [| |] - + writeInt32 os 0x4550 - + write (Some peFileHeaderChunk.addr) os "pe file header" [| |] - + if (modul.Platform = Some AMD64) then writeInt32AsUInt16 os 0x8664 // Machine - IMAGE_FILE_MACHINE_AMD64 elif isItanium then writeInt32AsUInt16 os 0x200 else writeInt32AsUInt16 os 0x014c // Machine - IMAGE_FILE_MACHINE_I386 - + writeInt32AsUInt16 os numSections - let pdbData = + let pdbData = + // Hash code, data and metadata if deterministic then - // Hash code, data and metadata - use sha = System.Security.Cryptography.SHA1.Create() // IncrementalHash is core only + use sha = + match checksumAlgorithm with + | HashAlgorithm.Sha1 -> System.Security.Cryptography.SHA1.Create() :> System.Security.Cryptography.HashAlgorithm + | HashAlgorithm.Sha256 -> System.Security.Cryptography.SHA256.Create() :> System.Security.Cryptography.HashAlgorithm + let hCode = sha.ComputeHash code let hData = sha.ComputeHash data let hMeta = sha.ComputeHash metadata @@ -3848,6 +3872,7 @@ let writeBinaryAndReportMappings (outfile, // Use last 4 bytes for timestamp - High bit set, to stop tool chains becoming confused let timestamp = int final.[16] ||| (int final.[17] <<< 8) ||| (int final.[18] <<< 16) ||| (int (final.[19] ||| 128uy) <<< 24) writeInt32 os timestamp + // Update pdbData with new guid and timestamp. Portable and embedded PDBs don't need the ModuleID // Full and PdbOnly aren't supported under deterministic builds currently, they rely on non-determinsitic Windows native code { pdbData with ModuleID = final.[0..15] ; Timestamp = timestamp } @@ -4133,10 +4158,14 @@ let writeBinaryAndReportMappings (outfile, if pdbfile.IsSome then write (Some (textV2P debugDirectoryChunk.addr)) os "debug directory" (Array.create debugDirectoryChunk.size 0x0uy) write (Some (textV2P debugDataChunk.addr)) os "debug data" (Array.create debugDataChunk.size 0x0uy) + write (Some (textV2P debugChecksumPdbChunk.addr)) os "debug checksum" (Array.create debugChecksumPdbChunk.size 0x0uy) if embeddedPDB then write (Some (textV2P debugEmbeddedPdbChunk.addr)) os "debug data" (Array.create debugEmbeddedPdbChunk.size 0x0uy) + if deterministic then + write (Some (textV2P debugDeterministicPdbChunk.addr)) os "debug deterministic" Array.empty + writePadding os "end of .text" (dataSectionPhysLoc - textSectionPhysLoc - textSectionSize) // DATA SECTION @@ -4182,7 +4211,7 @@ let writeBinaryAndReportMappings (outfile, FileSystemUtilites.setExecutablePermission outfile with _ -> () - pdbData, pdbOpt, debugDirectoryChunk, debugDataChunk, debugEmbeddedPdbChunk, textV2P, mappings + pdbData, pdbOpt, debugDirectoryChunk, debugDataChunk, debugChecksumPdbChunk, debugEmbeddedPdbChunk, debugDeterministicPdbChunk, textV2P, mappings // Looks like a finally with e -> @@ -4207,11 +4236,11 @@ let writeBinaryAndReportMappings (outfile, try let idd = match pdbOpt with - | Some (originalLength, contentId, stream) -> + | Some (originalLength, contentId, stream, algorithmName, checkSum) -> if embeddedPDB then - embedPortablePdbInfo originalLength contentId stream showTimes fpdb debugDataChunk debugEmbeddedPdbChunk + embedPortablePdbInfo originalLength contentId stream showTimes fpdb debugDataChunk debugEmbeddedPdbChunk debugDeterministicPdbChunk debugChecksumPdbChunk algorithmName checkSum embeddedPDB deterministic else - writePortablePdbInfo contentId stream showTimes fpdb pathMap debugDataChunk + writePortablePdbInfo contentId stream showTimes fpdb pathMap debugDataChunk debugDeterministicPdbChunk debugChecksumPdbChunk algorithmName checkSum embeddedPDB deterministic | None -> #if FX_NO_PDB_WRITER Array.empty @@ -4232,16 +4261,17 @@ let writeBinaryAndReportMappings (outfile, writeInt32AsUInt16 os2 i.iddMajorVersion writeInt32AsUInt16 os2 i.iddMinorVersion writeInt32 os2 i.iddType - writeInt32 os2 i.iddData.Length // IMAGE_DEBUG_DIRECTORY.SizeOfData - writeInt32 os2 i.iddChunk.addr // IMAGE_DEBUG_DIRECTORY.AddressOfRawData - writeInt32 os2 (textV2P i.iddChunk.addr) // IMAGE_DEBUG_DIRECTORY.PointerToRawData + writeInt32 os2 i.iddData.Length // IMAGE_DEBUG_DIRECTORY.SizeOfData + writeInt32 os2 i.iddChunk.addr // IMAGE_DEBUG_DIRECTORY.AddressOfRawData + writeInt32 os2 (textV2P i.iddChunk.addr) // IMAGE_DEBUG_DIRECTORY.PointerToRawData // Write the Debug Data for i in idd do - // write the debug raw data as given us by the PDB writer - os2.BaseStream.Seek (int64 (textV2P i.iddChunk.addr), SeekOrigin.Begin) |> ignore - if i.iddChunk.size < i.iddData.Length then failwith "Debug data area is not big enough. Debug info may not be usable" - writeBytes os2 i.iddData + if i.iddChunk.size <> 0 then + // write the debug raw data as given us by the PDB writer + os2.BaseStream.Seek (int64 (textV2P i.iddChunk.addr), SeekOrigin.Begin) |> ignore + if i.iddChunk.size < i.iddData.Length then failwith "Debug data area is not big enough. Debug info may not be usable" + writeBytes os2 i.iddData os2.Dispose() with e -> failwith ("Error while writing debug directory entry: "+e.Message) @@ -4250,9 +4280,7 @@ let writeBinaryAndReportMappings (outfile, with e -> reraise() - end - ignore debugDataChunk - ignore debugEmbeddedPdbChunk + end reportTime showTimes "Finalize PDB" /// Sign the binary. No further changes to binary allowed past this point! @@ -4280,9 +4308,10 @@ type options = embedAllSource: bool embedSourceList: string list sourceLink: string + checksumAlgorithm: HashAlgorithm signer: ILStrongNameSigner option - emitTailcalls : bool - deterministic : bool + emitTailcalls: bool + deterministic: bool showTimes: bool dumpDebugInfo: bool pathMap: PathMap } @@ -4290,5 +4319,5 @@ type options = let WriteILBinary (outfile, (args: options), modul, normalizeAssemblyRefs) = writeBinaryAndReportMappings (outfile, args.ilg, args.pdbfile, args.signer, args.portablePDB, args.embeddedPDB, args.embedAllSource, - args.embedSourceList, args.sourceLink, args.emitTailcalls, args.deterministic, args.showTimes, args.dumpDebugInfo, args.pathMap) modul normalizeAssemblyRefs + args.embedSourceList, args.sourceLink, args.checksumAlgorithm, args.emitTailcalls, args.deterministic, args.showTimes, args.dumpDebugInfo, args.pathMap) modul normalizeAssemblyRefs |> ignore diff --git a/src/absil/ilwrite.fsi b/src/absil/ilwrite.fsi index f1955f82a20..9dba89c9b6c 100644 --- a/src/absil/ilwrite.fsi +++ b/src/absil/ilwrite.fsi @@ -1,12 +1,13 @@ // Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. /// The IL Binary writer. -module internal FSharp.Compiler.AbstractIL.ILBinaryWriter +module internal FSharp.Compiler.AbstractIL.ILBinaryWriter open Internal.Utilities -open FSharp.Compiler.AbstractIL -open FSharp.Compiler.AbstractIL.Internal -open FSharp.Compiler.AbstractIL.IL +open FSharp.Compiler.AbstractIL +open FSharp.Compiler.AbstractIL.Internal +open FSharp.Compiler.AbstractIL.IL +open FSharp.Compiler.AbstractIL.ILPdbWriter [] type ILStrongNameSigner = @@ -24,6 +25,7 @@ type options = embedAllSource: bool embedSourceList: string list sourceLink: string + checksumAlgorithm: HashAlgorithm signer : ILStrongNameSigner option emitTailcalls: bool deterministic: bool diff --git a/src/absil/ilwritepdb.fs b/src/absil/ilwritepdb.fs index 2a992ed4855..c1ffd692249 100644 --- a/src/absil/ilwritepdb.fs +++ b/src/absil/ilwritepdb.fs @@ -11,8 +11,9 @@ open System.Reflection open System.Reflection.Metadata open System.Reflection.Metadata.Ecma335 open System.Reflection.PortableExecutable +open System.Text open Internal.Utilities -open FSharp.Compiler.AbstractIL.IL +open FSharp.Compiler.AbstractIL.IL open FSharp.Compiler.AbstractIL.Diagnostics open FSharp.Compiler.AbstractIL.Internal.Support open FSharp.Compiler.AbstractIL.Internal.Library @@ -125,6 +126,27 @@ type idd = iddData: byte[] iddChunk: BinaryChunk } +/// The specified Hash algorithm to use on portable pdb files. +type HashAlgorithm = + | Sha1 + | Sha256 + +// Document checksum algorithms +let guidSha1 = Guid("ff1816ec-aa5e-4d10-87f7-6f4963833460") +let guidSha2 = Guid("8829d00f-11b8-4213-878b-770e8597ac16") + +let checkSum (url: string) (checksumAlgorithm: HashAlgorithm) = + try + use file = FileSystem.FileStreamReadShim url + let guid, alg = + match checksumAlgorithm with + | HashAlgorithm.Sha1 -> guidSha1, System.Security.Cryptography.SHA1.Create() :> System.Security.Cryptography.HashAlgorithm + | HashAlgorithm.Sha256 -> guidSha2, System.Security.Cryptography.SHA256.Create() :> System.Security.Cryptography.HashAlgorithm + + let checkSum = alg.ComputeHash file + Some (guid, checkSum) + with _ -> None + //--------------------------------------------------------------------- // Portable PDB Writer //--------------------------------------------------------------------- @@ -153,7 +175,7 @@ let pdbGetCvDebugInfo (mvid: byte[]) (timestamp: int32) (filepath: string) (cvCh } let pdbMagicNumber= 0x4244504dL -let pdbGetPdbDebugInfo (embeddedPDBChunk: BinaryChunk) (uncompressedLength: int64) (stream: MemoryStream) = +let pdbGetEmbeddedPdbDebugInfo (embeddedPdbChunk: BinaryChunk) (uncompressedLength: int64) (stream: MemoryStream) = let iddPdbBuffer = let buffer = Array.zeroCreate (sizeof + sizeof + int(stream.Length)) let (offset, size) = (0, sizeof) // Magic Number dword: 0x4244504dL @@ -169,28 +191,52 @@ let pdbGetPdbDebugInfo (embeddedPDBChunk: BinaryChunk) (uncompressedLength: int6 iddType = 17 // IMAGE_DEBUG_TYPE_EMBEDDEDPDB iddTimestamp = 0 iddData = iddPdbBuffer // Path name to the pdb file when built - iddChunk = embeddedPDBChunk + iddChunk = embeddedPdbChunk } -let pdbGetDebugInfo (mvid: byte[]) (timestamp: int32) (filepath: string) (cvChunk: BinaryChunk) (embeddedPDBChunk: BinaryChunk option) (uncompressedLength: int64) (stream: MemoryStream option) = - match stream, embeddedPDBChunk with - | None, _ | _, None -> [| pdbGetCvDebugInfo mvid timestamp filepath cvChunk |] - | Some s, Some chunk -> [| pdbGetCvDebugInfo mvid timestamp filepath cvChunk; pdbGetPdbDebugInfo chunk uncompressedLength s |] +let pdbChecksumDebugInfo timestamp (checksumPdbChunk: BinaryChunk) (algorithmName:string) (checksum: byte[]) = + let iddBuffer = + let alg = Encoding.UTF8.GetBytes(algorithmName) + let buffer = Array.zeroCreate (alg.Length + 1 + checksum.Length) + Buffer.BlockCopy(alg, 0, buffer, 0, alg.Length) + Buffer.BlockCopy(checksum, 0, buffer, alg.Length + 1, checksum.Length) + buffer + { iddCharacteristics = 0 // Reserved + iddMajorVersion = 1 // VersionMajor should be 1 + iddMinorVersion = 0x0100 // VersionMinor should be 0x0100 + iddType = 19 // IMAGE_DEBUG_TYPE_CHECKSUMPDB + iddTimestamp = timestamp + iddData = iddBuffer // Path name to the pdb file when built + iddChunk = checksumPdbChunk + } -// Document checksum algorithms -let guidSourceHashMD5 = System.Guid(0x406ea660u, 0x64cfus, 0x4c82us, 0xb6uy, 0xf0uy, 0x42uy, 0xd4uy, 0x81uy, 0x72uy, 0xa7uy, 0x99uy) //406ea660-64cf-4c82-b6f0-42d48172a799 -let hashSizeOfMD5 = 16 +let pdbGetPdbDebugDeterministicInfo (deterministicPdbChunk: BinaryChunk) = + { iddCharacteristics = 0 // Reserved + iddMajorVersion = 0 // VersionMajor should be 0 + iddMinorVersion = 0 // VersionMinor should be 00 + iddType = 16 // IMAGE_DEBUG_TYPE_DETERMINISTIC + iddTimestamp = 0 + iddData = Array.empty // No DATA + iddChunk = deterministicPdbChunk + } -// If the FIPS algorithm policy is enabled on the computer (e.g., for US government employees and contractors) -// then obtaining the MD5 implementation in BCL will throw. -// In this case, catch the failure, and not set a checksum. -let checkSum (url: string) = - try - use file = FileSystem.FileStreamReadShim url - use md5 = System.Security.Cryptography.MD5.Create() - let checkSum = md5.ComputeHash file - Some (guidSourceHashMD5, checkSum) - with _ -> None +let pdbGetDebugInfo (contentId: byte[]) (timestamp: int32) (filepath: string) + (cvChunk: BinaryChunk) + (embeddedPdbChunk: BinaryChunk option) + (deterministicPdbChunk: BinaryChunk) + (checksumPdbChunk: BinaryChunk) (algorithmName:string) (checksum: byte []) + (uncompressedLength: int64) (stream: MemoryStream option) + (embeddedPdb: bool) (deterministic: bool) = + [| yield pdbGetCvDebugInfo contentId timestamp filepath cvChunk + yield pdbChecksumDebugInfo timestamp checksumPdbChunk algorithmName checksum + if embeddedPdb then + match stream, embeddedPdbChunk with + | None, _ | _, None -> () + | Some s, Some chunk -> + yield pdbGetEmbeddedPdbDebugInfo chunk uncompressedLength s + if deterministic then + yield pdbGetPdbDebugDeterministicInfo deterministicPdbChunk + |] //------------------------------------------------------------------------------ // PDB Writer. The function [WritePdbInfo] abstracts the @@ -219,7 +265,7 @@ let getRowCounts tableRowCounts = tableRowCounts |> Seq.iter(fun x -> builder.Add x) builder.MoveToImmutable() -let generatePortablePdb (embedAllSource: bool) (embedSourceList: string list) (sourceLink: string) showTimes (info: PdbData) isDeterministic (pathMap: PathMap) = +let generatePortablePdb (embedAllSource: bool) (embedSourceList: string list) (sourceLink: string) checksumAlgorithm showTimes (info: PdbData) (pathMap: PathMap) = sortMethods showTimes info let externalRowCounts = getRowCounts info.TableRowCounts let docs = @@ -286,7 +332,7 @@ let generatePortablePdb (embedAllSource: bool) (embedSourceList: string list) (s metadata.SetCapacity(TableIndex.Document, docLength) for doc in docs do let handle = - match checkSum doc.File with + match checkSum doc.File checksumAlgorithm with | Some (hashAlg, checkSum) -> let dbgInfo = (serializeDocumentName doc.File, @@ -481,25 +527,28 @@ let generatePortablePdb (embedAllSource: bool) (embedSourceList: string list) (s | None -> MetadataTokens.MethodDefinitionHandle 0 | Some x -> MetadataTokens.MethodDefinitionHandle x - let deterministicIdProvider isDeterministic : System.Func, BlobContentId> = - match isDeterministic with - | false -> null - | true -> - let convert (content: IEnumerable) = - use sha = System.Security.Cryptography.SHA1.Create() // IncrementalHash is core only - let hash = content - |> Seq.collect (fun c -> c.GetBytes().Array |> sha.ComputeHash) - |> Array.ofSeq |> sha.ComputeHash - BlobContentId.FromHash hash - System.Func, BlobContentId>( convert ) - - let serializer = PortablePdbBuilder(metadata, externalRowCounts, entryPoint, deterministicIdProvider isDeterministic) + // Compute the contentId for the pdb. Always do it deterministically, since we have to compute the anyway. + // The contentId is the hash of the ID using whichever algorithm has been specified to the compiler + let mutable contentHash = Array.empty + + let algorithmName, hashAlgorithm = + match checksumAlgorithm with + | HashAlgorithm.Sha1 -> "SHA1", System.Security.Cryptography.SHA1.Create() :> System.Security.Cryptography.HashAlgorithm + | HashAlgorithm.Sha256 -> "SHA256", System.Security.Cryptography.SHA256.Create() :> System.Security.Cryptography.HashAlgorithm + let idProvider: System.Func, BlobContentId> = + let convert (content: IEnumerable) = + let contentBytes = content |> Seq.collect (fun c -> c.GetBytes()) |> Array.ofSeq + contentHash <- contentBytes |> hashAlgorithm.ComputeHash + BlobContentId.FromHash contentHash + System.Func, BlobContentId>(convert) + + let serializer = PortablePdbBuilder(metadata, externalRowCounts, entryPoint, idProvider) let blobBuilder = new BlobBuilder() let contentId= serializer.Serialize blobBuilder let portablePdbStream = new MemoryStream() blobBuilder.WriteContentTo portablePdbStream reportTime showTimes "PDB: Created" - (portablePdbStream.Length, contentId, portablePdbStream) + (portablePdbStream.Length, contentId, portablePdbStream, algorithmName, contentHash) let compressPortablePdbStream (uncompressedLength: int64) (contentId: BlobContentId) (stream: MemoryStream) = let compressedStream = new MemoryStream() @@ -507,17 +556,17 @@ let compressPortablePdbStream (uncompressedLength: int64) (contentId: BlobConten stream.WriteTo compressionStream (uncompressedLength, contentId, compressedStream) -let writePortablePdbInfo (contentId: BlobContentId) (stream: MemoryStream) showTimes fpdb pathMap cvChunk = +let writePortablePdbInfo (contentId: BlobContentId) (stream: MemoryStream) showTimes fpdb pathMap cvChunk deterministicPdbChunk checksumPdbChunk algName checksum embeddedPdb deterministicPdb = try FileSystem.FileDelete fpdb with _ -> () use pdbFile = new FileStream(fpdb, FileMode.Create, FileAccess.ReadWrite) stream.WriteTo pdbFile reportTime showTimes "PDB: Closed" - pdbGetDebugInfo (contentId.Guid.ToByteArray()) (int32 (contentId.Stamp)) (PathMap.apply pathMap fpdb) cvChunk None 0L None + pdbGetDebugInfo (contentId.Guid.ToByteArray()) (int32 (contentId.Stamp)) (PathMap.apply pathMap fpdb) cvChunk None deterministicPdbChunk checksumPdbChunk algName checksum 0L None embeddedPdb deterministicPdb -let embedPortablePdbInfo (uncompressedLength: int64) (contentId: BlobContentId) (stream: MemoryStream) showTimes fpdb cvChunk pdbChunk = +let embedPortablePdbInfo (uncompressedLength: int64) (contentId: BlobContentId) (stream: MemoryStream) showTimes fpdb cvChunk pdbChunk deterministicPdbChunk checksumPdbChunk algName checksum embeddedPdb deterministicPdb = reportTime showTimes "PDB: Closed" let fn = Path.GetFileName fpdb - pdbGetDebugInfo (contentId.Guid.ToByteArray()) (int32 (contentId.Stamp)) fn cvChunk (Some pdbChunk) uncompressedLength (Some stream) + pdbGetDebugInfo (contentId.Guid.ToByteArray()) (int32 (contentId.Stamp)) fn cvChunk (Some pdbChunk) deterministicPdbChunk checksumPdbChunk algName checksum uncompressedLength (Some stream) embeddedPdb deterministicPdb #if !FX_NO_PDB_WRITER //--------------------------------------------------------------------- diff --git a/src/absil/ilwritepdb.fsi b/src/absil/ilwritepdb.fsi index 2713d9769b2..748e178a461 100644 --- a/src/absil/ilwritepdb.fsi +++ b/src/absil/ilwritepdb.fsi @@ -4,7 +4,7 @@ module internal FSharp.Compiler.AbstractIL.ILPdbWriter open Internal.Utilities -open FSharp.Compiler.AbstractIL.IL +open FSharp.Compiler.AbstractIL.IL open FSharp.Compiler.ErrorLogger open FSharp.Compiler.Range open System.Collections.Generic @@ -83,10 +83,14 @@ type idd = iddData: byte[]; iddChunk: BinaryChunk } -val generatePortablePdb : embedAllSource:bool -> embedSourceList:string list -> sourceLink: string -> showTimes:bool -> info:PdbData -> isDeterministic:bool -> pathMap:PathMap -> (int64 * BlobContentId * MemoryStream) +type HashAlgorithm = + | Sha1 + | Sha256 + +val generatePortablePdb : embedAllSource: bool -> embedSourceList: string list -> sourceLink: string -> checksumAlgorithm: HashAlgorithm -> showTimes: bool -> info: PdbData -> pathMap:PathMap -> (int64 * BlobContentId * MemoryStream * string * byte[]) val compressPortablePdbStream : uncompressedLength:int64 -> contentId:BlobContentId -> stream:MemoryStream -> (int64 * BlobContentId * MemoryStream) -val embedPortablePdbInfo : uncompressedLength:int64 -> contentId:BlobContentId -> stream:MemoryStream -> showTimes:bool -> fpdb:string -> cvChunk:BinaryChunk -> pdbChunk:BinaryChunk -> idd[] -val writePortablePdbInfo : contentId:BlobContentId -> stream:MemoryStream -> showTimes:bool -> fpdb:string -> pathMap:PathMap -> cvChunk:BinaryChunk -> idd[] +val embedPortablePdbInfo: uncompressedLength: int64 -> contentId: BlobContentId -> stream: MemoryStream -> showTimes: bool -> fpdb: string -> cvChunk: BinaryChunk -> pdbChunk: BinaryChunk -> deterministicPdbChunk: BinaryChunk -> checksumPdbChunk: BinaryChunk -> algorithmName: string -> checksum: byte[] -> embeddedPDB: bool -> deterministic: bool -> idd[] +val writePortablePdbInfo: contentId: BlobContentId -> stream: MemoryStream -> showTimes: bool -> fpdb: string -> pathMap: PathMap -> cvChunk: BinaryChunk -> deterministicPdbChunk: BinaryChunk -> checksumPdbChunk: BinaryChunk -> algorithmName: string -> checksum: byte[] -> embeddedPDB: bool -> deterministic: bool -> idd[] #if !FX_NO_PDB_WRITER val writePdbInfo : showTimes:bool -> f:string -> fpdb:string -> info:PdbData -> cvChunk:BinaryChunk -> idd[] diff --git a/src/fsharp/CompileOps.fs b/src/fsharp/CompileOps.fs index 85728909cf3..5b75cf1077c 100644 --- a/src/fsharp/CompileOps.fs +++ b/src/fsharp/CompileOps.fs @@ -17,6 +17,7 @@ open Internal.Utilities.Text open FSharp.Compiler.AbstractIL open FSharp.Compiler.AbstractIL.IL open FSharp.Compiler.AbstractIL.ILBinaryReader +open FSharp.Compiler.AbstractIL.ILPdbWriter open FSharp.Compiler.AbstractIL.Internal open FSharp.Compiler.AbstractIL.Internal.Library open FSharp.Compiler.AbstractIL.Extensions.ILX @@ -2100,6 +2101,7 @@ type TcConfigBuilder = mutable maxErrors: int mutable abortOnError: bool (* intended for fsi scripts that should exit on first error *) mutable baseAddress: int32 option + mutable checksumAlgorithm: HashAlgorithm #if DEBUG mutable showOptimizationData: bool #endif @@ -2231,6 +2233,7 @@ type TcConfigBuilder = maxErrors = 100 abortOnError = false baseAddress = None + checksumAlgorithm = HashAlgorithm.Sha256 delaysign = false publicsign = false @@ -2740,6 +2743,7 @@ type TcConfig private (data: TcConfigBuilder, validate: bool) = member x.flatErrors = data.flatErrors member x.maxErrors = data.maxErrors member x.baseAddress = data.baseAddress + member x.checksumAlgorithm = data.checksumAlgorithm #if DEBUG member x.showOptimizationData = data.showOptimizationData #endif diff --git a/src/fsharp/CompileOps.fsi b/src/fsharp/CompileOps.fsi index 71bb7c6f8b6..1262542cd9f 100644 --- a/src/fsharp/CompileOps.fsi +++ b/src/fsharp/CompileOps.fsi @@ -10,6 +10,7 @@ open Internal.Utilities open FSharp.Compiler.AbstractIL open FSharp.Compiler.AbstractIL.IL open FSharp.Compiler.AbstractIL.ILBinaryReader +open FSharp.Compiler.AbstractIL.ILPdbWriter open FSharp.Compiler.AbstractIL.Internal.Library open FSharp.Compiler open FSharp.Compiler.TypeChecker @@ -337,6 +338,7 @@ type TcConfigBuilder = mutable maxErrors: int mutable abortOnError: bool mutable baseAddress: int32 option + mutable checksumAlgorithm: HashAlgorithm #if DEBUG mutable showOptimizationData: bool #endif @@ -497,6 +499,7 @@ type TcConfig = member maxErrors: int member baseAddress: int32 option + member checksumAlgorithm: HashAlgorithm #if DEBUG member showOptimizationData: bool #endif diff --git a/src/fsharp/CompileOptions.fs b/src/fsharp/CompileOptions.fs index 0c385cc3670..e548a49e712 100644 --- a/src/fsharp/CompileOptions.fs +++ b/src/fsharp/CompileOptions.fs @@ -9,6 +9,7 @@ open System open FSharp.Compiler open FSharp.Compiler.AbstractIL open FSharp.Compiler.AbstractIL.IL +open FSharp.Compiler.AbstractIL.ILPdbWriter open FSharp.Compiler.AbstractIL.Internal.Library open FSharp.Compiler.AbstractIL.Extensions.ILX open FSharp.Compiler.AbstractIL.Diagnostics @@ -522,6 +523,7 @@ let tagFullPDBOnlyPortable = "{full|pdbonly|portable|embedded}" let tagWarnList = "" let tagSymbolList = "" let tagAddress = "
" +let tagAlgorithm = "{SHA1|SHA256}" let tagInt = "" let tagPathMap = "" let tagNone = "" @@ -933,6 +935,16 @@ let advancedFlagsFsc tcConfigB = OptionString (fun s -> tcConfigB.baseAddress <- Some(int32 s)), None, Some (FSComp.SR.optsBaseaddress())) + yield CompilerOption + ("checksumalgorithm", tagAlgorithm, + OptionString (fun s -> + tcConfigB.checksumAlgorithm <- + match s.ToUpperInvariant() with + | "SHA1" -> HashAlgorithm.Sha1 + | "SHA256" -> HashAlgorithm.Sha256 + | _ -> error(Error(FSComp.SR.optsUnknownChecksumAlgorithm s, rangeCmdArgs))), None, + Some (FSComp.SR.optsChecksumAlgorithm())) + yield noFrameworkFlag true tcConfigB yield CompilerOption diff --git a/src/fsharp/FSComp.txt b/src/fsharp/FSComp.txt index ee2b41f2e9d..831597c031a 100644 --- a/src/fsharp/FSComp.txt +++ b/src/fsharp/FSComp.txt @@ -878,6 +878,7 @@ optsUtf8output,"Output messages in UTF-8 encoding" optsFullpaths,"Output messages with fully qualified paths" optsLib,"Specify a directory for the include path which is used to resolve source files and assemblies (Short form: -I)" optsBaseaddress,"Base address for the library to be built" +optsChecksumAlgorithm,"Specify algorithm for calculating source file checksum stored in PDB. Supported values are: SHA1 or SHA256 (default)" optsNoframework,"Do not reference the default CLI assemblies by default" optsStandalone,"Statically link the F# library and all referenced DLLs that depend on it into the assembly being generated" optsStaticlink,"Statically link the given assembly and all referenced DLLs that depend on this assembly. Use an assembly name e.g. mylib, not a DLL name." @@ -900,6 +901,7 @@ optsHelpBannerLanguage,"- LANGUAGE -" optsHelpBannerErrsAndWarns,"- ERRORS AND WARNINGS -" 1063,optsUnknownArgumentToTheTestSwitch,"Unknown --test argument: '%s'" 1064,optsUnknownPlatform,"Unrecognized platform '%s', valid values are 'x86', 'x64', 'Itanium', 'anycpu32bitpreferred', and 'anycpu'" +1065,optsUnknownChecksumAlgorithm,"Algorithm '%s' is not supported" optsInternalNoDescription,"The command-line option '%s' is for test purposes only" optsDCLONoDescription,"The command-line option '%s' has been deprecated" optsDCLODeprecatedSuggestAlternative,"The command-line option '%s' has been deprecated. Use '%s' instead." diff --git a/src/fsharp/FSharp.Build/Fsc.fs b/src/fsharp/FSharp.Build/Fsc.fs index 19d8cd171fa..8080637fcdf 100644 --- a/src/fsharp/FSharp.Build/Fsc.fs +++ b/src/fsharp/FSharp.Build/Fsc.fs @@ -24,6 +24,7 @@ type public Fsc () as this = let mutable baseAddress : string = null let mutable capturedArguments : string list = [] // list of individual args, to pass to HostObject Compile() let mutable capturedFilenames : string list = [] // list of individual source filenames, to pass to HostObject Compile() + let mutable checksumAlgorithm: string = null let mutable codePage : string = null let mutable commandLineArgs : ITaskItem list = [] let mutable debugSymbols = false @@ -135,7 +136,7 @@ type public Fsc () as this = builder.AppendSwitch("--tailcalls-") // PdbFile builder.AppendSwitchIfNotNull("--pdb:", pdbFile) - // Platform +// Platform builder.AppendSwitchIfNotNull("--platform:", let ToUpperInvariant (s:string) = if s = null then null else s.ToUpperInvariant() match ToUpperInvariant(platform), prefer32bit, ToUpperInvariant(targetType) with @@ -145,6 +146,13 @@ type public Fsc () as this = | "X86", _, _ -> "x86" | "X64", _, _ -> "x64" | _ -> null) + // checksumAlgorithm + builder.AppendSwitchIfNotNull("--checksumalgorithm:", + let ToUpperInvariant (s:string) = if s = null then null else s.ToUpperInvariant() + match ToUpperInvariant(checksumAlgorithm) with + | "SHA1" -> "Sha1" + | "SHA256" -> "Sha256" + | _ -> null) // Resources if resources <> null then for item in resources do @@ -258,6 +266,11 @@ type public Fsc () as this = with get() = baseAddress and set(s) = baseAddress <- s + // --checksumalgorithm + member fsc.ChecksumAlgorithm + with get() = checksumAlgorithm + and set(s) = checksumAlgorithm <- s + // --codepage : Specify the codepage to use when opening source files member fsc.CodePage with get() = codePage diff --git a/src/fsharp/FSharp.Build/Microsoft.FSharp.Targets b/src/fsharp/FSharp.Build/Microsoft.FSharp.Targets index c36ce52c50f..a5d036b885a 100644 --- a/src/fsharp/FSharp.Build/Microsoft.FSharp.Targets +++ b/src/fsharp/FSharp.Build/Microsoft.FSharp.Targets @@ -276,6 +276,7 @@ this file. AbsIL\ilread.fs - - AbsIL\ilwrite.fsi - AbsIL\ilwritepdb.fsi AbsIL\ilwritepdb.fs + + AbsIL\ilwrite.fsi + AbsIL\ilwrite.fs diff --git a/src/fsharp/fsc.fs b/src/fsharp/fsc.fs index e4e693e99ca..7799d409e5d 100644 --- a/src/fsharp/fsc.fs +++ b/src/fsharp/fsc.fs @@ -2145,6 +2145,7 @@ let main4 dynamicAssemblyCreator (Args (ctok, tcConfig, tcImports: TcImports, t embedAllSource = tcConfig.embedAllSource embedSourceList = tcConfig.embedSourceList sourceLink = tcConfig.sourceLink + checksumAlgorithm = tcConfig.checksumAlgorithm signer = GetStrongNameSigner signingInfo dumpDebugInfo = tcConfig.dumpDebugInfo pathMap = tcConfig.pathMap }, diff --git a/src/fsharp/xlf/FSComp.txt.cs.xlf b/src/fsharp/xlf/FSComp.txt.cs.xlf index 3354ee57b5f..883582e5e67 100644 --- a/src/fsharp/xlf/FSComp.txt.cs.xlf +++ b/src/fsharp/xlf/FSComp.txt.cs.xlf @@ -7,6 +7,16 @@ {0} for F# {1} + + Specify algorithm for calculating source file checksum stored in PDB. Supported values are: SHA1 or SHA256 (default) + Specify algorithm for calculating source file checksum stored in PDB. Supported values are: SHA1 or SHA256 (default) + + + + Algorithm '{0}' is not supported + Algorithm '{0}' is not supported + + The namespace '{0}' is not defined. Není definovaný obor názvů {0}. diff --git a/src/fsharp/xlf/FSComp.txt.de.xlf b/src/fsharp/xlf/FSComp.txt.de.xlf index 320acf4e03d..12791db46fa 100644 --- a/src/fsharp/xlf/FSComp.txt.de.xlf +++ b/src/fsharp/xlf/FSComp.txt.de.xlf @@ -7,6 +7,16 @@ {0} for F# {1} + + Specify algorithm for calculating source file checksum stored in PDB. Supported values are: SHA1 or SHA256 (default) + Specify algorithm for calculating source file checksum stored in PDB. Supported values are: SHA1 or SHA256 (default) + + + + Algorithm '{0}' is not supported + Algorithm '{0}' is not supported + + The namespace '{0}' is not defined. Der Namespace "{0}" ist nicht definiert. diff --git a/src/fsharp/xlf/FSComp.txt.es.xlf b/src/fsharp/xlf/FSComp.txt.es.xlf index b08960e4861..e4096bec532 100644 --- a/src/fsharp/xlf/FSComp.txt.es.xlf +++ b/src/fsharp/xlf/FSComp.txt.es.xlf @@ -7,6 +7,16 @@ {0} for F# {1} + + Specify algorithm for calculating source file checksum stored in PDB. Supported values are: SHA1 or SHA256 (default) + Specify algorithm for calculating source file checksum stored in PDB. Supported values are: SHA1 or SHA256 (default) + + + + Algorithm '{0}' is not supported + Algorithm '{0}' is not supported + + The namespace '{0}' is not defined. El espacio de nombres "{0}" no está definido. diff --git a/src/fsharp/xlf/FSComp.txt.fr.xlf b/src/fsharp/xlf/FSComp.txt.fr.xlf index f23037f6a88..1a0d745e9f2 100644 --- a/src/fsharp/xlf/FSComp.txt.fr.xlf +++ b/src/fsharp/xlf/FSComp.txt.fr.xlf @@ -7,6 +7,16 @@ {0} for F# {1} + + Specify algorithm for calculating source file checksum stored in PDB. Supported values are: SHA1 or SHA256 (default) + Specify algorithm for calculating source file checksum stored in PDB. Supported values are: SHA1 or SHA256 (default) + + + + Algorithm '{0}' is not supported + Algorithm '{0}' is not supported + + The namespace '{0}' is not defined. L'espace de noms '{0}' n'est pas défini. diff --git a/src/fsharp/xlf/FSComp.txt.it.xlf b/src/fsharp/xlf/FSComp.txt.it.xlf index 32637f988da..baec2ba7fd6 100644 --- a/src/fsharp/xlf/FSComp.txt.it.xlf +++ b/src/fsharp/xlf/FSComp.txt.it.xlf @@ -7,6 +7,16 @@ {0} for F# {1} + + Specify algorithm for calculating source file checksum stored in PDB. Supported values are: SHA1 or SHA256 (default) + Specify algorithm for calculating source file checksum stored in PDB. Supported values are: SHA1 or SHA256 (default) + + + + Algorithm '{0}' is not supported + Algorithm '{0}' is not supported + + The namespace '{0}' is not defined. Lo spazio dei nomi '{0}' non è definito. diff --git a/src/fsharp/xlf/FSComp.txt.ja.xlf b/src/fsharp/xlf/FSComp.txt.ja.xlf index 8157060c9d8..a2a18f153ad 100644 --- a/src/fsharp/xlf/FSComp.txt.ja.xlf +++ b/src/fsharp/xlf/FSComp.txt.ja.xlf @@ -7,6 +7,16 @@ {0} for F# {1} + + Specify algorithm for calculating source file checksum stored in PDB. Supported values are: SHA1 or SHA256 (default) + Specify algorithm for calculating source file checksum stored in PDB. Supported values are: SHA1 or SHA256 (default) + + + + Algorithm '{0}' is not supported + Algorithm '{0}' is not supported + + The namespace '{0}' is not defined. 名前空間 '{0}' が定義されていません。 diff --git a/src/fsharp/xlf/FSComp.txt.ko.xlf b/src/fsharp/xlf/FSComp.txt.ko.xlf index f642d6b444d..92ead77838e 100644 --- a/src/fsharp/xlf/FSComp.txt.ko.xlf +++ b/src/fsharp/xlf/FSComp.txt.ko.xlf @@ -7,6 +7,16 @@ {0} for F# {1} + + Specify algorithm for calculating source file checksum stored in PDB. Supported values are: SHA1 or SHA256 (default) + Specify algorithm for calculating source file checksum stored in PDB. Supported values are: SHA1 or SHA256 (default) + + + + Algorithm '{0}' is not supported + Algorithm '{0}' is not supported + + The namespace '{0}' is not defined. '{0}' 네임스페이스가 정의되지 않았습니다. diff --git a/src/fsharp/xlf/FSComp.txt.pl.xlf b/src/fsharp/xlf/FSComp.txt.pl.xlf index b9749bedda5..0187c22d016 100644 --- a/src/fsharp/xlf/FSComp.txt.pl.xlf +++ b/src/fsharp/xlf/FSComp.txt.pl.xlf @@ -7,6 +7,16 @@ {0} for F# {1} + + Specify algorithm for calculating source file checksum stored in PDB. Supported values are: SHA1 or SHA256 (default) + Specify algorithm for calculating source file checksum stored in PDB. Supported values are: SHA1 or SHA256 (default) + + + + Algorithm '{0}' is not supported + Algorithm '{0}' is not supported + + The namespace '{0}' is not defined. Nie zdefiniowano przestrzeni nazw „{0}”. diff --git a/src/fsharp/xlf/FSComp.txt.pt-BR.xlf b/src/fsharp/xlf/FSComp.txt.pt-BR.xlf index 39537bc8cde..1ed97eb22d3 100644 --- a/src/fsharp/xlf/FSComp.txt.pt-BR.xlf +++ b/src/fsharp/xlf/FSComp.txt.pt-BR.xlf @@ -7,6 +7,16 @@ {0} for F# {1} + + Specify algorithm for calculating source file checksum stored in PDB. Supported values are: SHA1 or SHA256 (default) + Specify algorithm for calculating source file checksum stored in PDB. Supported values are: SHA1 or SHA256 (default) + + + + Algorithm '{0}' is not supported + Algorithm '{0}' is not supported + + The namespace '{0}' is not defined. O namespace '{0}' não está definido. diff --git a/src/fsharp/xlf/FSComp.txt.ru.xlf b/src/fsharp/xlf/FSComp.txt.ru.xlf index fcd4c723f70..bdeac0f9592 100644 --- a/src/fsharp/xlf/FSComp.txt.ru.xlf +++ b/src/fsharp/xlf/FSComp.txt.ru.xlf @@ -7,6 +7,16 @@ {0} for F# {1} + + Specify algorithm for calculating source file checksum stored in PDB. Supported values are: SHA1 or SHA256 (default) + Specify algorithm for calculating source file checksum stored in PDB. Supported values are: SHA1 or SHA256 (default) + + + + Algorithm '{0}' is not supported + Algorithm '{0}' is not supported + + The namespace '{0}' is not defined. Пространство имен "{0}" не определено. diff --git a/src/fsharp/xlf/FSComp.txt.tr.xlf b/src/fsharp/xlf/FSComp.txt.tr.xlf index 80929708832..de62c337f55 100644 --- a/src/fsharp/xlf/FSComp.txt.tr.xlf +++ b/src/fsharp/xlf/FSComp.txt.tr.xlf @@ -7,6 +7,16 @@ {0} for F# {1} + + Specify algorithm for calculating source file checksum stored in PDB. Supported values are: SHA1 or SHA256 (default) + Specify algorithm for calculating source file checksum stored in PDB. Supported values are: SHA1 or SHA256 (default) + + + + Algorithm '{0}' is not supported + Algorithm '{0}' is not supported + + The namespace '{0}' is not defined. '{0}' ad alanı tanımlı değil. diff --git a/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf b/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf index 1a7945d7124..b0264288fb1 100644 --- a/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf +++ b/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf @@ -7,6 +7,16 @@ {0} for F# {1} + + Specify algorithm for calculating source file checksum stored in PDB. Supported values are: SHA1 or SHA256 (default) + Specify algorithm for calculating source file checksum stored in PDB. Supported values are: SHA1 or SHA256 (default) + + + + Algorithm '{0}' is not supported + Algorithm '{0}' is not supported + + The namespace '{0}' is not defined. 未定义命名空间“{0}”。 diff --git a/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf b/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf index 0f67d46dbc2..ab73b60a7f4 100644 --- a/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf +++ b/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf @@ -7,6 +7,16 @@ {0} for F# {1} + + Specify algorithm for calculating source file checksum stored in PDB. Supported values are: SHA1 or SHA256 (default) + Specify algorithm for calculating source file checksum stored in PDB. Supported values are: SHA1 or SHA256 (default) + + + + Algorithm '{0}' is not supported + Algorithm '{0}' is not supported + + The namespace '{0}' is not defined. 未定義命名空間 '{0}'。 diff --git a/tests/EndToEndBuildTests/ProvidedTypes/ProvidedTypes.fs b/tests/EndToEndBuildTests/ProvidedTypes/ProvidedTypes.fs index 45974519909..f6395b91c49 100644 --- a/tests/EndToEndBuildTests/ProvidedTypes/ProvidedTypes.fs +++ b/tests/EndToEndBuildTests/ProvidedTypes/ProvidedTypes.fs @@ -12495,7 +12495,7 @@ namespace ProviderImplementation.ProvidedTypes let pdbOpt = match portablePDB with | true -> - let (uncompressedLength, contentId, stream) as pdbStream = generatePortablePdb embedAllSource embedSourceList sourceLink showTimes pdbData deterministic + let (uncompressedLength, contentId, stream) as pdbStream = generatePortablePdb embedAllSource embedSourceList sourceLink showTimes pdbData if embeddedPDB then Some (compressPortablePdbStream uncompressedLength contentId stream) else Some (pdbStream) | _ -> None diff --git a/tests/fsharp/.gitignore b/tests/fsharp/.gitignore index 0493c881790..ea4771517da 100644 --- a/tests/fsharp/.gitignore +++ b/tests/fsharp/.gitignore @@ -13,4 +13,5 @@ Library1.dll cd.tmp - +*.err +*.vserr diff --git a/tests/fsharpqa/Source/CompilerOptions/fsc/dumpAllCommandLineOptions/dummy.fs b/tests/fsharpqa/Source/CompilerOptions/fsc/dumpAllCommandLineOptions/dummy.fs index 65d7f3ba86d..0c3c619c33e 100644 --- a/tests/fsharpqa/Source/CompilerOptions/fsc/dumpAllCommandLineOptions/dummy.fs +++ b/tests/fsharpqa/Source/CompilerOptions/fsc/dumpAllCommandLineOptions/dummy.fs @@ -39,6 +39,7 @@ //section='- ADVANCED - ' ! option=fullpaths kind=OptionUnit //section='- ADVANCED - ' ! option=lib kind=OptionStringList //section='- ADVANCED - ' ! option=baseaddress kind=OptionString +//section='- ADVANCED - ' ! option=checksumalgorithm kind=OptionString //section='- ADVANCED - ' ! option=noframework kind=OptionUnit //section='- ADVANCED - ' ! option=standalone kind=OptionUnit //section='- ADVANCED - ' ! option=staticlink kind=OptionString diff --git a/tests/fsharpqa/Source/CompilerOptions/fsc/help/help40.437.1033.bsl b/tests/fsharpqa/Source/CompilerOptions/fsc/help/help40.437.1033.bsl index b0fd6746810..9309a03e5e6 100644 --- a/tests/fsharpqa/Source/CompilerOptions/fsc/help/help40.437.1033.bsl +++ b/tests/fsharpqa/Source/CompilerOptions/fsc/help/help40.437.1033.bsl @@ -133,6 +133,10 @@ Copyright (c) Microsoft Corporation. All Rights Reserved. Default - mscorlib --baseaddress:
Base address for the library to be built +--checksumalgorithm:{SHA1|SHA256} Specify algorithm for calculating + source file checksum stored in PDB. + Supported values are: SHA1 or SHA256 + (default) --noframework Do not reference the default CLI assemblies by default --standalone Statically link the F# library and From c70ead8048a2dd7865195bd90edfd64a260dc1e9 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Sat, 20 Jul 2019 10:04:05 -0700 Subject: [PATCH 30/46] Update dependencies from https://github.com/dotnet/arcade build 20190719.2 (#7260) - Microsoft.DotNet.Arcade.Sdk - 1.0.0-beta.19369.2 --- eng/Version.Details.xml | 4 ++-- global.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 7a60463a0fb..7228968c11e 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -3,9 +3,9 @@ - + https://github.com/dotnet/arcade - eecde8a8751dbe7fdb17ba4dfbd032e26f4cae7d + a190d4865fe3c86a168ec49c4fc61c90c96ae051 diff --git a/global.json b/global.json index 78425fae2ed..c8c5b129393 100644 --- a/global.json +++ b/global.json @@ -10,7 +10,7 @@ } }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19368.7", + "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19369.2", "Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19069.2" } } From ff7b8ff392cee40388a08e377138030784c7cc35 Mon Sep 17 00:00:00 2001 From: "Kevin Ransom (msft)" Date: Mon, 22 Jul 2019 12:24:18 -0700 Subject: [PATCH 31/46] Improve netcore reference selection (#7263) * Improve netcore reference selection * Update baselines --- tests/fsharp/Compiler/CompilerAssert.fs | 87 ++++++++++-- .../Language/SpanOptimizationTests.fs | 124 +++++++++--------- 2 files changed, 136 insertions(+), 75 deletions(-) diff --git a/tests/fsharp/Compiler/CompilerAssert.fs b/tests/fsharp/Compiler/CompilerAssert.fs index ade3ca8e4a3..52ec325df86 100644 --- a/tests/fsharp/Compiler/CompilerAssert.fs +++ b/tests/fsharp/Compiler/CompilerAssert.fs @@ -32,6 +32,76 @@ module CompilerAssert = let private config = TestFramework.initializeSuite () + +// Do a one time dotnet sdk build to compute the proper set of reference assemblies to pass to the compiler +#if !NETCOREAPP +#else + let projectFile = """ + + + + Exe + netcoreapp2.1 + + + + + + + + +""" + + let programFs = """ +open System + +[] +let main argv = 0""" + + let getNetCoreAppReferences = + let mutable output = "" + let mutable errors = "" + let mutable cleanUp = true + let projectDirectory = Path.Combine(Path.GetTempPath(), "netcoreapp2.1", Path.GetRandomFileName()) + try + try + Directory.CreateDirectory(projectDirectory) |> ignore + let projectFileName = Path.Combine(projectDirectory, "ProjectFile.fsproj") + let programFsFileName = Path.Combine(projectDirectory, "Program.fs") + let frameworkReferencesFileName = Path.Combine(projectDirectory, "FrameworkReferences.txt") + + File.WriteAllText(projectFileName, projectFile) + File.WriteAllText(programFsFileName, programFs) + + let pInfo = ProcessStartInfo () + + pInfo.FileName <- config.DotNetExe + pInfo.Arguments <- "build" + pInfo.WorkingDirectory <- projectDirectory + pInfo.RedirectStandardOutput <- true + pInfo.RedirectStandardError <- true + pInfo.UseShellExecute <- false + + let p = Process.Start(pInfo) + p.WaitForExit() + + output <- p.StandardOutput.ReadToEnd () + errors <- p.StandardError.ReadToEnd () + if not (String.IsNullOrWhiteSpace errors) then Assert.Fail errors + + if p.ExitCode <> 0 then Assert.Fail(sprintf "Program exited with exit code %d" p.ExitCode) + + File.ReadLines(frameworkReferencesFileName) |> Seq.toArray + with | e -> + cleanUp <- false + printfn "%s" output + printfn "%s" errors + raise (new Exception (sprintf "An error occured getting netcoreapp references: %A" e)) + finally + if cleanUp then + try Directory.Delete(projectDirectory) with | _ -> () +#endif + let private defaultProjectOptions = { ProjectFileName = "Z:\\test.fsproj" @@ -41,14 +111,7 @@ module CompilerAssert = OtherOptions = [|"--preferreduilang:en-US";|] #else OtherOptions = - // Hack: Currently a hack to get the runtime assemblies for netcore in order to compile. - let assemblies = - typeof.Assembly.Location - |> Path.GetDirectoryName - |> Directory.EnumerateFiles - |> Seq.toArray - |> Array.filter (fun x -> x.ToLowerInvariant().Contains("system.")) - |> Array.map (fun x -> sprintf "-r:%s" x) + let assemblies = getNetCoreAppReferences |> Array.map (fun x -> sprintf "-r:%s" x) Array.append [|"--preferreduilang:en-US"; "--targetprofile:netcore"; "--noframework"|] assemblies #endif ReferencedProjects = [||] @@ -60,7 +123,7 @@ module CompilerAssert = ExtraProjectInfo = None Stamp = None } - + let private gate = obj () let private compile isExe source f = @@ -110,8 +173,6 @@ module CompilerAssert = Assert.IsEmpty(typeCheckResults.Errors, sprintf "Type Check errors: %A" typeCheckResults.Errors) - - let TypeCheckWithErrors (source: string) expectedTypeErrors = lock gate <| fun () -> let parseResults, fileAnswer = checker.ParseAndCheckFileInProject("test.fs", 0, SourceText.ofString source, defaultProjectOptions) |> Async.RunSynchronously @@ -141,7 +202,7 @@ module CompilerAssert = TypeCheckWithErrors (source: string) [| expectedServerity, expectedErrorNumber, expectedErrorRange, expectedErrorMsg |] let CompileExe (source: string) = - compile true source (fun (errors, _) -> + compile true source (fun (errors, _) -> if errors.Length > 0 then Assert.Fail (sprintf "Compile had warnings and/or errors: %A" errors)) @@ -216,7 +277,7 @@ module CompilerAssert = ||> Seq.iter2 (fun expectedErrorMessage errorMessage -> Assert.AreEqual(expectedErrorMessage, errorMessage) ) - + let ParseWithErrors (source: string) expectedParseErrors = let parseResults = checker.ParseFile("test.fs", SourceText.ofString source, FSharpParsingOptions.Default) |> Async.RunSynchronously diff --git a/tests/fsharp/Compiler/Language/SpanOptimizationTests.fs b/tests/fsharp/Compiler/Language/SpanOptimizationTests.fs index efcea68afd3..c5fd682e993 100644 --- a/tests/fsharp/Compiler/Language/SpanOptimizationTests.fs +++ b/tests/fsharp/Compiler/Language/SpanOptimizationTests.fs @@ -27,45 +27,45 @@ let test () = verifier.VerifyIL [ """.method public static void test() cil managed -{ - - .maxstack 5 - .locals init (valuetype [System.Private.CoreLib]System.Span`1 V_0, - int32 V_1, - valuetype [System.Private.CoreLib]System.Int32 V_2, - class [System.Private.CoreLib]System.Object& V_3) - IL_0000: call valuetype [System.Private.CoreLib]System.Span`1 valuetype [System.Private.CoreLib]System.Span`1::get_Empty() - IL_0005: stloc.0 - IL_0006: ldc.i4.0 - IL_0007: stloc.2 - IL_0008: ldloca.s V_0 - IL_000a: call instance int32 valuetype [System.Private.CoreLib]System.Span`1::get_Length() - IL_000f: ldc.i4.1 - IL_0010: sub - IL_0011: stloc.1 - IL_0012: ldloc.1 - IL_0013: ldloc.2 - IL_0014: blt.s IL_0034 - - IL_0016: ldloca.s V_0 - IL_0018: ldloc.2 - IL_0019: call instance !0& valuetype [System.Private.CoreLib]System.Span`1::get_Item(int32) - IL_001e: stloc.3 - IL_001f: ldloc.3 - IL_0020: ldobj [System.Private.CoreLib]System.Object - IL_0025: call void [System.Console]System.Console::WriteLine(object) - IL_002a: ldloc.2 - IL_002b: ldc.i4.1 - IL_002c: add - IL_002d: stloc.2 - IL_002e: ldloc.2 - IL_002f: ldloc.1 - IL_0030: ldc.i4.1 - IL_0031: add - IL_0032: bne.un.s IL_0016 - - IL_0034: ret -} """ + { + + .maxstack 5 + .locals init (valuetype [System.Runtime]System.Span`1 V_0, + int32 V_1, + int32 V_2, + object& V_3) + IL_0000: call valuetype [System.Runtime]System.Span`1 valuetype [System.Runtime]System.Span`1::get_Empty() + IL_0005: stloc.0 + IL_0006: ldc.i4.0 + IL_0007: stloc.2 + IL_0008: ldloca.s V_0 + IL_000a: call instance int32 valuetype [System.Runtime]System.Span`1::get_Length() + IL_000f: ldc.i4.1 + IL_0010: sub + IL_0011: stloc.1 + IL_0012: ldloc.1 + IL_0013: ldloc.2 + IL_0014: blt.s IL_0034 + + IL_0016: ldloca.s V_0 + IL_0018: ldloc.2 + IL_0019: call instance !0& valuetype [System.Runtime]System.Span`1::get_Item(int32) + IL_001e: stloc.3 + IL_001f: ldloc.3 + IL_0020: ldobj [System.Runtime]System.Object + IL_0025: call void [System.Console]System.Console::WriteLine(object) + IL_002a: ldloc.2 + IL_002b: ldc.i4.1 + IL_002c: add + IL_002d: stloc.2 + IL_002e: ldloc.2 + IL_002f: ldloc.1 + IL_0030: ldc.i4.1 + IL_0031: add + IL_0032: bne.un.s IL_0016 + + IL_0034: ret + }""" ]) [] @@ -88,18 +88,18 @@ let test () = [ """.method public static void test() cil managed { - + .maxstack 5 - .locals init (valuetype [System.Private.CoreLib]System.ReadOnlySpan`1 V_0, + .locals init (valuetype [System.Runtime]System.ReadOnlySpan`1 V_0, int32 V_1, - valuetype [System.Private.CoreLib]System.Int32 V_2, - class [System.Private.CoreLib]System.Object& V_3) - IL_0000: call valuetype [System.Private.CoreLib]System.ReadOnlySpan`1 valuetype [System.Private.CoreLib]System.ReadOnlySpan`1::get_Empty() + int32 V_2, + object& V_3) + IL_0000: call valuetype [System.Runtime]System.ReadOnlySpan`1 valuetype [System.Runtime]System.ReadOnlySpan`1::get_Empty() IL_0005: stloc.0 IL_0006: ldc.i4.0 IL_0007: stloc.2 IL_0008: ldloca.s V_0 - IL_000a: call instance int32 valuetype [System.Private.CoreLib]System.ReadOnlySpan`1::get_Length() + IL_000a: call instance int32 valuetype [System.Runtime]System.ReadOnlySpan`1::get_Length() IL_000f: ldc.i4.1 IL_0010: sub IL_0011: stloc.1 @@ -109,10 +109,10 @@ let test () = IL_0016: ldloca.s V_0 IL_0018: ldloc.2 - IL_0019: call instance !0& modreq([System.Private.CoreLib]System.Runtime.InteropServices.InAttribute) valuetype [System.Private.CoreLib]System.ReadOnlySpan`1::get_Item(int32) + IL_0019: call instance !0& modreq([System.Runtime]System.Runtime.InteropServices.InAttribute) valuetype [System.Runtime]System.ReadOnlySpan`1::get_Item(int32) IL_001e: stloc.3 IL_001f: ldloc.3 - IL_0020: ldobj [System.Private.CoreLib]System.Object + IL_0020: ldobj [System.Runtime]System.Object IL_0025: call void [System.Console]System.Console::WriteLine(object) IL_002a: ldloc.2 IL_002b: ldc.i4.1 @@ -176,29 +176,29 @@ module Test = [ """.method public static void test() cil managed { - + .maxstack 3 - .locals init (valuetype System.Span`1 V_0, - class [System.Private.CoreLib]System.Collections.IEnumerator V_1, + .locals init (valuetype System.Span`1 V_0, + class [System.Runtime]System.Collections.IEnumerator V_1, class [FSharp.Core]Microsoft.FSharp.Core.Unit V_2, - class [System.Private.CoreLib]System.IDisposable V_3) + class [System.Runtime]System.IDisposable V_3) IL_0000: ldc.i4.0 - IL_0001: newarr [System.Private.CoreLib]System.Object - IL_0006: newobj instance void valuetype System.Span`1::.ctor(!0[]) + IL_0001: newarr [System.Runtime]System.Object + IL_0006: newobj instance void valuetype System.Span`1::.ctor(!0[]) IL_000b: stloc.0 IL_000c: ldloc.0 - IL_000d: box valuetype System.Span`1 - IL_0012: unbox.any [System.Private.CoreLib]System.Collections.IEnumerable - IL_0017: callvirt instance class [System.Private.CoreLib]System.Collections.IEnumerator [System.Private.CoreLib]System.Collections.IEnumerable::GetEnumerator() + IL_000d: box valuetype System.Span`1 + IL_0012: unbox.any [System.Runtime]System.Collections.IEnumerable + IL_0017: callvirt instance class [System.Runtime]System.Collections.IEnumerator [System.Runtime]System.Collections.IEnumerable::GetEnumerator() IL_001c: stloc.1 .try { IL_001d: ldloc.1 - IL_001e: callvirt instance bool [System.Private.CoreLib]System.Collections.IEnumerator::MoveNext() + IL_001e: callvirt instance bool [System.Runtime]System.Collections.IEnumerator::MoveNext() IL_0023: brfalse.s IL_0032 IL_0025: ldloc.1 - IL_0026: callvirt instance object [System.Private.CoreLib]System.Collections.IEnumerator::get_Current() + IL_0026: callvirt instance object [System.Runtime]System.Collections.IEnumerator::get_Current() IL_002b: call void [System.Console]System.Console::WriteLine(object) IL_0030: br.s IL_001d @@ -206,24 +206,24 @@ module Test = IL_0033: stloc.2 IL_0034: leave.s IL_004c - } + } finally { IL_0036: ldloc.1 - IL_0037: isinst [System.Private.CoreLib]System.IDisposable + IL_0037: isinst [System.Runtime]System.IDisposable IL_003c: stloc.3 IL_003d: ldloc.3 IL_003e: brfalse.s IL_0049 IL_0040: ldloc.3 - IL_0041: callvirt instance void [System.Private.CoreLib]System.IDisposable::Dispose() + IL_0041: callvirt instance void [System.Runtime]System.IDisposable::Dispose() IL_0046: ldnull IL_0047: pop IL_0048: endfinally IL_0049: ldnull IL_004a: pop IL_004b: endfinally - } + } IL_004c: ldloc.2 IL_004d: pop IL_004e: ret From d53a38c019b361a1f5b72362f199c86e829adc7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Chassaing?= Date: Tue, 23 Jul 2019 00:57:02 +0200 Subject: [PATCH 32/46] Moving Libraries Control tests to NUnit (#7234) * Moving Libraries Control tests to NUnit * Names tests as Async instead of Control --- tests/fsharp/FSharpSuite.Tests.fsproj | 1 + tests/fsharp/Libraries/Async/AsyncTests.fs | 168 ++++++++++++++++++ .../Control/ExecuteAsyncMultipleTimes01.fs | 17 -- .../Libraries/Control/JoiningStartChild01.fs | 25 --- .../Control/MailboxAsyncNoStackOverflow01.fs | 78 -------- .../StartChildNoObjectDisposedException01.fs | 12 -- .../StartChildTestTrampolineHijackLimit01.fs | 19 -- .../fsharpqa/Source/Libraries/Control/env.lst | 6 - 8 files changed, 169 insertions(+), 157 deletions(-) create mode 100644 tests/fsharp/Libraries/Async/AsyncTests.fs delete mode 100644 tests/fsharpqa/Source/Libraries/Control/ExecuteAsyncMultipleTimes01.fs delete mode 100644 tests/fsharpqa/Source/Libraries/Control/JoiningStartChild01.fs delete mode 100644 tests/fsharpqa/Source/Libraries/Control/MailboxAsyncNoStackOverflow01.fs delete mode 100644 tests/fsharpqa/Source/Libraries/Control/StartChildNoObjectDisposedException01.fs delete mode 100644 tests/fsharpqa/Source/Libraries/Control/StartChildTestTrampolineHijackLimit01.fs delete mode 100644 tests/fsharpqa/Source/Libraries/Control/env.lst diff --git a/tests/fsharp/FSharpSuite.Tests.fsproj b/tests/fsharp/FSharpSuite.Tests.fsproj index 9d80400c401..9291db2f740 100644 --- a/tests/fsharp/FSharpSuite.Tests.fsproj +++ b/tests/fsharp/FSharpSuite.Tests.fsproj @@ -48,6 +48,7 @@ + diff --git a/tests/fsharp/Libraries/Async/AsyncTests.fs b/tests/fsharp/Libraries/Async/AsyncTests.fs new file mode 100644 index 00000000000..04a82a97160 --- /dev/null +++ b/tests/fsharp/Libraries/Async/AsyncTests.fs @@ -0,0 +1,168 @@ +namespace FSharp.Libraries.UnitTests + +open System +open NUnit.Framework +open FSharp.Compiler.UnitTests + +[] +module AsyncTests = + // Regression for FSHARP1.0:5969 + // Async.StartChild: error when wait async is executed more than once + [] + let ``Execute Async multiple times``() = + CompilerAssert.CompileExeAndRun + """ +module M + +let a = async { + let! a = Async.StartChild( + async { + do! Async.Sleep(1) + return 27 + }) + let! result = Async.Parallel [ a; a; a; a ] + return result + } |> Async.RunSynchronously + +exit 0 + """ + + + // Regression for FSHARP1.0:5970 + // Async.StartChild: race in implementation of ResultCell in FSharp.Core + [] + let ``Joining StartChild``() = + CompilerAssert.CompileExeAndRun + """ +module M + +let Join (a1: Async<'a>) (a2: Async<'b>) = async { + let! task1 = a1 |> Async.StartChild + let! task2 = a2 |> Async.StartChild + + let! res1 = task1 + let! res2 = task2 + return (res1,res2) } + +let r = + try + Async.RunSynchronously (Join (async { do! Async.Sleep(30) + failwith "fail" + return 3+3 }) + (async { do! Async.Sleep(30) + return 2 + 2 } )) + with _ -> + (0,0) + +exit 0 + + """ + + // Regression test for FSHARP1.0:6086 + [] + let ``Mailbox Async dot not StackOverflow``() = + CompilerAssert.CompileExeAndRun + """ +open Microsoft.FSharp.Control + +type Color = Blue | Red | Yellow +let complement = function + | (Red, Yellow) | (Yellow, Red) -> Blue + | (Red, Blue) | (Blue, Red) -> Yellow + | (Yellow, Blue) | (Blue, Yellow) -> Red + | (Blue, Blue) -> Blue + | (Red, Red) -> Red + | (Yellow, Yellow) -> Yellow + +type Message = Color * AsyncReplyChannel + +let chameleon (meetingPlace : MailboxProcessor) initial = + let rec loop c meets = async { + let replyMessage = meetingPlace.PostAndReply(fun reply -> c, reply) + match replyMessage with + | Some(newColor) -> return! loop newColor (meets + 1) + | None -> return meets + } + loop initial 0 + +let meetingPlace chams n = MailboxProcessor.Start(fun (processor : MailboxProcessor)-> + let rec fadingLoop total = + async { + if total <> 0 then + let! (_, reply) = processor.Receive() + reply.Reply None + return! fadingLoop (total - 1) + else + printfn "Done" + } + let rec mainLoop curr = + async { + if (curr > 0) then + let! (color1, reply1) = processor.Receive() + let! (color2, reply2) = processor.Receive() + let newColor = complement (color1, color2) + reply1.Reply <| Some(newColor) + reply2.Reply <| Some(newColor) + return! mainLoop (curr - 1) + else + return! fadingLoop chams + } + mainLoop n + ) + +open System +open System.Diagnostics + +let meetings = 100000 + +let colors = [Blue; Red; Yellow; Blue] +let mp = meetingPlace (colors.Length) meetings +let watch = Stopwatch.StartNew() +let meets = + colors + |> List.map (chameleon mp) + |> Async.Parallel + |> Async.RunSynchronously +watch.Stop() +for meet in meets do + printfn "%d" meet +printfn "Total: %d in %O" (Seq.sum meets) (watch.Elapsed) + +exit 0 + """ + + // Regression for FSHARP1.0:5971 + [] + let ``StartChild do not throw ObjectDisposedException``() = + CompilerAssert.CompileExeAndRun + """ +module M + +let b = async {return 5} |> Async.StartChild +printfn "%A" (b |> Async.RunSynchronously |> Async.RunSynchronously) + +exit 0 + """ + + + [] + let ``StartChild test Trampoline HijackLimit``() = + CompilerAssert.CompileExeAndRun + """ +module M + +let r = + async { + let! a = Async.StartChild( + async { + do! Async.Sleep(1) + return 5 + } + ) + let! _ = a + for __ in 1..10000 do // 10000 > bindHijackLimit + () + } |> Async.RunSynchronously + +exit 0 + """ diff --git a/tests/fsharpqa/Source/Libraries/Control/ExecuteAsyncMultipleTimes01.fs b/tests/fsharpqa/Source/Libraries/Control/ExecuteAsyncMultipleTimes01.fs deleted file mode 100644 index e042c6f02df..00000000000 --- a/tests/fsharpqa/Source/Libraries/Control/ExecuteAsyncMultipleTimes01.fs +++ /dev/null @@ -1,17 +0,0 @@ -// #Regression #Libraries #Async -// Regression for FSHARP1.0:5969 -// Async.StartChild: error when wait async is executed more than once - -module M - -let a = async { - let! a = Async.StartChild( - async { - do! Async.Sleep(500) - return 27 - }) - let! result = Async.Parallel [ a; a; a; a ] - return result - } |> Async.RunSynchronously - -exit 0 diff --git a/tests/fsharpqa/Source/Libraries/Control/JoiningStartChild01.fs b/tests/fsharpqa/Source/Libraries/Control/JoiningStartChild01.fs deleted file mode 100644 index 692bb583844..00000000000 --- a/tests/fsharpqa/Source/Libraries/Control/JoiningStartChild01.fs +++ /dev/null @@ -1,25 +0,0 @@ -// #Regression #Libraries #Async -// Regression for FSHARP1.0:5970 -// Async.StartChild: race in implementation of ResultCell in FSharp.Core - -module M - -let Join (a1: Async<'a>) (a2: Async<'b>) = async { - let! task1 = a1 |> Async.StartChild - let! task2 = a2 |> Async.StartChild - - let! res1 = task1 - let! res2 = task2 - return (res1,res2) } - -let r = - try - Async.RunSynchronously (Join (async { do! Async.Sleep(30) - failwith "fail" - return 3+3 }) - (async { do! Async.Sleep(30) - return 2 + 2 } )) - with _ -> - (0,0) - -exit 0 diff --git a/tests/fsharpqa/Source/Libraries/Control/MailboxAsyncNoStackOverflow01.fs b/tests/fsharpqa/Source/Libraries/Control/MailboxAsyncNoStackOverflow01.fs deleted file mode 100644 index 33e0e590a7b..00000000000 --- a/tests/fsharpqa/Source/Libraries/Control/MailboxAsyncNoStackOverflow01.fs +++ /dev/null @@ -1,78 +0,0 @@ -// #Regression #Libraries #Async -// Regression test for FSHARP1.0:6086 -// This is a bit of duplication because the same/similar test -// can also be found under the FSHARP suite. Yet, I like to have -// it here... - -// The interesting thing about this test is that is used to throw -// an exception when executed on 64bit (FSharp.Core 2.0) - -open Microsoft.FSharp.Control - -type Color = Blue | Red | Yellow -let complement = function - | (Red, Yellow) | (Yellow, Red) -> Blue - | (Red, Blue) | (Blue, Red) -> Yellow - | (Yellow, Blue) | (Blue, Yellow) -> Red - | (Blue, Blue) -> Blue - | (Red, Red) -> Red - | (Yellow, Yellow) -> Yellow - -type Message = Color * AsyncReplyChannel - -let chameleon (meetingPlace : MailboxProcessor) initial = - let rec loop c meets = async { - let replyMessage = meetingPlace.PostAndReply(fun reply -> c, reply) - match replyMessage with - | Some(newColor) -> return! loop newColor (meets + 1) - | None -> return meets - } - loop initial 0 - -let meetingPlace chams n = MailboxProcessor.Start(fun (processor : MailboxProcessor)-> - let rec fadingLoop total = - async { - if total <> 0 then - let! (_, reply) = processor.Receive() - reply.Reply None - return! fadingLoop (total - 1) - else - printfn "Done" - } - let rec mainLoop curr = - async { - if (curr > 0) then - let! (color1, reply1) = processor.Receive() - let! (color2, reply2) = processor.Receive() - let newColor = complement (color1, color2) - reply1.Reply <| Some(newColor) - reply2.Reply <| Some(newColor) - return! mainLoop (curr - 1) - else - return! fadingLoop chams - } - mainLoop n - ) - -open System -open System.Diagnostics - -[] -let main(args : string[]) = - printfn "CommandLine : %s" (String.concat ", " args) - let meetings = if args.Length > 0 then Int32.Parse(args.[0]) else 100000 - - let colors = [Blue; Red; Yellow; Blue] - let mp = meetingPlace (colors.Length) meetings - let watch = Stopwatch.StartNew() - let meets = - colors - |> List.map (chameleon mp) - |> Async.Parallel - |> Async.RunSynchronously - watch.Stop() - for meet in meets do - printfn "%d" meet - printfn "Total: %d in %O" (Seq.sum meets) (watch.Elapsed) - 0 - diff --git a/tests/fsharpqa/Source/Libraries/Control/StartChildNoObjectDisposedException01.fs b/tests/fsharpqa/Source/Libraries/Control/StartChildNoObjectDisposedException01.fs deleted file mode 100644 index 5186548c79a..00000000000 --- a/tests/fsharpqa/Source/Libraries/Control/StartChildNoObjectDisposedException01.fs +++ /dev/null @@ -1,12 +0,0 @@ -// #Regression #Libraries #Async -// Regression for FSHARP1.0:5971 -// Async.StartChild: ObjectDisposedException - -module M - -let shortVersion(args: string []) = - let b = async {return 5} |> Async.StartChild - printfn "%A" (b |> Async.RunSynchronously |> Async.RunSynchronously) - (0) - -exit 0 diff --git a/tests/fsharpqa/Source/Libraries/Control/StartChildTestTrampolineHijackLimit01.fs b/tests/fsharpqa/Source/Libraries/Control/StartChildTestTrampolineHijackLimit01.fs deleted file mode 100644 index 46cfeb59376..00000000000 --- a/tests/fsharpqa/Source/Libraries/Control/StartChildTestTrampolineHijackLimit01.fs +++ /dev/null @@ -1,19 +0,0 @@ -// #Regression #Libraries #Async -// Regression for FSHARP1.0:5972 -// Async.StartChild: fails to install trampolines properly -module M - -let r = - async { - let! a = Async.StartChild( - async { - do! Async.Sleep(500) - return 5 - } - ) - let! b = a - for i in 1..10000 do // 10000 > bindHijackLimit - () - } |> Async.RunSynchronously - -exit 0 diff --git a/tests/fsharpqa/Source/Libraries/Control/env.lst b/tests/fsharpqa/Source/Libraries/Control/env.lst deleted file mode 100644 index 6c034ca5b46..00000000000 --- a/tests/fsharpqa/Source/Libraries/Control/env.lst +++ /dev/null @@ -1,6 +0,0 @@ - SOURCE=MailboxAsyncNoStackOverflow01.fs # MailboxAsyncNoStackOverflow01.fs - - SOURCE=ExecuteAsyncMultipleTimes01.fs # ExecuteAsyncMultipleTimes01.fs - SOURCE=JoiningStartChild01.fs # JoiningStartChild01.fs - SOURCE=StartChildNoObjectDisposedException01.fs # StartChildNoObjectDisposedException01.fs - SOURCE=StartChildTestTrampolineHijackLimit01.fs # StartChildTestTrampolineHijackLimit01.fs \ No newline at end of file From 5efa8a7ba0bd4e3d62515f14d0b48c8a0edd5c58 Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Tue, 23 Jul 2019 01:00:28 +0200 Subject: [PATCH 33/46] Member constraints and PrimitiveConstraints (#7210) --- tests/fsharp/Compiler/CompilerAssert.fs | 18 ++- .../ConstraintSolver/MemberConstraints.fs | 45 ++++++++ .../ConstraintSolver/PrimitiveConstraints.fs | 109 ++++++++++++++++++ tests/fsharp/FSharpSuite.Tests.fsproj | 2 + .../E_MemberConstraints01.fs | 6 - .../ConstraintSolving/E_PrimConstraint04.fs | 16 --- .../ConstraintSolving/MemberConstraints01.fs | 24 ---- .../ConstraintSolving/PrimConstraint01.fs | 26 ----- .../ConstraintSolving/PrimConstraint02.fs | 33 ------ .../ConstraintSolving/PrimConstraint03.fs | 23 ---- .../ConstraintSolving/env.lst | 8 -- 11 files changed, 171 insertions(+), 139 deletions(-) create mode 100644 tests/fsharp/Compiler/ConstraintSolver/MemberConstraints.fs create mode 100644 tests/fsharp/Compiler/ConstraintSolver/PrimitiveConstraints.fs delete mode 100644 tests/fsharpqa/Source/Conformance/InferenceProcedures/ConstraintSolving/E_MemberConstraints01.fs delete mode 100644 tests/fsharpqa/Source/Conformance/InferenceProcedures/ConstraintSolving/E_PrimConstraint04.fs delete mode 100644 tests/fsharpqa/Source/Conformance/InferenceProcedures/ConstraintSolving/MemberConstraints01.fs delete mode 100644 tests/fsharpqa/Source/Conformance/InferenceProcedures/ConstraintSolving/PrimConstraint01.fs delete mode 100644 tests/fsharpqa/Source/Conformance/InferenceProcedures/ConstraintSolving/PrimConstraint02.fs delete mode 100644 tests/fsharpqa/Source/Conformance/InferenceProcedures/ConstraintSolving/PrimConstraint03.fs diff --git a/tests/fsharp/Compiler/CompilerAssert.fs b/tests/fsharp/Compiler/CompilerAssert.fs index 52ec325df86..9f64824bb48 100644 --- a/tests/fsharp/Compiler/CompilerAssert.fs +++ b/tests/fsharp/Compiler/CompilerAssert.fs @@ -173,9 +173,15 @@ let main argv = 0""" Assert.IsEmpty(typeCheckResults.Errors, sprintf "Type Check errors: %A" typeCheckResults.Errors) - let TypeCheckWithErrors (source: string) expectedTypeErrors = + let TypeCheckWithErrorsAndOptions options (source: string) expectedTypeErrors = lock gate <| fun () -> - let parseResults, fileAnswer = checker.ParseAndCheckFileInProject("test.fs", 0, SourceText.ofString source, defaultProjectOptions) |> Async.RunSynchronously + let parseResults, fileAnswer = + checker.ParseAndCheckFileInProject( + "test.fs", + 0, + SourceText.ofString source, + { defaultProjectOptions with OtherOptions = Array.append options defaultProjectOptions.OtherOptions}) + |> Async.RunSynchronously Assert.IsEmpty(parseResults.Errors, sprintf "Parse errors: %A" parseResults.Errors) @@ -198,8 +204,14 @@ let main argv = 0""" Assert.AreEqual(expectedErrorMsg, info.Message, "expectedErrorMsg") ) + let TypeCheckWithErrors (source: string) expectedTypeErrors = + TypeCheckWithErrorsAndOptions [||] source expectedTypeErrors + + let TypeCheckSingleErrorWithOptions options (source: string) (expectedServerity: FSharpErrorSeverity) (expectedErrorNumber: int) (expectedErrorRange: int * int * int * int) (expectedErrorMsg: string) = + TypeCheckWithErrorsAndOptions options source [| expectedServerity, expectedErrorNumber, expectedErrorRange, expectedErrorMsg |] + let TypeCheckSingleError (source: string) (expectedServerity: FSharpErrorSeverity) (expectedErrorNumber: int) (expectedErrorRange: int * int * int * int) (expectedErrorMsg: string) = - TypeCheckWithErrors (source: string) [| expectedServerity, expectedErrorNumber, expectedErrorRange, expectedErrorMsg |] + TypeCheckWithErrors source [| expectedServerity, expectedErrorNumber, expectedErrorRange, expectedErrorMsg |] let CompileExe (source: string) = compile true source (fun (errors, _) -> diff --git a/tests/fsharp/Compiler/ConstraintSolver/MemberConstraints.fs b/tests/fsharp/Compiler/ConstraintSolver/MemberConstraints.fs new file mode 100644 index 00000000000..d422c9b31fd --- /dev/null +++ b/tests/fsharp/Compiler/ConstraintSolver/MemberConstraints.fs @@ -0,0 +1,45 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace FSharp.Compiler.UnitTests + +open NUnit.Framework +open FSharp.Compiler.SourceCodeServices + +[] +module MemberConstraints = + + [] + let ``we can overload operators on a type and not add all the extra jazz such as inlining and the ^ operator.``() = + CompilerAssert.CompileExeAndRun + """ +type Foo(x : int) = + member this.Val = x + + static member (-->) ((src : Foo), (target : Foo)) = new Foo(src.Val + target.Val) + static member (-->) ((src : Foo), (target : int)) = new Foo(src.Val + target) + + static member (+) ((src : Foo), (target : Foo)) = new Foo(src.Val + target.Val) + static member (+) ((src : Foo), (target : int)) = new Foo(src.Val + target) + +let x = Foo(3) --> 4 +let y = Foo(3) --> Foo(4) +let x2 = Foo(3) + 4 +let y2 = Foo(3) + Foo(4) + +if x.Val <> 7 then exit 1 +if y.Val <> 7 then exit 1 +if x2.Val <> 7 then exit 1 +if y2.Val <> 7 then exit 1 + """ + + [] + let ``Invalid member constraint with ErrorRanges``() = // Regression test for FSharp1.0:2262 + CompilerAssert.TypeCheckSingleErrorWithOptions + [| "--test:ErrorRanges" |] + """ +let inline length (x: ^a) : int = (^a : (member Length : int with get, set) (x, ())) + """ + FSharpErrorSeverity.Error + 697 + (2, 42, 2, 75) + "Invalid constraint" diff --git a/tests/fsharp/Compiler/ConstraintSolver/PrimitiveConstraints.fs b/tests/fsharp/Compiler/ConstraintSolver/PrimitiveConstraints.fs new file mode 100644 index 00000000000..fbfedfb550d --- /dev/null +++ b/tests/fsharp/Compiler/ConstraintSolver/PrimitiveConstraints.fs @@ -0,0 +1,109 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace FSharp.Compiler.UnitTests + +open NUnit.Framework +open FSharp.Compiler.SourceCodeServices + +[] +module PrimitiveConstraints = + + [] + let ``Test primitive : constraints``() = + CompilerAssert.CompileExeAndRun + """ +#light + +type Foo(x : int) = + member this.Value = x + override this.ToString() = "Foo" + +type Bar(x : int) = + inherit Foo(-1) + member this.Value2 = x + override this.ToString() = "Bar" + +let test1 (x : Foo) = x.Value +let test2 (x : Bar) = (x.Value, x.Value2) + +let f = new Foo(128) +let b = new Bar(256) + +if test1 f <> 128 then exit 1 +if test2 b <> (-1, 256) then exit 1 +""" + + [] + let ``Test primitive :> constraints``() = + CompilerAssert.CompileExeAndRun + """ +#light +type Foo(x : int) = + member this.Value = x + override this.ToString() = "Foo" + +type Bar(x : int) = + inherit Foo(-1) + member this.Value2 = x + override this.ToString() = "Bar" + +type Ram(x : int) = + inherit Foo(10) + member this.ValueA = x + override this.ToString() = "Ram" + +let test (x : Foo) = (x.Value, x.ToString()) + +let f = new Foo(128) +let b = new Bar(256) +let r = new Ram(314) + +if test f <> (128, "Foo") then exit 1 +if test b <> (-1, "Bar") then exit 1 +if test r <> (10, "Ram") then exit 1 +""" + + [] + let ``Test primitive : null constraint``() = + CompilerAssert.CompileExeAndRun + """ +let inline isNull<'a when 'a : null> (x : 'a) = + match x with + | null -> "is null" + | _ -> (x :> obj).ToString() + +let runTest = + // Wrapping in try block to work around FSB 1989 + try + if isNull null <> "is null" then exit 1 + if isNull "F#" <> "F#" then exit 1 + true + with _ -> exit 1 + +if runTest <> true then exit 1 + +exit 0 +""" + + [] + /// Title: Type checking oddity + /// + /// This suggestion was resolved as by design, + /// so the test makes sure, we're emitting error message about 'not being a valid object construction expression' + let ``Invalid object constructor``() = // Regression test for FSharp1.0:4189 + CompilerAssert.TypeCheckWithErrorsAndOptions + [| "--test:ErrorRanges" |] + """ +type ImmutableStack<'a> private(items: 'a list) = + + member this.Push item = ImmutableStack(item::items) + member this.Pop = match items with | [] -> failwith "No elements in stack" | x::xs -> x,ImmutableStack(xs) + + // Notice type annotation is commented out, which results in an error + new(col (*: seq<'a>*)) = ImmutableStack(List.ofSeq col) + + """ + [| FSharpErrorSeverity.Error, 41, (4, 29, 4, 56), "A unique overload for method 'ImmutableStack`1' could not be determined based on type information prior to this program point. A type annotation may be needed. Candidates: new : col:'b -> ImmutableStack<'a>, private new : items:'a list -> ImmutableStack<'a>" + FSharpErrorSeverity.Error, 41, (5, 93, 5, 111), "A unique overload for method 'ImmutableStack`1' could not be determined based on type information prior to this program point. A type annotation may be needed. Candidates: new : col:'b -> ImmutableStack<'a>, private new : items:'a list -> ImmutableStack<'a>" + FSharpErrorSeverity.Error, 41, (8, 30, 8, 60), "A unique overload for method 'ImmutableStack`1' could not be determined based on type information prior to this program point. A type annotation may be needed. Candidates: new : col:'b -> ImmutableStack<'a> when 'b :> seq<'c>, private new : items:'a list -> ImmutableStack<'a>" + FSharpErrorSeverity.Error, 696, (8, 30, 8, 60), "This is not a valid object construction expression. Explicit object constructors must either call an alternate constructor or initialize all fields of the object and specify a call to a super class constructor." |] \ No newline at end of file diff --git a/tests/fsharp/FSharpSuite.Tests.fsproj b/tests/fsharp/FSharpSuite.Tests.fsproj index 9291db2f740..2be8d09cd72 100644 --- a/tests/fsharp/FSharpSuite.Tests.fsproj +++ b/tests/fsharp/FSharpSuite.Tests.fsproj @@ -35,6 +35,8 @@ + + diff --git a/tests/fsharpqa/Source/Conformance/InferenceProcedures/ConstraintSolving/E_MemberConstraints01.fs b/tests/fsharpqa/Source/Conformance/InferenceProcedures/ConstraintSolving/E_MemberConstraints01.fs deleted file mode 100644 index 643ec7f7db7..00000000000 --- a/tests/fsharpqa/Source/Conformance/InferenceProcedures/ConstraintSolving/E_MemberConstraints01.fs +++ /dev/null @@ -1,6 +0,0 @@ -// #Regression #Conformance #TypeInference #TypeConstraints -// Regression test for FSharp1.0:2262 -// We should emit an error, not ICE -//Invalid constraint - -let inline length (x: ^a) : int = (^a : (member Length : int with get, set) (x, ())) diff --git a/tests/fsharpqa/Source/Conformance/InferenceProcedures/ConstraintSolving/E_PrimConstraint04.fs b/tests/fsharpqa/Source/Conformance/InferenceProcedures/ConstraintSolving/E_PrimConstraint04.fs deleted file mode 100644 index 08dcbfde122..00000000000 --- a/tests/fsharpqa/Source/Conformance/InferenceProcedures/ConstraintSolving/E_PrimConstraint04.fs +++ /dev/null @@ -1,16 +0,0 @@ -// #Regression #Conformance #TypeInference #TypeConstraints -// Regression test for FSharp1.0:4189 -// Title: Type checking oddity - -// This suggestion was resolved as by design, -// so the test makes sure, we're emitting error message about 'not being avalid object construction expression' - -//This is not a valid object construction expression\. Explicit object constructors must either call an alternate constructor or initialize all fields of the object and specify a call to a super class constructor\.$ - -type ImmutableStack<'a> private(items: 'a list) = - - member this.Push item = ImmutableStack(item::items) - member this.Pop = match items with | [] -> failwith "No elements in stack" | x::xs -> x,ImmutableStack(xs) - - // Notice type annotation is commented out, which results in an error - new(col (*: seq<'a>*)) = ImmutableStack(List.ofSeq col) diff --git a/tests/fsharpqa/Source/Conformance/InferenceProcedures/ConstraintSolving/MemberConstraints01.fs b/tests/fsharpqa/Source/Conformance/InferenceProcedures/ConstraintSolving/MemberConstraints01.fs deleted file mode 100644 index af263142458..00000000000 --- a/tests/fsharpqa/Source/Conformance/InferenceProcedures/ConstraintSolving/MemberConstraints01.fs +++ /dev/null @@ -1,24 +0,0 @@ -// #Conformance #TypeInference #TypeConstraints -// Verify you can overload operators on a type and not add all the extra jazz -// such as inlining and the ^ operator. - -type Foo(x : int) = - member this.Val = x - - static member (-->) ((src : Foo), (target : Foo)) = new Foo(src.Val + target.Val) - static member (-->) ((src : Foo), (target : int)) = new Foo(src.Val + target) - - static member (+) ((src : Foo), (target : Foo)) = new Foo(src.Val + target.Val) - static member (+) ((src : Foo), (target : int)) = new Foo(src.Val + target) - -let x = Foo(3) --> 4 -let y = Foo(3) --> Foo(4) -let x2 = Foo(3) + 4 -let y2 = Foo(3) + Foo(4) - -if x.Val <> 7 then exit 1 -if y.Val <> 7 then exit 1 -if x2.Val <> 7 then exit 1 -if y2.Val <> 7 then exit 1 - -exit 0 diff --git a/tests/fsharpqa/Source/Conformance/InferenceProcedures/ConstraintSolving/PrimConstraint01.fs b/tests/fsharpqa/Source/Conformance/InferenceProcedures/ConstraintSolving/PrimConstraint01.fs deleted file mode 100644 index e9b11b1c99f..00000000000 --- a/tests/fsharpqa/Source/Conformance/InferenceProcedures/ConstraintSolving/PrimConstraint01.fs +++ /dev/null @@ -1,26 +0,0 @@ -// #Conformance #TypeInference #TypeConstraints -#light - -// Test primitive constraints - -// Test ':' constraints - -type Foo(x : int) = - member this.Value = x - override this.ToString() = "Foo" - -type Bar(x : int) = - inherit Foo(-1) - member this.Value2 = x - override this.ToString() = "Bar" - -let test1 (x : Foo) = x.Value -let test2 (x : Bar) = (x.Value, x.Value2) - -let f = new Foo(128) -let b = new Bar(256) - -if test1 f <> 128 then exit 1 -if test2 b <> (-1, 256) then exit 1 - -exit 0 diff --git a/tests/fsharpqa/Source/Conformance/InferenceProcedures/ConstraintSolving/PrimConstraint02.fs b/tests/fsharpqa/Source/Conformance/InferenceProcedures/ConstraintSolving/PrimConstraint02.fs deleted file mode 100644 index b410f4e528f..00000000000 --- a/tests/fsharpqa/Source/Conformance/InferenceProcedures/ConstraintSolving/PrimConstraint02.fs +++ /dev/null @@ -1,33 +0,0 @@ -// #Conformance #TypeInference #TypeConstraints - -#light - -// Test primitive constraints - -// Test ':>' constraints - -type Foo(x : int) = - member this.Value = x - override this.ToString() = "Foo" - -type Bar(x : int) = - inherit Foo(-1) - member this.Value2 = x - override this.ToString() = "Bar" - -type Ram(x : int) = - inherit Foo(10) - member this.ValueA = x - override this.ToString() = "Ram" - -let test (x : Foo) = (x.Value, x.ToString()) - -let f = new Foo(128) -let b = new Bar(256) -let r = new Ram(314) - -if test f <> (128, "Foo") then exit 1 -if test b <> (-1, "Bar") then exit 1 -if test r <> (10, "Ram") then exit 1 - -exit 0 diff --git a/tests/fsharpqa/Source/Conformance/InferenceProcedures/ConstraintSolving/PrimConstraint03.fs b/tests/fsharpqa/Source/Conformance/InferenceProcedures/ConstraintSolving/PrimConstraint03.fs deleted file mode 100644 index 7f9a072fd65..00000000000 --- a/tests/fsharpqa/Source/Conformance/InferenceProcedures/ConstraintSolving/PrimConstraint03.fs +++ /dev/null @@ -1,23 +0,0 @@ -// #Conformance #TypeInference #TypeConstraints -#light - -// Test primitive constraints - -// Test ': null' constraints - -let inline isNull<'a when 'a : null> (x : 'a) = - match x with - | null -> "is null" - | _ -> (x :> obj).ToString() - -let runTest = - // Wrapping in try block to work around FSB 1989 - try - if isNull null <> "is null" then exit 1 - if isNull "F#" <> "F#" then exit 1 - true - with _ -> exit 1 - -if runTest <> true then exit 1 - -exit 0 diff --git a/tests/fsharpqa/Source/Conformance/InferenceProcedures/ConstraintSolving/env.lst b/tests/fsharpqa/Source/Conformance/InferenceProcedures/ConstraintSolving/env.lst index 4b89bcc2ba8..041ba830d0b 100644 --- a/tests/fsharpqa/Source/Conformance/InferenceProcedures/ConstraintSolving/env.lst +++ b/tests/fsharpqa/Source/Conformance/InferenceProcedures/ConstraintSolving/env.lst @@ -1,10 +1,5 @@ SOURCE=E_NoImplicitDowncast01.fs SCFLAGS="--test:ErrorRanges --flaterrors" # E_NoImplicitDowncast01.fs - SOURCE=PrimConstraint01.fs # PrimConstraint01.fs - SOURCE=PrimConstraint02.fs # PrimConstraint02.fs - SOURCE=PrimConstraint03.fs # PrimConstraint03.fs - SOURCE=E_PrimConstraint04.fs SCFLAGS="--test:ErrorRanges" # E_PrimConstraint04.fs - SOURCE=E_TypeFuncDeclaredExplicit01.fs # E_TypeFuncDeclaredExplicit01.fs SOURCE=ValueRestriction01.fs # ValueRestriction01.fs @@ -16,7 +11,4 @@ SOURCE=DelegateConstraint01.fs # DelegateConstraint01.fs SOURCE=E_DelegateConstraint01.fs # E_DelegateConstraint01.fs - SOURCE=MemberConstraints01.fs # MemberConstraints01.fs - SOURCE=E_MemberConstraints01.fs SCFLAGS="--test:ErrorRanges" # E_MemberConstraints01.fs - SOURCE=ConstructorConstraint01.fs # ConstructorConstraint01.fs \ No newline at end of file From a7c68c3aed7980a6220a40738b718a7196de017a Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Tue, 23 Jul 2019 09:48:39 -0700 Subject: [PATCH 34/46] Update dependencies from https://github.com/dotnet/arcade build 20190722.10 (#7268) - Microsoft.DotNet.Arcade.Sdk - 1.0.0-beta.19372.10 --- eng/Version.Details.xml | 4 ++-- eng/common/init-tools-native.ps1 | 8 +++++++- global.json | 2 +- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 7228968c11e..e278bed29a9 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -3,9 +3,9 @@ - + https://github.com/dotnet/arcade - a190d4865fe3c86a168ec49c4fc61c90c96ae051 + 0793e2df782efc9ccae387bc779b2549208fa4a1 diff --git a/eng/common/init-tools-native.ps1 b/eng/common/init-tools-native.ps1 index 9d18645f455..eaa05880c55 100644 --- a/eng/common/init-tools-native.ps1 +++ b/eng/common/init-tools-native.ps1 @@ -103,7 +103,13 @@ try { if ($LASTEXITCODE -Ne "0") { $errMsg = "$ToolName installation failed" if ((Get-Variable 'DoNotAbortNativeToolsInstallationOnFailure' -ErrorAction 'SilentlyContinue') -and $DoNotAbortNativeToolsInstallationOnFailure) { - Write-Warning $errMsg + $showNativeToolsWarning = $true + if ((Get-Variable 'DoNotDisplayNativeToolsInstallationWarnings' -ErrorAction 'SilentlyContinue') -and $DoNotDisplayNativeToolsInstallationWarnings) { + $showNativeToolsWarning = $false + } + if ($showNativeToolsWarning) { + Write-Warning $errMsg + } $toolInstallationFailure = $true } else { Write-Error $errMsg diff --git a/global.json b/global.json index c8c5b129393..1d496dc84bf 100644 --- a/global.json +++ b/global.json @@ -10,7 +10,7 @@ } }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19369.2", + "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19372.10", "Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19069.2" } } From 37970b41db5c858411fc42876233e608844c9f58 Mon Sep 17 00:00:00 2001 From: "Kevin Ransom (msft)" Date: Wed, 24 Jul 2019 18:08:15 -0700 Subject: [PATCH 35/46] fixes issue #6832 (#7259) * fixes issue #6832 * Fix comment * Forgot to remove pdbs from fsharp.compiler.nuget * Rename Program.fs and exclude FSharpSdk from checks * Embedded doesn't need to verify tmp or obj directories. * typo * typo * Don't check FSharpSdk for hash * Make comment match code * Empty commit to force rebuild --- FSharpBuild.Directory.Build.props | 3 +- eng/Build.ps1 | 11 ++-- eng/build-utils.ps1 | 3 +- src/absil/ilwritepdb.fs | 2 +- .../buildtools/AssemblyCheck/AssemblyCheck.fs | 66 +++++++++++++++---- .../AssemblyCheck/AssemblyCheck.fsproj | 17 +++++ src/buildtools/buildtools.proj | 1 + .../Microsoft.FSharp.Compiler.nuspec | 14 +--- .../FSharp.Core.nuget/FSharp.Core.nuspec | 2 - 9 files changed, 86 insertions(+), 33 deletions(-) rename scripts/AssemblyVersionCheck.fsx => src/buildtools/AssemblyCheck/AssemblyCheck.fs (51%) create mode 100644 src/buildtools/AssemblyCheck/AssemblyCheck.fsproj diff --git a/FSharpBuild.Directory.Build.props b/FSharpBuild.Directory.Build.props index 515de9bbdc7..6687fb40888 100644 --- a/FSharpBuild.Directory.Build.props +++ b/FSharpBuild.Directory.Build.props @@ -75,6 +75,7 @@ https://github.com/Microsoft/visualfsharp git + <_DotGitDir>$(RepoRoot).git <_HeadFileContent Condition="Exists('$(_DotGitDir)/HEAD')">$([System.IO.File]::ReadAllText('$(_DotGitDir)/HEAD').Trim()) @@ -87,7 +88,7 @@ $(NoWarn);FS2003 true - portable + embedded fs false true diff --git a/eng/Build.ps1 b/eng/Build.ps1 index f329cba02ac..8011827a643 100644 --- a/eng/Build.ps1 +++ b/eng/Build.ps1 @@ -224,13 +224,14 @@ function UpdatePath() { TestAndAddToPath "$ArtifactsDir\bin\fsiAnyCpu\$configuration\net472" } -function VerifyAssemblyVersions() { - $fsiPath = Join-Path $ArtifactsDir "bin\fsi\Proto\net472\publish\fsi.exe" +function VerifyAssemblyVersionsAndSymbols() { + $assemblyVerCheckPath = Join-Path $ArtifactsDir "Bootstrap\AssemblyCheck\AssemblyCheck.dll" # Only verify versions on CI or official build if ($ci -or $official) { - $asmVerCheckPath = "$RepoRoot\scripts" - Exec-Console $fsiPath """$asmVerCheckPath\AssemblyVersionCheck.fsx"" -- ""$ArtifactsDir""" + $dotnetPath = InitializeDotNetCli + $dotnetExe = Join-Path $dotnetPath "dotnet.exe" + Exec-Console $dotnetExe """$assemblyVerCheckPath"" ""$ArtifactsDir""" } } @@ -307,7 +308,7 @@ try { } if ($build) { - VerifyAssemblyVersions + VerifyAssemblyVersionsAndSymbols } $desktopTargetFramework = "net472" diff --git a/eng/build-utils.ps1 b/eng/build-utils.ps1 index fcda1a58e26..772de110ca2 100644 --- a/eng/build-utils.ps1 +++ b/eng/build-utils.ps1 @@ -236,10 +236,11 @@ function Make-BootstrapBuild() { Remove-Item -re $dir -ErrorAction SilentlyContinue Create-Directory $dir - # prepare FsLex and Fsyacc + # prepare FsLex and Fsyacc and AssemblyCheck Run-MSBuild "$RepoRoot\src\buildtools\buildtools.proj" "/restore /t:Publish" -logFileName "BuildTools" -configuration $bootstrapConfiguration Copy-Item "$ArtifactsDir\bin\fslex\$bootstrapConfiguration\netcoreapp2.1\publish" -Destination "$dir\fslex" -Force -Recurse Copy-Item "$ArtifactsDir\bin\fsyacc\$bootstrapConfiguration\netcoreapp2.1\publish" -Destination "$dir\fsyacc" -Force -Recurse + Copy-Item "$ArtifactsDir\bin\AssemblyCheck\$bootstrapConfiguration\netcoreapp2.1\publish" -Destination "$dir\AssemblyCheck" -Force -Recurse # prepare compiler $projectPath = "$RepoRoot\proto.proj" diff --git a/src/absil/ilwritepdb.fs b/src/absil/ilwritepdb.fs index c1ffd692249..86b7ee9224f 100644 --- a/src/absil/ilwritepdb.fs +++ b/src/absil/ilwritepdb.fs @@ -186,7 +186,7 @@ let pdbGetEmbeddedPdbDebugInfo (embeddedPdbChunk: BinaryChunk) (uncompressedLeng Buffer.BlockCopy(stream.ToArray(), 0, buffer, offset, size) buffer { iddCharacteristics = 0 // Reserved - iddMajorVersion = 0 // VersionMajor should be 0 + iddMajorVersion = 0x0100 // VersionMajor should be 0x0100 iddMinorVersion = 0x0100 // VersionMinor should be 0x0100 iddType = 17 // IMAGE_DEBUG_TYPE_EMBEDDEDPDB iddTimestamp = 0 diff --git a/scripts/AssemblyVersionCheck.fsx b/src/buildtools/AssemblyCheck/AssemblyCheck.fs similarity index 51% rename from scripts/AssemblyVersionCheck.fsx rename to src/buildtools/AssemblyCheck/AssemblyCheck.fs index 0f3816a2e6c..c6bd035a673 100644 --- a/scripts/AssemblyVersionCheck.fsx +++ b/src/buildtools/AssemblyCheck/AssemblyCheck.fs @@ -1,22 +1,50 @@ -// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. open System open System.Diagnostics open System.IO open System.Reflection +open System.Reflection.PortableExecutable open System.Text.RegularExpressions -module AssemblyVersionCheck = +module AssemblyCheck = let private versionZero = Version(0, 0, 0, 0) let private versionOne = Version(1, 0, 0, 0) let private commitHashPattern = new Regex(@"Commit Hash: ()|([0-9a-fA-F]{40})", RegexOptions.Compiled) let private devVersionPattern = new Regex(@"-(ci|dev)", RegexOptions.Compiled) - let verifyAssemblyVersions (binariesPath:string) = + let verifyEmbeddedPdb (filename:string) = + use fileStream = File.OpenRead(filename) + let reader = new PEReader(fileStream) + let mutable hasEmbeddedPdb = false + + try + for entry in reader.ReadDebugDirectory() do + match entry.Type with + | DebugDirectoryEntryType.CodeView -> + let _ = reader.ReadCodeViewDebugDirectoryData(entry) + () + + | DebugDirectoryEntryType.EmbeddedPortablePdb -> + let _ = reader.ReadEmbeddedPortablePdbDebugDirectoryData(entry) + hasEmbeddedPdb <- true + () + + | DebugDirectoryEntryType.PdbChecksum -> + let _ = reader.ReadPdbChecksumDebugDirectoryData(entry) + () + + | _ -> () + with | e -> printfn "Error validating assembly %s\nMessage: %s" filename (e.ToString()) + hasEmbeddedPdb + + let verifyAssemblies (binariesPath:string) = + let excludedAssemblies = [ "FSharp.Data.TypeProviders.dll" ] |> Set.ofList + let fsharpAssemblies = [ "FSharp*.dll" "fsc.exe" @@ -28,12 +56,17 @@ module AssemblyVersionCheck = |> List.ofSeq |> List.filter (fun p -> (Set.contains (Path.GetFileName(p)) excludedAssemblies) |> not) + let fsharpExecutingWithEmbeddedPdbs = + fsharpAssemblies + |> List.filter (fun p -> not (p.Contains(@"\Proto\") || p.Contains(@"\Bootstrap\") || p.Contains(@".resources.") || p.Contains(@"\FSharpSdk\") || p.Contains(@"\tmp\") || p.Contains(@"\obj\"))) + // verify that all assemblies have a version number other than 0.0.0.0 or 1.0.0.0 let failedVersionCheck = fsharpAssemblies |> List.filter (fun a -> let assemblyVersion = AssemblyName.GetAssemblyName(a).Version assemblyVersion = versionZero || assemblyVersion = versionOne) + if failedVersionCheck.Length > 0 then printfn "The following assemblies had a version of %A or %A" versionZero versionOne printfn "%s\r\n" <| String.Join("\r\n", failedVersionCheck) @@ -43,27 +76,36 @@ module AssemblyVersionCheck = // verify that all assemblies have a commit hash let failedCommitHash = fsharpAssemblies + |> List.filter (fun p -> not (p.Contains(@"\FSharpSdk\"))) |> List.filter (fun a -> let fileProductVersion = FileVersionInfo.GetVersionInfo(a).ProductVersion not (commitHashPattern.IsMatch(fileProductVersion) || devVersionPattern.IsMatch(fileProductVersion))) + if failedCommitHash.Length > 0 then printfn "The following assemblies don't have a commit hash set" printfn "%s\r\n" <| String.Join("\r\n", failedCommitHash) else printfn "All shipping assemblies had an appropriate commit hash." + // verify that all assemblies have an embedded pdb + let failedVerifyEmbeddedPdb = + fsharpExecutingWithEmbeddedPdbs + |> List.filter (fun a -> not (verifyEmbeddedPdb a)) + + if failedVerifyEmbeddedPdb.Length > 0 then + printfn "The following assemblies don't have an embedded pdb" + printfn "%s\r\n" <| String.Join("\r\n", failedVerifyEmbeddedPdb) + else + printfn "All shipping assemblies had an embedded PDB." + // return code is the number of failures - failedVersionCheck.Length + failedCommitHash.Length + failedVersionCheck.Length + failedCommitHash.Length + failedVerifyEmbeddedPdb.Length + +[] let main (argv:string array) = if argv.Length <> 1 then - printfn "Usage: fsi.exe AssemblyVersionCheck.fsx -- path/to/binaries" + printfn "Usage: dotnet AssemblyCheck.dll -- path/to/binaries" 1 else - AssemblyVersionCheck.verifyAssemblyVersions argv.[0] - -Environment.GetCommandLineArgs() -|> Seq.skipWhile ((<>) "--") -|> Seq.skip 1 -|> Array.ofSeq -|> main + AssemblyCheck.verifyAssemblies argv.[0] diff --git a/src/buildtools/AssemblyCheck/AssemblyCheck.fsproj b/src/buildtools/AssemblyCheck/AssemblyCheck.fsproj new file mode 100644 index 00000000000..72f79d02f93 --- /dev/null +++ b/src/buildtools/AssemblyCheck/AssemblyCheck.fsproj @@ -0,0 +1,17 @@ + + + + Exe + netcoreapp2.1 + true + + + + + + + + + + + diff --git a/src/buildtools/buildtools.proj b/src/buildtools/buildtools.proj index 630bb678561..7ac48ba2a37 100644 --- a/src/buildtools/buildtools.proj +++ b/src/buildtools/buildtools.proj @@ -8,6 +8,7 @@ + diff --git a/src/fsharp/FSharp.Compiler.nuget/Microsoft.FSharp.Compiler.nuspec b/src/fsharp/FSharp.Compiler.nuget/Microsoft.FSharp.Compiler.nuspec index d3756ebc392..a82fbb1ac3e 100644 --- a/src/fsharp/FSharp.Compiler.nuget/Microsoft.FSharp.Compiler.nuspec +++ b/src/fsharp/FSharp.Compiler.nuget/Microsoft.FSharp.Compiler.nuspec @@ -49,15 +49,7 @@ - - - - - - - + target="lib\netcoreapp2.1" /> @@ -69,9 +61,9 @@ + target="lib\netcoreapp2.1" /> + target="lib\netcoreapp2.1" /> diff --git a/src/fsharp/FSharp.Core.nuget/FSharp.Core.nuspec b/src/fsharp/FSharp.Core.nuget/FSharp.Core.nuspec index 750052c45db..ee7a88b29d6 100644 --- a/src/fsharp/FSharp.Core.nuget/FSharp.Core.nuspec +++ b/src/fsharp/FSharp.Core.nuget/FSharp.Core.nuspec @@ -38,13 +38,11 @@ - - From 8e843ae254c7c1e2fd29dbe23e0b45e5fbf514d2 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Thu, 25 Jul 2019 17:47:38 -0700 Subject: [PATCH 36/46] [master] Update dependencies from dotnet/arcade (#7269) * Update dependencies from https://github.com/dotnet/arcade build 20190723.6 - Microsoft.DotNet.Arcade.Sdk - 1.0.0-beta.19373.6 * Update dependencies from https://github.com/dotnet/arcade build 20190724.2 - Microsoft.DotNet.Arcade.Sdk - 1.0.0-beta.19374.2 * Update dependencies from https://github.com/dotnet/arcade build 20190725.2 - Microsoft.DotNet.Arcade.Sdk - 1.0.0-beta.19375.2 --- eng/Version.Details.xml | 4 +-- eng/common/build.sh | 0 eng/common/cibuild.sh | 0 eng/common/cross/armel/tizen-build-rootfs.sh | 0 eng/common/cross/armel/tizen-fetch.sh | 0 eng/common/cross/build-android-rootfs.sh | 0 eng/common/cross/build-rootfs.sh | 0 eng/common/darc-init.sh | 0 eng/common/dotnet-install.sh | 0 eng/common/init-tools-native.sh | 0 eng/common/internal-feed-operations.sh | 0 eng/common/msbuild.sh | 0 eng/common/native/common-library.sh | 0 eng/common/native/install-cmake.sh | 0 eng/common/performance/performance-setup.sh | 0 eng/common/pipeline-logging-functions.sh | 0 eng/common/post-build/darc-gather-drop.ps1 | 36 +++++++++++++++++++ .../channels/internal-servicing.yml | 23 ------------ .../channels/public-dev-release.yml | 24 ++----------- .../post-build/channels/public-release.yml | 23 ------------ .../channels/public-validation-release.yml | 26 ++------------ .../templates/post-build/darc-gather-drop.yml | 22 ++++++++++++ .../post-build/trigger-subscription.yml | 2 +- eng/common/tools.sh | 0 global.json | 2 +- 25 files changed, 68 insertions(+), 94 deletions(-) mode change 100644 => 100755 eng/common/build.sh mode change 100644 => 100755 eng/common/cibuild.sh mode change 100644 => 100755 eng/common/cross/armel/tizen-build-rootfs.sh mode change 100644 => 100755 eng/common/cross/armel/tizen-fetch.sh mode change 100644 => 100755 eng/common/cross/build-android-rootfs.sh mode change 100644 => 100755 eng/common/cross/build-rootfs.sh mode change 100644 => 100755 eng/common/darc-init.sh mode change 100644 => 100755 eng/common/dotnet-install.sh mode change 100644 => 100755 eng/common/init-tools-native.sh mode change 100644 => 100755 eng/common/internal-feed-operations.sh mode change 100644 => 100755 eng/common/msbuild.sh mode change 100644 => 100755 eng/common/native/common-library.sh mode change 100644 => 100755 eng/common/native/install-cmake.sh mode change 100644 => 100755 eng/common/performance/performance-setup.sh mode change 100644 => 100755 eng/common/pipeline-logging-functions.sh create mode 100644 eng/common/post-build/darc-gather-drop.ps1 create mode 100644 eng/common/templates/post-build/darc-gather-drop.yml mode change 100644 => 100755 eng/common/tools.sh diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index e278bed29a9..1ed95d393af 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -3,9 +3,9 @@ - + https://github.com/dotnet/arcade - 0793e2df782efc9ccae387bc779b2549208fa4a1 + 3dfa62fddcde597959c323d17426f215384e773a diff --git a/eng/common/build.sh b/eng/common/build.sh old mode 100644 new mode 100755 diff --git a/eng/common/cibuild.sh b/eng/common/cibuild.sh old mode 100644 new mode 100755 diff --git a/eng/common/cross/armel/tizen-build-rootfs.sh b/eng/common/cross/armel/tizen-build-rootfs.sh old mode 100644 new mode 100755 diff --git a/eng/common/cross/armel/tizen-fetch.sh b/eng/common/cross/armel/tizen-fetch.sh old mode 100644 new mode 100755 diff --git a/eng/common/cross/build-android-rootfs.sh b/eng/common/cross/build-android-rootfs.sh old mode 100644 new mode 100755 diff --git a/eng/common/cross/build-rootfs.sh b/eng/common/cross/build-rootfs.sh old mode 100644 new mode 100755 diff --git a/eng/common/darc-init.sh b/eng/common/darc-init.sh old mode 100644 new mode 100755 diff --git a/eng/common/dotnet-install.sh b/eng/common/dotnet-install.sh old mode 100644 new mode 100755 diff --git a/eng/common/init-tools-native.sh b/eng/common/init-tools-native.sh old mode 100644 new mode 100755 diff --git a/eng/common/internal-feed-operations.sh b/eng/common/internal-feed-operations.sh old mode 100644 new mode 100755 diff --git a/eng/common/msbuild.sh b/eng/common/msbuild.sh old mode 100644 new mode 100755 diff --git a/eng/common/native/common-library.sh b/eng/common/native/common-library.sh old mode 100644 new mode 100755 diff --git a/eng/common/native/install-cmake.sh b/eng/common/native/install-cmake.sh old mode 100644 new mode 100755 diff --git a/eng/common/performance/performance-setup.sh b/eng/common/performance/performance-setup.sh old mode 100644 new mode 100755 diff --git a/eng/common/pipeline-logging-functions.sh b/eng/common/pipeline-logging-functions.sh old mode 100644 new mode 100755 diff --git a/eng/common/post-build/darc-gather-drop.ps1 b/eng/common/post-build/darc-gather-drop.ps1 new file mode 100644 index 00000000000..9cc2f1a0091 --- /dev/null +++ b/eng/common/post-build/darc-gather-drop.ps1 @@ -0,0 +1,36 @@ +param( + [Parameter(Mandatory=$true)][string] $BarBuildId, # ID of the build which assets should be downloaded + [Parameter(Mandatory=$true)][string] $MaestroAccessToken, # Token used to access Maestro API + [Parameter(Mandatory=$true)][string] $DropLocation # Where the assets should be downloaded to +) + +$ErrorActionPreference = "Stop" +Set-StrictMode -Version 2.0 + +. $PSScriptRoot\..\tools.ps1 + +try { + Write-Host "Installing DARC ..." + + . $PSScriptRoot\..\darc-init.ps1 + $exitCode = $LASTEXITCODE + + if ($exitCode -ne 0) { + Write-PipelineTaskError "Something failed while running 'darc-init.ps1'. Check for errors above. Exiting now..." + ExitWithExitCode $exitCode + } + + darc gather-drop --non-shipping ` + --continue-on-error ` + --id $BarBuildId ` + --output-dir $DropLocation ` + --bar-uri https://maestro-prod.westus2.cloudapp.azure.com/ ` + --password $MaestroAccessToken ` + --latest-location +} +catch { + Write-Host $_ + Write-Host $_.Exception + Write-Host $_.ScriptStackTrace + ExitWithExitCode 1 +} diff --git a/eng/common/templates/post-build/channels/internal-servicing.yml b/eng/common/templates/post-build/channels/internal-servicing.yml index 648e854e0ed..5c07b66926f 100644 --- a/eng/common/templates/post-build/channels/internal-servicing.yml +++ b/eng/common/templates/post-build/channels/internal-servicing.yml @@ -143,29 +143,6 @@ stages: filePath: $(Build.SourcesDirectory)/eng/common/post-build/symbols-validation.ps1 arguments: -InputPath $(Build.ArtifactStagingDirectory)/PackageArtifacts/ -ExtractPath $(Agent.BuildDirectory)/Temp/ -DotnetSymbolVersion $(SymbolToolVersion) - - job: - displayName: Gather Drop - dependsOn: setupMaestroVars - variables: - BARBuildId: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ] - condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], variables.InternalServicing_30_Channel_Id) - pool: - vmImage: 'windows-2019' - steps: - - task: PowerShell@2 - displayName: Setup Darc CLI - inputs: - targetType: filePath - filePath: '$(Build.SourcesDirectory)/eng/common/darc-init.ps1' - - - task: PowerShell@2 - displayName: Run Darc gather-drop - inputs: - targetType: inline - script: | - darc gather-drop --non-shipping --continue-on-error --id $(BARBuildId) --output-dir $(Agent.BuildDirectory)/Temp/Drop/ --bar-uri https://maestro-prod.westus2.cloudapp.azure.com/ --password $(MaestroAccessToken) --latest-location - enabled: false - - template: ../promote-build.yml parameters: ChannelId: ${{ variables.InternalServicing_30_Channel_Id }} diff --git a/eng/common/templates/post-build/channels/public-dev-release.yml b/eng/common/templates/post-build/channels/public-dev-release.yml index bdc631016b6..b46b0699233 100644 --- a/eng/common/templates/post-build/channels/public-dev-release.yml +++ b/eng/common/templates/post-build/channels/public-dev-release.yml @@ -140,27 +140,9 @@ stages: filePath: $(Build.SourcesDirectory)/eng/common/post-build/symbols-validation.ps1 arguments: -InputPath $(Build.ArtifactStagingDirectory)/PackageArtifacts/ -ExtractPath $(Agent.BuildDirectory)/Temp/ -DotnetSymbolVersion $(SymbolToolVersion) - - job: - displayName: Gather Drop - dependsOn: setupMaestroVars - variables: - BARBuildId: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ] - condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], variables.PublicDevRelease_30_Channel_Id) - pool: - vmImage: 'windows-2019' - steps: - - task: PowerShell@2 - displayName: Setup Darc CLI - inputs: - targetType: filePath - filePath: '$(Build.SourcesDirectory)/eng/common/darc-init.ps1' - - - task: PowerShell@2 - displayName: Run Darc gather-drop - inputs: - targetType: inline - script: | - darc gather-drop --non-shipping --continue-on-error --id $(BARBuildId) --output-dir $(Agent.BuildDirectory)/Temp/Drop/ --bar-uri https://maestro-prod.westus2.cloudapp.azure.com/ --password $(MaestroAccessToken) --latest-location + - template: ../darc-gather-drop.yml + parameters: + ChannelId: ${{ variables.PublicDevRelease_30_Channel_Id }} - template: ../promote-build.yml parameters: diff --git a/eng/common/templates/post-build/channels/public-release.yml b/eng/common/templates/post-build/channels/public-release.yml index f6a7efdfe9d..a31d37139b7 100644 --- a/eng/common/templates/post-build/channels/public-release.yml +++ b/eng/common/templates/post-build/channels/public-release.yml @@ -143,29 +143,6 @@ stages: filePath: $(Build.SourcesDirectory)/eng/common/post-build/symbols-validation.ps1 arguments: -InputPath $(Build.ArtifactStagingDirectory)/PackageArtifacts/ -ExtractPath $(Agent.BuildDirectory)/Temp/ -DotnetSymbolVersion $(SymbolToolVersion) - - job: - displayName: Gather Drop - dependsOn: setupMaestroVars - variables: - BARBuildId: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ] - condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], variables.PublicRelease_30_Channel_Id) - pool: - vmImage: 'windows-2019' - steps: - - task: PowerShell@2 - displayName: Setup Darc CLI - inputs: - targetType: filePath - filePath: '$(Build.SourcesDirectory)/eng/common/darc-init.ps1' - - - task: PowerShell@2 - displayName: Run Darc gather-drop - inputs: - targetType: inline - script: | - darc gather-drop --non-shipping --continue-on-error --id $(BARBuildId) --output-dir $(Agent.BuildDirectory)/Temp/Drop/ --bar-uri https://maestro-prod.westus2.cloudapp.azure.com/ --password $(MaestroAccessToken) --latest-location - enabled: false - - template: ../promote-build.yml parameters: ChannelId: ${{ variables.PublicRelease_30_Channel_Id }} diff --git a/eng/common/templates/post-build/channels/public-validation-release.yml b/eng/common/templates/post-build/channels/public-validation-release.yml index f12f402ad9a..02dae0937da 100644 --- a/eng/common/templates/post-build/channels/public-validation-release.yml +++ b/eng/common/templates/post-build/channels/public-validation-release.yml @@ -91,29 +91,9 @@ stages: jobs: - template: ../setup-maestro-vars.yml - - job: - displayName: Gather Drop - dependsOn: setupMaestroVars - condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], variables.PublicValidationRelease_30_Channel_Id) - variables: - - name: BARBuildId - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ] - - group: Publish-Build-Assets - pool: - vmImage: 'windows-2019' - steps: - - task: PowerShell@2 - displayName: Setup Darc CLI - inputs: - targetType: filePath - filePath: '$(Build.SourcesDirectory)/eng/common/darc-init.ps1' - - - task: PowerShell@2 - displayName: Run Darc gather-drop - inputs: - targetType: inline - script: | - darc gather-drop --non-shipping --continue-on-error --id $(BARBuildId) --output-dir $(Agent.BuildDirectory)/Temp/Drop/ --bar-uri https://maestro-prod.westus2.cloudapp.azure.com --password $(MaestroAccessToken) --latest-location + - template: ../darc-gather-drop.yml + parameters: + ChannelId: ${{ variables.PublicValidationRelease_30_Channel_Id }} - template: ../promote-build.yml parameters: diff --git a/eng/common/templates/post-build/darc-gather-drop.yml b/eng/common/templates/post-build/darc-gather-drop.yml new file mode 100644 index 00000000000..e0a9f0a6d26 --- /dev/null +++ b/eng/common/templates/post-build/darc-gather-drop.yml @@ -0,0 +1,22 @@ +parameters: + ChannelId: 0 + +jobs: +- job: gatherDrop + displayName: Gather Drop + dependsOn: setupMaestroVars + condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], ${{ parameters.ChannelId }}) + variables: + - group: Publish-Build-Assets + - name: BARBuildId + value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ] + pool: + vmImage: 'windows-2019' + steps: + - task: PowerShell@2 + displayName: Darc gather-drop + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/post-build/darc-gather-drop.ps1 + arguments: -BarBuildId $(BARBuildId) + -DropLocation $(Agent.BuildDirectory)/Temp/Drop/ + -MaestroAccessToken $(MaestroAccessToken) diff --git a/eng/common/templates/post-build/trigger-subscription.yml b/eng/common/templates/post-build/trigger-subscription.yml index 65259d4e685..3915cdcd1ad 100644 --- a/eng/common/templates/post-build/trigger-subscription.yml +++ b/eng/common/templates/post-build/trigger-subscription.yml @@ -8,4 +8,4 @@ steps: filePath: $(Build.SourcesDirectory)/eng/common/post-build/trigger-subscriptions.ps1 arguments: -SourceRepo $(Build.Repository.Uri) -ChannelId ${{ parameters.ChannelId }} - -BarToken $(MaestroAccessTokenInt) \ No newline at end of file + -BarToken $(MaestroAccessToken) diff --git a/eng/common/tools.sh b/eng/common/tools.sh old mode 100644 new mode 100755 diff --git a/global.json b/global.json index 1d496dc84bf..ef694a9855a 100644 --- a/global.json +++ b/global.json @@ -10,7 +10,7 @@ } }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19372.10", + "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19375.2", "Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19069.2" } } From ce483c0e01625949a49aeb45c97d87d0549773c5 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Fri, 26 Jul 2019 12:37:13 -0700 Subject: [PATCH 37/46] Update dependencies from https://github.com/dotnet/arcade build 20190725.15 (#7282) - Microsoft.DotNet.Arcade.Sdk - 1.0.0-beta.19375.15 --- eng/Version.Details.xml | 4 +-- eng/common/init-tools-native.ps1 | 2 +- eng/common/native/CommonLibrary.psm1 | 33 +++++++++++++++++-- .../channels/public-dev-release.yml | 2 +- .../channels/public-validation-release.yml | 2 +- eng/common/tools.sh | 4 +-- global.json | 2 +- 7 files changed, 39 insertions(+), 10 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 1ed95d393af..7a0a634b410 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -3,9 +3,9 @@ - + https://github.com/dotnet/arcade - 3dfa62fddcde597959c323d17426f215384e773a + ef1c110152df0d500fffb87878a86f88d1ca5295 diff --git a/eng/common/init-tools-native.ps1 b/eng/common/init-tools-native.ps1 index eaa05880c55..8cf18bcfeba 100644 --- a/eng/common/init-tools-native.ps1 +++ b/eng/common/init-tools-native.ps1 @@ -98,7 +98,7 @@ try { } Write-Verbose "Installing $ToolName version $ToolVersion" - Write-Verbose "Executing '$InstallerPath $LocalInstallerArguments'" + Write-Verbose "Executing '$InstallerPath $($LocalInstallerArguments.Keys.ForEach({"-$_ '$($LocalInstallerArguments.$_)'"}) -join ' ')'" & $InstallerPath @LocalInstallerArguments if ($LASTEXITCODE -Ne "0") { $errMsg = "$ToolName installation failed" diff --git a/eng/common/native/CommonLibrary.psm1 b/eng/common/native/CommonLibrary.psm1 index 7a34c7e8a42..2a08d5246e7 100644 --- a/eng/common/native/CommonLibrary.psm1 +++ b/eng/common/native/CommonLibrary.psm1 @@ -59,9 +59,38 @@ function DownloadAndExtract { -Verbose:$Verbose if ($UnzipStatus -Eq $False) { - Write-Error "Unzip failed" - return $False + # Retry Download one more time with Force=true + $DownloadRetryStatus = CommonLibrary\Get-File -Uri $Uri ` + -Path $TempToolPath ` + -DownloadRetries 1 ` + -RetryWaitTimeInSeconds $RetryWaitTimeInSeconds ` + -Force:$True ` + -Verbose:$Verbose + + if ($DownloadRetryStatus -Eq $False) { + Write-Error "Last attempt of download failed as well" + return $False + } + + # Retry unzip again one more time with Force=true + $UnzipRetryStatus = CommonLibrary\Expand-Zip -ZipPath $TempToolPath ` + -OutputDirectory $InstallDirectory ` + -Force:$True ` + -Verbose:$Verbose + if ($UnzipRetryStatus -Eq $False) + { + Write-Error "Last attempt of unzip failed as well" + # Clean up partial zips and extracts + if (Test-Path $TempToolPath) { + Remove-Item $TempToolPath -Force + } + if (Test-Path $InstallDirectory) { + Remove-Item $InstallDirectory -Force -Recurse + } + return $False + } } + return $True } diff --git a/eng/common/templates/post-build/channels/public-dev-release.yml b/eng/common/templates/post-build/channels/public-dev-release.yml index b46b0699233..4eaa6e4ff0f 100644 --- a/eng/common/templates/post-build/channels/public-dev-release.yml +++ b/eng/common/templates/post-build/channels/public-dev-release.yml @@ -77,7 +77,7 @@ stages: filePath: eng\common\sdk-task.ps1 arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet /p:ChannelId=$(PublicDevRelease_30_Channel_Id) - /p:ArtifactsCategory=.NetCore + /p:ArtifactsCategory=$(_DotNetArtifactsCategory) /p:IsStableBuild=$(IsStableBuild) /p:IsInternalBuild=$(IsInternalBuild) /p:RepositoryName=$(Build.Repository.Name) diff --git a/eng/common/templates/post-build/channels/public-validation-release.yml b/eng/common/templates/post-build/channels/public-validation-release.yml index 02dae0937da..8c4d8f6ef33 100644 --- a/eng/common/templates/post-build/channels/public-validation-release.yml +++ b/eng/common/templates/post-build/channels/public-validation-release.yml @@ -48,7 +48,7 @@ stages: filePath: eng\common\sdk-task.ps1 arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet /p:ChannelId=$(PublicValidationRelease_30_Channel_Id) - /p:ArtifactsCategory=.NetCoreValidation + /p:ArtifactsCategory=$(_DotNetArtifactsCategory) /p:IsStableBuild=$(IsStableBuild) /p:IsInternalBuild=$(IsInternalBuild) /p:RepositoryName=$(Build.Repository.Name) diff --git a/eng/common/tools.sh b/eng/common/tools.sh index 0deb01c480b..738bb5669da 100755 --- a/eng/common/tools.sh +++ b/eng/common/tools.sh @@ -77,7 +77,7 @@ function ReadGlobalVersion { local pattern="\"$key\" *: *\"(.*)\"" if [[ ! $line =~ $pattern ]]; then - Write-PipelineTelemetryError -category 'InitializeTools' "Error: Cannot find \"$key\" in $global_json_file" + Write-PipelineTelemetryError -category 'InitializeToolset' "Error: Cannot find \"$key\" in $global_json_file" ExitWithExitCode 1 fi @@ -245,7 +245,7 @@ function InitializeNativeTools() { then local nativeArgs="" if [[ "$ci" == true ]]; then - nativeArgs="-InstallDirectory $tools_dir" + nativeArgs="--installDirectory $tools_dir" fi "$_script_dir/init-tools-native.sh" $nativeArgs fi diff --git a/global.json b/global.json index ef694a9855a..67df8eb1531 100644 --- a/global.json +++ b/global.json @@ -10,7 +10,7 @@ } }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19375.2", + "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19375.15", "Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19069.2" } } From 969a9c4661b277093aedf804e92d68532f991b92 Mon Sep 17 00:00:00 2001 From: "Kevin Ransom (msft)" Date: Fri, 26 Jul 2019 15:42:35 -0700 Subject: [PATCH 38/46] Fix test assert (#7283) --- tests/fsharp/Compiler/CompilerAssert.fs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/fsharp/Compiler/CompilerAssert.fs b/tests/fsharp/Compiler/CompilerAssert.fs index 9f64824bb48..c663e9b9c29 100644 --- a/tests/fsharp/Compiler/CompilerAssert.fs +++ b/tests/fsharp/Compiler/CompilerAssert.fs @@ -290,8 +290,10 @@ let main argv = 0""" Assert.AreEqual(expectedErrorMessage, errorMessage) ) - let ParseWithErrors (source: string) expectedParseErrors = - let parseResults = checker.ParseFile("test.fs", SourceText.ofString source, FSharpParsingOptions.Default) |> Async.RunSynchronously + let ParseWithErrors (source: string) expectedParseErrors = + let sourceFileName = "test.fs" + let parsingOptions = { FSharpParsingOptions.Default with SourceFiles = [| sourceFileName |] } + let parseResults = checker.ParseFile(sourceFileName, SourceText.ofString source, parsingOptions) |> Async.RunSynchronously Assert.True(parseResults.ParseHadErrors) From c03755fa47fe9660b40394b3e45779b9e02e409b Mon Sep 17 00:00:00 2001 From: Kevin Ransom Date: Fri, 26 Jul 2019 21:31:00 -0700 Subject: [PATCH 39/46] disablewarningtests --- .../ErrorMessages/WarnExpressionTests.fs | 45 +++++++++++-------- 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/tests/fsharp/Compiler/ErrorMessages/WarnExpressionTests.fs b/tests/fsharp/Compiler/ErrorMessages/WarnExpressionTests.fs index 557aa81a4d4..7bf6cc211c1 100644 --- a/tests/fsharp/Compiler/ErrorMessages/WarnExpressionTests.fs +++ b/tests/fsharp/Compiler/ErrorMessages/WarnExpressionTests.fs @@ -105,9 +105,10 @@ let changeX() = (6, 5, 6, 15) "The result of this equality expression has type 'bool' and is implicitly discarded. Consider using 'let' to bind the result to a name, e.g. 'let result = expression'." - [] + // [] // Disable this test until we refactor tcImports and tcGlobals let ``Warn If Discarded In List``() = - CompilerAssert.TypeCheckSingleError + CompilerAssert.TypeCheckWithErrorsAndOptions + [| "--langversion:4.6" |] """ let div _ _ = 1 let subView _ _ = [1; 2] @@ -119,14 +120,17 @@ let view model dispatch = div [] [] ] """ - FSharpErrorSeverity.Warning - 3221 - (9, 8, 9, 17) - "This expression returns a value of type 'int' but is implicitly discarded. Consider using 'let' to bind the result to a name, e.g. 'let result = expression'. If you intended to use the expression as a value in the sequence then use an explicit 'yield'." + [| + FSharpErrorSeverity.Warning, + 3221, + (9, 8, 9, 17), + "This expression returns a value of type 'int' but is implicitly discarded. Consider using 'let' to bind the result to a name, e.g. 'let result = expression'. If you intended to use the expression as a value in the sequence then use an explicit 'yield'." + |] - [] + // [] // Disable this test until we refactor tcImports and tcGlobals let ``Warn If Discarded In List 2``() = - CompilerAssert.TypeCheckSingleError + CompilerAssert.TypeCheckWithErrorsAndOptions + [| "--langversion:4.6" |] """ // stupid things to make the sample compile let div _ _ = 1 @@ -143,14 +147,17 @@ let view model dispatch = ] ] """ - FSharpErrorSeverity.Warning - 3222 - (13, 19, 13, 41) - "This expression returns a value of type 'int list' but is implicitly discarded. Consider using 'let' to bind the result to a name, e.g. 'let result = expression'. If you intended to use the expression as a value in the sequence then use an explicit 'yield!'." + [| + FSharpErrorSeverity.Warning, + 3222, + (13, 19, 13, 41), + "This expression returns a value of type 'int list' but is implicitly discarded. Consider using 'let' to bind the result to a name, e.g. 'let result = expression'. If you intended to use the expression as a value in the sequence then use an explicit 'yield!'." + |] - [] + // [] // Disable this test until we refactor tcImports and tcGlobals let ``Warn If Discarded In List 3``() = - CompilerAssert.TypeCheckSingleError + CompilerAssert.TypeCheckWithErrorsAndOptions + [| "--langversion:4.6" |] """ // stupid things to make the sample compile let div _ _ = 1 @@ -167,10 +174,12 @@ let view model dispatch = ] ] """ - FSharpErrorSeverity.Warning - 20 - (13, 19, 13, 41) - "The result of this expression has type 'bool' and is implicitly ignored. Consider using 'ignore' to discard this value explicitly, e.g. 'expr |> ignore', or 'let' to bind the result to a name, e.g. 'let result = expr'." + [| + FSharpErrorSeverity.Warning, + 20, + (13, 19, 13, 41), + "The result of this expression has type 'bool' and is implicitly ignored. Consider using 'ignore' to discard this value explicitly, e.g. 'expr |> ignore', or 'let' to bind the result to a name, e.g. 'let result = expr'." + |] [] let ``Warn Only On Last Expression``() = From cc60ed6fca25126b856db939afc43c4ca3cfe48d Mon Sep 17 00:00:00 2001 From: Don Syme Date: Sat, 27 Jul 2019 19:25:06 +0100 Subject: [PATCH 40/46] code cleanup prior to optional interop improvements (#7276) * add test cases we need to make work * cleanup method call argument processing --- src/fsharp/ConstraintSolver.fs | 2 +- src/fsharp/MethodCalls.fs | 451 +++++++++++--- src/fsharp/TastOps.fs | 35 +- src/fsharp/TastOps.fsi | 11 +- src/fsharp/TypeChecker.fs | 553 +++++------------- src/fsharp/xlf/FSComp.txt.es.xlf | 2 +- tests/fsharp/core/fsfromfsviacs/lib3.cs | 26 + tests/fsharp/core/fsfromfsviacs/test.fsx | 63 +- ...osoft.VisualStudio.Editors.Designer.cs.xlf | 3 +- ...osoft.VisualStudio.Editors.Designer.de.xlf | 3 +- ...osoft.VisualStudio.Editors.Designer.es.xlf | 3 +- ...osoft.VisualStudio.Editors.Designer.fr.xlf | 3 +- ...osoft.VisualStudio.Editors.Designer.it.xlf | 3 +- ...osoft.VisualStudio.Editors.Designer.ja.xlf | 3 +- ...osoft.VisualStudio.Editors.Designer.ko.xlf | 3 +- ...osoft.VisualStudio.Editors.Designer.pl.xlf | 3 +- ...ft.VisualStudio.Editors.Designer.pt-BR.xlf | 3 +- ...osoft.VisualStudio.Editors.Designer.ru.xlf | 3 +- ...osoft.VisualStudio.Editors.Designer.tr.xlf | 3 +- ....VisualStudio.Editors.Designer.zh-Hans.xlf | 3 +- ....VisualStudio.Editors.Designer.zh-Hant.xlf | 3 +- 21 files changed, 664 insertions(+), 518 deletions(-) diff --git a/src/fsharp/ConstraintSolver.fs b/src/fsharp/ConstraintSolver.fs index 586b91c41b0..4f00fd73ed2 100644 --- a/src/fsharp/ConstraintSolver.fs +++ b/src/fsharp/ConstraintSolver.fs @@ -1931,7 +1931,7 @@ and SolveTypeIsNonNullableValueType (csenv: ConstraintSolverEnv) ndeep m2 trace | _ -> let underlyingTy = stripTyEqnsAndMeasureEqns g ty if isStructTy g underlyingTy then - if isAppTy g underlyingTy && tyconRefEq g g.system_Nullable_tcref (tcrefOfAppTy g underlyingTy) then + if isNullableTy g underlyingTy then return! ErrorD (ConstraintSolverError(FSComp.SR.csTypeParameterCannotBeNullable(), m, m)) else return! ErrorD (ConstraintSolverError(FSComp.SR.csGenericConstructRequiresStructType(NicePrint.minimalStringOfType denv ty), m, m2)) diff --git a/src/fsharp/MethodCalls.fs b/src/fsharp/MethodCalls.fs index 5a8d66c875b..895f2d1f729 100644 --- a/src/fsharp/MethodCalls.fs +++ b/src/fsharp/MethodCalls.fs @@ -20,6 +20,7 @@ open FSharp.Compiler.Tastops.DebugPrint open FSharp.Compiler.TcGlobals open FSharp.Compiler.TypeRelations open FSharp.Compiler.AttributeChecking +open Internal.Utilities #if !NO_EXTENSIONTYPING open FSharp.Compiler.ExtensionTyping @@ -151,7 +152,9 @@ let AdjustCalledArgType (infoReader: InfoReader) isConstraint (calledArg: Called mkRefCellTy g (destByrefTy g calledArgTy) else - // If the called method argument is a delegate type, then the caller may provide a function + // If the called method argument is a delegate type, and the caller is known to be a function type, then the caller may provide a function + // If the called method argument is an Expression type, and the caller is known to be a function type, then the caller may provide a T + // If the called method argument is an [] Quotations.Expr, and the caller is not known to be a quoted expression type, then the caller may provide a T let calledArgTy = let adjustDelegateTy calledTy = let (SigOfFunctionForDelegate(_, delArgTys, _, fty)) = GetSigOfFunctionForDelegate infoReader calledTy m AccessibleFromSomewhere @@ -178,14 +181,18 @@ let AdjustCalledArgType (infoReader: InfoReader) isConstraint (calledArg: Called else calledArgTy // Adjust the called argument type to take into account whether the caller's argument is M(?arg=Some(3)) or M(arg=1) - // If the called method argument is optional with type Option, then the caller may provide a T, unless their argument is propagating-optional (i.e. isOptCallerArg) + // If the called method argument is Callee-side optional with type Option, and the caller argument is not explicitly optional (callerArg.IsOptional), then the caller may provide a T + // If the called method argument is Caller-side optional with type Nullable, and the caller argument is not explicitly optional (callerArg.IsOptional), then the caller may provide a T let calledArgTy = match calledArg.OptArgInfo with - | NotOptional -> calledArgTy + | NotOptional -> calledArgTy | CalleeSide when not callerArg.IsOptional && isOptionTy g calledArgTy -> destOptionTy g calledArgTy - | CalleeSide | CallerSide _ -> calledArgTy - calledArgTy - + // This will be added in https://github.com/dotnet/fsharp/pull/7276 + //| CallerSide _ when not callerArg.IsOptional && isNullableTy g calledArgTy -> destNullableTy g calledArgTy + | CalleeSide + | CallerSide _ -> calledArgTy + + calledArgTy //------------------------------------------------------------------------- // CalledMeth @@ -540,6 +547,351 @@ let ExamineMethodForLambdaPropagation (x: CalledMeth) = else None +//------------------------------------------------------------------------- +// Adjust caller arguments as part of building a method call +//------------------------------------------------------------------------- + +/// Build a call to the System.Object constructor taking no arguments, +let BuildObjCtorCall (g: TcGlobals) m = + let ilMethRef = (mkILCtorMethSpecForTy(g.ilg.typ_Object, [])).MethodRef + Expr.Op (TOp.ILCall (false, false, false, false, CtorValUsedAsSuperInit, false, true, ilMethRef, [], [], [g.obj_ty]), [], [], m) + +/// Implements the elaborated form of adhoc conversions from functions to delegates at member callsites +let BuildNewDelegateExpr (eventInfoOpt: EventInfo option, g, amap, delegateTy, invokeMethInfo: MethInfo, delArgTys, f, fty, m) = + let slotsig = invokeMethInfo.GetSlotSig(amap, m) + let delArgVals, expr = + let topValInfo = ValReprInfo([], List.replicate (max 1 (List.length delArgTys)) ValReprInfo.unnamedTopArg, ValReprInfo.unnamedRetVal) + + // Try to pull apart an explicit lambda and use it directly + // Don't do this in the case where we're adjusting the arguments of a function used to build a .NET-compatible event handler + let lambdaContents = + if Option.isSome eventInfoOpt then + None + else + tryDestTopLambda g amap topValInfo (f, fty) + + match lambdaContents with + | None -> + + if List.exists (isByrefTy g) delArgTys then + error(Error(FSComp.SR.tcFunctionRequiresExplicitLambda(List.length delArgTys), m)) + + let delArgVals = delArgTys |> List.mapi (fun i argty -> fst (mkCompGenLocal m ("delegateArg" + string i) argty)) + let expr = + let args = + match eventInfoOpt with + | Some einfo -> + match delArgVals with + | [] -> error(nonStandardEventError einfo.EventName m) + | h :: _ when not (isObjTy g h.Type) -> error(nonStandardEventError einfo.EventName m) + | h :: t -> [exprForVal m h; mkRefTupledVars g m t] + | None -> + if isNil delArgTys then [mkUnit g m] else List.map (exprForVal m) delArgVals + mkApps g ((f, fty), [], args, m) + delArgVals, expr + + | Some _ -> + let _, _, _, vsl, body, _ = IteratedAdjustArityOfLambda g amap topValInfo f + List.concat vsl, body + + let meth = TObjExprMethod(slotsig, [], [], [delArgVals], expr, m) + mkObjExpr(delegateTy, None, BuildObjCtorCall g m, [meth], [], m) + +let CoerceFromFSharpFuncToDelegate g amap infoReader ad callerArgTy m callerArgExpr delegateTy = + let (SigOfFunctionForDelegate(invokeMethInfo, delArgTys, _, _)) = GetSigOfFunctionForDelegate infoReader delegateTy m ad + BuildNewDelegateExpr (None, g, amap, delegateTy, invokeMethInfo, delArgTys, callerArgExpr, callerArgTy, m) + +// Handle adhoc argument conversions +let AdjustCallerArgExprForCoercions (g: TcGlobals) amap infoReader ad isOutArg calledArgTy (reflArgInfo: ReflectedArgInfo) callerArgTy m callerArgExpr = + + if isByrefTy g calledArgTy && isRefCellTy g callerArgTy then + None, Expr.Op (TOp.RefAddrGet false, [destRefCellTy g callerArgTy], [callerArgExpr], m) + +#if IMPLICIT_ADDRESS_OF + elif isInByrefTy g calledArgTy && not (isByrefTy g callerArgTy) then + let wrap, callerArgExprAddress, _readonly, _writeonly = mkExprAddrOfExpr g true false NeverMutates callerArgExpr None m + Some wrap, callerArgExprAddress +#endif + + elif isDelegateTy g calledArgTy && isFunTy g callerArgTy then + None, CoerceFromFSharpFuncToDelegate g amap infoReader ad callerArgTy m callerArgExpr calledArgTy + + elif isLinqExpressionTy g calledArgTy && isDelegateTy g (destLinqExpressionTy g calledArgTy) && isFunTy g callerArgTy then + let delegateTy = destLinqExpressionTy g calledArgTy + let expr = CoerceFromFSharpFuncToDelegate g amap infoReader ad callerArgTy m callerArgExpr delegateTy + None, mkCallQuoteToLinqLambdaExpression g m delegateTy (Expr.Quote (expr, ref None, false, m, mkQuotedExprTy g delegateTy)) + + // auto conversions to quotations (to match auto conversions to LINQ expressions) + elif reflArgInfo.AutoQuote && isQuotedExprTy g calledArgTy && not (isQuotedExprTy g callerArgTy) then + match reflArgInfo with + | ReflectedArgInfo.Quote true -> + None, mkCallLiftValueWithDefn g m calledArgTy callerArgExpr + | ReflectedArgInfo.Quote false -> + None, Expr.Quote (callerArgExpr, ref None, false, m, calledArgTy) + | ReflectedArgInfo.None -> failwith "unreachable" // unreachable due to reflArgInfo.AutoQuote condition + + // Note: out args do not need to be coerced + elif isOutArg then + None, callerArgExpr + + // Note: not all these casts are reported in quotations + else + None, mkCoerceIfNeeded g calledArgTy callerArgTy callerArgExpr + +// Handle CallerSide optional arguments. +// +// CallerSide optional arguments are largely for COM interop, e.g. to PIA assemblies for Word etc. +// As a result we follow the VB and C# behavior here. +// +// "1. If the parameter is statically typed as System.Object and does not have a value, then there are four cases: +// a. The parameter is marked with MarshalAs(IUnknown), MarshalAs(Interface), or MarshalAs(IDispatch). In this case we pass null. +// b. Else if the parameter is marked with IUnknownConstantAttribute. In this case we pass new System.Runtime.InteropServices.UnknownWrapper(null) +// c. Else if the parameter is marked with IDispatchConstantAttribute. In this case we pass new System.Runtime.InteropServices.DispatchWrapper(null) +// d. Else, we will pass Missing.Value. +// 2. Otherwise, if there is a value attribute, then emit the default value. +// 3. Otherwise, we emit default(T). +// 4. Finally, we apply conversions from the value to the parameter type. This is where the nullable conversions take place for VB. +// - VB allows you to mark ref parameters as optional. The semantics of this is that we create a temporary +// with type = type of parameter, load the optional value to it, and call the method. +// - VB also allows you to mark arrays with Nothing as the optional value. +// - VB also allows you to pass intrinsic values as optional values to parameters +// typed as Object. What we do in this case is we box the intrinsic value." +// +let AdjustOptionalCallerArgExprs tcFieldInit eCallerMemberName g (calledMeth: CalledMeth<_>) mItem mMethExpr = + + let assignedNamedArgs = calledMeth.ArgSets |> List.collect (fun argSet -> argSet.AssignedNamedArgs) + let unnamedCalledArgs = calledMeth.ArgSets |> List.collect (fun argSet -> argSet.UnnamedCalledArgs) + let unnamedCallerArgs = calledMeth.ArgSets |> List.collect (fun argSet -> argSet.UnnamedCallerArgs) + let unnamedArgs = + (unnamedCalledArgs, unnamedCallerArgs) ||> List.map2 (fun called caller -> + { NamedArgIdOpt = None; CalledArg=called; CallerArg=caller }) + + let emptyPreBinder (e: Expr) = e + + // Adjust all the optional arguments that require a default value to be inserted into the call + let optArgs, optArgPreBinder = + (emptyPreBinder, calledMeth.UnnamedCalledOptArgs) ||> List.mapFold (fun wrapper calledArg -> + let calledArgTy = calledArg.CalledArgumentType + let wrapper2, expr = + match calledArg.OptArgInfo with + | NotOptional -> + error(InternalError("Unexpected NotOptional", mItem)) + + | CallerSide dfltVal -> + + let rec build currCalledArgTy currDfltVal = + match currDfltVal with + | MissingValue -> + // Add an I_nop if this is an initonly field to make sure we never recognize it as an lvalue. See mkExprAddrOfExpr. + emptyPreBinder, mkAsmExpr ([ mkNormalLdsfld (fspec_Missing_Value g); AI_nop ], [], [], [currCalledArgTy], mMethExpr) + + | DefaultValue -> + emptyPreBinder, mkDefault(mMethExpr, currCalledArgTy) + + | Constant fieldInit -> + match currCalledArgTy with + | NullableTy g inst when fieldInit <> ILFieldInit.Null -> + let nullableTy = mkILNonGenericBoxedTy(g.FindSysILTypeRef "System.Nullable`1") + let ctor = mkILCtorMethSpecForTy(nullableTy, [ILType.TypeVar 0us]).MethodRef + let ctorArgs = [Expr.Const (tcFieldInit mMethExpr fieldInit, mMethExpr, inst)] + emptyPreBinder, Expr.Op (TOp.ILCall (false, false, true, true, NormalValUse, false, false, ctor, [inst], [], [currCalledArgTy]), [], ctorArgs, mMethExpr) + | ByrefTy g inst -> + build inst (PassByRef(inst, currDfltVal)) + | _ -> + match calledArg.CallerInfo, eCallerMemberName with + | CallerLineNumber, _ when typeEquiv g currCalledArgTy g.int_ty -> + emptyPreBinder, Expr.Const (Const.Int32(mMethExpr.StartLine), mMethExpr, currCalledArgTy) + | CallerFilePath, _ when typeEquiv g currCalledArgTy g.string_ty -> + let fileName = mMethExpr.FileName |> FileSystem.GetFullPathShim |> PathMap.apply g.pathMap + emptyPreBinder, Expr.Const (Const.String fileName, mMethExpr, currCalledArgTy) + | CallerMemberName, Some callerName when (typeEquiv g currCalledArgTy g.string_ty) -> + emptyPreBinder, Expr.Const (Const.String callerName, mMethExpr, currCalledArgTy) + | _ -> + emptyPreBinder, Expr.Const (tcFieldInit mMethExpr fieldInit, mMethExpr, currCalledArgTy) + + | WrapperForIDispatch -> + match g.TryFindSysILTypeRef "System.Runtime.InteropServices.DispatchWrapper" with + | None -> error(Error(FSComp.SR.fscSystemRuntimeInteropServicesIsRequired(), mMethExpr)) + | Some tref -> + let ty = mkILNonGenericBoxedTy tref + let mref = mkILCtorMethSpecForTy(ty, [g.ilg.typ_Object]).MethodRef + let expr = Expr.Op (TOp.ILCall (false, false, false, true, NormalValUse, false, false, mref, [], [], [g.obj_ty]), [], [mkDefault(mMethExpr, currCalledArgTy)], mMethExpr) + emptyPreBinder, expr + + | WrapperForIUnknown -> + match g.TryFindSysILTypeRef "System.Runtime.InteropServices.UnknownWrapper" with + | None -> error(Error(FSComp.SR.fscSystemRuntimeInteropServicesIsRequired(), mMethExpr)) + | Some tref -> + let ty = mkILNonGenericBoxedTy tref + let mref = mkILCtorMethSpecForTy(ty, [g.ilg.typ_Object]).MethodRef + let expr = Expr.Op (TOp.ILCall (false, false, false, true, NormalValUse, false, false, mref, [], [], [g.obj_ty]), [], [mkDefault(mMethExpr, currCalledArgTy)], mMethExpr) + emptyPreBinder, expr + + | PassByRef (ty, dfltVal2) -> + let v, _ = mkCompGenLocal mMethExpr "defaultByrefArg" ty + let wrapper2, rhs = build currCalledArgTy dfltVal2 + (wrapper2 >> mkCompGenLet mMethExpr v rhs), mkValAddr mMethExpr false (mkLocalValRef v) + build calledArgTy dfltVal + + | CalleeSide -> + let calledNonOptTy = + if isOptionTy g calledArgTy then + destOptionTy g calledArgTy + else + calledArgTy // should be unreachable + + match calledArg.CallerInfo, eCallerMemberName with + | CallerLineNumber, _ when typeEquiv g calledNonOptTy g.int_ty -> + let lineExpr = Expr.Const(Const.Int32 mMethExpr.StartLine, mMethExpr, calledNonOptTy) + emptyPreBinder, mkSome g calledNonOptTy lineExpr mMethExpr + | CallerFilePath, _ when typeEquiv g calledNonOptTy g.string_ty -> + let fileName = mMethExpr.FileName |> FileSystem.GetFullPathShim |> PathMap.apply g.pathMap + let filePathExpr = Expr.Const (Const.String(fileName), mMethExpr, calledNonOptTy) + emptyPreBinder, mkSome g calledNonOptTy filePathExpr mMethExpr + | CallerMemberName, Some(callerName) when typeEquiv g calledNonOptTy g.string_ty -> + let memberNameExpr = Expr.Const (Const.String callerName, mMethExpr, calledNonOptTy) + emptyPreBinder, mkSome g calledNonOptTy memberNameExpr mMethExpr + | _ -> + emptyPreBinder, mkNone g calledNonOptTy mMethExpr + + // Combine the variable allocators (if any) + let wrapper = (wrapper >> wrapper2) + let callerArg = CallerArg(calledArgTy, mMethExpr, false, expr) + { NamedArgIdOpt = None; CalledArg = calledArg; CallerArg = callerArg }, wrapper) + + // Adjust all the optional arguments + let wrapOptionalArg (assignedArg: AssignedCalledArg<_>) = + let (CallerArg(callerArgTy, m, isOptCallerArg, callerArgExpr)) = assignedArg.CallerArg + match assignedArg.CalledArg.OptArgInfo with + | NotOptional -> + if isOptCallerArg then errorR(Error(FSComp.SR.tcFormalArgumentIsNotOptional(), m)) + assignedArg + | _ -> + let callerArgExpr2 = + match assignedArg.CalledArg.OptArgInfo with + | CallerSide _ -> + if isOptCallerArg then + // M(?x=bopt) when M(A) --> M(?x=bopt.Value) for caller-side + // STRUCT OPTIONS: if we allow struct options as optional arguments then we should take + // the address correctly. + mkUnionCaseFieldGetUnprovenViaExprAddr (callerArgExpr, mkSomeCase g, [destOptionTy g callerArgTy], 0, m) + else + // M(x=b) when M(A) --> M(?x=b) for caller-side + callerArgExpr + + | CalleeSide -> + if isOptCallerArg then + // M(?x=bopt) when M(A) --> M(?x=Some(bopt.Value)) + callerArgExpr + else + // M(x=b) when M(A) --> M(?x=Some(b :> A)) + let calledArgTy = assignedArg.CalledArg.CalledArgumentType + if isOptionTy g calledArgTy then + let calledNonOptTy = destOptionTy g calledArgTy + mkSome g calledNonOptTy (mkCoerceIfNeeded g calledNonOptTy callerArgTy callerArgExpr) m + else + callerArgExpr // should be unreachable + + | _ -> failwith "Unreachable" + { assignedArg with CallerArg=CallerArg(tyOfExpr g callerArgExpr2, m, isOptCallerArg, callerArgExpr2) } + + let adjustedNormalUnnamedArgs = List.map wrapOptionalArg unnamedArgs + let adjustedAssignedNamedArgs = List.map wrapOptionalArg assignedNamedArgs + + optArgs, optArgPreBinder, adjustedNormalUnnamedArgs, adjustedAssignedNamedArgs + +/// Adjust any 'out' arguments, passing in the address of a mutable local +let AdjustOutCallerArgExprs g (calledMeth: CalledMeth<_>) mMethExpr = + calledMeth.UnnamedCalledOutArgs |> List.map (fun calledArg -> + let calledArgTy = calledArg.CalledArgumentType + let outArgTy = destByrefTy g calledArgTy + let outv, outArgExpr = mkMutableCompGenLocal mMethExpr PrettyNaming.outArgCompilerGeneratedName outArgTy // mutable! + let expr = mkDefault (mMethExpr, outArgTy) + let callerArg = CallerArg (calledArgTy, mMethExpr, false, mkValAddr mMethExpr false (mkLocalValRef outv)) + let outArg = { NamedArgIdOpt=None;CalledArg=calledArg;CallerArg=callerArg } + outArg, outArgExpr, mkCompGenBind outv expr) + |> List.unzip3 + +let AdjustParamArrayCallerArgExprs g amap infoReader ad (calledMeth: CalledMeth<_>) mMethExpr = + let argSets = calledMeth.ArgSets + + let paramArrayCallerArgs = argSets |> List.collect (fun argSet -> argSet.ParamArrayCallerArgs) + match calledMeth.ParamArrayCalledArgOpt with + | None -> + [], [] + | Some paramArrayCalledArg -> + let paramArrayCalledArgElementType = destArrayTy g paramArrayCalledArg.CalledArgumentType + + let paramArrayPreBinders, es = + paramArrayCallerArgs + |> List.map (fun callerArg -> + let (CallerArg(callerArgTy, m, isOutArg, callerArgExpr)) = callerArg + AdjustCallerArgExprForCoercions g amap infoReader ad isOutArg paramArrayCalledArgElementType paramArrayCalledArg.ReflArgInfo callerArgTy m callerArgExpr) + |> List.unzip + + let arg = + [ { NamedArgIdOpt = None + CalledArg=paramArrayCalledArg + CallerArg=CallerArg(paramArrayCalledArg.CalledArgumentType, mMethExpr, false, Expr.Op (TOp.Array, [paramArrayCalledArgElementType], es, mMethExpr)) } ] + paramArrayPreBinders, arg + +/// Build the argument list for a method call. Adjust for param array, optional arguments, byref arguments and coercions. +/// For example, if you pass an F# reference cell to a byref then we must get the address of the +/// contents of the ref. Likewise lots of adjustments are made for optional arguments etc. +let AdjustCallerArgExprs tcFieldInit eCallerMemberName g amap infoReader ad (calledMeth: CalledMeth<_>) objArgs lambdaVars mItem mMethExpr = + let calledMethInfo = calledMeth.Method + + // Some of the code below must allocate temporary variables or bind other variables to particular values. + // As usual we represent variable allocators by expr -> expr functions + // which we then use to wrap the whole expression. These will either do nothing or pre-bind a variable. It doesn't + // matter what order they are applied in as long as they are all composed together. + let emptyPreBinder (e: Expr) = e + + // For unapplied 'e.M' we first evaluate 'e' outside the lambda, i.e. 'let v = e in (fun arg -> v.M(arg))' + let objArgPreBinder, objArgs = + match objArgs, lambdaVars with + | [objArg], Some _ -> + if calledMethInfo.IsExtensionMember && calledMethInfo.ObjArgNeedsAddress(amap, mMethExpr) then + error(Error(FSComp.SR.tcCannotPartiallyApplyExtensionMethodForByref(calledMethInfo.DisplayName), mMethExpr)) + let objArgTy = tyOfExpr g objArg + let v, ve = mkCompGenLocal mMethExpr "objectArg" objArgTy + (fun body -> mkCompGenLet mMethExpr v objArg body), [ve] + | _ -> + emptyPreBinder, objArgs + + // Handle param array and optional arguments + let paramArrayPreBinders, paramArrayArgs = + AdjustParamArrayCallerArgExprs g amap infoReader ad calledMeth mMethExpr + + let optArgs, optArgPreBinder, adjustedNormalUnnamedArgs, adjustedFinalAssignedNamedArgs = + AdjustOptionalCallerArgExprs tcFieldInit eCallerMemberName g calledMeth mItem mMethExpr + + let outArgs, outArgExprs, outArgTmpBinds = + AdjustOutCallerArgExprs g calledMeth mMethExpr + + let allArgs = + adjustedNormalUnnamedArgs @ + adjustedFinalAssignedNamedArgs @ + paramArrayArgs @ + optArgs @ + outArgs + + let allArgs = + allArgs |> List.sortBy (fun x -> x.Position) + + let allArgsPreBinders, allArgsCoerced = + allArgs + |> List.map (fun assignedArg -> + let isOutArg = assignedArg.CalledArg.IsOutArg + let reflArgInfo = assignedArg.CalledArg.ReflArgInfo + let calledArgTy = assignedArg.CalledArg.CalledArgumentType + let (CallerArg(callerArgTy, m, _, e)) = assignedArg.CallerArg + + AdjustCallerArgExprForCoercions g amap infoReader ad isOutArg calledArgTy reflArgInfo callerArgTy m e) + |> List.unzip + + objArgPreBinder, objArgs, allArgsPreBinders, allArgs, allArgsCoerced, optArgPreBinder, paramArrayPreBinders, outArgExprs, outArgTmpBinds + //------------------------------------------------------------------------- // Additional helpers for building method calls and doing TAST generation //------------------------------------------------------------------------- @@ -573,27 +925,30 @@ let ComputeConstrainedCallInfo g amap m (objArgs, minfo: MethInfo) = | _ -> None - /// Adjust the 'this' pointer before making a call /// Take the address of a struct, and coerce to an interface/base/constraint type if necessary let TakeObjAddrForMethodCall g amap (minfo: MethInfo) isMutable m objArgs f = let ccallInfo = ComputeConstrainedCallInfo g amap m (objArgs, minfo) let wrap, objArgs = + match objArgs with | [objArgExpr] -> + let hasCallInfo = ccallInfo.IsSome let mustTakeAddress = hasCallInfo || minfo.ObjArgNeedsAddress(amap, m) let objArgTy = tyOfExpr g objArgExpr - let wrap, objArgExpr', isReadOnly, _isWriteOnly = mkExprAddrOfExpr g mustTakeAddress hasCallInfo isMutable objArgExpr None m + + let wrap, objArgExprAddr, isReadOnly, _isWriteOnly = + mkExprAddrOfExpr g mustTakeAddress hasCallInfo isMutable objArgExpr None m // Extension members and calls to class constraints may need a coercion for their object argument - let objArgExpr' = + let objArgExprCoerced = if not hasCallInfo && not (TypeDefinitelySubsumesTypeNoCoercion 0 g amap m minfo.ApparentEnclosingType objArgTy) then - mkCoerceExpr(objArgExpr', minfo.ApparentEnclosingType, m, objArgTy) + mkCoerceExpr(objArgExprAddr, minfo.ApparentEnclosingType, m, objArgTy) else - objArgExpr' + objArgExprAddr // Check to see if the extension member uses the extending type as a byref. // If so, make sure we don't allow readonly/immutable values to be passed byref from an extension member. @@ -605,7 +960,7 @@ let TakeObjAddrForMethodCall g amap (minfo: MethInfo) isMutable m objArgs f = errorR(Error(FSComp.SR.tcCannotCallExtensionMethodInrefToByref(minfo.DisplayName), m))) - wrap, [objArgExpr'] + wrap, [objArgExprCoerced] | _ -> id, objArgs @@ -616,11 +971,6 @@ let TakeObjAddrForMethodCall g amap (minfo: MethInfo) isMutable m objArgs f = // Build method calls. //------------------------------------------------------------------------- -//------------------------------------------------------------------------- -// Build calls -//------------------------------------------------------------------------- - - /// Build an expression node that is a call to a .NET method. let BuildILMethInfoCall g amap m isProp (minfo: ILMethInfo) valUseFlags minst direct args = let valu = isStructTy g minfo.ApparentEnclosingType @@ -638,11 +988,6 @@ let BuildILMethInfoCall g amap m isProp (minfo: ILMethInfo) valUseFlags minst di Expr.Op (TOp.ILCall (useCallvirt, isProtected, valu, newobj, valUseFlags, isProp, isDllImport, ilMethRef, minfo.DeclaringTypeInst, minst, retTy), [], args, m), exprTy -/// Build a call to the System.Object constructor taking no arguments, -let BuildObjCtorCall (g: TcGlobals) m = - let ilMethRef = (mkILCtorMethSpecForTy(g.ilg.typ_Object, [])).MethodRef - Expr.Op (TOp.ILCall (false, false, false, false, CtorValUsedAsSuperInit, false, true, ilMethRef, [], [], [g.obj_ty]), [], [], m) - /// Build a call to an F# method. /// @@ -825,55 +1170,6 @@ let BuildMethodCall tcVal g amap isMutable m isProp minfo valUseFlags minst objA errorR(Error(FSComp.SR.tcDefaultStructConstructorCall(), m)) mkDefault (m, ty), ty) -//------------------------------------------------------------------------- -// Build delegate constructions (lambdas/functions to delegates) -//------------------------------------------------------------------------- - -/// Implements the elaborated form of adhoc conversions from functions to delegates at member callsites -let BuildNewDelegateExpr (eventInfoOpt: EventInfo option, g, amap, delegateTy, invokeMethInfo: MethInfo, delArgTys, f, fty, m) = - let slotsig = invokeMethInfo.GetSlotSig(amap, m) - let delArgVals, expr = - let topValInfo = ValReprInfo([], List.replicate (max 1 (List.length delArgTys)) ValReprInfo.unnamedTopArg, ValReprInfo.unnamedRetVal) - - // Try to pull apart an explicit lambda and use it directly - // Don't do this in the case where we're adjusting the arguments of a function used to build a .NET-compatible event handler - let lambdaContents = - if Option.isSome eventInfoOpt then - None - else - tryDestTopLambda g amap topValInfo (f, fty) - - match lambdaContents with - | None -> - - if List.exists (isByrefTy g) delArgTys then - error(Error(FSComp.SR.tcFunctionRequiresExplicitLambda(List.length delArgTys), m)) - - let delArgVals = delArgTys |> List.mapi (fun i argty -> fst (mkCompGenLocal m ("delegateArg" + string i) argty)) - let expr = - let args = - match eventInfoOpt with - | Some einfo -> - match delArgVals with - | [] -> error(nonStandardEventError einfo.EventName m) - | h :: _ when not (isObjTy g h.Type) -> error(nonStandardEventError einfo.EventName m) - | h :: t -> [exprForVal m h; mkRefTupledVars g m t] - | None -> - if isNil delArgTys then [mkUnit g m] else List.map (exprForVal m) delArgVals - mkApps g ((f, fty), [], args, m) - delArgVals, expr - - | Some _ -> - let _, _, _, vsl, body, _ = IteratedAdjustArityOfLambda g amap topValInfo f - List.concat vsl, body - - let meth = TObjExprMethod(slotsig, [], [], [delArgVals], expr, m) - mkObjExpr(delegateTy, None, BuildObjCtorCall g m, [meth], [], m) - -let CoerceFromFSharpFuncToDelegate g amap infoReader ad callerArgTy m callerArgExpr delegateTy = - let (SigOfFunctionForDelegate(invokeMethInfo, delArgTys, _, _)) = GetSigOfFunctionForDelegate infoReader delegateTy m ad - BuildNewDelegateExpr (None, g, amap, delegateTy, invokeMethInfo, delArgTys, callerArgExpr, callerArgTy, m) - //------------------------------------------------------------------------- // Import provided expressions @@ -972,11 +1268,14 @@ module ProvidedMethodCalls = st loop inputType - let convertProvidedExpressionToExprAndWitness tcVal (thisArg: Expr option, - allArgs: Exprs, - paramVars: Tainted[], - g, amap, mut, isProp, isSuperInit, m, - expr: Tainted) = + let convertProvidedExpressionToExprAndWitness + tcVal + (thisArg: Expr option, + allArgs: Exprs, + paramVars: Tainted[], + g, amap, mut, isProp, isSuperInit, m, + expr: Tainted) = + let varConv = // note: using paramVars.Length as assumed initial size, but this might not // be the optimal value; this wasn't checked before obsoleting Dictionary.ofList diff --git a/src/fsharp/TastOps.fs b/src/fsharp/TastOps.fs index 00fb9a08278..c638d9a864e 100644 --- a/src/fsharp/TastOps.fs +++ b/src/fsharp/TastOps.fs @@ -839,16 +839,6 @@ let tryNiceEntityRefOfTyOption ty = | TType_app (tcref, _) -> Some tcref | TType_measure (Measure.Con tcref) -> Some tcref | _ -> None - -let (|NullableTy|_|) g ty = - match tryAppTy g ty with - | ValueSome (tcref, [tyarg]) when tyconRefEq g tcref g.system_Nullable_tcref -> Some tyarg - | _ -> None - -let (|StripNullableTy|) g ty = - match tryAppTy g ty with - | ValueSome (tcref, [tyarg]) when tyconRefEq g tcref g.system_Nullable_tcref -> tyarg - | _ -> ty let mkInstForAppTy g ty = match tryAppTy g ty with @@ -3125,6 +3115,31 @@ let destOptionTy g ty = | ValueSome ty -> ty | ValueNone -> failwith "destOptionTy: not an option type" +let isNullableTy (g: TcGlobals) ty = + match tryDestAppTy g ty with + | ValueNone -> false + | ValueSome tcref -> tyconRefEq g g.system_Nullable_tcref tcref + +let tryDestNullableTy g ty = + match argsOfAppTy g ty with + | [ty1] when isNullableTy g ty -> ValueSome ty1 + | _ -> ValueNone + +let destNullableTy g ty = + match tryDestNullableTy g ty with + | ValueSome ty -> ty + | ValueNone -> failwith "destNullableTy: not a Nullable type" + +let (|NullableTy|_|) g ty = + match tryAppTy g ty with + | ValueSome (tcref, [tyarg]) when tyconRefEq g tcref g.system_Nullable_tcref -> Some tyarg + | _ -> None + +let (|StripNullableTy|) g ty = + match tryDestNullableTy g ty with + | ValueSome tyarg -> tyarg + | _ -> ty + let isLinqExpressionTy g ty = match tryDestAppTy g ty with | ValueNone -> false diff --git a/src/fsharp/TastOps.fsi b/src/fsharp/TastOps.fsi index 8c71736a844..b0743de8536 100755 --- a/src/fsharp/TastOps.fsi +++ b/src/fsharp/TastOps.fsi @@ -1388,7 +1388,7 @@ val mkVoidPtrTy : TcGlobals -> TType /// Build a single-dimensional array type val mkArrayType : TcGlobals -> TType -> TType -/// Determine is a type is an option type +/// Determine if a type is an option type val isOptionTy : TcGlobals -> TType -> bool /// Take apart an option type @@ -1397,6 +1397,15 @@ val destOptionTy : TcGlobals -> TType -> TType /// Try to take apart an option type val tryDestOptionTy : TcGlobals -> TType -> ValueOption +/// Determine is a type is a System.Nullable type +val isNullableTy : TcGlobals -> TType -> bool + +/// Try to take apart a System.Nullable type +val tryDestNullableTy: TcGlobals -> TType -> ValueOption + +/// Take apart a System.Nullable type +val destNullableTy: TcGlobals -> TType -> TType + /// Determine if a type is a System.Linq.Expression type val isLinqExpressionTy : TcGlobals -> TType -> bool diff --git a/src/fsharp/TypeChecker.fs b/src/fsharp/TypeChecker.fs index ae464f15758..70bb0f6b212 100644 --- a/src/fsharp/TypeChecker.fs +++ b/src/fsharp/TypeChecker.fs @@ -9671,75 +9671,74 @@ and TcMethodApplication // In one case (the second "single named item" rule) we delay the application of a // argument until we've produced a lambda that detuples an input tuple let curriedCallerArgsOpt, unnamedDelayedCallerArgExprOpt, exprTy = - match curriedCallerArgs with - | [] -> - None, None, exprTy - | _ -> - let unnamedCurriedCallerArgs, namedCurriedCallerArgs = curriedCallerArgs |> List.map GetMethodArgs |> List.unzip + match curriedCallerArgs with + | [] -> + None, None, exprTy + | _ -> + let unnamedCurriedCallerArgs, namedCurriedCallerArgs = curriedCallerArgs |> List.map GetMethodArgs |> List.unzip - // There is an mismatch when _uses_ of indexed property setters in the tc.fs code that calls this function. - // The arguments are passed as if they are curried with arity [numberOfIndexParameters;1], however in the TAST, indexed property setters - // are uncurried and have arity [numberOfIndexParameters+1]. - // - // Here we work around this mismatch by crunching all property argument lists to uncirred form. - // Ideally the problem needs to be solved at its root cause at the callsites to this function - let unnamedCurriedCallerArgs, namedCurriedCallerArgs = - if isProp then - [List.concat unnamedCurriedCallerArgs], [List.concat namedCurriedCallerArgs] - else - unnamedCurriedCallerArgs, namedCurriedCallerArgs + // There is an mismatch when _uses_ of indexed property setters in the tc.fs code that calls this function. + // The arguments are passed as if they are curried with arity [numberOfIndexParameters;1], however in the TAST, indexed property setters + // are uncurried and have arity [numberOfIndexParameters+1]. + // + // Here we work around this mismatch by crunching all property argument lists to uncirred form. + // Ideally the problem needs to be solved at its root cause at the callsites to this function + let unnamedCurriedCallerArgs, namedCurriedCallerArgs = + if isProp then + [List.concat unnamedCurriedCallerArgs], [List.concat namedCurriedCallerArgs] + else + unnamedCurriedCallerArgs, namedCurriedCallerArgs - let MakeUnnamedCallerArgInfo x = (x, GetNewInferenceTypeForMethodArg cenv env tpenv x, x.Range) - - // "single named item" rule. This is where we have a single accessible method - // member x.M(arg1) - // being used with - // x.M (x, y) - // Without this rule this requires - // x.M ((x, y)) - match candidates with - | [calledMeth] - when (namedCurriedCallerArgs |> List.forall isNil && - let curriedCalledArgs = calledMeth.GetParamAttribs(cenv.amap, mItem) - curriedCalledArgs.Length = 1 && - curriedCalledArgs.Head.Length = 1 && - curriedCalledArgs.Head.Head |> isSimpleFormalArg) -> - let unnamedCurriedCallerArgs = curriedCallerArgs |> List.map (MakeUnnamedCallerArgInfo >> List.singleton) - let namedCurriedCallerArgs = namedCurriedCallerArgs |> List.map (fun _ -> []) - (Some (unnamedCurriedCallerArgs, namedCurriedCallerArgs), None, exprTy) - - // "single named item" rule. This is where we have a single accessible method - // member x.M(arg1, arg2) - // being used with - // x.M p - // We typecheck this as if it has been written "(fun (v1, v2) -> x.M(v1, v2)) p" - // Without this rule this requires - // x.M (fst p, snd p) - | [calledMeth] - when (namedCurriedCallerArgs |> List.forall isNil && - unnamedCurriedCallerArgs.Length = 1 && - unnamedCurriedCallerArgs.Head.Length = 1 && - let curriedCalledArgs = calledMeth.GetParamAttribs(cenv.amap, mItem) - curriedCalledArgs.Length = 1 && - curriedCalledArgs.Head.Length > 1 && - curriedCalledArgs.Head |> List.forall isSimpleFormalArg) -> - - // The call lambda has function type - let exprTy = mkFunTy (NewInferenceType ()) exprTy + let MakeUnnamedCallerArgInfo x = (x, GetNewInferenceTypeForMethodArg cenv env tpenv x, x.Range) + + // "single named item" rule. This is where we have a single accessible method + // member x.M(arg1) + // being used with + // x.M (x, y) + // Without this rule this requires + // x.M ((x, y)) + match candidates with + | [calledMeth] + when (namedCurriedCallerArgs |> List.forall isNil && + let curriedCalledArgs = calledMeth.GetParamAttribs(cenv.amap, mItem) + curriedCalledArgs.Length = 1 && + curriedCalledArgs.Head.Length = 1 && + curriedCalledArgs.Head.Head |> isSimpleFormalArg) -> + let unnamedCurriedCallerArgs = curriedCallerArgs |> List.map (MakeUnnamedCallerArgInfo >> List.singleton) + let namedCurriedCallerArgs = namedCurriedCallerArgs |> List.map (fun _ -> []) + (Some (unnamedCurriedCallerArgs, namedCurriedCallerArgs), None, exprTy) + + // "single named item" rule. This is where we have a single accessible method + // member x.M(arg1, arg2) + // being used with + // x.M p + // We typecheck this as if it has been written "(fun (v1, v2) -> x.M(v1, v2)) p" + // Without this rule this requires + // x.M (fst p, snd p) + | [calledMeth] + when (namedCurriedCallerArgs |> List.forall isNil && + unnamedCurriedCallerArgs.Length = 1 && + unnamedCurriedCallerArgs.Head.Length = 1 && + let curriedCalledArgs = calledMeth.GetParamAttribs(cenv.amap, mItem) + curriedCalledArgs.Length = 1 && + curriedCalledArgs.Head.Length > 1 && + curriedCalledArgs.Head |> List.forall isSimpleFormalArg) -> + + // The call lambda has function type + let exprTy = mkFunTy (NewInferenceType ()) exprTy - (None, Some unnamedCurriedCallerArgs.Head.Head, exprTy) + (None, Some unnamedCurriedCallerArgs.Head.Head, exprTy) - | _ -> - let unnamedCurriedCallerArgs = unnamedCurriedCallerArgs |> List.mapSquared MakeUnnamedCallerArgInfo - let namedCurriedCallerArgs = namedCurriedCallerArgs |> List.mapSquared (fun (isOpt, nm, x) -> - let ty = GetNewInferenceTypeForMethodArg cenv env tpenv x - // #435263: compiler crash with .net optional parameters and F# optional syntax - // named optional arguments should always have option type - let ty = if isOpt then mkOptionTy denv.g ty else ty - nm, isOpt, x, ty, x.Range - ) - - (Some (unnamedCurriedCallerArgs, namedCurriedCallerArgs), None, exprTy) + | _ -> + let unnamedCurriedCallerArgs = unnamedCurriedCallerArgs |> List.mapSquared MakeUnnamedCallerArgInfo + let namedCurriedCallerArgs = namedCurriedCallerArgs |> List.mapSquared (fun (isOpt, nm, x) -> + let ty = GetNewInferenceTypeForMethodArg cenv env tpenv x + // #435263: compiler crash with .net optional parameters and F# optional syntax + // named optional arguments should always have option type + let ty = if isOpt then mkOptionTy denv.g ty else ty + nm, isOpt, x, ty, x.Range) + + (Some (unnamedCurriedCallerArgs, namedCurriedCallerArgs), None, exprTy) let CalledMethHasSingleArgumentGroupOfThisLength n (calledMeth: MethInfo) = @@ -9983,21 +9982,12 @@ and TcMethodApplication let finalCalledMethInfo = finalCalledMeth.Method let finalCalledMethInst = finalCalledMeth.CalledTyArgs - let finalArgSets = finalCalledMeth.ArgSets let finalAssignedItemSetters = finalCalledMeth.AssignedItemSetters - let finalCalledPropInfoOpt = finalCalledMeth.AssociatedPropertyInfo let finalAttributeAssignedNamedItems = finalCalledMeth.AttributeAssignedNamedArgs - let finalUnnamedCalledOptArgs = finalCalledMeth.UnnamedCalledOptArgs - let finalUnnamedCalledOutArgs = finalCalledMeth.UnnamedCalledOutArgs - let finalAssignedNamedArgs = finalArgSets |> List.collect (fun argSet -> argSet.AssignedNamedArgs) - let finalParamArrayCallerArgs = finalArgSets |> List.collect (fun argSet -> argSet.ParamArrayCallerArgs) - let finalUnnamedCalledArgs = finalArgSets |> List.collect (fun argSet -> argSet.UnnamedCalledArgs) - let finalUnnamedCallerArgs = finalArgSets |> List.collect (fun argSet -> argSet.UnnamedCallerArgs) - // STEP 4. Check the attributes on the method and the corresponding event/property, if any - finalCalledPropInfoOpt |> Option.iter (fun pinfo -> CheckPropInfoAttributes pinfo mItem |> CommitOperationResult) + finalCalledMeth.AssociatedPropertyInfo |> Option.iter (fun pinfo -> CheckPropInfoAttributes pinfo mItem |> CommitOperationResult) let isInstance = not (isNil objArgs) MethInfoChecks cenv.g cenv.amap isInstance tyargsOpt objArgs ad mItem finalCalledMethInfo @@ -10026,266 +10016,13 @@ and TcMethodApplication | _ -> () end - if (finalArgSets |> List.existsi (fun i argSet -> argSet.UnnamedCalledArgs |> List.existsi (fun j ca -> ca.Position <> (i, j)))) then + if (finalCalledMeth.ArgSets |> List.existsi (fun i argSet -> argSet.UnnamedCalledArgs |> List.existsi (fun j ca -> ca.Position <> (i, j)))) then errorR(Deprecated(FSComp.SR.tcUnnamedArgumentsDoNotFormPrefix(), mMethExpr)) + /// STEP 5. Build the argument list. Adjust for optional arguments, byref arguments and coercions. - // STEP 5. Build the argument list. Adjust for optional arguments, byref arguments and coercions. - // For example, if you pass an F# reference cell to a byref then we must get the address of the - // contents of the ref. Likewise lots of adjustments are made for optional arguments etc. - - // Some of the code below must allocate temporary variables or bind other variables to particular values. - // As usual we represent variable allocators by expr -> expr functions - // which we then use to wrap the whole expression. These will either do nothing or pre-bind a variable. It doesn't - // matter what order they are applied in as long as they are all composed together. - let emptyPreBinder (e: Expr) = e - - // For unapplied 'e.M' we first evaluate 'e' outside the lambda, i.e. 'let v = e in (fun arg -> v.M(arg))' - let objArgPreBinder, objArgs = - match objArgs, lambdaVars with - | [objArg], Some _ -> - if finalCalledMethInfo.IsExtensionMember && finalCalledMethInfo.ObjArgNeedsAddress(cenv.amap, mMethExpr) then - error(Error(FSComp.SR.tcCannotPartiallyApplyExtensionMethodForByref(finalCalledMethInfo.DisplayName), mMethExpr)) - let objArgTy = tyOfExpr cenv.g objArg - let v, ve = mkCompGenLocal mMethExpr "objectArg" objArgTy - (fun body -> mkCompGenLet mMethExpr v objArg body), [ve] - | _ -> - emptyPreBinder, objArgs - - // Handle adhoc argument conversions - let coerceExpr isOutArg calledArgTy (reflArgInfo: ReflectedArgInfo) callerArgTy m callerArgExpr = - let g = cenv.g - - if isByrefTy g calledArgTy && isRefCellTy g callerArgTy then - None, Expr.Op (TOp.RefAddrGet false, [destRefCellTy g callerArgTy], [callerArgExpr], m) - -#if IMPLICIT_ADDRESS_OF - elif isInByrefTy g calledArgTy && not (isByrefTy cenv.g callerArgTy) then - let wrap, callerArgExprAddress, _readonly, _writeonly = mkExprAddrOfExpr g true false NeverMutates callerArgExpr None m - Some wrap, callerArgExprAddress -#endif - - elif isDelegateTy cenv.g calledArgTy && isFunTy cenv.g callerArgTy then - None, CoerceFromFSharpFuncToDelegate cenv.g cenv.amap cenv.infoReader ad callerArgTy m callerArgExpr calledArgTy - - elif isLinqExpressionTy cenv.g calledArgTy && isDelegateTy cenv.g (destLinqExpressionTy cenv.g calledArgTy) && isFunTy cenv.g callerArgTy then - let delegateTy = destLinqExpressionTy cenv.g calledArgTy - let expr = CoerceFromFSharpFuncToDelegate cenv.g cenv.amap cenv.infoReader ad callerArgTy m callerArgExpr delegateTy - None, mkCallQuoteToLinqLambdaExpression cenv.g m delegateTy (Expr.Quote (expr, ref None, false, m, mkQuotedExprTy cenv.g delegateTy)) - - // auto conversions to quotations (to match auto conversions to LINQ expressions) - elif reflArgInfo.AutoQuote && isQuotedExprTy cenv.g calledArgTy && not (isQuotedExprTy cenv.g callerArgTy) then - match reflArgInfo with - | ReflectedArgInfo.Quote true -> - None, mkCallLiftValueWithDefn cenv.g m calledArgTy callerArgExpr - | ReflectedArgInfo.Quote false -> - None, Expr.Quote (callerArgExpr, ref None, false, m, calledArgTy) - | ReflectedArgInfo.None -> failwith "unreachable" // unreachable due to reflArgInfo.AutoQuote condition - - // Note: out args do not need to be coerced - elif isOutArg then - None, callerArgExpr - - // Note: not all these casts are reported in quotations - else - None, mkCoerceIfNeeded cenv.g calledArgTy callerArgTy callerArgExpr - - // Handle param array and optional arguments - let optArgPreBinder, paramArrayPreBinders, allArgs, outArgExprs, outArgTmpBinds = - - let normalUnnamedArgs = - (finalUnnamedCalledArgs, finalUnnamedCallerArgs) ||> List.map2 (fun called caller -> { NamedArgIdOpt = None; CalledArg=called; CallerArg=caller }) - - let paramArrayPreBinders, paramArrayArgs = - match finalCalledMeth.ParamArrayCalledArgOpt with - | None -> - [], [] - | Some paramArrayCalledArg -> - let paramArrayCalledArgElementType = destArrayTy cenv.g paramArrayCalledArg.CalledArgumentType - - let paramArrayPreBinders, es = - finalParamArrayCallerArgs - |> List.map (fun callerArg -> - let (CallerArg(callerArgTy, m, isOutArg, callerArgExpr)) = callerArg - coerceExpr isOutArg paramArrayCalledArgElementType paramArrayCalledArg.ReflArgInfo callerArgTy m callerArgExpr) - |> List.unzip - - let arg = - [ { NamedArgIdOpt = None - CalledArg=paramArrayCalledArg - CallerArg=CallerArg(paramArrayCalledArg.CalledArgumentType, mMethExpr, false, Expr.Op (TOp.Array, [paramArrayCalledArgElementType], es, mMethExpr)) } ] - paramArrayPreBinders, arg - - // CLEANUP: Move all this code into some isolated file, e.g. "optional.fs" - // - // Handle CallerSide optional arguments. - // - // CallerSide optional arguments are largely for COM interop, e.g. to PIA assemblies for Word etc. - // As a result we follow the VB and C# behavior here. - // - // "1. If the parameter is statically typed as System.Object and does not have a value, then there are four cases: - // a. The parameter is marked with MarshalAs(IUnknown), MarshalAs(Interface), or MarshalAs(IDispatch). In this case we pass null. - // b. Else if the parameter is marked with IUnknownConstantAttribute. In this case we pass new System.Runtime.InteropServices.UnknownWrapper(null) - // c. Else if the parameter is marked with IDispatchConstantAttribute. In this case we pass new System.Runtime.InteropServices.DispatchWrapper(null) - // d. Else, we will pass Missing.Value. - // 2. Otherwise, if there is a value attribute, then emit the default value. - // 3. Otherwise, we emit default(T). - // 4. Finally, we apply conversions from the value to the parameter type. This is where the nullable conversions take place for VB. - // - VB allows you to mark ref parameters as optional. The semantics of this is that we create a temporary - // with type = type of parameter, load the optional value to it, and call the method. - // - VB also allows you to mark arrays with Nothing as the optional value. - // - VB also allows you to pass intrinsic values as optional values to parameters - // typed as Object. What we do in this case is we box the intrinsic value." - // - let optArgs, optArgPreBinder = - (emptyPreBinder, finalUnnamedCalledOptArgs) ||> List.mapFold (fun wrapper calledArg -> - let calledArgTy = calledArg.CalledArgumentType - let wrapper2, expr = - match calledArg.OptArgInfo with - | NotOptional -> - error(InternalError("Unexpected NotOptional", mItem)) - | CallerSide dfltVal -> - let rec build currCalledArgTy currDfltVal = - match currDfltVal with - | MissingValue -> - // Add an I_nop if this is an initonly field to make sure we never recognize it as an lvalue. See mkExprAddrOfExpr. - emptyPreBinder, mkAsmExpr ([ mkNormalLdsfld (fspec_Missing_Value cenv.g); AI_nop ], [], [], [currCalledArgTy], mMethExpr) - | DefaultValue -> - emptyPreBinder, mkDefault(mMethExpr, currCalledArgTy) - | Constant fieldInit -> - match currCalledArgTy with - | NullableTy cenv.g inst when fieldInit <> ILFieldInit.Null -> - let nullableTy = mkILNonGenericBoxedTy(cenv.g.FindSysILTypeRef "System.Nullable`1") - let ctor = mkILCtorMethSpecForTy(nullableTy, [ILType.TypeVar 0us]).MethodRef - let ctorArgs = [Expr.Const (TcFieldInit mMethExpr fieldInit, mMethExpr, inst)] - emptyPreBinder, Expr.Op (TOp.ILCall (false, false, true, true, NormalValUse, false, false, ctor, [inst], [], [currCalledArgTy]), [], ctorArgs, mMethExpr) - | ByrefTy cenv.g inst -> - build inst (PassByRef(inst, currDfltVal)) - | _ -> - match calledArg.CallerInfo, env.eCallerMemberName with - | CallerLineNumber, _ when typeEquiv cenv.g currCalledArgTy cenv.g.int_ty -> - emptyPreBinder, Expr.Const (Const.Int32(mMethExpr.StartLine), mMethExpr, currCalledArgTy) - | CallerFilePath, _ when typeEquiv cenv.g currCalledArgTy cenv.g.string_ty -> - let fileName = mMethExpr.FileName |> FileSystem.GetFullPathShim |> PathMap.apply cenv.g.pathMap - emptyPreBinder, Expr.Const (Const.String fileName, mMethExpr, currCalledArgTy) - | CallerMemberName, Some callerName when (typeEquiv cenv.g currCalledArgTy cenv.g.string_ty) -> - emptyPreBinder, Expr.Const (Const.String callerName, mMethExpr, currCalledArgTy) - | _ -> - emptyPreBinder, Expr.Const (TcFieldInit mMethExpr fieldInit, mMethExpr, currCalledArgTy) - - | WrapperForIDispatch -> - match cenv.g.TryFindSysILTypeRef "System.Runtime.InteropServices.DispatchWrapper" with - | None -> error(Error(FSComp.SR.fscSystemRuntimeInteropServicesIsRequired(), mMethExpr)) - | Some tref -> - let ty = mkILNonGenericBoxedTy tref - let mref = mkILCtorMethSpecForTy(ty, [cenv.g.ilg.typ_Object]).MethodRef - let expr = Expr.Op (TOp.ILCall (false, false, false, true, NormalValUse, false, false, mref, [], [], [cenv.g.obj_ty]), [], [mkDefault(mMethExpr, currCalledArgTy)], mMethExpr) - emptyPreBinder, expr - | WrapperForIUnknown -> - match cenv.g.TryFindSysILTypeRef "System.Runtime.InteropServices.UnknownWrapper" with - | None -> error(Error(FSComp.SR.fscSystemRuntimeInteropServicesIsRequired(), mMethExpr)) - | Some tref -> - let ty = mkILNonGenericBoxedTy tref - let mref = mkILCtorMethSpecForTy(ty, [cenv.g.ilg.typ_Object]).MethodRef - let expr = Expr.Op (TOp.ILCall (false, false, false, true, NormalValUse, false, false, mref, [], [], [cenv.g.obj_ty]), [], [mkDefault(mMethExpr, currCalledArgTy)], mMethExpr) - emptyPreBinder, expr - | PassByRef (ty, dfltVal2) -> - let v, _ = mkCompGenLocal mMethExpr "defaultByrefArg" ty - let wrapper2, rhs = build currCalledArgTy dfltVal2 - (wrapper2 >> mkCompGenLet mMethExpr v rhs), mkValAddr mMethExpr false (mkLocalValRef v) - build calledArgTy dfltVal - | CalleeSide -> - let calledNonOptTy = - if isOptionTy cenv.g calledArgTy then - destOptionTy cenv.g calledArgTy - else - calledArgTy // should be unreachable - - match calledArg.CallerInfo, env.eCallerMemberName with - | CallerLineNumber, _ when typeEquiv cenv.g calledNonOptTy cenv.g.int_ty -> - let lineExpr = Expr.Const(Const.Int32 mMethExpr.StartLine, mMethExpr, calledNonOptTy) - emptyPreBinder, mkSome cenv.g calledNonOptTy lineExpr mMethExpr - | CallerFilePath, _ when typeEquiv cenv.g calledNonOptTy cenv.g.string_ty -> - let fileName = mMethExpr.FileName |> FileSystem.GetFullPathShim |> PathMap.apply cenv.g.pathMap - let filePathExpr = Expr.Const (Const.String(fileName), mMethExpr, calledNonOptTy) - emptyPreBinder, mkSome cenv.g calledNonOptTy filePathExpr mMethExpr - | CallerMemberName, Some(callerName) when typeEquiv cenv.g calledNonOptTy cenv.g.string_ty -> - let memberNameExpr = Expr.Const (Const.String callerName, mMethExpr, calledNonOptTy) - emptyPreBinder, mkSome cenv.g calledNonOptTy memberNameExpr mMethExpr - | _ -> - emptyPreBinder, mkNone cenv.g calledNonOptTy mMethExpr - - // Combine the variable allocators (if any) - let wrapper = (wrapper >> wrapper2) - let callerArg = CallerArg(calledArgTy, mMethExpr, false, expr) - { NamedArgIdOpt = None; CalledArg = calledArg; CallerArg = callerArg }, wrapper) - - - // Handle optional arguments - let wrapOptionalArg (assignedArg: AssignedCalledArg<_>) = - let (CallerArg(callerArgTy, m, isOptCallerArg, expr)) = assignedArg.CallerArg - match assignedArg.CalledArg.OptArgInfo with - | NotOptional -> - if isOptCallerArg then errorR(Error(FSComp.SR.tcFormalArgumentIsNotOptional(), m)) - assignedArg - | _ -> - let expr = - match assignedArg.CalledArg.OptArgInfo with - | CallerSide _ -> - if isOptCallerArg then - // STRUCT OPTIONS: if we allow struct options as optional arguments then we should take - // the address correctly. - mkUnionCaseFieldGetUnprovenViaExprAddr (expr, mkSomeCase cenv.g, [destOptionTy cenv.g callerArgTy], 0, m) - else - expr - | CalleeSide -> - if isOptCallerArg then - // M(?x=bopt) when M(A) --> M(?x=Some(b.Value)) - expr - else - // M(x=b) when M(A) --> M(?x=Some(b :> A)) - let calledArgTy = assignedArg.CalledArg.CalledArgumentType - if isOptionTy cenv.g calledArgTy then - let calledNonOptTy = destOptionTy cenv.g calledArgTy - mkSome cenv.g calledNonOptTy (mkCoerceIfNeeded cenv.g calledNonOptTy callerArgTy expr) m - else - expr // should be unreachable - - | _ -> failwith "Unreachable" - { assignedArg with CallerArg=CallerArg((tyOfExpr cenv.g expr), m, isOptCallerArg, expr) } - - let outArgsAndExprs, outArgTmpBinds = - finalUnnamedCalledOutArgs |> List.map (fun calledArg -> - let calledArgTy = calledArg.CalledArgumentType - let outArgTy = destByrefTy cenv.g calledArgTy - let outv, outArgExpr = mkMutableCompGenLocal mMethExpr PrettyNaming.outArgCompilerGeneratedName outArgTy // mutable! - let expr = mkDefault(mMethExpr, outArgTy) - let callerArg = CallerArg(calledArgTy, mMethExpr, false, mkValAddr mMethExpr false (mkLocalValRef outv)) - let outArg = { NamedArgIdOpt=None;CalledArg=calledArg;CallerArg=callerArg } - (outArg, outArgExpr), mkCompGenBind outv expr) - |> List.unzip - - let outArgs, outArgExprs = List.unzip outArgsAndExprs - - let allArgs = - List.map wrapOptionalArg normalUnnamedArgs @ - List.map wrapOptionalArg finalAssignedNamedArgs @ - paramArrayArgs @ - optArgs @ - outArgs - - let allArgs = - allArgs |> List.sortBy (fun x -> x.Position) - - optArgPreBinder, paramArrayPreBinders, allArgs, outArgExprs, outArgTmpBinds - - let coerce (assignedArg: AssignedCalledArg<_>) = - let isOutArg = assignedArg.CalledArg.IsOutArg - let reflArgInfo = assignedArg.CalledArg.ReflArgInfo - let calledArgTy = assignedArg.CalledArg.CalledArgumentType - let (CallerArg(callerArgTy, m, _, e)) = assignedArg.CallerArg - - coerceExpr isOutArg calledArgTy reflArgInfo callerArgTy m e + let objArgPreBinder, objArgs, allArgsPreBinders, allArgs, allArgsCoerced, optArgPreBinder, paramArrayPreBinders, outArgExprs, outArgTmpBinds = + AdjustCallerArgExprs TcFieldInit env.eCallerMemberName cenv.g cenv.amap cenv.infoReader ad finalCalledMeth objArgs lambdaVars mItem mMethExpr // Record the resolution of the named argument for the Language Service allArgs |> List.iter (fun assignedArg -> @@ -10295,84 +10032,61 @@ and TcMethodApplication let item = Item.ArgName (defaultArg assignedArg.CalledArg.NameOpt id, assignedArg.CalledArg.CalledArgumentType, Some(ArgumentContainer.Method finalCalledMethInfo)) CallNameResolutionSink cenv.tcSink (id.idRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Use, env.DisplayEnv, ad)) - let allArgsPreBinders, allArgsCoerced = List.map coerce allArgs |> List.unzip - // Make the call expression - let expr, exprty = + /// STEP 6. Build the call expression, then adjust for byref-returns, out-parameters-as-tuples, post-hoc property assignments, methods-as-first-class-value, + /// + + let callExpr0, exprty = BuildPossiblyConditionalMethodCall cenv env mut mMethExpr isProp finalCalledMethInfo isSuperInit finalCalledMethInst objArgs allArgsCoerced // Handle byref returns - let expr = + let callExpr1 = // byref-typed returns get implicitly dereferenced - let vty = tyOfExpr cenv.g expr + let vty = tyOfExpr cenv.g callExpr0 if isByrefTy cenv.g vty then let v, _ = mkCompGenLocal mMethExpr "byrefReturn" vty - mkCompGenLet mMethExpr v expr (mkAddrGet mMethExpr (mkLocalValRef v)) + mkCompGenLet mMethExpr v callExpr0 (mkAddrGet mMethExpr (mkLocalValRef v)) else - expr + callExpr0 // Bind "out" parameters as part of the result tuple - let expr, exprty = + let callExpr2, exprty = + let expr = callExpr1 if isNil outArgTmpBinds then expr, exprty else let outArgTys = outArgExprs |> List.map (tyOfExpr cenv.g) - let expr = if isUnitTy cenv.g exprty then mkCompGenSequential mMethExpr expr (mkRefTupled cenv.g mMethExpr outArgExprs outArgTys) - else mkRefTupled cenv.g mMethExpr (expr :: outArgExprs) (exprty :: outArgTys) + let expr = + if isUnitTy cenv.g exprty then + mkCompGenSequential mMethExpr expr (mkRefTupled cenv.g mMethExpr outArgExprs outArgTys) + else + mkRefTupled cenv.g mMethExpr (expr :: outArgExprs) (exprty :: outArgTys) let expr = mkLetsBind mMethExpr outArgTmpBinds expr expr, tyOfExpr cenv.g expr // Handle post-hoc property assignments - let setterExprPrebinders, expr = - if isCheckingAttributeCall then - [], expr - elif isNil finalAssignedItemSetters then - [], expr - else - // This holds the result of the call - let objv, objExpr = mkMutableCompGenLocal mMethExpr "returnVal" exprty // mutable in case it's a struct - // This expression mutates the properties on the result of the call - let setterExprPrebinders, propSetExpr = - (mkUnit cenv.g mMethExpr, finalAssignedItemSetters) ||> List.mapFold (fun acc (AssignedItemSetter(id, setter, CallerArg(callerArgTy, m, isOptCallerArg, argExpr))) -> - if isOptCallerArg then error(Error(FSComp.SR.tcInvalidOptionalAssignmentToPropertyOrField(), m)) - - let argExprPrebinder, action, defnItem = - match setter with - | AssignedPropSetter (pinfo, pminfo, pminst) -> - MethInfoChecks cenv.g cenv.amap true None [objExpr] ad m pminfo - let calledArgTy = List.head (List.head (pminfo.GetParamTypes(cenv.amap, m, pminst))) - let argExprPrebinder, argExpr = coerceExpr false calledArgTy ReflectedArgInfo.None callerArgTy m argExpr - let mut = (if isStructTy cenv.g (tyOfExpr cenv.g objExpr) then DefinitelyMutates else PossiblyMutates) - let action = BuildPossiblyConditionalMethodCall cenv env mut m true pminfo NormalValUse pminst [objExpr] [argExpr] |> fst - argExprPrebinder, action, Item.Property (pinfo.PropertyName, [pinfo]) - - | AssignedILFieldSetter finfo -> - // Get or set instance IL field - ILFieldInstanceChecks cenv.g cenv.amap ad m finfo - let calledArgTy = finfo.FieldType (cenv.amap, m) - let argExprPrebinder, argExpr = coerceExpr false calledArgTy ReflectedArgInfo.None callerArgTy m argExpr - let action = BuildILFieldSet cenv.g m objExpr finfo argExpr - argExprPrebinder, action, Item.ILField finfo - - | AssignedRecdFieldSetter rfinfo -> - RecdFieldInstanceChecks cenv.g cenv.amap ad m rfinfo - let calledArgTy = rfinfo.FieldType - CheckRecdFieldMutation m denv rfinfo - let argExprPrebinder, argExpr = coerceExpr false calledArgTy ReflectedArgInfo.None callerArgTy m argExpr - let action = BuildRecdFieldSet cenv.g m objExpr rfinfo argExpr - argExprPrebinder, action, Item.RecdField rfinfo - - // Record the resolution for the Language Service - let item = Item.SetterArg (id, defnItem) - CallNameResolutionSink cenv.tcSink (id.idRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Use, env.DisplayEnv, ad) - - argExprPrebinder, mkCompGenSequential m acc action) - - // now put them together - let expr = mkCompGenLet mMethExpr objv expr (mkCompGenSequential mMethExpr propSetExpr objExpr) - setterExprPrebinders, expr - - // Build the lambda expression if any - let expr = + let setterExprPrebinders, callExpr3 = + let expr = callExpr2 + if isCheckingAttributeCall then + [], expr + elif isNil finalAssignedItemSetters then + [], expr + else + // This holds the result of the call + let objv, objExpr = mkMutableCompGenLocal mMethExpr "returnVal" exprty // mutable in case it's a struct + + // Build the expression that mutates the properties on the result of the call + let setterExprPrebinders, propSetExpr = + (mkUnit cenv.g mMethExpr, finalAssignedItemSetters) ||> List.mapFold (fun acc assignedItemSetter -> + let argExprPrebinder, action, m = TcSetterArgExpr cenv env denv objExpr ad assignedItemSetter + argExprPrebinder, mkCompGenSequential m acc action) + + // now put them together + let expr = mkCompGenLet mMethExpr objv expr (mkCompGenSequential mMethExpr propSetExpr objExpr) + setterExprPrebinders, expr + + // Build the lambda expression if any, if the method is used as a first-class value + let callExpr4 = + let expr = callExpr3 match lambdaVars with | None -> expr | Some curriedLambdaVars -> @@ -10382,7 +10096,8 @@ and TcMethodApplication | _ -> mkMultiLambda mMethExpr vs (expr, tyOfExpr cenv.g expr) List.foldBack mkLambda curriedLambdaVars expr - let expr, tpenv = + let callExpr5, tpenv = + let expr = callExpr4 match unnamedDelayedCallerArgExprOpt with | Some synArgExpr -> match lambdaVars with @@ -10395,15 +10110,53 @@ and TcMethodApplication expr, tpenv // Apply the PreBinders, if any - let expr = (expr, setterExprPrebinders) ||> List.fold (fun expr argPreBinder -> match argPreBinder with None -> expr | Some f -> f expr) - let expr = (expr, paramArrayPreBinders) ||> List.fold (fun expr argPreBinder -> match argPreBinder with None -> expr | Some f -> f expr) - let expr = (expr, allArgsPreBinders) ||> List.fold (fun expr argPreBinder -> match argPreBinder with None -> expr | Some f -> f expr) + let callExpr6 = + let expr = callExpr5 + let expr = (expr, setterExprPrebinders) ||> List.fold (fun expr argPreBinder -> match argPreBinder with None -> expr | Some f -> f expr) + let expr = (expr, paramArrayPreBinders) ||> List.fold (fun expr argPreBinder -> match argPreBinder with None -> expr | Some f -> f expr) + let expr = (expr, allArgsPreBinders) ||> List.fold (fun expr argPreBinder -> match argPreBinder with None -> expr | Some f -> f expr) - let expr = optArgPreBinder expr - let expr = objArgPreBinder expr + let expr = optArgPreBinder expr + let expr = objArgPreBinder expr + expr - (expr, finalAttributeAssignedNamedItems, delayed), tpenv + (callExpr6, finalAttributeAssignedNamedItems, delayed), tpenv +and TcSetterArgExpr cenv env denv objExpr ad (AssignedItemSetter(id, setter, CallerArg(callerArgTy, m, isOptCallerArg, argExpr))) = + if isOptCallerArg then error(Error(FSComp.SR.tcInvalidOptionalAssignmentToPropertyOrField(), m)) + + let argExprPrebinder, action, defnItem = + match setter with + | AssignedPropSetter (pinfo, pminfo, pminst) -> + MethInfoChecks cenv.g cenv.amap true None [objExpr] ad m pminfo + let calledArgTy = List.head (List.head (pminfo.GetParamTypes(cenv.amap, m, pminst))) + let argExprPrebinder, argExpr = MethodCalls.AdjustCallerArgExprForCoercions cenv.g cenv.amap cenv.infoReader ad false calledArgTy ReflectedArgInfo.None callerArgTy m argExpr + let mut = (if isStructTy cenv.g (tyOfExpr cenv.g objExpr) then DefinitelyMutates else PossiblyMutates) + let action = BuildPossiblyConditionalMethodCall cenv env mut m true pminfo NormalValUse pminst [objExpr] [argExpr] |> fst + argExprPrebinder, action, Item.Property (pinfo.PropertyName, [pinfo]) + + | AssignedILFieldSetter finfo -> + // Get or set instance IL field + ILFieldInstanceChecks cenv.g cenv.amap ad m finfo + let calledArgTy = finfo.FieldType (cenv.amap, m) + let argExprPrebinder, argExpr = MethodCalls.AdjustCallerArgExprForCoercions cenv.g cenv.amap cenv.infoReader ad false calledArgTy ReflectedArgInfo.None callerArgTy m argExpr + let action = BuildILFieldSet cenv.g m objExpr finfo argExpr + argExprPrebinder, action, Item.ILField finfo + + | AssignedRecdFieldSetter rfinfo -> + RecdFieldInstanceChecks cenv.g cenv.amap ad m rfinfo + let calledArgTy = rfinfo.FieldType + CheckRecdFieldMutation m denv rfinfo + let argExprPrebinder, argExpr = MethodCalls.AdjustCallerArgExprForCoercions cenv.g cenv.amap cenv.infoReader ad false calledArgTy ReflectedArgInfo.None callerArgTy m argExpr + let action = BuildRecdFieldSet cenv.g m objExpr rfinfo argExpr + argExprPrebinder, action, Item.RecdField rfinfo + + // Record the resolution for the Language Service + let item = Item.SetterArg (id, defnItem) + CallNameResolutionSink cenv.tcSink (id.idRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Use, env.DisplayEnv, ad) + + argExprPrebinder, action, m + and TcUnnamedMethodArgs cenv env lambdaPropagationInfo tpenv args = List.mapiFoldSquared (TcUnnamedMethodArg cenv env) (lambdaPropagationInfo, tpenv) args diff --git a/src/fsharp/xlf/FSComp.txt.es.xlf b/src/fsharp/xlf/FSComp.txt.es.xlf index 56f087fb38d..279d16a7c90 100644 --- a/src/fsharp/xlf/FSComp.txt.es.xlf +++ b/src/fsharp/xlf/FSComp.txt.es.xlf @@ -124,7 +124,7 @@ All branches of a pattern match expression must return values of the same type as the first branch, which here is '{0}'. This branch returns a value of type '{1}'. - Todas las ramas de una expresión de coincidencia de patrón deben devolver valores del mismo tipo. La primera rama devolvió un valor de tipo "{0}", pero esta rama devolvió un valor de tipo "\{1 \}". + All branches of a pattern match expression must return values of the same type as the first branch, which here is '{0}'. This branch returns a value of type '{1}'. diff --git a/tests/fsharp/core/fsfromfsviacs/lib3.cs b/tests/fsharp/core/fsfromfsviacs/lib3.cs index b688b710bc2..91a3dffe4bb 100644 --- a/tests/fsharp/core/fsfromfsviacs/lib3.cs +++ b/tests/fsharp/core/fsfromfsviacs/lib3.cs @@ -24,3 +24,29 @@ public static void SomeMethod() { } } } +namespace CSharpOptionalParameters +{ + // This should be preferred over the same type in lib2.cs + public class SomeClass + { + public SomeClass() { } + public static int MethodTakingOptionals(int x = 3, string y = "abc", double d = 5.0) + { + return x + y.Length + (int) d; + } + public static int MethodTakingNullableOptionalsWithDefaults(int? x = 3, string y = "abc", double? d = 5.0) + { + return (x.HasValue ? x.Value : -100) + y.Length + (int) (d.HasValue ? d.Value : 0.0); + } + public static int MethodTakingNullableOptionals(int? x = null, string y = null, double? d = null) + { + int length; + if (y == null) + length = -1; + else + length = y.Length; + return (x.HasValue ? x.Value : -1) + length + (int) (d.HasValue ? d.Value : -1.0); + } + } + +} diff --git a/tests/fsharp/core/fsfromfsviacs/test.fsx b/tests/fsharp/core/fsfromfsviacs/test.fsx index 76ec203112f..072a896c1eb 100644 --- a/tests/fsharp/core/fsfromfsviacs/test.fsx +++ b/tests/fsharp/core/fsfromfsviacs/test.fsx @@ -71,22 +71,53 @@ let _ = test "structunion394b36" (Lib.NestedStructUnionsTests.testPattern3mut(u2 // F# option implicit converter tests -let testFsOpt() = - let testOpt (t : 'T option) = - test (sprintf "fsimplicitconv (%A)" t) (ApiWrapper.ConsumeOptionalParam<'T>(t) = t) - - testOpt(Option.None) - testOpt(Some 42) - - // check that implicit conversion of optionals does - // differentiate between 'null' and 'Some null' - testOpt(Option.None) - testOpt(Option.Some null) - testOpt(Some "") - testOpt(Some "test") - -testFsOpt() - +module TestConsumeOptionalParameter = + let testFsOpt() = + let testOpt (t : 'T option) = + test (sprintf "fsimplicitconv (%A)" t) (ApiWrapper.ConsumeOptionalParam<'T>(t) = t) + + testOpt(Option.None) + testOpt(Some 42) + + // check that implicit conversion of optionals does + // differentiate between 'null' and 'Some null' + testOpt(Option.None) + testOpt(Option.Some null) + testOpt(Some "") + testOpt(Some "test") + + testFsOpt() + +module TestConsumeCSharpOptionalParameter = + open System + open CSharpOptionalParameters + check "csoptional23982f31" (SomeClass.MethodTakingOptionals()) 11 + check "csoptional23982f32" (SomeClass.MethodTakingOptionals(x = 6)) 14 + check "csoptional23982f33" (SomeClass.MethodTakingOptionals(y = "aaaaaa")) 14 + check "csoptional23982f34" (SomeClass.MethodTakingOptionals(d = 8.0)) 14 + + check "csoptional23982f41" (SomeClass.MethodTakingNullableOptionalsWithDefaults()) 11 + check "csoptional23982f42" (SomeClass.MethodTakingNullableOptionalsWithDefaults(x = Nullable 6)) 14 + check "csoptional23982f43" (SomeClass.MethodTakingNullableOptionalsWithDefaults(y = "aaaaaa")) 14 + check "csoptional23982f44" (SomeClass.MethodTakingNullableOptionalsWithDefaults(d = Nullable 8.0)) 14 + + check "csoptional23982f51" (SomeClass.MethodTakingNullableOptionals()) -3 + check "csoptional23982f52" (SomeClass.MethodTakingNullableOptionals(x = Nullable 6)) 4 + check "csoptional23982f53" (SomeClass.MethodTakingNullableOptionals(y = "aaaaaa")) 4 + check "csoptional23982f54" (SomeClass.MethodTakingNullableOptionals(d = Nullable 8.0)) 6 + + // These require https://github.com/fsharp/fslang-suggestions/issues/774 to be implemented + //check "csoptional23982f3no" (SomeClass.SomeMethod(?x = Some 6)) 14 + //check "csoptional23982f3no" (SomeClass.SomeMethod(?y = Some "aaaaaa")) 14 + //check "csoptional23982f3no" (SomeClass.SomeMethod(?d = Some 8.0)) 14 + //check "csoptional23982f3no" (SomeClass.SomeMethod(?x = None)) 11 + //check "csoptional23982f3no" (SomeClass.SomeMethod(?y = None)) 11 + //check "csoptional23982f3no" (SomeClass.SomeMethod(?d = None)) 11 + + //check "csoptional23982f42" (SomeClass.MethodTakingNullableOptionalsWithDefaults(x = 6)) 14 + //check "csoptional23982f44" (SomeClass.MethodTakingNullableOptionalsWithDefaults(d = 8.0)) 14 + //check "csoptional23982f52" (SomeClass.MethodTakingNullableOptionals(x = 6)) 4 + //check "csoptional23982f54" (SomeClass.MethodTakingNullableOptionals(d = 8.0)) 6 module NestedStructPatternMatchingAcrossAssemblyBoundaries = open Lib.NestedStructUnionsTests diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.cs.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.cs.xlf index a678a4bcfeb..860555f3440 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.cs.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.cs.xlf @@ -1828,8 +1828,9 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size + # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.de.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.de.xlf index 662133483e3..65b4328fdc2 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.de.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.de.xlf @@ -1828,8 +1828,9 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size + # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.es.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.es.xlf index 41dbc88f0bd..1153755c3dd 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.es.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.es.xlf @@ -1828,8 +1828,9 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size + # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.fr.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.fr.xlf index 0f1e16e95f2..cd60e9f07e9 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.fr.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.fr.xlf @@ -1828,8 +1828,9 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size + # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.it.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.it.xlf index 8902030751c..dd58cb9a119 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.it.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.it.xlf @@ -1828,8 +1828,9 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size + # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ja.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ja.xlf index a39e49dfa0d..bdb896a5c83 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ja.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ja.xlf @@ -1828,8 +1828,9 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size + # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ko.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ko.xlf index e7191ac3c4a..6f540b54250 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ko.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ko.xlf @@ -1828,8 +1828,9 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size + # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.pl.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.pl.xlf index d0675bd2fcb..73bef853b9f 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.pl.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.pl.xlf @@ -1828,8 +1828,9 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size + # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.pt-BR.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.pt-BR.xlf index acfade88845..3e8a1693485 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.pt-BR.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.pt-BR.xlf @@ -1828,8 +1828,9 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size + # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ru.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ru.xlf index 355d363084e..2b5303d91de 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ru.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.ru.xlf @@ -1828,8 +1828,9 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size + # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.tr.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.tr.xlf index 86ac32f4b37..73a72b806a2 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.tr.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.tr.xlf @@ -1828,8 +1828,9 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size + # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.zh-Hans.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.zh-Hans.xlf index 0537632d5fc..474f99a3dcd 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.zh-Hans.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.zh-Hans.xlf @@ -1828,8 +1828,9 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size + # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" diff --git a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.zh-Hant.xlf b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.zh-Hant.xlf index 17c64ffefb9..16b7339b2a4 100644 --- a/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.zh-Hant.xlf +++ b/vsintegration/src/FSharp.ProjectSystem.PropertyPages/Resources/xlf/Microsoft.VisualStudio.Editors.Designer.zh-Hant.xlf @@ -1828,8 +1828,9 @@ CONSIDER: get this from CodeDom {0} x {1} - {0} x {1} + {0} x {1} Format string for showing a graphic's size + # {0} = width (as an integer) # {1} = height (as an integer) #Example, for a bitmap of width=123, height = 456, the English version of this string would be "123x456" From e72ded1638bf17f7310c2b0080dc38edceedea1f Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Sat, 27 Jul 2019 11:26:05 -0700 Subject: [PATCH 41/46] Update dependencies from https://github.com/dotnet/arcade build 20190726.18 (#7285) - Microsoft.DotNet.Arcade.Sdk - 1.0.0-beta.19376.18 --- eng/Version.Details.xml | 4 +- eng/common/post-build/darc-gather-drop.ps1 | 17 ++-- eng/common/post-build/nuget-validation.ps1 | 5 +- eng/common/post-build/post-build-utils.ps1 | 90 +++++++++++++++++++ eng/common/post-build/promote-build.ps1 | 37 ++++---- eng/common/post-build/setup-maestro-vars.ps1 | 26 ++++++ .../post-build/sourcelink-validation.ps1 | 31 ++++--- eng/common/post-build/symbols-validation.ps1 | 29 +++--- .../post-build/trigger-subscriptions.ps1 | 48 ++++------ .../channels/internal-servicing.yml | 5 +- .../channels/public-dev-release.yml | 5 +- .../post-build/channels/public-release.yml | 5 +- .../channels/public-validation-release.yml | 9 +- .../templates/post-build/common-variables.yml | 34 +++++-- .../templates/post-build/darc-gather-drop.yml | 5 +- .../templates/post-build/post-build.yml | 5 +- .../templates/post-build/promote-build.yml | 5 +- .../post-build/setup-maestro-vars.yml | 21 +---- .../post-build/trigger-subscription.yml | 4 +- global.json | 2 +- 20 files changed, 246 insertions(+), 141 deletions(-) create mode 100644 eng/common/post-build/post-build-utils.ps1 create mode 100644 eng/common/post-build/setup-maestro-vars.ps1 diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 7a0a634b410..0893278ac13 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -3,9 +3,9 @@ - + https://github.com/dotnet/arcade - ef1c110152df0d500fffb87878a86f88d1ca5295 + 316481e57ee5e6acbbf2401eb6778a1d3d48d25b diff --git a/eng/common/post-build/darc-gather-drop.ps1 b/eng/common/post-build/darc-gather-drop.ps1 index 9cc2f1a0091..93a0bd83285 100644 --- a/eng/common/post-build/darc-gather-drop.ps1 +++ b/eng/common/post-build/darc-gather-drop.ps1 @@ -1,13 +1,12 @@ param( - [Parameter(Mandatory=$true)][string] $BarBuildId, # ID of the build which assets should be downloaded - [Parameter(Mandatory=$true)][string] $MaestroAccessToken, # Token used to access Maestro API - [Parameter(Mandatory=$true)][string] $DropLocation # Where the assets should be downloaded to + [Parameter(Mandatory=$true)][int] $BarBuildId, # ID of the build which assets should be downloaded + [Parameter(Mandatory=$true)][string] $DropLocation, # Where the assets should be downloaded to + [Parameter(Mandatory=$true)][string] $MaestroApiAccessToken, # Token used to access Maestro API + [Parameter(Mandatory=$false)][string] $MaestroApiEndPoint = "https://maestro-prod.westus2.cloudapp.azure.com", # Maestro API URL + [Parameter(Mandatory=$false)][string] $MaestroApiVersion = "2019-01-16" # Version of Maestro API to use ) -$ErrorActionPreference = "Stop" -Set-StrictMode -Version 2.0 - -. $PSScriptRoot\..\tools.ps1 +. $PSScriptRoot\post-build-utils.ps1 try { Write-Host "Installing DARC ..." @@ -24,8 +23,8 @@ try { --continue-on-error ` --id $BarBuildId ` --output-dir $DropLocation ` - --bar-uri https://maestro-prod.westus2.cloudapp.azure.com/ ` - --password $MaestroAccessToken ` + --bar-uri $MaestroApiEndpoint ` + --password $MaestroApiAccessToken ` --latest-location } catch { diff --git a/eng/common/post-build/nuget-validation.ps1 b/eng/common/post-build/nuget-validation.ps1 index 1bdced1e307..78ed0d540f5 100644 --- a/eng/common/post-build/nuget-validation.ps1 +++ b/eng/common/post-build/nuget-validation.ps1 @@ -6,10 +6,7 @@ param( [Parameter(Mandatory=$true)][string] $ToolDestinationPath # Where the validation tool should be downloaded to ) -$ErrorActionPreference = "Stop" -Set-StrictMode -Version 2.0 - -. $PSScriptRoot\..\tools.ps1 +. $PSScriptRoot\post-build-utils.ps1 try { $url = "https://raw.githubusercontent.com/NuGet/NuGetGallery/jver-verify/src/VerifyMicrosoftPackage/verify.ps1" diff --git a/eng/common/post-build/post-build-utils.ps1 b/eng/common/post-build/post-build-utils.ps1 new file mode 100644 index 00000000000..551ae113f89 --- /dev/null +++ b/eng/common/post-build/post-build-utils.ps1 @@ -0,0 +1,90 @@ +# Most of the functions in this file require the variables `MaestroApiEndPoint`, +# `MaestroApiVersion` and `MaestroApiAccessToken` to be globally available. + +$ErrorActionPreference = "Stop" +Set-StrictMode -Version 2.0 + +# `tools.ps1` checks $ci to perform some actions. Since the post-build +# scripts don't necessarily execute in the same agent that run the +# build.ps1/sh script this variable isn't automatically set. +$ci = $true +. $PSScriptRoot\..\tools.ps1 + +function Create-MaestroApiRequestHeaders([string]$ContentType = "application/json") { + Validate-MaestroVars + + $headers = New-Object 'System.Collections.Generic.Dictionary[[String],[String]]' + $headers.Add('Accept', $ContentType) + $headers.Add('Authorization',"Bearer $MaestroApiAccessToken") + return $headers +} + +function Get-MaestroChannel([int]$ChannelId) { + Validate-MaestroVars + + $apiHeaders = Create-MaestroApiRequestHeaders + $apiEndpoint = "$MaestroApiEndPoint/api/channels/${ChannelId}?api-version=$MaestroApiVersion" + + $result = try { Invoke-WebRequest -Method Get -Uri $apiEndpoint -Headers $apiHeaders | ConvertFrom-Json } catch { Write-Host "Error: $_" } + return $result +} + +function Get-MaestroBuild([int]$BuildId) { + Validate-MaestroVars + + $apiHeaders = Create-MaestroApiRequestHeaders -AuthToken $MaestroApiAccessToken + $apiEndpoint = "$MaestroApiEndPoint/api/builds/${BuildId}?api-version=$MaestroApiVersion" + + $result = try { return Invoke-WebRequest -Method Get -Uri $apiEndpoint -Headers $apiHeaders | ConvertFrom-Json } catch { Write-Host "Error: $_" } + return $result +} + +function Get-MaestroSubscriptions([string]$SourceRepository, [int]$ChannelId) { + Validate-MaestroVars + + $SourceRepository = [System.Web.HttpUtility]::UrlEncode($SourceRepository) + $apiHeaders = Create-MaestroApiRequestHeaders -AuthToken $MaestroApiAccessToken + $apiEndpoint = "$MaestroApiEndPoint/api/subscriptions?sourceRepository=$SourceRepository&channelId=$ChannelId&api-version=$MaestroApiVersion" + + $result = try { Invoke-WebRequest -Method Get -Uri $apiEndpoint -Headers $apiHeaders | ConvertFrom-Json } catch { Write-Host "Error: $_" } + return $result +} + +function Trigger-Subscription([string]$SubscriptionId) { + Validate-MaestroVars + + $apiHeaders = Create-MaestroApiRequestHeaders -AuthToken $MaestroApiAccessToken + $apiEndpoint = "$MaestroApiEndPoint/api/subscriptions/$SubscriptionId/trigger?api-version=$MaestroApiVersion" + Invoke-WebRequest -Uri $apiEndpoint -Headers $apiHeaders -Method Post | Out-Null +} + +function Assign-BuildToChannel([int]$BuildId, [int]$ChannelId) { + Validate-MaestroVars + + $apiHeaders = Create-MaestroApiRequestHeaders -AuthToken $MaestroApiAccessToken + $apiEndpoint = "$MaestroApiEndPoint/api/channels/${ChannelId}/builds/${BuildId}?api-version=$MaestroApiVersion" + Invoke-WebRequest -Method Post -Uri $apiEndpoint -Headers $apiHeaders | Out-Null +} + +function Validate-MaestroVars { + try { + Get-Variable MaestroApiEndPoint -Scope Global | Out-Null + Get-Variable MaestroApiVersion -Scope Global | Out-Null + Get-Variable MaestroApiAccessToken -Scope Global | Out-Null + + if (!($MaestroApiEndPoint -Match "^http[s]?://maestro-(int|prod).westus2.cloudapp.azure.com$")) { + Write-PipelineTaskError "MaestroApiEndPoint is not a valid Maestro URL. '$MaestroApiEndPoint'" + ExitWithExitCode 1 + } + + if (!($MaestroApiVersion -Match "^[0-9]{4}-[0-9]{2}-[0-9]{2}$")) { + Write-PipelineTaskError "MaestroApiVersion does not match a version string in the format yyyy-MM-DD. '$MaestroApiVersion'" + ExitWithExitCode 1 + } + } + catch { + Write-PipelineTaskError "Error: Variables `MaestroApiEndPoint`, `MaestroApiVersion` and `MaestroApiAccessToken` are required while using this script." + Write-Host $_ + ExitWithExitCode 1 + } +} diff --git a/eng/common/post-build/promote-build.ps1 b/eng/common/post-build/promote-build.ps1 index 84a608fa569..e5ae85f2517 100644 --- a/eng/common/post-build/promote-build.ps1 +++ b/eng/common/post-build/promote-build.ps1 @@ -1,30 +1,25 @@ param( [Parameter(Mandatory=$true)][int] $BuildId, [Parameter(Mandatory=$true)][int] $ChannelId, - [Parameter(Mandatory=$true)][string] $BarToken, - [string] $MaestroEndpoint = "https://maestro-prod.westus2.cloudapp.azure.com", - [string] $ApiVersion = "2019-01-16" + [Parameter(Mandatory=$true)][string] $MaestroApiAccessToken, + [Parameter(Mandatory=$false)][string] $MaestroApiEndPoint = "https://maestro-prod.westus2.cloudapp.azure.com", + [Parameter(Mandatory=$false)][string] $MaestroApiVersion = "2019-01-16" ) -$ErrorActionPreference = "Stop" -Set-StrictMode -Version 2.0 - -. $PSScriptRoot\..\tools.ps1 - -function Get-Headers([string]$accept, [string]$barToken) { - $headers = New-Object 'System.Collections.Generic.Dictionary[[String],[String]]' - $headers.Add('Accept',$accept) - $headers.Add('Authorization',"Bearer $barToken") - return $headers -} +. $PSScriptRoot\post-build-utils.ps1 try { - $maestroHeaders = Get-Headers 'application/json' $BarToken + # Check that the channel we are going to promote the build to exist + $channelInfo = Get-MaestroChannel -ChannelId $ChannelId - # Get info about which channels the build has already been promoted to - $getBuildApiEndpoint = "$MaestroEndpoint/api/builds/${BuildId}?api-version=$ApiVersion" - $buildInfo = Invoke-WebRequest -Method Get -Uri $getBuildApiEndpoint -Headers $maestroHeaders | ConvertFrom-Json + if (!$channelInfo) { + Write-Host "Channel with BAR ID $ChannelId was not found in BAR!" + ExitWithExitCode 1 + } + # Get info about which channels the build has already been promoted to + $buildInfo = Get-MaestroBuild -BuildId $BuildId + if (!$buildInfo) { Write-Host "Build with BAR ID $BuildId was not found in BAR!" ExitWithExitCode 1 @@ -40,10 +35,10 @@ try { } } - Write-Host "Build not present in channel $ChannelId. Promoting build ... " + Write-Host "Promoting build '$BuildId' to channel '$ChannelId'." + + Assign-BuildToChannel -BuildId $BuildId -ChannelId $ChannelId - $promoteBuildApiEndpoint = "$maestroEndpoint/api/channels/${ChannelId}/builds/${BuildId}?api-version=$ApiVersion" - Invoke-WebRequest -Method Post -Uri $promoteBuildApiEndpoint -Headers $maestroHeaders Write-Host "done." } catch { diff --git a/eng/common/post-build/setup-maestro-vars.ps1 b/eng/common/post-build/setup-maestro-vars.ps1 new file mode 100644 index 00000000000..d7f64dc63cb --- /dev/null +++ b/eng/common/post-build/setup-maestro-vars.ps1 @@ -0,0 +1,26 @@ +param( + [Parameter(Mandatory=$true)][string] $ReleaseConfigsPath # Full path to ReleaseConfigs.txt asset +) + +. $PSScriptRoot\post-build-utils.ps1 + +try { + $Content = Get-Content $ReleaseConfigsPath + + $BarId = $Content | Select -Index 0 + + $Channels = "" + $Content | Select -Index 1 | ForEach-Object { $Channels += "$_ ," } + + $IsStableBuild = $Content | Select -Index 2 + + Write-PipelineSetVariable -Name 'BARBuildId' -Value $BarId + Write-PipelineSetVariable -Name 'InitialChannels' -Value "$Channels" + Write-PipelineSetVariable -Name 'IsStableBuild' -Value $IsStableBuild +} +catch { + Write-Host $_ + Write-Host $_.Exception + Write-Host $_.ScriptStackTrace + ExitWithExitCode 1 +} diff --git a/eng/common/post-build/sourcelink-validation.ps1 b/eng/common/post-build/sourcelink-validation.ps1 index 8abd684e9e5..41e01ae6e67 100644 --- a/eng/common/post-build/sourcelink-validation.ps1 +++ b/eng/common/post-build/sourcelink-validation.ps1 @@ -6,10 +6,7 @@ param( [Parameter(Mandatory=$true)][string] $SourcelinkCliVersion # Version of SourceLink CLI to use ) -$ErrorActionPreference = "Stop" -Set-StrictMode -Version 2.0 - -. $PSScriptRoot\..\tools.ps1 +. $PSScriptRoot\post-build-utils.ps1 # Cache/HashMap (File -> Exist flag) used to consult whether a file exist # in the repository at a specific commit point. This is populated by inserting @@ -200,21 +197,27 @@ function ValidateSourceLinkLinks { } } -function CheckExitCode ([string]$stage) { - $exitCode = $LASTEXITCODE - if ($exitCode -ne 0) { - Write-PipelineTaskError "Something failed while '$stage'. Check for errors above. Exiting now..." - ExitWithExitCode $exitCode +function InstallSourcelinkCli { + $sourcelinkCliPackageName = "sourcelink" + + $dotnetRoot = InitializeDotNetCli -install:$true + $dotnet = "$dotnetRoot\dotnet.exe" + $toolList = & "$dotnet" tool list --global + + if (($toolList -like "*$sourcelinkCliPackageName*") -and ($toolList -like "*$sourcelinkCliVersion*")) { + Write-Host "SourceLink CLI version $sourcelinkCliVersion is already installed." + } + else { + Write-Host "Installing SourceLink CLI version $sourcelinkCliVersion..." + Write-Host "You may need to restart your command window if this is the first dotnet tool you have installed." + & "$dotnet" tool install $sourcelinkCliPackageName --version $sourcelinkCliVersion --verbosity "minimal" --global } } try { - Write-Host "Installing SourceLink CLI..." - Get-Location - . $PSScriptRoot\sourcelink-cli-init.ps1 -sourcelinkCliVersion $SourcelinkCliVersion - CheckExitCode "Running sourcelink-cli-init" + InstallSourcelinkCli - Measure-Command { ValidateSourceLinkLinks } + ValidateSourceLinkLinks } catch { Write-Host $_ diff --git a/eng/common/post-build/symbols-validation.ps1 b/eng/common/post-build/symbols-validation.ps1 index 69456854e04..d5ec51b150f 100644 --- a/eng/common/post-build/symbols-validation.ps1 +++ b/eng/common/post-build/symbols-validation.ps1 @@ -4,10 +4,7 @@ param( [Parameter(Mandatory=$true)][string] $DotnetSymbolVersion # Version of dotnet symbol to use ) -$ErrorActionPreference = "Stop" -Set-StrictMode -Version 2.0 - -. $PSScriptRoot\..\tools.ps1 +. $PSScriptRoot\post-build-utils.ps1 Add-Type -AssemblyName System.IO.Compression.FileSystem @@ -162,19 +159,25 @@ function CheckSymbolsAvailable { } } -function CheckExitCode ([string]$stage) { - $exitCode = $LASTEXITCODE - if ($exitCode -ne 0) { - Write-PipelineTaskError "Something failed while '$stage'. Check for errors above. Exiting now..." - ExitWithExitCode $exitCode +function Installdotnetsymbol { + $dotnetsymbolPackageName = "dotnet-symbol" + + $dotnetRoot = InitializeDotNetCli -install:$true + $dotnet = "$dotnetRoot\dotnet.exe" + $toolList = & "$dotnet" tool list --global + + if (($toolList -like "*$dotnetsymbolPackageName*") -and ($toolList -like "*$dotnetsymbolVersion*")) { + Write-Host "dotnet-symbol version $dotnetsymbolVersion is already installed." + } + else { + Write-Host "Installing dotnet-symbol version $dotnetsymbolVersion..." + Write-Host "You may need to restart your command window if this is the first dotnet tool you have installed." + & "$dotnet" tool install $dotnetsymbolPackageName --version $dotnetsymbolVersion --verbosity "minimal" --global } } try { - Write-Host "Installing dotnet symbol ..." - Get-Location - . $PSScriptRoot\dotnetsymbol-init.ps1 -dotnetsymbolVersion $DotnetSymbolVersion - CheckExitCode "Running dotnetsymbol-init" + Installdotnetsymbol CheckSymbolsAvailable } diff --git a/eng/common/post-build/trigger-subscriptions.ps1 b/eng/common/post-build/trigger-subscriptions.ps1 index 1a91dab0371..926d5b45513 100644 --- a/eng/common/post-build/trigger-subscriptions.ps1 +++ b/eng/common/post-build/trigger-subscriptions.ps1 @@ -1,33 +1,20 @@ -param( +param( [Parameter(Mandatory=$true)][string] $SourceRepo, [Parameter(Mandatory=$true)][int] $ChannelId, - [string] $MaestroEndpoint = "https://maestro-prod.westus2.cloudapp.azure.com", - [string] $BarToken, - [string] $ApiVersion = "2019-01-16" + [Parameter(Mandatory=$true)][string] $MaestroApiAccessToken, + [Parameter(Mandatory=$false)][string] $MaestroApiEndPoint = "https://maestro-prod.westus2.cloudapp.azure.com", + [Parameter(Mandatory=$false)][string] $MaestroApiVersion = "2019-01-16" ) -$ErrorActionPreference = "Stop" -Set-StrictMode -Version 2.0 - -. $PSScriptRoot\..\tools.ps1 - -function Get-Headers([string]$accept, [string]$barToken) { - $headers = New-Object 'System.Collections.Generic.Dictionary[[String],[String]]' - $headers.Add('Accept',$accept) - $headers.Add('Authorization',"Bearer $barToken") - return $headers -} +. $PSScriptRoot\post-build-utils.ps1 # Get all the $SourceRepo subscriptions $normalizedSourceRepo = $SourceRepo.Replace('dnceng@', '') -$getSubscriptionsApiEndpoint = "$maestroEndpoint/api/subscriptions?sourceRepository=$normalizedSourceRepo&api-version=$apiVersion" -$headers = Get-Headers 'application/json' $barToken - -$subscriptions = Invoke-WebRequest -Uri $getSubscriptionsApiEndpoint -Headers $headers | ConvertFrom-Json +$subscriptions = Get-MaestroSubscriptions -SourceRepository $normalizedSourceRepo -ChannelId $ChannelId if (!$subscriptions) { Write-Host "No subscriptions found for source repo '$normalizedSourceRepo' in channel '$ChannelId'" - return + ExitWithExitCode 0 } $subscriptionsToTrigger = New-Object System.Collections.Generic.List[string] @@ -36,21 +23,18 @@ $failedTriggeredSubscription = $false # Get all enabled subscriptions that need dependency flow on 'everyBuild' foreach ($subscription in $subscriptions) { if ($subscription.enabled -and $subscription.policy.updateFrequency -like 'everyBuild' -and $subscription.channel.id -eq $ChannelId) { - Write-Host "$subscription.id" + Write-Host "Should trigger this subscription: $subscription.id" [void]$subscriptionsToTrigger.Add($subscription.id) } } foreach ($subscriptionToTrigger in $subscriptionsToTrigger) { try { - $triggerSubscriptionApiEndpoint = "$maestroEndpoint/api/subscriptions/$subscriptionToTrigger/trigger?api-version=$apiVersion" - $headers = Get-Headers 'application/json' $BarToken - - Write-Host "Triggering subscription '$subscriptionToTrigger'..." + Write-Host "Triggering subscription '$subscriptionToTrigger'." - Invoke-WebRequest -Uri $triggerSubscriptionApiEndpoint -Headers $headers -Method Post + Trigger-Subscription -SubscriptionId $subscriptionToTrigger - Write-Host "Subscription '$subscriptionToTrigger' triggered!" + Write-Host "done." } catch { @@ -61,9 +45,13 @@ foreach ($subscriptionToTrigger in $subscriptionsToTrigger) { } } -if ($failedTriggeredSubscription) { +if ($subscriptionsToTrigger.Count -eq 0) { + Write-Host "No subscription matched source repo '$normalizedSourceRepo' and channel ID '$ChannelId'." +} +elseif ($failedTriggeredSubscription) { Write-Host "At least one subscription failed to be triggered..." ExitWithExitCode 1 } - -Write-Host "All subscriptions were triggered successfully!" +else { + Write-Host "All subscriptions were triggered successfully!" +} diff --git a/eng/common/templates/post-build/channels/internal-servicing.yml b/eng/common/templates/post-build/channels/internal-servicing.yml index 5c07b66926f..12fd2b4653d 100644 --- a/eng/common/templates/post-build/channels/internal-servicing.yml +++ b/eng/common/templates/post-build/channels/internal-servicing.yml @@ -41,7 +41,6 @@ stages: dependsOn: setupMaestroVars variables: - group: DotNet-Blob-Feed - - group: Publish-Build-Assets - group: AzureDevOps-Artifact-Feeds-Pats - name: BARBuildId value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ] @@ -87,8 +86,8 @@ stages: /p:StaticInternalFeed=$(dotnetfeed-internal-nonstable-feed-url) /p:NugetPath=$(Agent.BuildDirectory)\Nuget\NuGet.exe /p:BARBuildId=$(BARBuildId) - /p:MaestroApiEndpoint='https://maestro-prod.westus2.cloudapp.azure.com' - /p:BuildAssetRegistryToken='$(MaestroAccessToken)' + /p:MaestroApiEndpoint='$(MaestroApiEndPoint)' + /p:BuildAssetRegistryToken='$(MaestroApiAccessToken)' /p:ManifestsBasePath='$(Build.ArtifactStagingDirectory)/AssetManifests/' /p:BlobBasePath='$(Build.ArtifactStagingDirectory)\BlobArtifacts' /p:PackageBasePath='$(Build.ArtifactStagingDirectory)\PackageArtifacts' diff --git a/eng/common/templates/post-build/channels/public-dev-release.yml b/eng/common/templates/post-build/channels/public-dev-release.yml index 4eaa6e4ff0f..b0f085b1420 100644 --- a/eng/common/templates/post-build/channels/public-dev-release.yml +++ b/eng/common/templates/post-build/channels/public-dev-release.yml @@ -41,7 +41,6 @@ stages: dependsOn: setupMaestroVars variables: - group: DotNet-Blob-Feed - - group: Publish-Build-Assets - group: AzureDevOps-Artifact-Feeds-Pats - name: BARBuildId value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ] @@ -87,8 +86,8 @@ stages: /p:TargetFeedPAT='$(dn-bot-dnceng-unviersal-packages-rw)' /p:AzureStorageTargetFeedPAT='$(dotnetfeed-storage-access-key-1)' /p:BARBuildId=$(BARBuildId) - /p:MaestroApiEndpoint='https://maestro-prod.westus2.cloudapp.azure.com' - /p:BuildAssetRegistryToken='$(MaestroAccessToken)' + /p:MaestroApiEndpoint='$(MaestroApiEndPoint)' + /p:BuildAssetRegistryToken='$(MaestroApiAccessToken)' /p:ManifestsBasePath='$(Build.ArtifactStagingDirectory)/AssetManifests/' /p:BlobBasePath='$(Build.ArtifactStagingDirectory)/BlobArtifacts/' /p:PackageBasePath='$(Build.ArtifactStagingDirectory)/PackageArtifacts/' diff --git a/eng/common/templates/post-build/channels/public-release.yml b/eng/common/templates/post-build/channels/public-release.yml index a31d37139b7..4c63fb43f0c 100644 --- a/eng/common/templates/post-build/channels/public-release.yml +++ b/eng/common/templates/post-build/channels/public-release.yml @@ -41,7 +41,6 @@ stages: dependsOn: setupMaestroVars variables: - group: DotNet-Blob-Feed - - group: Publish-Build-Assets - group: AzureDevOps-Artifact-Feeds-Pats - name: BARBuildId value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ] @@ -87,8 +86,8 @@ stages: /p:StaticInternalFeed=$(dotnetfeed-internal-nonstable-feed-url) /p:NugetPath=$(Agent.BuildDirectory)\Nuget\NuGet.exe /p:BARBuildId=$(BARBuildId) - /p:MaestroApiEndpoint='https://maestro-prod.westus2.cloudapp.azure.com' - /p:BuildAssetRegistryToken='$(MaestroAccessToken)' + /p:MaestroApiEndpoint='$(MaestroApiEndPoint)' + /p:BuildAssetRegistryToken='$(MaestroApiAccessToken)' /p:ManifestsBasePath='$(Build.ArtifactStagingDirectory)/AssetManifests/' /p:BlobBasePath='$(Build.ArtifactStagingDirectory)\BlobArtifacts' /p:PackageBasePath='$(Build.ArtifactStagingDirectory)\PackageArtifacts' diff --git a/eng/common/templates/post-build/channels/public-validation-release.yml b/eng/common/templates/post-build/channels/public-validation-release.yml index 8c4d8f6ef33..1089ac5fa6b 100644 --- a/eng/common/templates/post-build/channels/public-validation-release.yml +++ b/eng/common/templates/post-build/channels/public-validation-release.yml @@ -12,7 +12,6 @@ stages: dependsOn: setupMaestroVars variables: - group: DotNet-Blob-Feed - - group: Publish-Build-Assets - group: AzureDevOps-Artifact-Feeds-Pats - name: BARBuildId value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ] @@ -48,7 +47,7 @@ stages: filePath: eng\common\sdk-task.ps1 arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet /p:ChannelId=$(PublicValidationRelease_30_Channel_Id) - /p:ArtifactsCategory=$(_DotNetArtifactsCategory) + /p:ArtifactsCategory=$(_DotNetValidationArtifactsCategory) /p:IsStableBuild=$(IsStableBuild) /p:IsInternalBuild=$(IsInternalBuild) /p:RepositoryName=$(Build.Repository.Name) @@ -58,13 +57,13 @@ stages: /p:TargetFeedPAT='$(dn-bot-dnceng-unviersal-packages-rw)' /p:AzureStorageTargetFeedPAT='$(dotnetfeed-storage-access-key-1)' /p:BARBuildId=$(BARBuildId) - /p:MaestroApiEndpoint='https://maestro-prod.westus2.cloudapp.azure.com' - /p:BuildAssetRegistryToken='$(MaestroAccessToken)' + /p:MaestroApiEndpoint='$(MaestroApiEndPoint)' + /p:BuildAssetRegistryToken='$(MaestroApiAccessToken)' /p:ManifestsBasePath='$(Build.ArtifactStagingDirectory)/AssetManifests/' /p:BlobBasePath='$(Build.ArtifactStagingDirectory)\BlobArtifacts' /p:PackageBasePath='$(Build.ArtifactStagingDirectory)\PackageArtifacts' /p:Configuration=Release - + - task: NuGetCommand@2 displayName: Publish Packages to AzDO Feed condition: contains(variables['TargetAzDOFeed'], 'pkgs.visualstudio.com') diff --git a/eng/common/templates/post-build/common-variables.yml b/eng/common/templates/post-build/common-variables.yml index 42df4ae77e3..bd0bc5e4daa 100644 --- a/eng/common/templates/post-build/common-variables.yml +++ b/eng/common/templates/post-build/common-variables.yml @@ -1,21 +1,39 @@ variables: + - group: Publish-Build-Assets + # .NET Core 3 Dev - PublicDevRelease_30_Channel_Id: 3 + - name: PublicDevRelease_30_Channel_Id + value: 3 # .NET Tools - Validation - PublicValidationRelease_30_Channel_Id: 9 + - name: PublicValidationRelease_30_Channel_Id + value: 9 # .NET Core 3.0 Internal Servicing - InternalServicing_30_Channel_Id: 184 + - name: InternalServicing_30_Channel_Id + value: 184 # .NET Core 3.0 Release - PublicRelease_30_Channel_Id: 19 + - name: PublicRelease_30_Channel_Id + value: 19 # Whether the build is internal or not - IsInternalBuild: ${{ and(ne(variables['System.TeamProject'], 'public'), contains(variables['Build.SourceBranch'], 'internal')) }} + - name: IsInternalBuild + value: ${{ and(ne(variables['System.TeamProject'], 'public'), contains(variables['Build.SourceBranch'], 'internal')) }} # Storage account name for proxy-backed feeds - ProxyBackedFeedsAccountName: dotnetfeed + - name: ProxyBackedFeedsAccountName + value: dotnetfeed + + # Default Maestro++ API Endpoint and API Version + - name: MaestroApiEndPoint + value: "https://maestro-prod.westus2.cloudapp.azure.com" + - name: MaestroApiAccessToken + value: $(MaestroAccessToken) + - name: MaestroApiVersion + value: "2019-01-16" - SourceLinkCLIVersion: 3.0.0 - SymbolToolVersion: 1.0.1 + - name: SourceLinkCLIVersion + value: 3.0.0 + - name: SymbolToolVersion + value: 1.0.1 diff --git a/eng/common/templates/post-build/darc-gather-drop.yml b/eng/common/templates/post-build/darc-gather-drop.yml index e0a9f0a6d26..f4e3bfcf5cd 100644 --- a/eng/common/templates/post-build/darc-gather-drop.yml +++ b/eng/common/templates/post-build/darc-gather-drop.yml @@ -7,7 +7,6 @@ jobs: dependsOn: setupMaestroVars condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], ${{ parameters.ChannelId }}) variables: - - group: Publish-Build-Assets - name: BARBuildId value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ] pool: @@ -19,4 +18,6 @@ jobs: filePath: $(Build.SourcesDirectory)/eng/common/post-build/darc-gather-drop.ps1 arguments: -BarBuildId $(BARBuildId) -DropLocation $(Agent.BuildDirectory)/Temp/Drop/ - -MaestroAccessToken $(MaestroAccessToken) + -MaestroApiAccessToken $(MaestroApiAccessToken) + -MaestroApiEndPoint $(MaestroApiEndPoint) + -MaestroApiVersion $(MaestroApiVersion) diff --git a/eng/common/templates/post-build/post-build.yml b/eng/common/templates/post-build/post-build.yml index daa799259c7..0872db4ed94 100644 --- a/eng/common/templates/post-build/post-build.yml +++ b/eng/common/templates/post-build/post-build.yml @@ -7,9 +7,12 @@ parameters: enable: false params: '' + # Which stages should finish execution before post-build stages start + dependsOn: [build] + stages: - stage: validate - dependsOn: build + dependsOn: ${{ parameters.dependsOn }} displayName: Validate jobs: - ${{ if eq(parameters.enableNugetValidation, 'true') }}: diff --git a/eng/common/templates/post-build/promote-build.yml b/eng/common/templates/post-build/promote-build.yml index af48b0b339e..9387c583b31 100644 --- a/eng/common/templates/post-build/promote-build.yml +++ b/eng/common/templates/post-build/promote-build.yml @@ -11,7 +11,6 @@ jobs: value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ] - name: ChannelId value: ${{ parameters.ChannelId }} - - group: Publish-Build-Assets pool: vmImage: 'windows-2019' steps: @@ -21,4 +20,6 @@ jobs: filePath: $(Build.SourcesDirectory)/eng/common/post-build/promote-build.ps1 arguments: -BuildId $(BARBuildId) -ChannelId $(ChannelId) - -BarToken $(MaestroAccessToken) + -MaestroApiAccessToken $(MaestroApiAccessToken) + -MaestroApiEndPoint $(MaestroApiEndPoint) + -MaestroApiVersion $(MaestroApiVersion) diff --git a/eng/common/templates/post-build/setup-maestro-vars.yml b/eng/common/templates/post-build/setup-maestro-vars.yml index f6120dc1e1c..56242b068e1 100644 --- a/eng/common/templates/post-build/setup-maestro-vars.yml +++ b/eng/common/templates/post-build/setup-maestro-vars.yml @@ -14,22 +14,5 @@ jobs: name: setReleaseVars displayName: Set Release Configs Vars inputs: - targetType: inline - script: | - # This is needed to make Write-PipelineSetVariable works in this context - $ci = $true - - . "$(Build.SourcesDirectory)/eng/common/tools.ps1" - - $Content = Get-Content "$(Build.StagingDirectory)/ReleaseConfigs/ReleaseConfigs.txt" - - $BarId = $Content | Select -Index 0 - - $Channels = "" - $Content | Select -Index 1 | ForEach-Object { $Channels += "$_ ," } - - $IsStableBuild = $Content | Select -Index 2 - - Write-PipelineSetVariable -Name 'BARBuildId' -Value $BarId - Write-PipelineSetVariable -Name 'InitialChannels' -Value "$Channels" - Write-PipelineSetVariable -Name 'IsStableBuild' -Value $IsStableBuild + filePath: $(Build.SourcesDirectory)/eng/common/post-build/setup-maestro-vars.ps1 + arguments: -ReleaseConfigsPath '$(Build.StagingDirectory)/ReleaseConfigs/ReleaseConfigs.txt' diff --git a/eng/common/templates/post-build/trigger-subscription.yml b/eng/common/templates/post-build/trigger-subscription.yml index 3915cdcd1ad..da669030daf 100644 --- a/eng/common/templates/post-build/trigger-subscription.yml +++ b/eng/common/templates/post-build/trigger-subscription.yml @@ -8,4 +8,6 @@ steps: filePath: $(Build.SourcesDirectory)/eng/common/post-build/trigger-subscriptions.ps1 arguments: -SourceRepo $(Build.Repository.Uri) -ChannelId ${{ parameters.ChannelId }} - -BarToken $(MaestroAccessToken) + -MaestroApiAccessToken $(MaestroAccessToken) + -MaestroApiEndPoint $(MaestroApiEndPoint) + -MaestroApiVersion $(MaestroApiVersion) diff --git a/global.json b/global.json index 67df8eb1531..2e6618dad53 100644 --- a/global.json +++ b/global.json @@ -10,7 +10,7 @@ } }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19375.15", + "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19376.18", "Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19069.2" } } From bdb229c3da0edec3e2c03d604f35be2ac31029d5 Mon Sep 17 00:00:00 2001 From: Sergey Tihon Date: Sat, 27 Jul 2019 21:58:59 +0300 Subject: [PATCH 42/46] Moving ClassesTests over to NUnit (#7264) * Moving ClassesTests over to NUnit * Fixed assertion for ParseWithErrors test --- .../Compiler/ErrorMessages/ClassesTests.fs | 127 ++++++++++++++++++ tests/fsharp/FSharpSuite.Tests.fsproj | 1 + .../DoCannotHaveVisibilityDeclarations.fs | 11 -- ...MatchingMethodWithSameNameIsNotAbstract.fs | 14 -- .../MemberHasMultiplePossibleDispatchSlots.fs | 15 --- .../Source/Warnings/MethodIsNotStatic.fs | 9 -- .../NoMatchingAbstractMethodWithSameName.fs | 14 -- .../Source/Warnings/TupleInAbstractMethod.fs | 13 -- tests/fsharpqa/Source/Warnings/WrongArity.fs | 11 -- tests/fsharpqa/Source/Warnings/env.lst | 7 - 10 files changed, 128 insertions(+), 94 deletions(-) create mode 100644 tests/fsharp/Compiler/ErrorMessages/ClassesTests.fs delete mode 100644 tests/fsharpqa/Source/Warnings/DoCannotHaveVisibilityDeclarations.fs delete mode 100644 tests/fsharpqa/Source/Warnings/MatchingMethodWithSameNameIsNotAbstract.fs delete mode 100644 tests/fsharpqa/Source/Warnings/MemberHasMultiplePossibleDispatchSlots.fs delete mode 100644 tests/fsharpqa/Source/Warnings/MethodIsNotStatic.fs delete mode 100644 tests/fsharpqa/Source/Warnings/NoMatchingAbstractMethodWithSameName.fs delete mode 100644 tests/fsharpqa/Source/Warnings/TupleInAbstractMethod.fs delete mode 100644 tests/fsharpqa/Source/Warnings/WrongArity.fs diff --git a/tests/fsharp/Compiler/ErrorMessages/ClassesTests.fs b/tests/fsharp/Compiler/ErrorMessages/ClassesTests.fs new file mode 100644 index 00000000000..1ce10cb7080 --- /dev/null +++ b/tests/fsharp/Compiler/ErrorMessages/ClassesTests.fs @@ -0,0 +1,127 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace FSharp.Compiler.UnitTests + +open NUnit.Framework +open FSharp.Compiler.SourceCodeServices + +[] +module ``Classes`` = + + [] + let ``Tuple In Abstract Method``() = + CompilerAssert.TypeCheckWithErrors + """ +type IInterface = + abstract Function : (int32 * int32) -> unit + +let x = + { new IInterface with + member this.Function (i, j) = () + } + """ + [| + FSharpErrorSeverity.Error, 768, (7, 16, 7, 36), "The member 'Function' does not accept the correct number of arguments. 1 argument(s) are expected, but 2 were given. The required signature is 'member IInterface.Function : (int32 * int32) -> unit'.\nA tuple type is required for one or more arguments. Consider wrapping the given arguments in additional parentheses or review the definition of the interface." + FSharpErrorSeverity.Error, 17, (7, 21, 7, 29), "The member 'Function : 'a * 'b -> unit' does not have the correct type to override the corresponding abstract method. The required signature is 'Function : (int32 * int32) -> unit'." + FSharpErrorSeverity.Error, 783, (6, 9, 6, 19), "At least one override did not correctly implement its corresponding abstract member" + |] + + [] + let ``Wrong Arity``() = + CompilerAssert.TypeCheckSingleError + """ +type MyType() = + static member MyMember(arg1, arg2:int ) = () + static member MyMember(arg1, arg2:byte) = () + + +MyType.MyMember("", 0, 0) + """ + FSharpErrorSeverity.Error + 503 + (7, 1, 7, 26) + "A member or object constructor 'MyMember' taking 3 arguments is not accessible from this code location. All accessible versions of method 'MyMember' take 2 arguments." + + [] + let ``Method Is Not Static``() = + CompilerAssert.TypeCheckSingleError + """ +type Class1() = + member this.X() = "F#" + +let x = Class1.X() + """ + FSharpErrorSeverity.Error + 3214 + (5, 9, 5, 17) + "Method or object constructor 'X' is not static" + + [] + let ``Matching Method With Same Name Is Not Abstract``() = + CompilerAssert.TypeCheckWithErrors + """ +type Foo(x : int) = + member v.MyX() = x + +let foo = + { new Foo(3) + with + member v.MyX() = 4 } + """ + [| + FSharpErrorSeverity.Error, 767, (8, 16, 8, 23), "The type Foo contains the member 'MyX' but it is not a virtual or abstract method that is available to override or implement." + FSharpErrorSeverity.Error, 17, (8, 18, 8, 21), "The member 'MyX : unit -> int' does not have the correct type to override any given virtual method" + FSharpErrorSeverity.Error, 783, (6, 11, 6, 14), "At least one override did not correctly implement its corresponding abstract member" + |] + + [] + let ``No Matching Abstract Method With Same Name``() = + CompilerAssert.TypeCheckWithErrors + """ +type IInterface = + abstract MyFunction : int32 * int32 -> unit + abstract SomeOtherFunction : int32 * int32 -> unit + +let x = + { new IInterface with + member this.Function (i, j) = () + } + """ + [| + FSharpErrorSeverity.Error, 767, (8, 14, 8, 34), "The member 'Function' does not correspond to any abstract or virtual method available to override or implement." + FSharpErrorSeverity.Error, 17, (8, 19, 8, 27), "The member 'Function : 'a * 'b -> unit' does not have the correct type to override any given virtual method" + FSharpErrorSeverity.Error, 366, (7, 3, 9, 4), "No implementation was given for those members: \r\n\t'abstract member IInterface.MyFunction : int32 * int32 -> unit'\r\n\t'abstract member IInterface.SomeOtherFunction : int32 * int32 -> unit'\r\nNote that all interface members must be implemented and listed under an appropriate 'interface' declaration, e.g. 'interface ... with member ...'." + FSharpErrorSeverity.Error, 783, (7, 9, 7, 19), "At least one override did not correctly implement its corresponding abstract member" + |] + + [] + let ``Member Has Multiple Possible Dispatch Slots``() = + CompilerAssert.TypeCheckWithErrors + """ +type IOverload = + abstract member Bar : int -> int + abstract member Bar : double -> int + +type Overload = + interface IOverload with + override __.Bar _ = 1 + """ + [| + FSharpErrorSeverity.Error, 366, (7, 15, 7, 24), "No implementation was given for those members: \r\n\t'abstract member IOverload.Bar : double -> int'\r\n\t'abstract member IOverload.Bar : int -> int'\r\nNote that all interface members must be implemented and listed under an appropriate 'interface' declaration, e.g. 'interface ... with member ...'." + FSharpErrorSeverity.Error, 3213, (8, 21, 8, 24), "The member 'Bar<'a0> : 'a0 -> int' matches multiple overloads of the same method.\nPlease restrict it to one of the following:\r\n Bar : double -> int\r\n Bar : int -> int." + |] + + [] + let ``Do Cannot Have Visibility Declarations``() = + CompilerAssert.ParseWithErrors + """ +type X() = + do () + private do () + static member Y() = 1 + """ + [| + FSharpErrorSeverity.Error, 531, (4, 5, 4, 12), "Accessibility modifiers should come immediately prior to the identifier naming a construct" + FSharpErrorSeverity.Error, 512, (4, 13, 4, 18), "Accessibility modifiers are not permitted on 'do' bindings, but 'Private' was given." + FSharpErrorSeverity.Error, 222, (2, 1, 3, 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." + |] diff --git a/tests/fsharp/FSharpSuite.Tests.fsproj b/tests/fsharp/FSharpSuite.Tests.fsproj index 9f3aeee1e43..651f0363ae6 100644 --- a/tests/fsharp/FSharpSuite.Tests.fsproj +++ b/tests/fsharp/FSharpSuite.Tests.fsproj @@ -33,6 +33,7 @@ + diff --git a/tests/fsharpqa/Source/Warnings/DoCannotHaveVisibilityDeclarations.fs b/tests/fsharpqa/Source/Warnings/DoCannotHaveVisibilityDeclarations.fs deleted file mode 100644 index b57356ee9a0..00000000000 --- a/tests/fsharpqa/Source/Warnings/DoCannotHaveVisibilityDeclarations.fs +++ /dev/null @@ -1,11 +0,0 @@ -// #Warnings -//Accessibility -//Accessibility modifiers are not permitted on 'do' bindings, but 'Private' was given. - -type X() = - do () - private do () - static member Y() = 1 - - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/MatchingMethodWithSameNameIsNotAbstract.fs b/tests/fsharpqa/Source/Warnings/MatchingMethodWithSameNameIsNotAbstract.fs deleted file mode 100644 index 36275ff0e92..00000000000 --- a/tests/fsharpqa/Source/Warnings/MatchingMethodWithSameNameIsNotAbstract.fs +++ /dev/null @@ -1,14 +0,0 @@ -// #Warnings -//The type Foo contains the member 'MyX' but it is not a virtual or abstract method that is available to override or implement. -//ToString - -type Foo(x : int) = - member v.MyX() = x - -let foo = - { new Foo(3) - with - member v.MyX() = 4 } - - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/MemberHasMultiplePossibleDispatchSlots.fs b/tests/fsharpqa/Source/Warnings/MemberHasMultiplePossibleDispatchSlots.fs deleted file mode 100644 index ae6738208b6..00000000000 --- a/tests/fsharpqa/Source/Warnings/MemberHasMultiplePossibleDispatchSlots.fs +++ /dev/null @@ -1,15 +0,0 @@ -// #Warnings -//The member 'Bar -//Please restrict it to one of the following: -//Bar : double -> int -//Bar : int -> int - -type IOverload = - abstract member Bar : int -> int - abstract member Bar : double -> int - -type Overload = - interface IOverload with - override __.Bar _ = 1 - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/MethodIsNotStatic.fs b/tests/fsharpqa/Source/Warnings/MethodIsNotStatic.fs deleted file mode 100644 index 299a88abc3a..00000000000 --- a/tests/fsharpqa/Source/Warnings/MethodIsNotStatic.fs +++ /dev/null @@ -1,9 +0,0 @@ -// #Warnings -//Method or object constructor 'X' is not static - -type Class1() = - member this.X() = "F#" - -let x = Class1.X() - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/NoMatchingAbstractMethodWithSameName.fs b/tests/fsharpqa/Source/Warnings/NoMatchingAbstractMethodWithSameName.fs deleted file mode 100644 index a59f863a774..00000000000 --- a/tests/fsharpqa/Source/Warnings/NoMatchingAbstractMethodWithSameName.fs +++ /dev/null @@ -1,14 +0,0 @@ -// #Warnings -//The member 'Function' does not correspond to any abstract or virtual method available to override or implement. -//MyFunction - -type IInterface = - abstract MyFunction : int32 * int32 -> unit - abstract SomeOtherFunction : int32 * int32 -> unit - -let x = - { new IInterface with - member this.Function (i, j) = () - } - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/TupleInAbstractMethod.fs b/tests/fsharpqa/Source/Warnings/TupleInAbstractMethod.fs deleted file mode 100644 index 0ed439073e3..00000000000 --- a/tests/fsharpqa/Source/Warnings/TupleInAbstractMethod.fs +++ /dev/null @@ -1,13 +0,0 @@ -// #Warnings -//The member 'Function' does not accept the correct number of arguments. -//A tuple type is required for one or more arguments - -type IInterface = - abstract Function : (int32 * int32) -> unit - -let x = - { new IInterface with - member this.Function (i, j) = () - } - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/WrongArity.fs b/tests/fsharpqa/Source/Warnings/WrongArity.fs deleted file mode 100644 index 459f9a5c7a4..00000000000 --- a/tests/fsharpqa/Source/Warnings/WrongArity.fs +++ /dev/null @@ -1,11 +0,0 @@ -// #Warnings -//A member or object constructor 'MyMember' taking 3 - -type MyType() = - static member MyMember(arg1, arg2:int ) = () - static member MyMember(arg1, arg2:byte) = () - - -MyType.MyMember("", 0, 0) - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/env.lst b/tests/fsharpqa/Source/Warnings/env.lst index 18ef811a2a5..2daa6d31680 100644 --- a/tests/fsharpqa/Source/Warnings/env.lst +++ b/tests/fsharpqa/Source/Warnings/env.lst @@ -1,8 +1,5 @@ SOURCE=WrongNumericLiteral.fs # WrongNumericLiteral.fs - SOURCE=TupleInAbstractMethod.fs # TupleInAbstractMethod.fs SOURCE=FS0988AtEndOfFile.fs # FS0988AtEndOfFile.fs - SOURCE=WrongArity.fs # WrongArity.fs - SOURCE=MethodIsNotStatic.fs # MethodIsNotStatic.fs SOURCE=EqualsInsteadOfInInForLoop.fs # EqualsInsteadOfInInForLoop.fs SOURCE=DontWarnExternalFunctionAsUnused.fs SCFLAGS="--warnon:1182 --warnaserror+" # DontWarnExternalFunctionAsUnused.fs SOURCE=SuggestTypesInModule.fs # SuggestTypesInModule.fs @@ -25,14 +22,10 @@ SOURCE=DontSuggestWhenThingsAreOpen.fs SCFLAGS="--vserrors" # DontSuggestWhenThingsAreOpen.fs SOURCE=SuggestDoubleBacktickIdentifiers.fs SCFLAGS="--vserrors" # SuggestDoubleBacktickIdentifiers.fs SOURCE=SuggestDoubleBacktickUnions.fs SCFLAGS="--vserrors" # SuggestDoubleBacktickUnions.fs - SOURCE=MatchingMethodWithSameNameIsNotAbstract.fs # MatchingMethodWithSameNameIsNotAbstract.fs - SOURCE=NoMatchingAbstractMethodWithSameName.fs # NoMatchingAbstractMethodWithSameName.fs SOURCE=MissingExpressionAfterLet.fs # MissingExpressionAfterLet.fs SOURCE=SuggestFieldsInCtor.fs # SuggestFieldsInCtor.fs SOURCE=FieldSuggestion.fs # FieldSuggestion.fs SOURCE=SuggestToUseIndexer.fs # SuggestToUseIndexer.fs - SOURCE=MemberHasMultiplePossibleDispatchSlots.fs # MemberHasMultiplePossibleDispatchSlots.fs SOURCE=Repro1548.fs SCFLAGS="-r:Repro1548.dll" # Repro1548.fs - SOURCE=DoCannotHaveVisibilityDeclarations.fs SOURCE=ModuleAbbreviationsArePrivate.fs SOURCE=DontSuggestIntentionallyUnusedVariables.fs SCFLAGS="--vserrors" # DontSuggestIntentionallyUnusedVariables.fs From 8370ef62ebca160bfb677f6a8a367cd941b6227b Mon Sep 17 00:00:00 2001 From: Faisal Alfaddaghi Date: Sun, 28 Jul 2019 00:23:42 +0300 Subject: [PATCH 43/46] Move Basic Constants to NUnit (#7262) * Move BasicConstants.fs Tests To Nunit * fix typo * Another typo --- .../BasicGrammarElements/BasicConstants.fs | 177 ++++++++++++++++++ tests/fsharp/FSharpSuite.Tests.fsproj | 1 + .../Constants/BasicConstants.fs | 99 ---------- .../BasicGrammarElements/Constants/env.lst | 1 - 4 files changed, 178 insertions(+), 100 deletions(-) create mode 100644 tests/fsharp/Compiler/Conformance/BasicGrammarElements/BasicConstants.fs delete mode 100644 tests/fsharpqa/Source/Conformance/BasicGrammarElements/Constants/BasicConstants.fs diff --git a/tests/fsharp/Compiler/Conformance/BasicGrammarElements/BasicConstants.fs b/tests/fsharp/Compiler/Conformance/BasicGrammarElements/BasicConstants.fs new file mode 100644 index 00000000000..9bae4946568 --- /dev/null +++ b/tests/fsharp/Compiler/Conformance/BasicGrammarElements/BasicConstants.fs @@ -0,0 +1,177 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace FSharp.Compiler.UnitTests + +open NUnit.Framework +open FSharp.Compiler.SourceCodeServices + +[] +module ``Basic Grammar Element Constants`` = + + [] + let `` Basic constants compile `` () = + CompilerAssert.Pass + """ +let sbyteConst = 1y +let int16Const = 1us +let int32Const = 1ul +let int64Const = 1UL + +let byteConst = 1uy +let uint16Const = 1us +let uint32Const = 1ul +let uint64Const = 1uL + +let ieee32Const1 = 1.0f +let ieee32Const2 = 1.0F +let ieee32Const3 = 0x0000000000000001lf + +let ieee64Const1 = 1.0 +let ieee64Const2 = 0x0000000000000001LF + +let bigintConst = 1I + +// let bignumConst = 1N - you need a reference to PowerPack.dll now + +let decimalConst1 = 1.0M +let decimalConst2 = 1.0m + +let charConst = '1' + +let stringConst = "1" + +let bytestringConst = "1"B + +let bytecharConst = '1'B + +let boolConst1 = true +let boolConst2 = false + +let unitConst = () + """ + + [] + let ``Long with underscores``() = + CompilerAssert.CompileExeAndRun + """ +let creditCardNumber = 1234_5678_9012_3456L +let socialSecurityNumber = 999_99_9999L + +if socialSecurityNumber <> 999999999L then failwith "Wrong parsing" +if creditCardNumber <> 1234567890123456L then failwith "Wrong parsing" +exit 0 + """ + + [] + let ``float 32 with underscores``() = + CompilerAssert.CompileExeAndRun + """ +let pi = 3.14_15F +if pi <> 3.1415F then failwith "Wrong parsing" +exit 0 + """ + + [] + let ``int with underscores hexBytes``() = + CompilerAssert.CompileExeAndRun + """ +let hexBytes = 0xFF_EC_DE_5E +if hexBytes <> 0xFFECDE5E then failwith "Wrong parsing" +exit 0 + """ + + + [] + let ``int with underscore hexWords``() = + CompilerAssert.CompileExeAndRun + """ +let hexWords = 0xCAFE_BABE +if hexWords <> 0xCAFEBABE then failwith "Wrong parsing" +exit 0 + """ + + [] + let ``Long with underscores maxLong``() = + CompilerAssert.CompileExeAndRun + """ +let maxLong = 0x7fff_ffff_ffff_ffffL +if maxLong <> 0x7fffffffffffffffL then failwith "Wrong parsing" +exit 0 + """ + + [] + let ``int with underscore nybbles``() = + CompilerAssert.CompileExeAndRun + """ +let nybbles = 0b0010_0101 +if nybbles <> 0b00100101 then failwith "Wrong parsing" +exit 0 + """ + + [] + let ``int with underscores bytes``() = + CompilerAssert.CompileExeAndRun + """ +let bytes = 0b11010010_01101001_10010100_10010010 +if bytes <> 0b11010010011010011001010010010010 then failwith "Wrong parsing" +exit 0 + """ + + [] + let ``int with single underscore literal``() = + CompilerAssert.CompileExeAndRun + """ +let x2 = 5_2 +if x2 <> 52 then failwith "Wrong parsing" +exit 0 + """ + + [] + let ``int with multiple underscores literal``() = + CompilerAssert.CompileExeAndRun + """ +let x4 = 5_______2 +if x4 <> 52 then failwith "Wrong parsing" +exit 0 + """ + + [] + let ``int with single underscore Hex literal``() = + CompilerAssert.CompileExeAndRun + """ +let x7 = 0x5_2 +if x7 <> 0x52 then + failwith "Wrong parsing" +exit 0 + """ + + [] + let ``int with single underscore after leading zero literal``() = + CompilerAssert.CompileExeAndRun + """ +let x9 = 0_52 +if x9 <> 052 then failwith "Wrong parsing" +exit 0 + """ + + [] + let ``int with single underscore after leteral with leading zero ``() = + CompilerAssert.CompileExeAndRun + """ +let x10 = 05_2 +if x10 <> 052 then failwith "Wrong parsing" +exit 0 + """ + + [] + let ``int with single underscore after octo leteral ``() = + CompilerAssert.CompileExeAndRun + """ +let x14 = 0o5_2 +if x14 <> 0o52 then failwith "Wrong parsing" +exit 0 + """ + + + + diff --git a/tests/fsharp/FSharpSuite.Tests.fsproj b/tests/fsharp/FSharpSuite.Tests.fsproj index 651f0363ae6..71fd78680a6 100644 --- a/tests/fsharp/FSharpSuite.Tests.fsproj +++ b/tests/fsharp/FSharpSuite.Tests.fsproj @@ -32,6 +32,7 @@ + diff --git a/tests/fsharpqa/Source/Conformance/BasicGrammarElements/Constants/BasicConstants.fs b/tests/fsharpqa/Source/Conformance/BasicGrammarElements/Constants/BasicConstants.fs deleted file mode 100644 index 78303d2713e..00000000000 --- a/tests/fsharpqa/Source/Conformance/BasicGrammarElements/Constants/BasicConstants.fs +++ /dev/null @@ -1,99 +0,0 @@ -// #Conformance #BasicGrammarElements #Constants -#light - -// Verify the ability to specify basic constants - -let sbyteConst = 1y -let int16Const = 1us -let int32Const = 1ul -let int64Const = 1UL - -let byteConst = 1uy -let uint16Const = 1us -let uint32Const = 1ul -let uint64Const = 1uL - -let ieee32Const1 = 1.0f -let ieee32Const2 = 1.0F -let ieee32Const3 = 0x0000000000000001lf - -let ieee64Const1 = 1.0 -let ieee64Const2 = 0x0000000000000001LF - -let bigintConst = 1I - -// let bignumConst = 1N - you need a reference to PowerPack.dll now - -let decimalConst1 = 1.0M -let decimalConst2 = 1.0m - -let charConst = '1' - -let stringConst = "1" - -let bytestringConst = "1"B - -let bytecharConst = '1'B - -let boolConst1 = true -let boolConst2 = false - -let unitConst = () - -let creditCardNumber = 1234_5678_9012_3456L -if creditCardNumber <> 1234567890123456L then - failwith "Wrong parsing" - -let socialSecurityNumber = 999_99_9999L -if socialSecurityNumber <> 999999999L then - failwith "Wrong parsing" - -let pi = 3.14_15F -if pi <> 3.1415F then - failwith "Wrong parsing" - -let hexBytes = 0xFF_EC_DE_5E -if hexBytes <> 0xFFECDE5E then - failwith "Wrong parsing" - -let hexWords = 0xCAFE_BABE -if hexWords <> 0xCAFEBABE then - failwith "Wrong parsing" - -let maxLong = 0x7fff_ffff_ffff_ffffL -if maxLong <> 0x7fffffffffffffffL then - failwith "Wrong parsing" - -let nybbles = 0b0010_0101 -if nybbles <> 0b00100101 then - failwith "Wrong parsing" - -let bytes = 0b11010010_01101001_10010100_10010010 -if bytes <> 0b11010010011010011001010010010010 then - failwith "Wrong parsing" - -let x2 = 5_2 -if x2 <> 52 then - failwith "Wrong parsing" - -let x4 = 5_______2 -if x4 <> 52 then - failwith "Wrong parsing" - -let x7 = 0x5_2 -if x7 <> 0x52 then - failwith "Wrong parsing" - -let x9 = 0_52 -if x9 <> 052 then - failwith "Wrong parsing" - -let x10 = 05_2 -if x10 <> 052 then - failwith "Wrong parsing" - -let x14 = 0o5_2 -if x14 <> 0o52 then - failwith "Wrong parsing" - -exit 0 diff --git a/tests/fsharpqa/Source/Conformance/BasicGrammarElements/Constants/env.lst b/tests/fsharpqa/Source/Conformance/BasicGrammarElements/Constants/env.lst index 500d42d77e1..97183b49781 100644 --- a/tests/fsharpqa/Source/Conformance/BasicGrammarElements/Constants/env.lst +++ b/tests/fsharpqa/Source/Conformance/BasicGrammarElements/Constants/env.lst @@ -1,4 +1,3 @@ - SOURCE=BasicConstants.fs # BasicConstants.fs NOMONO,NoMT SOURCE=E_BasicConstantsBigNum40.fsx SCFLAGS="--test:ErrorRanges" # E_BasicConstantsBigNum40.fsx From 3ce8eb1b2a4f8cfa29bb614ef8bb12e6a2fa67e0 Mon Sep 17 00:00:00 2001 From: Sergey Tihon Date: Mon, 29 Jul 2019 06:34:39 +0300 Subject: [PATCH 44/46] Moved Don't Suggest Tests over to NUnit (#7288) --- .../ErrorMessages/DontSuggestTests.fs | 48 +++++++++++++++++++ tests/fsharp/FSharpSuite.Tests.fsproj | 1 + .../DontSuggestCompletelyWrongStuff.fs | 7 --- ...DontSuggestIntentionallyUnusedVariables.fs | 8 ---- .../Warnings/DontSuggestWhenThingsAreOpen.fs | 13 ----- tests/fsharpqa/Source/Warnings/env.lst | 3 -- 6 files changed, 49 insertions(+), 31 deletions(-) create mode 100644 tests/fsharp/Compiler/ErrorMessages/DontSuggestTests.fs delete mode 100644 tests/fsharpqa/Source/Warnings/DontSuggestCompletelyWrongStuff.fs delete mode 100644 tests/fsharpqa/Source/Warnings/DontSuggestIntentionallyUnusedVariables.fs delete mode 100644 tests/fsharpqa/Source/Warnings/DontSuggestWhenThingsAreOpen.fs diff --git a/tests/fsharp/Compiler/ErrorMessages/DontSuggestTests.fs b/tests/fsharp/Compiler/ErrorMessages/DontSuggestTests.fs new file mode 100644 index 00000000000..0e5a4f19557 --- /dev/null +++ b/tests/fsharp/Compiler/ErrorMessages/DontSuggestTests.fs @@ -0,0 +1,48 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace FSharp.Compiler.UnitTests + +open NUnit.Framework +open FSharp.Compiler.SourceCodeServices + +[] +module ``Don't Suggest`` = + + [] + let ``Dont Suggest Completely Wrong Stuff``() = + CompilerAssert.TypeCheckSingleError + """ +let _ = Path.GetFullPath "images" + """ + FSharpErrorSeverity.Error + 39 + (2, 9, 2, 13) + "The value, namespace, type or module 'Path' is not defined." + + [] + let ``Dont Suggest When Things Are Open``() = + CompilerAssert.ParseWithErrors + """ +module N = + let name = "hallo" + +type T = + static member myMember = 1 + +let x = N. + """ + [| + FSharpErrorSeverity.Error, 599, (8, 10, 8, 11), "Missing qualification after '.'" + FSharpErrorSeverity.Error, 222, (2, 1, 3, 1), "Files in libraries or multiple-file applications must begin with a namespace or module declaration. When using a module declaration at the start of a file the '=' sign is not allowed. If this is a top-level module, consider removing the = to resolve this error." + |] + + [] + let ``Dont Suggest Intentionally Unused Variables``() = + CompilerAssert.TypeCheckSingleError + """ +let hober xy _xyz = xyz + """ + FSharpErrorSeverity.Error + 39 + (2, 21, 2, 24) + "The value or constructor 'xyz' is not defined." diff --git a/tests/fsharp/FSharpSuite.Tests.fsproj b/tests/fsharp/FSharpSuite.Tests.fsproj index 71fd78680a6..21b9367ec3a 100644 --- a/tests/fsharp/FSharpSuite.Tests.fsproj +++ b/tests/fsharp/FSharpSuite.Tests.fsproj @@ -46,6 +46,7 @@ + diff --git a/tests/fsharpqa/Source/Warnings/DontSuggestCompletelyWrongStuff.fs b/tests/fsharpqa/Source/Warnings/DontSuggestCompletelyWrongStuff.fs deleted file mode 100644 index 68b6d6dcb7e..00000000000 --- a/tests/fsharpqa/Source/Warnings/DontSuggestCompletelyWrongStuff.fs +++ /dev/null @@ -1,7 +0,0 @@ -// #Warnings -//The value, namespace, type or module 'Path' is not defined. -//Maybe you want one of the following:\s+Math - -let _ = Path.GetFullPath "images" - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/DontSuggestIntentionallyUnusedVariables.fs b/tests/fsharpqa/Source/Warnings/DontSuggestIntentionallyUnusedVariables.fs deleted file mode 100644 index 602d459d518..00000000000 --- a/tests/fsharpqa/Source/Warnings/DontSuggestIntentionallyUnusedVariables.fs +++ /dev/null @@ -1,8 +0,0 @@ -//The value or constructor 'xyz' is not defined. -//Maybe you want one of the following: -//\s+xy -//\s+_xyz - -let hober xy _xyz = xyz - -exit 0 diff --git a/tests/fsharpqa/Source/Warnings/DontSuggestWhenThingsAreOpen.fs b/tests/fsharpqa/Source/Warnings/DontSuggestWhenThingsAreOpen.fs deleted file mode 100644 index dad90178a5f..00000000000 --- a/tests/fsharpqa/Source/Warnings/DontSuggestWhenThingsAreOpen.fs +++ /dev/null @@ -1,13 +0,0 @@ -// #Warnings -//Missing qualification after '.' - -module N = - let name = "hallo" - -type T = - static member myMember = 1 - -let x = N. - - -exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Warnings/env.lst b/tests/fsharpqa/Source/Warnings/env.lst index 2daa6d31680..275959c6957 100644 --- a/tests/fsharpqa/Source/Warnings/env.lst +++ b/tests/fsharpqa/Source/Warnings/env.lst @@ -16,10 +16,8 @@ SOURCE=SuggestUnionCases.fs SCFLAGS="--vserrors" # SuggestUnionCases.fs SOURCE=SuggestArrayModuleFunctions.fs SCFLAGS="--vserrors" # SuggestArrayModuleFunctions.fs SOURCE=SuggestTypesInNamespace.fs # SuggestTypesInNamespace.fs - SOURCE=DontSuggestCompletelyWrongStuff.fs SCFLAGS="--vserrors" # DontSuggestCompletelyWrongStuff.fs SOURCE=SuggestTypesInNamespaceVS.fs SCFLAGS="--vserrors" # SuggestTypesInNamespaceVS.fs SOURCE=SuggestAsyncModule.fs SCFLAGS="--vserrors" # SuggestAsyncModule.fs - SOURCE=DontSuggestWhenThingsAreOpen.fs SCFLAGS="--vserrors" # DontSuggestWhenThingsAreOpen.fs SOURCE=SuggestDoubleBacktickIdentifiers.fs SCFLAGS="--vserrors" # SuggestDoubleBacktickIdentifiers.fs SOURCE=SuggestDoubleBacktickUnions.fs SCFLAGS="--vserrors" # SuggestDoubleBacktickUnions.fs SOURCE=MissingExpressionAfterLet.fs # MissingExpressionAfterLet.fs @@ -28,4 +26,3 @@ SOURCE=SuggestToUseIndexer.fs # SuggestToUseIndexer.fs SOURCE=Repro1548.fs SCFLAGS="-r:Repro1548.dll" # Repro1548.fs SOURCE=ModuleAbbreviationsArePrivate.fs - SOURCE=DontSuggestIntentionallyUnusedVariables.fs SCFLAGS="--vserrors" # DontSuggestIntentionallyUnusedVariables.fs From 868b76a743fad667e0a398475a88a63522cfd787 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Mon, 29 Jul 2019 10:42:20 -0700 Subject: [PATCH 45/46] [master] Update dependencies from dotnet/arcade (#7287) * Update dependencies from https://github.com/dotnet/arcade build 20190727.2 - Microsoft.DotNet.Arcade.Sdk - 1.0.0-beta.19377.2 * Update dependencies from https://github.com/dotnet/arcade build 20190728.1 - Microsoft.DotNet.Arcade.Sdk - 1.0.0-beta.19378.1 --- eng/Version.Details.xml | 4 ++-- global.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 0893278ac13..8a78856321e 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -3,9 +3,9 @@ - + https://github.com/dotnet/arcade - 316481e57ee5e6acbbf2401eb6778a1d3d48d25b + a8e982d3bac01d8f4f91a4c57191147570079448 diff --git a/global.json b/global.json index 2e6618dad53..fe2ea05490f 100644 --- a/global.json +++ b/global.json @@ -10,7 +10,7 @@ } }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19376.18", + "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19378.1", "Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19069.2" } } From 9c1a0d12bcdf114a9b1844ef194ea1e18f03c36e Mon Sep 17 00:00:00 2001 From: "Kevin Ransom (msft)" Date: Mon, 29 Jul 2019 20:05:36 -0700 Subject: [PATCH 46/46] Fix langversion with multiple projects (#7293) --- src/fsharp/CompileOps.fsi | 1 + src/fsharp/LanguageFeatures.fs | 3 + src/fsharp/LanguageFeatures.fsi | 3 + src/fsharp/service/IncrementalBuild.fs | 13 +- .../Compiler/Language/OpenStaticClasses.fs | 173 ++++++++++++++++++ tests/fsharp/FSharpSuite.Tests.fsproj | 1 + .../fsharp/core/longnames/version46/test.bsl | 39 ---- tests/fsharp/core/longnames/version46/test.fs | 84 --------- .../fsharp/core/longnames/version47/test.fsx | 91 --------- tests/fsharp/tests.fs | 15 -- 10 files changed, 188 insertions(+), 235 deletions(-) create mode 100644 tests/fsharp/Compiler/Language/OpenStaticClasses.fs delete mode 100644 tests/fsharp/core/longnames/version46/test.bsl delete mode 100644 tests/fsharp/core/longnames/version46/test.fs delete mode 100644 tests/fsharp/core/longnames/version47/test.fsx diff --git a/src/fsharp/CompileOps.fsi b/src/fsharp/CompileOps.fsi index 68abd98ac81..0b5f9cb0839 100644 --- a/src/fsharp/CompileOps.fsi +++ b/src/fsharp/CompileOps.fsi @@ -552,6 +552,7 @@ type TcConfig = member copyFSharpCore: CopyFSharpCoreFlag member shadowCopyReferences: bool member useSdkRefs: bool + member langVersion: LanguageVersion static member Create: TcConfigBuilder * validate: bool -> TcConfig diff --git a/src/fsharp/LanguageFeatures.fs b/src/fsharp/LanguageFeatures.fs index 8894fb1fc17..c4c46e4b666 100644 --- a/src/fsharp/LanguageFeatures.fs +++ b/src/fsharp/LanguageFeatures.fs @@ -93,3 +93,6 @@ type LanguageVersion (specifiedVersion) = let label = if v = defaultVersion then " (Default)" else "" yield sprintf "%M%s" v label |] + + /// Get the specified LanguageVersion + member __.SpecifiedVerson = specified diff --git a/src/fsharp/LanguageFeatures.fsi b/src/fsharp/LanguageFeatures.fsi index bda44fe171e..d1d190d3f96 100644 --- a/src/fsharp/LanguageFeatures.fsi +++ b/src/fsharp/LanguageFeatures.fsi @@ -34,3 +34,6 @@ type LanguageVersion = /// Get the list of valid options member ValidOptions: string array + + /// Get the specified LanguageVersion + member SpecifiedVerson: decimal diff --git a/src/fsharp/service/IncrementalBuild.fs b/src/fsharp/service/IncrementalBuild.fs index 4099b59c803..96e81e32147 100755 --- a/src/fsharp/service/IncrementalBuild.fs +++ b/src/fsharp/service/IncrementalBuild.fs @@ -1052,7 +1052,7 @@ type TypeCheckAccumulator = /// Global service state -type FrameworkImportsCacheKey = (*resolvedpath*)string list * string * (*TargetFrameworkDirectories*)string list* (*fsharpBinaries*)string +type FrameworkImportsCacheKey = (*resolvedpath*)string list * string * (*TargetFrameworkDirectories*)string list * (*fsharpBinaries*)string * (*langVersion*)decimal /// Represents a cache of 'framework' references that can be shared betweeen multiple incremental builds type FrameworkImportsCache(keepStrongly) = @@ -1083,12 +1083,13 @@ type FrameworkImportsCache(keepStrongly) = // The data elements in this key are very important. There should be nothing else in the TcConfig that logically affects // the import of a set of framework DLLs into F# CCUs. That is, the F# CCUs that result from a set of DLLs (including // FSharp.Core.dll and mscorlib.dll) must be logically invariant of all the other compiler configuration parameters. - let key = (frameworkDLLsKey, - tcConfig.primaryAssembly.Name, - tcConfig.GetTargetFrameworkDirectories(), - tcConfig.fsharpBinariesDir) + let key = (frameworkDLLsKey, + tcConfig.primaryAssembly.Name, + tcConfig.GetTargetFrameworkDirectories(), + tcConfig.fsharpBinariesDir, + tcConfig.langVersion.SpecifiedVerson) - match frameworkTcImportsCache.TryGet (ctok, key) with + match frameworkTcImportsCache.TryGet (ctok, key) with | Some res -> return res | None -> let tcConfigP = TcConfigProvider.Constant tcConfig diff --git a/tests/fsharp/Compiler/Language/OpenStaticClasses.fs b/tests/fsharp/Compiler/Language/OpenStaticClasses.fs new file mode 100644 index 00000000000..bd036d3a109 --- /dev/null +++ b/tests/fsharp/Compiler/Language/OpenStaticClasses.fs @@ -0,0 +1,173 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace FSharp.Compiler.UnitTests + +open FSharp.Compiler.SourceCodeServices +open NUnit.Framework + + +(* + Tests in this file evaluate whether the language supports accessing functions on static classes using open + The feature was added in FSharp4.7, the test cases ensure that the original errors are reproduced when the langversion:4.6 is specified +*) + +[] +module OpenStaticClassesTests = + + let baseModule = """ +module Core_OpenStaticClasses + +[] +type MyMath() = + static member Min(a: double, b: double) = System.Math.Min(a, b) + static member Min(a: int, b: int) = System.Math.Min(a, b) + +[] +type AutoOpenMyMath() = + static member AutoMin(a: double, b: double) = System.Math.Min(a, b) + static member AutoMin(a: int, b: int) = System.Math.Min(a, b) + +[] +type NotAllowedToOpen() = + static member QualifiedMin(a: double, b: double) = System.Math.Min(a, b) + static member QualifiedMin(a: int, b: int) = System.Math.Min(a, b) + +""" + + [] + let ``OpenStaticClassesTests - OpenSystemMathOnce - langversion:v4.6`` () = + CompilerAssert.TypeCheckWithErrorsAndOptions + [| "--langversion:4.6" |] + (baseModule + """ +module OpenSystemMathOnce = + + open System.Math + let x = Min(1.0, 2.0)""") + [| + (FSharpErrorSeverity.Error, 39, (22,28,22,32), "The namespace 'Math' is not defined."); + (FSharpErrorSeverity.Error, 39, (23,24,23,27), "The value or constructor 'Min' is not defined.") + |] + + [] + let ``OpenStaticClassesTests - OpenSystemMathOnce - langversion:v4.7`` () = + CompilerAssert.TypeCheckWithErrorsAndOptions + [| "--langversion:4.7" |] + (baseModule + """ +module OpenSystemMathOnce = + + open System.Math + let x = Min(1.0, 2.0)""") + [| |] + + [] + let ``OpenStaticClassesTests - OpenSystemMathTwice - langversion:v4.6`` () = + CompilerAssert.TypeCheckWithErrorsAndOptions + [| "--langversion:4.6" |] + (baseModule + """ +module OpenSystemMathTwice = + + open System.Math + let x = Min(1.0, 2.0) + + open System.Math + let x2 = Min(2.0, 1.0)""") + [| + (FSharpErrorSeverity.Error, 39, (22,17,22,21), "The namespace 'Math' is not defined."); + (FSharpErrorSeverity.Error, 39, (23,13,23,16), "The value or constructor 'Min' is not defined.") + (FSharpErrorSeverity.Error, 39, (25,17,25,21), "The namespace 'Math' is not defined."); + (FSharpErrorSeverity.Error, 39, (26,14,26,17), "The value or constructor 'Min' is not defined.") + |] + + [] + let ``OpenStaticClassesTests - OpenSystemMathTwice - langversion:v4.7`` () = + CompilerAssert.TypeCheckWithErrorsAndOptions + [| "--langversion:4.7" |] + (baseModule + """ +module OpenSystemMathOnce = + + open System.Math + let x = Min(1.0, 2.0)""") + [| |] + + [] + let ``OpenStaticClassesTests - OpenMyMathOnce - langversion:v4.6`` () = + CompilerAssert.TypeCheckWithErrorsAndOptions + [| "--langversion:4.6" |] + (baseModule + """ +module OpenMyMathOnce = + + open MyMath + let x = Min(1.0, 2.0) + let x2 = Min(1, 2)""") + [| + (FSharpErrorSeverity.Error, 39, (22,10,22,16), "The namespace or module 'MyMath' is not defined."); + (FSharpErrorSeverity.Error, 39, (23,13,23,16), "The value or constructor 'Min' is not defined.") + (FSharpErrorSeverity.Error, 39, (24,14,24,17), "The value or constructor 'Min' is not defined.") + |] + + [] + let ``OpenStaticClassesTests - OpenMyMathOnce - langversion:v4.7`` () = + CompilerAssert.TypeCheckWithErrorsAndOptions + [| "--langversion:4.7" |] + (baseModule + """ +module OpenMyMathOnce = + + open MyMath + let x = Min(1.0, 2.0) + let x2 = Min(1, 2)""") + [| |] + + [] + let ``OpenStaticClassesTests - DontOpenAutoMath - langversion:v4.6`` () = + CompilerAssert.TypeCheckWithErrorsAndOptions + [| "--langversion:4.6" |] + (baseModule + """ +module DontOpenAutoMath = + + let x = AutoMin(1.0, 2.0) + let x2 = AutoMin(1, 2)""") + [| + (FSharpErrorSeverity.Error, 39, (22,13,22,20), "The value or constructor 'AutoMin' is not defined."); + (FSharpErrorSeverity.Error, 39, (23,14,23,21), "The value or constructor 'AutoMin' is not defined.") + |] + + [] + let ``OpenStaticClassesTests - DontOpenAutoMath - langversion:v4.7`` () = + CompilerAssert.TypeCheckWithErrorsAndOptions + [| "--langversion:4.7" |] + (baseModule + """ +module DontOpenAutoMath = + + let x = AutoMin(1.0, 2.0) + let x2 = AutoMin(1, 2)""") + [| |] + + [] + let ``OpenStaticClassesTests - OpenAutoMath - langversion:v4.6`` () = + CompilerAssert.TypeCheckWithErrorsAndOptions + [| "--langversion:4.6" |] + (baseModule + """ +module OpenAutoMath = + open AutoOpenMyMath + //open NotAllowedToOpen + + let x = AutoMin(1.0, 2.0) + let x2 = AutoMin(1, 2)""") + [| + (FSharpErrorSeverity.Error, 39, (21,10,21,24), "The namespace or module 'AutoOpenMyMath' is not defined."); + (FSharpErrorSeverity.Error, 39, (24,13,24,20), "The value or constructor 'AutoMin' is not defined.") + (FSharpErrorSeverity.Error, 39, (25,14,25,21), "The value or constructor 'AutoMin' is not defined.") + |] + + [] + let ``OpenStaticClassesTests - OpenAutoMath - langversion:v4.7`` () = + CompilerAssert.TypeCheckWithErrorsAndOptions + [| "--langversion:4.7" |] + (baseModule + """ +module OpenAutoMath = + open AutoOpenMyMath + //open NotAllowedToOpen + + let x = AutoMin(1.0, 2.0) + let x2 = AutoMin(1, 2)""") + [| |] diff --git a/tests/fsharp/FSharpSuite.Tests.fsproj b/tests/fsharp/FSharpSuite.Tests.fsproj index 8883e8aabeb..438f7c58b14 100644 --- a/tests/fsharp/FSharpSuite.Tests.fsproj +++ b/tests/fsharp/FSharpSuite.Tests.fsproj @@ -47,6 +47,7 @@ + diff --git a/tests/fsharp/core/longnames/version46/test.bsl b/tests/fsharp/core/longnames/version46/test.bsl deleted file mode 100644 index 70f110197bb..00000000000 --- a/tests/fsharp/core/longnames/version46/test.bsl +++ /dev/null @@ -1,39 +0,0 @@ - -test.fs(34,17,34,21): typecheck error FS0039: The namespace 'Math' is not defined. - -test.fs(35,13,35,16): typecheck error FS0039: The value or constructor 'Min' is not defined. Maybe you want one of the following: - min - sin - -test.fs(41,17,41,21): typecheck error FS0039: The namespace 'Math' is not defined. - -test.fs(42,13,42,16): typecheck error FS0039: The value or constructor 'Min' is not defined. Maybe you want one of the following: - min - sin - -test.fs(44,17,44,21): typecheck error FS0039: The namespace 'Math' is not defined. - -test.fs(45,14,45,17): typecheck error FS0039: The value or constructor 'Min' is not defined. Maybe you want one of the following: - min - sin - -test.fs(51,10,51,16): typecheck error FS0039: The namespace or module 'MyMath' is not defined. Maybe you want one of the following: - Math - -test.fs(52,13,52,16): typecheck error FS0039: The value or constructor 'Min' is not defined. Maybe you want one of the following: - min - sin - -test.fs(53,14,53,17): typecheck error FS0039: The value or constructor 'Min' is not defined. Maybe you want one of the following: - min - sin - -test.fs(60,13,60,20): typecheck error FS0039: The value or constructor 'AutoMin' is not defined. - -test.fs(61,14,61,21): typecheck error FS0039: The value or constructor 'AutoMin' is not defined. - -test.fs(67,10,67,24): typecheck error FS0039: The namespace or module 'AutoOpenMyMath' is not defined. - -test.fs(70,13,70,20): typecheck error FS0039: The value or constructor 'AutoMin' is not defined. - -test.fs(71,14,71,21): typecheck error FS0039: The value or constructor 'AutoMin' is not defined. diff --git a/tests/fsharp/core/longnames/version46/test.fs b/tests/fsharp/core/longnames/version46/test.fs deleted file mode 100644 index 8c41fdc81f0..00000000000 --- a/tests/fsharp/core/longnames/version46/test.fs +++ /dev/null @@ -1,84 +0,0 @@ -module Core_longnames -let failures = ref [] - -let report_failure (s : string) = - stderr.Write" NO: " - stderr.WriteLine s - failures := !failures @ [s] - -let test (s : string) b = - stderr.Write(s) - if b then stderr.WriteLine " OK" - else report_failure (s) - -let check s b1 b2 = test s (b1 = b2) - -(* Some test expressions *) -[] -type MyMath() = - static member Min(a: double, b: double) = System.Math.Min(a, b) - static member Min(a: int, b: int) = System.Math.Min(a, b) - -[] -type AutoOpenMyMath() = - static member AutoMin(a: double, b: double) = System.Math.Min(a, b) - static member AutoMin(a: int, b: int) = System.Math.Min(a, b) - -[] -type NotAllowedToOpen() = - static member QualifiedMin(a: double, b: double) = System.Math.Min(a, b) - static member QualifiedMin(a: int, b: int) = System.Math.Min(a, b) - -module OpenSystemMathOnce = - - open System.Math - let x = Min(1.0, 2.0) - test "vwejhweoiu" (x = 1.0) - - -module OpenSystemMathTwice = - - open System.Math - let x = Min(1.0, 2.0) - - open System.Math - let x2 = Min(2.0, 1.0) - - test "vwejhweoiu2" (x2 = 1.0) - -module OpenMyMathOnce = - - open MyMath - let x = Min(1.0, 2.0) - let x2 = Min(1, 2) - - test "vwejhweoiu2" (x = 1.0) - test "vwejhweoiu3" (x2 = 1) - -module DontOpenAutoMath = - - let x = AutoMin(1.0, 2.0) - let x2 = AutoMin(1, 2) - - test "vwejhweoiu2" (x = 1.0) - test "vwejhweoiu3" (x2 = 1) - -module OpenAutoMath = - open AutoOpenMyMath - //open NotAllowedToOpen - - let x = AutoMin(1.0, 2.0) - let x2 = AutoMin(1, 2) - - test "vwejhweoiu2" (x = 1.0) - test "vwejhweoiu3" (x2 = 1) - -let RUN() = - match !failures with - | [] -> - stdout.WriteLine "Test Passed" - System.IO.File.WriteAllText("test.ok","ok") - exit 0 - | _ -> - stdout.WriteLine "Test Failed" - exit 1 diff --git a/tests/fsharp/core/longnames/version47/test.fsx b/tests/fsharp/core/longnames/version47/test.fsx deleted file mode 100644 index 03702cb996b..00000000000 --- a/tests/fsharp/core/longnames/version47/test.fsx +++ /dev/null @@ -1,91 +0,0 @@ -// #Conformance #ObjectConstructors -#if TESTS_AS_APP -module Core_longnames -#endif -let failures = ref [] - -let report_failure (s : string) = - stderr.Write" NO: " - stderr.WriteLine s - failures := !failures @ [s] - -let test (s : string) b = - stderr.Write(s) - if b then stderr.WriteLine " OK" - else report_failure (s) - -let check s b1 b2 = test s (b1 = b2) - -(* Some test expressions *) -[] -type MyMath() = - static member Min(a: double, b: double) = System.Math.Min(a, b) - static member Min(a: int, b: int) = System.Math.Min(a, b) - -[] -type AutoOpenMyMath() = - static member AutoMin(a: double, b: double) = System.Math.Min(a, b) - static member AutoMin(a: int, b: int) = System.Math.Min(a, b) - -[] -type NotAllowedToOpen() = - static member QualifiedMin(a: double, b: double) = System.Math.Min(a, b) - static member QualifiedMin(a: int, b: int) = System.Math.Min(a, b) - -module OpenSystemMathOnce = - - open System.Math - let x = Min(1.0, 2.0) - test "vwejhweoiu" (x = 1.0) - - -module OpenSystemMathTwice = - - open System.Math - let x = Min(1.0, 2.0) - - open System.Math - let x2 = Min(2.0, 1.0) - - test "vwejhweoiu2" (x2 = 1.0) - -module OpenMyMathOnce = - - open MyMath - let x = Min(1.0, 2.0) - let x2 = Min(1, 2) - - test "vwejhweoiu2" (x = 1.0) - test "vwejhweoiu3" (x2 = 1) - -module DontOpenAutoMath = - - let x = AutoMin(1.0, 2.0) - let x2 = AutoMin(1, 2) - - test "vwejhweoiu2" (x = 1.0) - test "vwejhweoiu3" (x2 = 1) - -module OpenAutoMath = - open AutoOpenMyMath - //open NotAllowedToOpen - - let x = AutoMin(1.0, 2.0) - let x2 = AutoMin(1, 2) - - test "vwejhweoiu2" (x = 1.0) - test "vwejhweoiu3" (x2 = 1) - -#if TESTS_AS_APP -let RUN() = !failures -#else -let aa = - match !failures 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/tests.fs b/tests/fsharp/tests.fs index fab4a5fa84b..94c46a1dced 100644 --- a/tests/fsharp/tests.fs +++ b/tests/fsharp/tests.fs @@ -1302,21 +1302,6 @@ module CoreTests = [] let ``longnames-FSI_BASIC`` () = singleTestBuildAndRun "core/longnames" FSI_BASIC -#if !FSHARP_SUITE_DRIVES_CORECLR_TESTS - [] - let ``longnames-version46`` () = - let cfg = testConfig "core/longnames/version46" - // For some reason this warning is off by default in the test framework but in this case we are testing for it - let cfg = { cfg with fsc_flags = cfg.fsc_flags.Replace("--nowarn:20", "") } - singleVersionedNegTest cfg "4.6" "test" -#endif - - [] - let ``longnames-version47-FSC_BASIC`` () = singleTestBuildAndRunVersion "core/longnames/version47" FSC_BASIC "preview" - - [] - let ``longnames-version47-FSI_BASIC`` () = singleTestBuildAndRunVersion "core/longnames/version47" FSI_BASIC "preview" - [] let ``math-numbersVS2008-FSC_BASIC`` () = singleTestBuildAndRun "core/math/numbersVS2008" FSC_BASIC