diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 118e6891389c..93003652a8ef 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -353,21 +353,18 @@ stages: - script: .\tests\EndToEndBuildTests\EndToEndBuildTests.cmd -c Release displayName: End to end build tests - # Determinism + # Determinism, we want to run it only in PR builds - job: Determinism_Debug + condition: eq(variables['Build.Reason'], 'PullRequest') + variables: + - name: _SignType + value: Test pool: - name: NetCore1ESPool-Public - demands: ImageOverride -equals Build.Windows.Amd64.VS2022.Pre.Open + vmImage: windows-latest timeoutInMinutes: 90 steps: - - checkout: none - - script: | - @echo on - git init - git remote add origin "$(Build.Repository.Uri)" - git fetch --progress --no-tags --depth=1 origin "$(Build.SourceVersion)" - git checkout "$(Build.SourceVersion)" - displayName: Shallow checkout + - checkout: self + clean: true - script: .\eng\test-determinism.cmd -configuration Debug displayName: Determinism tests with Debug configuration - task: PublishPipelineArtifact@1 diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 929f04667eff..08bcbebd47d5 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -8,9 +8,9 @@ - + https://github.com/dotnet/arcade - 97463777ee9a8445d4a4c5911ede0f0cd71fa8aa + 5d969787afb2fd87f642458687e3ad41094ac3ab diff --git a/eng/build-utils.ps1 b/eng/build-utils.ps1 index ffc4498fb857..055ddb7a5b6e 100644 --- a/eng/build-utils.ps1 +++ b/eng/build-utils.ps1 @@ -247,7 +247,7 @@ function Make-BootstrapBuild() { $args = "build $buildToolsProject -c $bootstrapConfiguration -v $verbosity" + $argNoRestore + $argNoIncremental if ($binaryLog) { $logFilePath = Join-Path $LogDir "toolsBootstrapLog.binlog" - $args += " /bl:$logFilePath" + $args += " /bl:`"$logFilePath`"" } Exec-Console $dotnetExe $args @@ -260,7 +260,7 @@ function Make-BootstrapBuild() { $args = "build $protoProject -c $bootstrapConfiguration -v $verbosity -f $bootstrapTfm" + $argNoRestore + $argNoIncremental if ($binaryLog) { $logFilePath = Join-Path $LogDir "protoBootstrapLog.binlog" - $args += " /bl:$logFilePath" + $args += " /bl:`"$logFilePath`"" } Exec-Console $dotnetExe $args diff --git a/eng/common/build.sh b/eng/common/build.sh index bc07a1c68482..55b298f16ccd 100755 --- a/eng/common/build.sh +++ b/eng/common/build.sh @@ -187,10 +187,6 @@ function InitializeCustomToolset { } function Build { - - if [[ "$ci" == true ]]; then - TryLogClientIpAddress - fi InitializeToolset InitializeCustomToolset diff --git a/eng/common/native/init-compiler.sh b/eng/common/native/init-compiler.sh index 8c944f30b286..e361e03fabdd 100644 --- a/eng/common/native/init-compiler.sh +++ b/eng/common/native/init-compiler.sh @@ -2,6 +2,7 @@ # # This file detects the C/C++ compiler and exports it to the CC/CXX environment variables # +# NOTE: some scripts source this file and rely on stdout being empty, make sure to not output anything here! if [[ "$#" -lt 3 ]]; then echo "Usage..." @@ -111,12 +112,10 @@ if [[ -z "$CC" ]]; then exit 1 fi -if [[ "$compiler" == "clang" ]]; then - if command -v "lld$desired_version" > /dev/null; then - # Only lld version >= 9 can be considered stable - if [[ "$majorVersion" -ge 9 ]]; then - LDFLAGS="-fuse-ld=lld" - fi +# Only lld version >= 9 can be considered stable +if [[ "$compiler" == "clang" && "$majorVersion" -ge 9 ]]; then + if "$CC" -fuse-ld=lld -Wl,--version >/dev/null 2>&1; then + LDFLAGS="-fuse-ld=lld" fi fi diff --git a/eng/common/sdk-task.ps1 b/eng/common/sdk-task.ps1 index 7ab9baac5c8d..b1bca63ab1d8 100644 --- a/eng/common/sdk-task.ps1 +++ b/eng/common/sdk-task.ps1 @@ -83,9 +83,6 @@ try { } if ($restore) { - if ($ci) { - Try-LogClientIpAddress - } Build 'Restore' } diff --git a/eng/common/sdl/packages.config b/eng/common/sdl/packages.config index 3bd8b29ebd72..4585cfd6bba1 100644 --- a/eng/common/sdl/packages.config +++ b/eng/common/sdl/packages.config @@ -1,4 +1,4 @@ - + diff --git a/eng/common/templates/job/execute-sdl.yml b/eng/common/templates/job/execute-sdl.yml index 3aafc82e4171..8128f2c35705 100644 --- a/eng/common/templates/job/execute-sdl.yml +++ b/eng/common/templates/job/execute-sdl.yml @@ -54,7 +54,7 @@ jobs: # The Guardian version specified in 'eng/common/sdl/packages.config'. This value must be kept in # sync with the packages.config file. - name: DefaultGuardianVersion - value: 0.53.3 + value: 0.109.0 - name: GuardianVersion value: ${{ coalesce(parameters.overrideGuardianVersion, '$(DefaultGuardianVersion)') }} - name: GuardianPackagesConfigFile diff --git a/eng/common/templates/job/job.yml b/eng/common/templates/job/job.yml index 37dceb1bab0a..7678b94ce740 100644 --- a/eng/common/templates/job/job.yml +++ b/eng/common/templates/job/job.yml @@ -114,6 +114,7 @@ jobs: continueOnError: ${{ parameters.continueOnError }} condition: and(succeeded(), in(variables['_SignType'], 'real', 'test'), eq(variables['Agent.Os'], 'Windows_NT')) + - ${{ if and(eq(parameters.runAsPublic, 'false'), eq(variables['System.TeamProject'], 'internal')) }}: - task: NuGetAuthenticate@0 - ${{ if or(eq(parameters.artifacts.download, 'true'), ne(parameters.artifacts.download, '')) }}: diff --git a/eng/common/tools.ps1 b/eng/common/tools.ps1 index 90b1f9fdcdb1..f1e1cb53953b 100644 --- a/eng/common/tools.ps1 +++ b/eng/common/tools.ps1 @@ -163,9 +163,6 @@ function InitializeDotNetCli([bool]$install, [bool]$createSdkLocationFile) { # Disable telemetry on CI. if ($ci) { $env:DOTNET_CLI_TELEMETRY_OPTOUT=1 - - # In case of network error, try to log the current IP for reference - Try-LogClientIpAddress } # Source Build uses DotNetCoreSdkDir variable @@ -895,24 +892,6 @@ if (!$disableConfigureToolsetImport) { } } -function Try-LogClientIpAddress() -{ - Write-Host "Attempting to log this client's IP for Azure Package feed telemetry purposes" - try - { - $result = Invoke-WebRequest -Uri "http://co1r5a.msedge.net/fdv2/diagnostics.aspx" -UseBasicParsing - $lines = $result.Content.Split([Environment]::NewLine) - $socketIp = $lines | Select-String -Pattern "^Socket IP:.*" - Write-Host $socketIp - $clientIp = $lines | Select-String -Pattern "^Client IP:.*" - Write-Host $clientIp - } - catch - { - Write-Host "Unable to get this machine's effective IP address for logging: $_" - } -} - # # If $ci flag is set, turn on (and log that we did) special environment variables for improved Nuget client retry logic. # diff --git a/eng/common/tools.sh b/eng/common/tools.sh index dd7030ff5385..17f0a365805d 100755 --- a/eng/common/tools.sh +++ b/eng/common/tools.sh @@ -178,7 +178,7 @@ function InstallDotNetSdk { if [[ $# -ge 3 ]]; then architecture=$3 fi - InstallDotNet "$root" "$version" $architecture 'sdk' 'false' $runtime_source_feed $runtime_source_feed_key + InstallDotNet "$root" "$version" $architecture 'sdk' 'true' $runtime_source_feed $runtime_source_feed_key } function InstallDotNet { @@ -405,13 +405,6 @@ function StopProcesses { return 0 } -function TryLogClientIpAddress () { - echo 'Attempting to log this client''s IP for Azure Package feed telemetry purposes' - if command -v curl > /dev/null; then - curl -s 'http://co1r5a.msedge.net/fdv2/diagnostics.aspx' | grep ' IP: ' || true - fi -} - function MSBuild { local args=$@ if [[ "$pipelines_log" == true ]]; then diff --git a/eng/pipelines/checkout-windows-task.yml b/eng/pipelines/checkout-windows-task.yml new file mode 100644 index 000000000000..76a97eb381ed --- /dev/null +++ b/eng/pipelines/checkout-windows-task.yml @@ -0,0 +1,11 @@ +# Shallow checkout sources on Windows +steps: + - checkout: none + + - script: | + @echo on + git init + git remote add origin "$(Build.Repository.Uri)" + git fetch --progress --no-tags --depth=1 origin "$(Build.SourceVersion)" + git checkout "$(Build.SourceVersion)" + displayName: Shallow Checkout diff --git a/eng/pipelines/publish-logs.yml b/eng/pipelines/publish-logs.yml new file mode 100644 index 000000000000..79835baea3f0 --- /dev/null +++ b/eng/pipelines/publish-logs.yml @@ -0,0 +1,17 @@ +# Build on windows desktop +parameters: +- name: jobName + type: string + default: '' +- name: configuration + type: string + default: 'Debug' + +steps: + - task: PublishPipelineArtifact@1 + displayName: Publish Logs + inputs: + targetPath: '$(Build.SourcesDirectory)/artifacts/log/${{ parameters.configuration }}' + artifactName: '${{ parameters.jobName }} Attempt $(System.JobAttempt) Logs' + continueOnError: true + condition: not(succeeded()) diff --git a/eng/test-determinism.cmd b/eng/test-determinism.cmd index 863e8bd5ca3f..972f85371e6b 100644 --- a/eng/test-determinism.cmd +++ b/eng/test-determinism.cmd @@ -1,2 +1,2 @@ @echo off -powershell -noprofile -executionPolicy RemoteSigned -file "%~dp0\test-determinism.ps1" %* \ No newline at end of file +powershell -noprofile -executionPolicy RemoteSigned -file "%~dp0\test-determinism.ps1" %* diff --git a/eng/test-determinism.ps1 b/eng/test-determinism.ps1 index 45b0cc396fbd..0356303cd017 100644 --- a/eng/test-determinism.ps1 +++ b/eng/test-determinism.ps1 @@ -39,7 +39,7 @@ function Run-Build([string]$rootDir, [string]$logFileName) { $stopWatch.Stop() Write-Host "Cleaning took $($stopWatch.Elapsed)" - $solution = Join-Path $rootDir "FSharp.sln" + $solution = Join-Path $rootDir (Join-Path "service" "FSharp.Compiler.Service.sln") if ($logFileName -eq "") { $logFileName = [IO.Path]::GetFileNameWithoutExtension($projectFilePath) @@ -59,6 +59,9 @@ function Run-Build([string]$rootDir, [string]$logFileName) { /p:Rebuild=false ` /p:Pack=false ` /p:Sign=false ` + /p:SignType=Test ` + /p:DotNetSignType=Test ` + /p:MicroBuild_SigningEnabled=false ` /p:Publish=false ` /p:ContinuousIntegrationBuild=false ` /p:OfficialBuildId="" ` @@ -194,10 +197,12 @@ function Test-Build([string]$rootDir, $dataMap, [string]$logFileName) { } $oldfileData = $datamap[$fileId] - if ($fileData.Hash -ne $oldFileData.Hash) { - Write-Host "`tERROR! $relativeDir\$fileName contents don't match" + $oldHash = $oldfileData.Hash + $newHash = $fileData.Hash + if ($newHash -ne $oldHash) { + Write-Host "`tERROR! $relativeDir\$fileName hashes don't match" $allGood = $false - $errorList += $fileName + $errorList += "$fileName (old hash: $oldHash; new hash: $newHash)" $errorCurrentDirLeft = Join-Path $errorDirLeft $relativeDir Create-Directory $errorCurrentDirLeft diff --git a/global.json b/global.json index be8025025fe1..8b3f7ea64686 100644 --- a/global.json +++ b/global.json @@ -14,7 +14,7 @@ } }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.21569.2", + "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.21606.6", "Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19069.2" } } diff --git a/src/fsharp/AugmentWithHashCompare.fs b/src/fsharp/AugmentWithHashCompare.fs index aa69ea08050c..eb723a014a31 100644 --- a/src/fsharp/AugmentWithHashCompare.fs +++ b/src/fsharp/AugmentWithHashCompare.fs @@ -823,7 +823,7 @@ let TyconIsCandidateForAugmentationWithCompare (g: TcGlobals) (tycon: Tycon) = // This type gets defined in prim-types, before we can add attributes to F# type definitions let isUnit = g.compilingFslib && tycon.DisplayName = "Unit" not isUnit && - not (TyconRefHasAttribute g tycon.Range g.attrib_IsByRefLikeAttribute (mkLocalTyconRef tycon)) && + not (isByrefLikeTyconRef g tycon.Range (mkLocalTyconRef tycon)) && match getAugmentationAttribs g tycon with // [< >] | true, true, None, None, None, None, None, None, None @@ -838,7 +838,7 @@ let TyconIsCandidateForAugmentationWithEquals (g: TcGlobals) (tycon: Tycon) = // This type gets defined in prim-types, before we can add attributes to F# type definitions let isUnit = g.compilingFslib && tycon.DisplayName = "Unit" not isUnit && - not (TyconRefHasAttribute g tycon.Range g.attrib_IsByRefLikeAttribute (mkLocalTyconRef tycon)) && + not (isByrefLikeTyconRef g tycon.Range (mkLocalTyconRef tycon)) && match getAugmentationAttribs g tycon with // [< >] diff --git a/src/fsharp/CompilerConfig.fs b/src/fsharp/CompilerConfig.fs index dae491a9d440..838075f689bb 100644 --- a/src/fsharp/CompilerConfig.fs +++ b/src/fsharp/CompilerConfig.fs @@ -325,6 +325,12 @@ type PackageManagerLine = static member StripDependencyManagerKey (packageKey: string) (line: string): string = line.Substring(packageKey.Length + 1).Trim() +[] +type MetadataAssemblyGeneration = + | None + | ReferenceOut of outputPath: string + | ReferenceOnly + [] type TcConfigBuilder = { @@ -437,6 +443,7 @@ type TcConfigBuilder = mutable emitTailcalls: bool mutable deterministic: bool mutable concurrentBuild: bool + mutable emitMetadataAssembly: MetadataAssemblyGeneration mutable preferredUiLang: string option mutable lcid: int option mutable productNameForBannerText: string @@ -642,6 +649,7 @@ type TcConfigBuilder = emitTailcalls = true deterministic = false concurrentBuild = true + emitMetadataAssembly = MetadataAssemblyGeneration.None preferredUiLang = None lcid = None productNameForBannerText = FSharpProductName @@ -1022,6 +1030,7 @@ type TcConfig private (data: TcConfigBuilder, validate: bool) = member x.emitTailcalls = data.emitTailcalls member x.deterministic = data.deterministic member x.concurrentBuild = data.concurrentBuild + member x.emitMetadataAssembly = data.emitMetadataAssembly member x.pathMap = data.pathMap member x.langVersion = data.langVersion member x.preferredUiLang = data.preferredUiLang diff --git a/src/fsharp/CompilerConfig.fsi b/src/fsharp/CompilerConfig.fsi index 4a80fea97d15..2e1861493259 100644 --- a/src/fsharp/CompilerConfig.fsi +++ b/src/fsharp/CompilerConfig.fsi @@ -143,6 +143,16 @@ type PackageManagerLine = static member SetLinesAsProcessed: string -> Map -> Map static member StripDependencyManagerKey: string -> string -> string +[] +type MetadataAssemblyGeneration = + | None + /// Includes F# signature and optimization metadata as resources in the emitting assembly. + /// Implementation assembly will still be emitted normally, but will emit the reference assembly with the specified output path. + | ReferenceOut of outputPath: string + /// Includes F# signature and optimization metadata as resources in the emitting assembly. + /// Only emits the assembly as a reference assembly. + | ReferenceOnly + [] type TcConfigBuilder = { mutable primaryAssembly: PrimaryAssembly @@ -249,6 +259,7 @@ type TcConfigBuilder = mutable emitTailcalls: bool mutable deterministic: bool mutable concurrentBuild: bool + mutable emitMetadataAssembly: MetadataAssemblyGeneration mutable preferredUiLang: string option mutable lcid : int option mutable productNameForBannerText: string @@ -439,6 +450,7 @@ type TcConfig = member emitTailcalls: bool member deterministic: bool member concurrentBuild: bool + member emitMetadataAssembly: MetadataAssemblyGeneration member pathMap: PathMap member preferredUiLang: string option member optsOn : bool diff --git a/src/fsharp/CompilerOptions.fs b/src/fsharp/CompilerOptions.fs index 0cf6ece074fc..74d8147a8bbf 100644 --- a/src/fsharp/CompilerOptions.fs +++ b/src/fsharp/CompilerOptions.fs @@ -406,6 +406,23 @@ let SetTailcallSwitch (tcConfigB: TcConfigBuilder) switch = let SetDeterministicSwitch (tcConfigB: TcConfigBuilder) switch = tcConfigB.deterministic <- (switch = OptionSwitch.On) +let SetReferenceAssemblyOnlySwitch (tcConfigB: TcConfigBuilder) switch = + match tcConfigB.emitMetadataAssembly with + | MetadataAssemblyGeneration.None -> + tcConfigB.emitMetadataAssembly <- if (switch = OptionSwitch.On) then MetadataAssemblyGeneration.ReferenceOnly else MetadataAssemblyGeneration.None + | _ -> + error(Error(FSComp.SR.optsInvalidRefAssembly(), rangeCmdArgs)) + +let SetReferenceAssemblyOutSwitch (tcConfigB: TcConfigBuilder) outputPath = + match tcConfigB.emitMetadataAssembly with + | MetadataAssemblyGeneration.None -> + if FileSystem.IsInvalidPathShim outputPath then + error(Error(FSComp.SR.optsInvalidRefOut(), rangeCmdArgs)) + else + tcConfigB.emitMetadataAssembly <- MetadataAssemblyGeneration.ReferenceOut outputPath + | _ -> + error(Error(FSComp.SR.optsInvalidRefAssembly(), rangeCmdArgs)) + let AddPathMapping (tcConfigB: TcConfigBuilder) (pathPair: string) = match pathPair.Split([|'='|], 2) with | [| oldPrefix; newPrefix |] -> @@ -723,6 +740,16 @@ let outputFileFlagsFsc (tcConfigB: TcConfigBuilder) = ("nocopyfsharpcore", tagNone, OptionUnit (fun () -> tcConfigB.copyFSharpCore <- CopyFSharpCoreFlag.No), None, Some (FSComp.SR.optsNoCopyFsharpCore())) + + CompilerOption + ("refonly", tagNone, + OptionSwitch (SetReferenceAssemblyOnlySwitch tcConfigB), None, + Some (FSComp.SR.optsRefOnly())) + + CompilerOption + ("refout", tagFile, + OptionString (SetReferenceAssemblyOutSwitch tcConfigB), None, + Some (FSComp.SR.optsRefOut())) ] diff --git a/src/fsharp/FSComp.txt b/src/fsharp/FSComp.txt index 057bc042c179..ded871675d12 100644 --- a/src/fsharp/FSComp.txt +++ b/src/fsharp/FSComp.txt @@ -874,6 +874,8 @@ optsDebug,"Specify debugging type: full, portable, embedded, pdbonly. ('%s' is t optsOptimize,"Enable optimizations (Short form: -O)" optsTailcalls,"Enable or disable tailcalls" optsDeterministic,"Produce a deterministic assembly (including module version GUID and timestamp)" +optsRefOnly,"Produce a reference assembly, instead of a full assembly, as the primary output" +optsRefOut,"Produce a reference assembly with the specified file path." optsPathMap,"Maps physical paths to source path names output by the compiler" optsCrossoptimize,"Enable or disable cross-module optimizations" optsWarnaserrorPM,"Report all warnings as errors" @@ -1168,6 +1170,8 @@ fscTooManyErrors,"Exiting - too many errors" 2026,fscDeterministicDebugRequiresPortablePdb,"Deterministic builds only support portable PDBs (--debug:portable or --debug:embedded)" 2027,fscPathMapDebugRequiresPortablePdb,"--pathmap can only be used with portable PDBs (--debug:portable or --debug:embedded)" 2028,optsInvalidPathMapFormat,"Invalid path map. Mappings must be comma separated and of the format 'path=sourcePath'" +2029,optsInvalidRefOut,"Invalid reference assembly path'" +2030,optsInvalidRefAssembly,"Invalid use of emitting a reference assembly. Check the compiler options to not specify static linking, or using '--refonly' and '--refout' together." 3000,etIllegalCharactersInNamespaceName,"Character '%s' is not allowed in provided namespace name '%s'" 3001,etNullOrEmptyMemberName,"The provided type '%s' returned a member with a null or empty member name" 3002,etNullMember,"The provided type '%s' returned a null member" diff --git a/src/fsharp/FSharp.Build/Microsoft.FSharp.Targets b/src/fsharp/FSharp.Build/Microsoft.FSharp.Targets index 6965a546cc7c..72c9527cad8b 100644 --- a/src/fsharp/FSharp.Build/Microsoft.FSharp.Targets +++ b/src/fsharp/FSharp.Build/Microsoft.FSharp.Targets @@ -364,6 +364,7 @@ this file. VisualStudioStyleErrors="$(VisualStudioStyleErrors)" WarningLevel="$(WarningLevel)" WarningsAsErrors="$(WarningsAsErrors)" + WarningsNotAsErrors="$(WarningsNotAsErrors)" WarnOn="$(WarnOn)" Win32IconFile="$(ApplicationIcon)" Win32ManifestFile="$(Win32Manifest)" diff --git a/src/fsharp/FSharp.Core/FSharp.Core.fsproj b/src/fsharp/FSharp.Core/FSharp.Core.fsproj index 7da0f5ed97a2..0fe4422cc23f 100644 --- a/src/fsharp/FSharp.Core/FSharp.Core.fsproj +++ b/src/fsharp/FSharp.Core/FSharp.Core.fsproj @@ -255,12 +255,6 @@ - - - - - - $(BaseOutputPath)\$(Configuration)\$(TargetFramework) diff --git a/src/fsharp/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.ProjectFile.fs b/src/fsharp/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.ProjectFile.fs index b5aba3ad10fc..497c42c2c47e 100644 --- a/src/fsharp/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.ProjectFile.fs +++ b/src/fsharp/FSharp.DependencyManager.Nuget/FSharp.DependencyManager.ProjectFile.fs @@ -130,7 +130,6 @@ $(POUND_R) $(TARGETFRAMEWORK) $(RUNTIMEIDENTIFIER) false - <_NETCoreSdkIsPreview>false true diff --git a/src/fsharp/IlxGen.fs b/src/fsharp/IlxGen.fs index 22266e786e5a..2d708e0bd577 100644 --- a/src/fsharp/IlxGen.fs +++ b/src/fsharp/IlxGen.fs @@ -8901,4 +8901,4 @@ type IlxAssemblyGenerator(amap: ImportMap, tcGlobals: TcGlobals, tcVal: Constrai member _.ForceSetGeneratedValue (ctxt, v, value: obj) = SetGeneratedValue ctxt tcGlobals ilxGenEnv true v value /// Invert the compilation of the given value and return its current dynamic value and its compiled System.Type - member _.LookupGeneratedValue (ctxt, v) = LookupGeneratedValue amap ctxt ilxGenEnv v + member _.LookupGeneratedValue (ctxt, v) = LookupGeneratedValue amap ctxt ilxGenEnv v \ No newline at end of file diff --git a/src/fsharp/ParseAndCheckInputs.fs b/src/fsharp/ParseAndCheckInputs.fs index 5ad43a53542b..833af64d19ca 100644 --- a/src/fsharp/ParseAndCheckInputs.fs +++ b/src/fsharp/ParseAndCheckInputs.fs @@ -35,6 +35,7 @@ open FSharp.Compiler.Text.Range open FSharp.Compiler.Xml open FSharp.Compiler.TypedTree open FSharp.Compiler.TypedTreeOps +open FSharp.Compiler.TypedTreeBasics open FSharp.Compiler.TcGlobals let CanonicalizeFilename filename = @@ -814,6 +815,11 @@ let GetInitialTcState(m, ccuName, tcConfig: TcConfig, tcGlobals, tcImports: TcIm tcsImplicitOpenDeclarations = openDecls0 } +/// Dummy typed impl file that contains no definitions and is not used for emitting any kind of assembly. +let CreateEmptyDummyTypedImplFile qualNameOfFile sigTy = + let dummyExpr = ModuleOrNamespaceExprWithSig.ModuleOrNamespaceExprWithSig(sigTy, ModuleOrNamespaceExpr.TMDefs [], range0) + TypedImplFile.TImplFile(qualNameOfFile, [], dummyExpr, false, false, StampMap.Empty) + /// Typecheck a single file (or interactive entry into F# Interactive) let TypeCheckOneInput(checkForErrors, tcConfig: TcConfig, @@ -890,10 +896,7 @@ let TypeCheckOneInput(checkForErrors, // Typecheck the implementation file let typeCheckOne = if skipImplIfSigExists && hadSig then - let dummyExpr = ModuleOrNamespaceExprWithSig.ModuleOrNamespaceExprWithSig(rootSigOpt.Value, ModuleOrNamespaceExpr.TMDefs [], range.Zero) - let dummyImplFile = TypedImplFile.TImplFile(qualNameOfFile, [], dummyExpr, false, false, StampMap []) - - (EmptyTopAttrs, dummyImplFile, Unchecked.defaultof<_>, tcImplEnv, false) + (EmptyTopAttrs, CreateEmptyDummyTypedImplFile qualNameOfFile rootSigOpt.Value, Unchecked.defaultof<_>, tcImplEnv, false) |> Cancellable.ret else TypeCheckOneImplFile (tcGlobals, tcState.tcsNiceNameGen, amap, tcState.tcsCcu, tcState.tcsImplicitOpenDeclarations, checkForErrors, conditionalDefines, tcSink, tcConfig.internalTestSpanStackReferring, tcImplEnv, rootSigOpt, file) diff --git a/src/fsharp/PostInferenceChecks.fs b/src/fsharp/PostInferenceChecks.fs index 21f98a518f43..6fe439b04ef8 100644 --- a/src/fsharp/PostInferenceChecks.fs +++ b/src/fsharp/PostInferenceChecks.fs @@ -2218,7 +2218,7 @@ let CheckRecdField isUnion cenv env (tycon: Tycon) (rfield: RecdField) = let access = AdjustAccess isHidden (fun () -> tycon.CompilationPath) rfield.Accessibility CheckTypeForAccess cenv env (fun () -> rfield.LogicalName) access m fieldTy - if TyconRefHasAttribute g m g.attrib_IsByRefLikeAttribute tcref then + if isByrefLikeTyconRef g m tcref then // Permit Span fields in IsByRefLike types CheckTypePermitSpanLike cenv env m fieldTy if cenv.reportErrors then @@ -2441,7 +2441,8 @@ let CheckEntityDefn cenv env (tycon: Entity) = else errorR(Error(FSComp.SR.chkDuplicateMethodInheritedTypeWithSuffix nm, m)) - if TyconRefHasAttribute g m g.attrib_IsByRefLikeAttribute tcref && not tycon.IsStructOrEnumTycon then + + if TyconRefHasAttributeByName m tname_IsByRefLikeAttribute tcref && not tycon.IsStructOrEnumTycon then errorR(Error(FSComp.SR.tcByRefLikeNotStruct(), tycon.Range)) if TyconRefHasAttribute g m g.attrib_IsReadOnlyAttribute tcref && not tycon.IsStructOrEnumTycon then diff --git a/src/fsharp/StaticLinking.fs b/src/fsharp/StaticLinking.fs index c2a1e9c25ce1..e8e3ce7e00cd 100644 --- a/src/fsharp/StaticLinking.fs +++ b/src/fsharp/StaticLinking.fs @@ -354,6 +354,11 @@ let StaticLink (ctok, tcConfig: TcConfig, tcImports: TcImports, ilGlobals: ILGlo id else (fun ilxMainModule -> + match tcConfig.emitMetadataAssembly with + | MetadataAssemblyGeneration.None -> () + | _ -> + error(Error(FSComp.SR.optsInvalidRefAssembly(), rangeCmdArgs)) + ReportTime tcConfig "Find assembly references" let dependentILModules = FindDependentILModulesForStaticLinking (ctok, tcConfig, tcImports, ilGlobals, ilxMainModule) diff --git a/src/fsharp/TcGlobals.fs b/src/fsharp/TcGlobals.fs index e6b819f448e1..5eabf3788804 100755 --- a/src/fsharp/TcGlobals.fs +++ b/src/fsharp/TcGlobals.fs @@ -165,11 +165,15 @@ let tname_RuntimeFieldHandle = "System.RuntimeFieldHandle" [] let tname_CompilerGeneratedAttribute = "System.Runtime.CompilerServices.CompilerGeneratedAttribute" [] +let tname_ReferenceAssemblyAttribute = "System.Runtime.CompilerServices.ReferenceAssemblyAttribute" +[] let tname_DebuggableAttribute = "System.Diagnostics.DebuggableAttribute" [] let tname_AsyncCallback = "System.AsyncCallback" [] let tname_IAsyncResult = "System.IAsyncResult" +[] +let tname_IsByRefLikeAttribute = "System.Runtime.CompilerServices.IsByRefLikeAttribute" //------------------------------------------------------------------------- // Table of all these "globals" @@ -1190,6 +1194,7 @@ type public TcGlobals(compilingFslib: bool, ilg:ILGlobals, fslibCcu: CcuThunk, d member val iltyp_RuntimeFieldHandle = findSysILTypeRef tname_RuntimeFieldHandle |> mkILNonGenericValueTy member val iltyp_RuntimeMethodHandle = findSysILTypeRef tname_RuntimeMethodHandle |> mkILNonGenericValueTy member val iltyp_RuntimeTypeHandle = findSysILTypeRef tname_RuntimeTypeHandle |> mkILNonGenericValueTy + member val iltyp_ReferenceAssemblyAttributeOpt = tryFindSysILTypeRef tname_ReferenceAssemblyAttribute |> Option.map mkILNonGenericBoxedTy member val attrib_AttributeUsageAttribute = findSysAttrib "System.AttributeUsageAttribute" @@ -1199,7 +1204,6 @@ type public TcGlobals(compilingFslib: bool, ilg:ILGlobals, fslibCcu: CcuThunk, d // We use 'findSysAttrib' here because lookup on attribute is done by name comparison, and can proceed // even if the type is not found in a system assembly. - member val attrib_IsByRefLikeAttribute = findSysAttrib "System.Runtime.CompilerServices.IsByRefLikeAttribute" member val attrib_IsReadOnlyAttribute = findSysAttrib "System.Runtime.CompilerServices.IsReadOnlyAttribute" member val attrib_SystemObsolete = findSysAttrib "System.ObsoleteAttribute" @@ -1229,6 +1233,7 @@ type public TcGlobals(compilingFslib: bool, ilg:ILGlobals, fslibCcu: CcuThunk, d member val attrib_CallerLineNumberAttribute = findSysAttrib "System.Runtime.CompilerServices.CallerLineNumberAttribute" member val attrib_CallerFilePathAttribute = findSysAttrib "System.Runtime.CompilerServices.CallerFilePathAttribute" member val attrib_CallerMemberNameAttribute = findSysAttrib "System.Runtime.CompilerServices.CallerMemberNameAttribute" + member val attrib_ReferenceAssemblyAttribute = findSysAttrib "System.Runtime.CompilerServices.ReferenceAssemblyAttribute" member val attrib_SkipLocalsInitAttribute = findSysAttrib "System.Runtime.CompilerServices.SkipLocalsInitAttribute" member val attribs_Unsupported = v_attribs_Unsupported diff --git a/src/fsharp/TypedTreeOps.fs b/src/fsharp/TypedTreeOps.fs index 1dedf910ac68..9a5e25f9bff8 100644 --- a/src/fsharp/TypedTreeOps.fs +++ b/src/fsharp/TypedTreeOps.fs @@ -1982,7 +1982,7 @@ let emptyFreeTyvars = { FreeTycons = emptyFreeTycons // The summary of values used as trait solutions FreeTraitSolutions = emptyFreeLocals - FreeTypars = emptyFreeTypars} + FreeTypars = emptyFreeTypars } let isEmptyFreeTyvars ftyvs = Zset.isEmpty ftyvs.FreeTypars && @@ -3201,6 +3201,28 @@ let TyconRefHasAttribute g m attribSpec tcref = (fun _ -> Some ()) |> Option.isSome +/// Check if a type definition has an attribute with a specific full name +let TyconRefHasAttributeByName (m: range) attrFullName (tcref: TyconRef) = + ignore m + match metadataOfTycon tcref.Deref with +#if !NO_EXTENSIONTYPING + | ProvidedTypeMetadata info -> + let provAttribs = info.ProvidedType.PApply((fun a -> (a :> IProvidedCustomAttributeProvider)), m) + provAttribs.PUntaint((fun a -> + a.GetAttributeConstructorArgs(provAttribs.TypeProvider.PUntaintNoFailure id, attrFullName)), m).IsSome +#endif + | ILTypeMetadata (TILObjectReprData(_, _, tdef)) -> + tdef.CustomAttrs.AsArray + |> Array.exists (fun attr -> isILAttribByName ([], attrFullName) attr) + | FSharpOrArrayOrByrefOrTupleOrExnTypeMetadata -> + tcref.Attribs + |> List.exists (fun attr -> + match attr.TyconRef.CompiledRepresentation with + | CompiledTypeRepr.ILAsmNamed(typeRef, _, _) -> + typeRef.Enclosing.IsEmpty + && typeRef.Name = attrFullName + | CompiledTypeRepr.ILAsmOpen _ -> false) + let isByrefTyconRef (g: TcGlobals) (tcref: TyconRef) = (g.byref_tcr.CanDeref && tyconRefEq g g.byref_tcr tcref) || (g.byref2_tcr.CanDeref && tyconRefEq g g.byref2_tcr tcref) || @@ -3218,7 +3240,7 @@ let isByrefLikeTyconRef (g: TcGlobals) m (tcref: TyconRef) = | _ -> let res = isByrefTyconRef g tcref || - (isStructTyconRef tcref && TyconRefHasAttribute g m g.attrib_IsByRefLikeAttribute tcref) + (isStructTyconRef tcref && TyconRefHasAttributeByName m tname_IsByRefLikeAttribute tcref) tcref.SetIsByRefLike res res diff --git a/src/fsharp/TypedTreeOps.fsi b/src/fsharp/TypedTreeOps.fsi index 2b9fbb8c049f..f6c84a6d2db6 100755 --- a/src/fsharp/TypedTreeOps.fsi +++ b/src/fsharp/TypedTreeOps.fsi @@ -760,7 +760,7 @@ val emptyFreeLocals: FreeLocals val unionFreeLocals: FreeLocals -> FreeLocals -> FreeLocals -type FreeVarOptions +type FreeVarOptions val CollectLocalsNoCaching: FreeVarOptions @@ -2155,6 +2155,9 @@ val TryFindTyconRefBoolAttribute: TcGlobals -> range -> BuiltinAttribInfo -> Tyc /// Try to find a specific attribute on a type definition val TyconRefHasAttribute: TcGlobals -> range -> BuiltinAttribInfo -> TyconRef -> bool +/// Try to find an attribute with a specific full name on a type definition +val TyconRefHasAttributeByName: range -> string -> TyconRef -> bool + /// Try to find the AttributeUsage attribute, looking for the value of the AllowMultiple named parameter val TryFindAttributeUsageAttribute: TcGlobals -> range -> TyconRef -> bool option diff --git a/src/fsharp/absil/ilwrite.fs b/src/fsharp/absil/ilwrite.fs index 7ddd68e404c1..b8a8c4d34150 100644 --- a/src/fsharp/absil/ilwrite.fs +++ b/src/fsharp/absil/ilwrite.fs @@ -564,6 +564,12 @@ type cenv = normalizeAssemblyRefs: ILAssemblyRef -> ILAssemblyRef + /// Indicates that the writing assembly will have an assembly-level attribute, System.Runtime.CompilerServices.InternalsVisibleToAttribute. + hasInternalsVisibleToAttrib: bool + + /// Indicates that the writing assembly will be a reference assembly. Method bodies will be replaced with a `throw null` if there are any. + referenceAssemblyOnly: bool + pdbImports: Dictionary } member cenv.GetTable (tab: TableName) = cenv.tables.[tab.Index] @@ -1076,6 +1082,14 @@ let GetTypeAccessFlags access = | ILTypeDefAccess.Nested ILMemberAccess.FamilyOrAssembly -> 0x00000007 | ILTypeDefAccess.Nested ILMemberAccess.Assembly -> 0x00000005 +let canGenMethodDef cenv (md: ILMethodDef) = + // When emitting a reference assembly, do not emit methods that are private unless they are virtual/abstract or provide an explicit interface implementation. + // Internal methods can be omitted only if the assembly does not contain a System.Runtime.CompilerServices.InternalsVisibleToAttribute. + if cenv.referenceAssemblyOnly && + (match md.Access with ILMemberAccess.Private -> true | ILMemberAccess.Assembly | ILMemberAccess.FamilyAndAssembly -> not cenv.hasInternalsVisibleToAttrib | _ -> false) && + not (md.IsVirtual || md.IsAbstract || md.IsNewSlot || md.IsFinal) then false + else true + let rec GetTypeDefAsRow cenv env _enc (td: ILTypeDef) = let nselem, nelem = GetTypeNameAsElemPair cenv td.Name let flags = @@ -1117,19 +1131,20 @@ and GetKeyForMethodDef cenv tidx (md: ILMethodDef) = MethodDefKey (cenv.ilg, tidx, md.GenericParams.Length, md.Name, md.Return.Type, md.ParameterTypes, md.CallingConv.IsStatic) and GenMethodDefPass2 cenv tidx md = - let idx = - cenv.methodDefIdxsByKey.AddUniqueEntry - "method" - (fun (key: MethodDefKey) -> - dprintn "Duplicate in method table is:" - dprintn (" Type index: "+string key.TypeIdx) - dprintn (" Method name: "+key.Name) - dprintn (" Method arity (num generic params): "+string key.GenericArity) - key.Name - ) - (GetKeyForMethodDef cenv tidx md) - - cenv.methodDefIdxs.[md] <- idx + if canGenMethodDef cenv md then + let idx = + cenv.methodDefIdxsByKey.AddUniqueEntry + "method" + (fun (key: MethodDefKey) -> + dprintn "Duplicate in method table is:" + dprintn (" Type index: "+string key.TypeIdx) + dprintn (" Method name: "+key.Name) + dprintn (" Method arity (num generic params): "+string key.GenericArity) + key.Name + ) + (GetKeyForMethodDef cenv tidx md) + + cenv.methodDefIdxs.[md] <- idx and GetKeyForPropertyDef tidx (x: ILPropertyDef) = PropKey (tidx, x.Name, x.PropertyType, x.Args) @@ -2507,6 +2522,10 @@ let GetMethodDefSigAsBytes cenv env (mdef: ILMethodDef) = let GenMethodDefSigAsBlobIdx cenv env mdef = GetBytesAsBlobIdx cenv (GetMethodDefSigAsBytes cenv env mdef) +let ilMethodBodyThrowNull = + let ilCode = IL.buildILCode "" (Dictionary()) [|ILInstr.AI_ldnull; ILInstr.I_throw|] [] [] + mkILMethodBody(false, ILLocals.Empty, 0, ilCode, None, None) + let GenMethodDefAsRow cenv env midx (md: ILMethodDef) = let flags = md.Attributes @@ -2518,7 +2537,11 @@ let GenMethodDefAsRow cenv env midx (md: ILMethodDef) = let codeAddr = (match md.Body with | MethodBody.IL ilmbodyLazy -> - let ilmbody = ilmbodyLazy.Value + let ilmbody = + if cenv.referenceAssemblyOnly then + ilMethodBodyThrowNull + else + ilmbodyLazy.Value let addr = cenv.nextCodeAddr let localToken, code, seqpoints, rootScope = GenILMethodBody md.Name cenv env ilmbody @@ -2581,55 +2604,57 @@ let GenMethodImplPass3 cenv env _tgparams tidx mimpl = MethodDefOrRef (midx2Tag, midx2Row) |]) |> ignore let GenMethodDefPass3 cenv env (md: ILMethodDef) = - let midx = GetMethodDefIdx cenv md - let idx2 = AddUnsharedRow cenv TableNames.Method (GenMethodDefAsRow cenv env midx md) - if midx <> idx2 then failwith "index of method def on pass 3 does not match index on pass 2" - GenReturnPass3 cenv md.Return - md.Parameters |> List.iteri (fun n param -> GenParamPass3 cenv env (n+1) param) - md.CustomAttrs |> GenCustomAttrsPass3Or4 cenv (hca_MethodDef, midx) - md.SecurityDecls.AsList |> GenSecurityDeclsPass3 cenv (hds_MethodDef, midx) - md.GenericParams |> List.iteri (fun n gp -> GenGenericParamPass3 cenv env n (tomd_MethodDef, midx) gp) - match md.Body with - | MethodBody.PInvoke attrLazy -> - let attr = attrLazy.Value - let flags = - begin match attr.CallingConv with - | PInvokeCallingConvention.None -> 0x0000 - | PInvokeCallingConvention.Cdecl -> 0x0200 - | PInvokeCallingConvention.Stdcall -> 0x0300 - | PInvokeCallingConvention.Thiscall -> 0x0400 - | PInvokeCallingConvention.Fastcall -> 0x0500 - | PInvokeCallingConvention.WinApi -> 0x0100 - end ||| - begin match attr.CharEncoding with - | PInvokeCharEncoding.None -> 0x0000 - | PInvokeCharEncoding.Ansi -> 0x0002 - | PInvokeCharEncoding.Unicode -> 0x0004 - | PInvokeCharEncoding.Auto -> 0x0006 - end ||| - begin match attr.CharBestFit with - | PInvokeCharBestFit.UseAssembly -> 0x0000 - | PInvokeCharBestFit.Enabled -> 0x0010 - | PInvokeCharBestFit.Disabled -> 0x0020 - end ||| - begin match attr.ThrowOnUnmappableChar with - | PInvokeThrowOnUnmappableChar.UseAssembly -> 0x0000 - | PInvokeThrowOnUnmappableChar.Enabled -> 0x1000 - | PInvokeThrowOnUnmappableChar.Disabled -> 0x2000 - end ||| - (if attr.NoMangle then 0x0001 else 0x0000) ||| - (if attr.LastError then 0x0040 else 0x0000) - AddUnsharedRow cenv TableNames.ImplMap - (UnsharedRow - [| UShort (uint16 flags) - MemberForwarded (mf_MethodDef, midx) - StringE (GetStringHeapIdx cenv attr.Name) - SimpleIndex (TableNames.ModuleRef, GetModuleRefAsIdx cenv attr.Where) |]) |> ignore - | _ -> () + if canGenMethodDef cenv md then + let midx = GetMethodDefIdx cenv md + let idx2 = AddUnsharedRow cenv TableNames.Method (GenMethodDefAsRow cenv env midx md) + if midx <> idx2 then failwith "index of method def on pass 3 does not match index on pass 2" + GenReturnPass3 cenv md.Return + md.Parameters |> List.iteri (fun n param -> GenParamPass3 cenv env (n+1) param) + md.CustomAttrs |> GenCustomAttrsPass3Or4 cenv (hca_MethodDef, midx) + md.SecurityDecls.AsList |> GenSecurityDeclsPass3 cenv (hds_MethodDef, midx) + md.GenericParams |> List.iteri (fun n gp -> GenGenericParamPass3 cenv env n (tomd_MethodDef, midx) gp) + match md.Body with + | MethodBody.PInvoke attrLazy -> + let attr = attrLazy.Value + let flags = + begin match attr.CallingConv with + | PInvokeCallingConvention.None -> 0x0000 + | PInvokeCallingConvention.Cdecl -> 0x0200 + | PInvokeCallingConvention.Stdcall -> 0x0300 + | PInvokeCallingConvention.Thiscall -> 0x0400 + | PInvokeCallingConvention.Fastcall -> 0x0500 + | PInvokeCallingConvention.WinApi -> 0x0100 + end ||| + begin match attr.CharEncoding with + | PInvokeCharEncoding.None -> 0x0000 + | PInvokeCharEncoding.Ansi -> 0x0002 + | PInvokeCharEncoding.Unicode -> 0x0004 + | PInvokeCharEncoding.Auto -> 0x0006 + end ||| + begin match attr.CharBestFit with + | PInvokeCharBestFit.UseAssembly -> 0x0000 + | PInvokeCharBestFit.Enabled -> 0x0010 + | PInvokeCharBestFit.Disabled -> 0x0020 + end ||| + begin match attr.ThrowOnUnmappableChar with + | PInvokeThrowOnUnmappableChar.UseAssembly -> 0x0000 + | PInvokeThrowOnUnmappableChar.Enabled -> 0x1000 + | PInvokeThrowOnUnmappableChar.Disabled -> 0x2000 + end ||| + (if attr.NoMangle then 0x0001 else 0x0000) ||| + (if attr.LastError then 0x0040 else 0x0000) + AddUnsharedRow cenv TableNames.ImplMap + (UnsharedRow + [| UShort (uint16 flags) + MemberForwarded (mf_MethodDef, midx) + StringE (GetStringHeapIdx cenv attr.Name) + SimpleIndex (TableNames.ModuleRef, GetModuleRefAsIdx cenv attr.Where) |]) |> ignore + | _ -> () let GenMethodDefPass4 cenv env md = - let midx = GetMethodDefIdx cenv md - List.iteri (fun n gp -> GenGenericParamPass4 cenv env n (tomd_MethodDef, midx) gp) md.GenericParams + if canGenMethodDef cenv md then + let midx = GetMethodDefIdx cenv md + List.iteri (fun n gp -> GenGenericParamPass4 cenv env n (tomd_MethodDef, midx) gp) md.GenericParams let GenPropertyMethodSemanticsPass3 cenv pidx kind mref = // REVIEW: why are we catching exceptions here? @@ -2940,9 +2965,27 @@ let DataCapacity = 200 [] let ResourceCapacity = 200 -let generateIL requiredDataFixups (desiredMetadataVersion, generatePdb, ilg : ILGlobals, emitTailcalls, deterministic, showTimes) (m : ILModuleDef) cilStartAddress normalizeAssemblyRefs = +let generateIL requiredDataFixups (desiredMetadataVersion, generatePdb, ilg : ILGlobals, emitTailcalls, deterministic, showTimes, referenceAssemblyOnly, referenceAssemblyAttribOpt: ILAttribute option) (m : ILModuleDef) cilStartAddress normalizeAssemblyRefs = let isDll = m.IsDLL + let hasInternalsVisibleToAttrib = + m.CustomAttrs.AsArray + |> Array.exists (fun x -> + x.Method.MethodRef.Name = "InternalsVisibleToAttribute" && + x.Method.MethodRef.DeclaringTypeRef.FullName = "System.Runtime.CompilerServices" + ) + + let m = + // Emit System.Runtime.CompilerServices.ReferenceAssemblyAttribute as an assembly-level attribute when generating a reference assembly. + // Useful for the runtime to know that the assembly is a reference assembly. + match referenceAssemblyAttribOpt with + | Some referenceAssemblyAttrib when referenceAssemblyOnly -> + { m with + CustomAttrsStored = + mkILCustomAttrsReader (fun _ -> Array.append [|referenceAssemblyAttrib|] m.CustomAttrs.AsArray) } + | _ -> + m + let tables = Array.init 64 (fun i -> if (i = TableNames.AssemblyRef.Index || @@ -2989,7 +3032,9 @@ let generateIL requiredDataFixups (desiredMetadataVersion, generatePdb, ilg : IL blobs= MetadataTable<_>.New("blobs", HashIdentity.Structural) strings= MetadataTable<_>.New("strings", EqualityComparer.Default) userStrings= MetadataTable<_>.New("user strings", EqualityComparer.Default) - normalizeAssemblyRefs = normalizeAssemblyRefs + normalizeAssemblyRefs = normalizeAssemblyRefs + hasInternalsVisibleToAttrib = hasInternalsVisibleToAttrib + referenceAssemblyOnly = referenceAssemblyOnly pdbImports = Dictionary<_, _>(HashIdentity.Reference) } // Now the main compilation step @@ -3091,7 +3136,7 @@ let TableCapacity = 20000 [] let MetadataCapacity = 500000 -let writeILMetadataAndCode (generatePdb, desiredMetadataVersion, ilg, emitTailcalls, deterministic, showTimes) modul cilStartAddress normalizeAssemblyRefs = +let writeILMetadataAndCode (generatePdb, desiredMetadataVersion, ilg, emitTailcalls, deterministic, showTimes, referenceAssemblyOnly, referenceAssemblyAttribOpt) modul cilStartAddress normalizeAssemblyRefs = // When we know the real RVAs of the data section we fixup the references for the FieldRVA table. // These references are stored as offsets into the metadata we return from this function @@ -3100,7 +3145,7 @@ let writeILMetadataAndCode (generatePdb, desiredMetadataVersion, ilg, emitTailca let next = cilStartAddress let strings, userStrings, blobs, guids, tables, entryPointToken, code, requiredStringFixups, data, resources, pdbData, mappings = - generateIL requiredDataFixups (desiredMetadataVersion, generatePdb, ilg, emitTailcalls, deterministic, showTimes) modul cilStartAddress normalizeAssemblyRefs + generateIL requiredDataFixups (desiredMetadataVersion, generatePdb, ilg, emitTailcalls, deterministic, showTimes, referenceAssemblyOnly, referenceAssemblyAttribOpt) modul cilStartAddress normalizeAssemblyRefs reportTime showTimes "Generated Tables and Code" let tableSize (tab: TableName) = tables.[tab.Index].Count @@ -3559,7 +3604,7 @@ let rec writeBinaryAndReportMappings (outfile, let pdbData, pdbOpt, debugDirectoryChunk, debugDataChunk, debugChecksumPdbChunk, debugEmbeddedPdbChunk, debugDeterministicPdbChunk, textV2P, mappings = try let res = writeBinaryAndReportMappingsAux(stream, false, ilg, pdbfile, signer, portablePDB, embeddedPDB, embedAllSource, embedSourceList, sourceLink, - checksumAlgorithm, emitTailcalls, deterministic, showTimes, pathMap) modul normalizeAssemblyRefs + checksumAlgorithm, emitTailcalls, deterministic, showTimes, false, None, pathMap) modul normalizeAssemblyRefs try FileSystemUtilities.setExecutablePermission outfile @@ -3578,16 +3623,16 @@ let rec writeBinaryAndReportMappings (outfile, and writeBinaryWithNoPdb (stream: Stream, ilg: ILGlobals, signer: ILStrongNameSigner option, portablePDB, embeddedPDB, - embedAllSource, embedSourceList, sourceLink, checksumAlgorithm, emitTailcalls, deterministic, showTimes, pathMap) + embedAllSource, embedSourceList, sourceLink, checksumAlgorithm, emitTailcalls, deterministic, showTimes, referenceAssemblyOnly, referenceAssemblyAttribOpt, pathMap) modul normalizeAssemblyRefs = writeBinaryAndReportMappingsAux(stream, true, ilg, None, signer, portablePDB, embeddedPDB, embedAllSource, embedSourceList, sourceLink, - checksumAlgorithm, emitTailcalls, deterministic, showTimes, pathMap) modul normalizeAssemblyRefs + checksumAlgorithm, emitTailcalls, deterministic, showTimes, referenceAssemblyOnly, referenceAssemblyAttribOpt, pathMap) modul normalizeAssemblyRefs |> ignore and writeBinaryAndReportMappingsAux (stream: Stream, leaveStreamOpen: bool, ilg: ILGlobals, pdbfile: string option, signer: ILStrongNameSigner option, portablePDB, embeddedPDB, - embedAllSource, embedSourceList, sourceLink, checksumAlgorithm, emitTailcalls, deterministic, showTimes, pathMap) + embedAllSource, embedSourceList, sourceLink, checksumAlgorithm, emitTailcalls, deterministic, showTimes, referenceAssemblyOnly, referenceAssemblyAttribOpt, 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 @@ -3699,7 +3744,7 @@ and writeBinaryAndReportMappingsAux (stream: Stream, leaveStreamOpen: bool, | None -> failwith "Expected mscorlib to have a version number" let entryPointToken, code, codePadding, metadata, data, resources, requiredDataFixups, pdbData, mappings, guidStart = - writeILMetadataAndCode ((pdbfile <> None), desiredMetadataVersion, ilg, emitTailcalls, deterministic, showTimes) modul next normalizeAssemblyRefs + writeILMetadataAndCode ((pdbfile <> None), desiredMetadataVersion, ilg, emitTailcalls, deterministic, showTimes, referenceAssemblyOnly, referenceAssemblyAttribOpt) modul next normalizeAssemblyRefs reportTime showTimes "Generated IL and metadata" let _codeChunk, next = chunk code.Length next @@ -4369,8 +4414,8 @@ let WriteILBinary (filename, options: options, inputModule, normalizeAssemblyRef options.embedSourceList, options.sourceLink, options.checksumAlgorithm, options.emitTailcalls, options.deterministic, options.showTimes, options.dumpDebugInfo, options.pathMap) inputModule normalizeAssemblyRefs |> ignore -let WriteILBinaryStreamWithNoPDB (stream, options: options, inputModule, normalizeAssemblyRefs) = +let WriteILBinaryStreamWithNoPDB (stream, (options: options), referenceAssemblyOnly, referenceAssemblyAttribOpt, inputModule, normalizeAssemblyRefs) = writeBinaryWithNoPdb (stream, options.ilg, options.signer, options.portablePDB, options.embeddedPDB, options.embedAllSource, - options.embedSourceList, options.sourceLink, options.checksumAlgorithm, options.emitTailcalls, options.deterministic, options.showTimes, options.pathMap) inputModule normalizeAssemblyRefs + options.embedSourceList, options.sourceLink, options.checksumAlgorithm, options.emitTailcalls, options.deterministic, options.showTimes, referenceAssemblyOnly, referenceAssemblyAttribOpt, options.pathMap) inputModule normalizeAssemblyRefs |> ignore diff --git a/src/fsharp/absil/ilwrite.fsi b/src/fsharp/absil/ilwrite.fsi index 152c9abc45f6..380f94f3b276 100644 --- a/src/fsharp/absil/ilwrite.fsi +++ b/src/fsharp/absil/ilwrite.fsi @@ -29,4 +29,4 @@ type options = val WriteILBinary: filename: string * options: options * inputModule: ILModuleDef * (ILAssemblyRef -> ILAssemblyRef) -> unit /// Write a binary to the given stream. Extra configuration parameters can also be specified. -val WriteILBinaryStreamWithNoPDB: stream: Stream * options: options * inputModule: ILModuleDef * (ILAssemblyRef -> ILAssemblyRef) -> unit \ No newline at end of file +val WriteILBinaryStreamWithNoPDB: stream: Stream * options: options * referenceAssemblyOnly: bool * referenceAssemblyAttribOpt: ILAttribute option * inputModule: ILModuleDef * (ILAssemblyRef -> ILAssemblyRef) -> unit \ No newline at end of file diff --git a/src/fsharp/fsc.fs b/src/fsharp/fsc.fs index aa7143e11b12..20658961a663 100644 --- a/src/fsharp/fsc.fs +++ b/src/fsharp/fsc.fs @@ -779,13 +779,6 @@ let main3(Args (ctok, tcConfig, tcImports, frameworkTcImports: TcImports, tcGlob errorRecoveryNoRange e exiter.Exit 1 - // Perform optimization - use unwindBuildPhase = PushThreadBuildPhaseUntilUnwind BuildPhase.Optimize - - let optEnv0 = GetInitialOptimizationEnv (tcImports, tcGlobals) - - let importMap = tcImports.GetImportMap() - let metadataVersion = match tcConfig.metadataVersion with | Some v -> v @@ -793,18 +786,26 @@ let main3(Args (ctok, tcConfig, tcImports, frameworkTcImports: TcImports, tcGlob match frameworkTcImports.DllTable.TryFind tcConfig.primaryAssembly.Name with | Some ib -> ib.RawMetadata.TryGetILModuleDef().Value.MetadataVersion | _ -> "" + + let optimizedImpls, optDataResources = + // Perform optimization + use unwindBuildPhase = PushThreadBuildPhaseUntilUnwind BuildPhase.Optimize + + let optEnv0 = GetInitialOptimizationEnv (tcImports, tcGlobals) - let optimizedImpls, optimizationData, _ = - ApplyAllOptimizations - (tcConfig, tcGlobals, (LightweightTcValForUsingInBuildMethodCall tcGlobals), outfile, - importMap, false, optEnv0, generatedCcu, typedImplFiles) + let importMap = tcImports.GetImportMap() - AbortOnError(errorLogger, exiter) + let optimizedImpls, optimizationData, _ = + ApplyAllOptimizations + (tcConfig, tcGlobals, (LightweightTcValForUsingInBuildMethodCall tcGlobals), outfile, + importMap, false, optEnv0, generatedCcu, typedImplFiles) - // Encode the optimization data - ReportTime tcConfig "Encoding OptData" + AbortOnError(errorLogger, exiter) + + // Encode the optimization data + ReportTime tcConfig ("Encoding OptData") - let optDataResources = EncodeOptimizationData(tcGlobals, tcConfig, outfile, exportRemapping, (generatedCcu, optimizationData), false) + optimizedImpls, EncodeOptimizationData(tcGlobals, tcConfig, outfile, exportRemapping, (generatedCcu, optimizationData), false) // Pass on only the minimum information required for the next phase Args (ctok, tcConfig, tcImports, tcGlobals, errorLogger, @@ -905,28 +906,79 @@ let main6 dynamicAssemblyCreator (Args (ctok, tcConfig, tcImports: TcImports, t match dynamicAssemblyCreator with | None -> try - try - ILBinaryWriter.WriteILBinary - (outfile, - { ilg = tcGlobals.ilg - pdbfile=pdbfile - emitTailcalls = tcConfig.emitTailcalls - deterministic = tcConfig.deterministic - showTimes = tcConfig.showTimes - portablePDB = tcConfig.portablePDB - embeddedPDB = tcConfig.embeddedPDB - embedAllSource = tcConfig.embedAllSource - embedSourceList = tcConfig.embedSourceList - sourceLink = tcConfig.sourceLink - checksumAlgorithm = tcConfig.checksumAlgorithm - signer = GetStrongNameSigner signingInfo - dumpDebugInfo = tcConfig.dumpDebugInfo - pathMap = tcConfig.pathMap }, - ilxMainModule, - normalizeAssemblyRefs - ) - with Failure msg -> - error(Error(FSComp.SR.fscProblemWritingBinary(outfile, msg), rangeCmdArgs)) + match tcConfig.emitMetadataAssembly with + | MetadataAssemblyGeneration.None -> () + | _ -> + let outfile = + match tcConfig.emitMetadataAssembly with + | MetadataAssemblyGeneration.ReferenceOut outputPath -> + outputPath + | _ -> + outfile + let referenceAssemblyAttribOpt = + tcGlobals.iltyp_ReferenceAssemblyAttributeOpt + |> Option.map (fun ilTy -> + mkILCustomAttribute (ilTy.TypeRef, [], [], []) + ) + try + use stream = + try + // Ensure the output directory exists otherwise it will fail + let dir = FileSystem.GetDirectoryNameShim outfile + if not (FileSystem.DirectoryExistsShim dir) then FileSystem.DirectoryCreateShim dir |> ignore + FileSystem.OpenFileForWriteShim(outfile, FileMode.Create, FileAccess.Write, FileShare.Read) + with _ -> + failwith ("Could not open file for writing (binary mode): " + outfile) + + ILBinaryWriter.WriteILBinaryStreamWithNoPDB + (stream, + { ilg = tcGlobals.ilg + pdbfile=pdbfile + emitTailcalls = tcConfig.emitTailcalls + deterministic = tcConfig.deterministic + showTimes = tcConfig.showTimes + portablePDB = tcConfig.portablePDB + embeddedPDB = tcConfig.embeddedPDB + embedAllSource = tcConfig.embedAllSource + embedSourceList = tcConfig.embedSourceList + sourceLink = tcConfig.sourceLink + checksumAlgorithm = tcConfig.checksumAlgorithm + signer = GetStrongNameSigner signingInfo + dumpDebugInfo = tcConfig.dumpDebugInfo + pathMap = tcConfig.pathMap }, + true, + referenceAssemblyAttribOpt, + ilxMainModule, + normalizeAssemblyRefs + ) + with Failure msg -> + error(Error(FSComp.SR.fscProblemWritingBinary(outfile, msg), rangeCmdArgs)) + + match tcConfig.emitMetadataAssembly with + | MetadataAssemblyGeneration.ReferenceOnly -> () + | _ -> + try + ILBinaryWriter.WriteILBinary + (outfile, + { ilg = tcGlobals.ilg + pdbfile=pdbfile + emitTailcalls = tcConfig.emitTailcalls + deterministic = tcConfig.deterministic + showTimes = tcConfig.showTimes + portablePDB = tcConfig.portablePDB + embeddedPDB = tcConfig.embeddedPDB + embedAllSource = tcConfig.embedAllSource + embedSourceList = tcConfig.embedSourceList + sourceLink = tcConfig.sourceLink + checksumAlgorithm = tcConfig.checksumAlgorithm + signer = GetStrongNameSigner signingInfo + dumpDebugInfo = tcConfig.dumpDebugInfo + pathMap = tcConfig.pathMap }, + ilxMainModule, + normalizeAssemblyRefs + ) + with Failure msg -> + error(Error(FSComp.SR.fscProblemWritingBinary(outfile, msg), rangeCmdArgs)) with e -> errorRecoveryNoRange e exiter.Exit 1 diff --git a/src/fsharp/fscmain.fs b/src/fsharp/fscmain.fs index d461f607afd9..42458640fd66 100644 --- a/src/fsharp/fscmain.fs +++ b/src/fsharp/fscmain.fs @@ -48,8 +48,8 @@ let main(argv) = // The F# compiler expects 'argv' to include the executable name, though it makes no use of it. let argv = Array.append [| compilerName |] argv - - // Check for --pause as the very first step so that a compiler can be attached here. + + // Check for --pause as the very first step so that a debugger can be attached here. let pauseFlag = argv |> Array.exists (fun x -> x = "/pause" || x = "--pause") if pauseFlag then System.Console.WriteLine("Press return to continue...") diff --git a/src/fsharp/pars.fsy b/src/fsharp/pars.fsy index f9b5444a58da..213c8a5a129b 100644 --- a/src/fsharp/pars.fsy +++ b/src/fsharp/pars.fsy @@ -827,8 +827,10 @@ moduleSpfn: { if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(), rhs parseState 2)) let (SynExceptionSig(SynExceptionDefnRepr(cas, a, b, c, d, d2), withKeyword, members, range)) = $3 let xmlDoc = grabXmlDoc(parseState, $1, 1) - let ec = SynExceptionSig(SynExceptionDefnRepr($1@cas, a, b, xmlDoc, d, d2), withKeyword, members, range) - SynModuleSigDecl.Exception(ec, rhs parseState 3) } + let mDefnReprWithAttributes = (d2, $1) ||> unionRangeWithListBy (fun a -> a.Range) + let mWhole = (mDefnReprWithAttributes, members) ||> unionRangeWithListBy (fun (m: SynMemberSig) -> m.Range) + let ec = SynExceptionSig(SynExceptionDefnRepr($1@cas, a, b, xmlDoc, d, mDefnReprWithAttributes), withKeyword, members, mWhole) + SynModuleSigDecl.Exception(ec, mWhole) } | openDecl { SynModuleSigDecl.Open($1, (rhs parseState 1)) } diff --git a/src/fsharp/service/FSharpCheckerResults.fs b/src/fsharp/service/FSharpCheckerResults.fs index ada57d64b6eb..0dcad7df7867 100644 --- a/src/fsharp/service/FSharpCheckerResults.fs +++ b/src/fsharp/service/FSharpCheckerResults.fs @@ -15,6 +15,7 @@ open Internal.Utilities.Library open Internal.Utilities.Library.Extras open FSharp.Core.Printf open FSharp.Compiler +open FSharp.Compiler.Syntax open FSharp.Compiler.AbstractIL.IL open FSharp.Compiler.AccessibilityLogic open FSharp.Compiler.CheckExpressions @@ -46,6 +47,10 @@ open FSharp.Compiler.Text.Position open FSharp.Compiler.Text.Range open FSharp.Compiler.TypedTree open FSharp.Compiler.TypedTreeOps +open FSharp.Compiler.AbstractIL +open System.Reflection.PortableExecutable +open FSharp.Compiler.CreateILModule +open FSharp.Compiler.IlxGen open FSharp.Compiler.BuildGraph open Internal.Utilities @@ -2206,7 +2211,7 @@ type FSharpCheckProjectResults keepAssemblyContents: bool, diagnostics: FSharpDiagnostic[], details:(TcGlobals * TcImports * CcuThunk * ModuleOrNamespaceType * Choice * - TopAttribs option * ILAssemblyRef * + TopAttribs option * (unit -> IRawFSharpAssemblyData option) * ILAssemblyRef * AccessorDomain * TypedImplFile list option * string[] * FSharpProjectOptions) option) = let getDetails() = @@ -2224,12 +2229,12 @@ type FSharpCheckProjectResults member _.HasCriticalErrors = details.IsNone member _.AssemblySignature = - let tcGlobals, tcImports, thisCcu, ccuSig, _builderOrSymbolUses, topAttribs, _ilAssemRef, _ad, _tcAssemblyExpr, _dependencyFiles, _projectOptions = getDetails() + let tcGlobals, tcImports, thisCcu, ccuSig, _builderOrSymbolUses, topAttribs, _tcAssemblyData, _ilAssemRef, _ad, _tcAssemblyExpr, _dependencyFiles, _projectOptions = getDetails() FSharpAssemblySignature(tcGlobals, thisCcu, ccuSig, tcImports, topAttribs, ccuSig) member _.TypedImplementationFiles = if not keepAssemblyContents then invalidOp "The 'keepAssemblyContents' flag must be set to true on the FSharpChecker in order to access the checked contents of assemblies" - let tcGlobals, tcImports, thisCcu, _ccuSig, _builderOrSymbolUses, _topAttribs, _ilAssemRef, _ad, tcAssemblyExpr, _dependencyFiles, _projectOptions = getDetails() + let tcGlobals, tcImports, thisCcu, _ccuSig, _builderOrSymbolUses, _topAttribs, _tcAssemblyData, _ilAssemRef, _ad, tcAssemblyExpr, _dependencyFiles, _projectOptions = getDetails() let mimpls = match tcAssemblyExpr with | None -> [] @@ -2238,7 +2243,7 @@ type FSharpCheckProjectResults member info.AssemblyContents = if not keepAssemblyContents then invalidOp "The 'keepAssemblyContents' flag must be set to true on the FSharpChecker in order to access the checked contents of assemblies" - let tcGlobals, tcImports, thisCcu, ccuSig, _builderOrSymbolUses, _topAttribs, _ilAssemRef, _ad, tcAssemblyExpr, _dependencyFiles, _projectOptions = getDetails() + let tcGlobals, tcImports, thisCcu, ccuSig, _builderOrSymbolUses, _topAttribs, _tcAssemblyData, _ilAssemRef, _ad, tcAssemblyExpr, _dependencyFiles, _projectOptions = getDetails() let mimpls = match tcAssemblyExpr with | None -> [] @@ -2247,7 +2252,7 @@ type FSharpCheckProjectResults member _.GetOptimizedAssemblyContents() = if not keepAssemblyContents then invalidOp "The 'keepAssemblyContents' flag must be set to true on the FSharpChecker in order to access the checked contents of assemblies" - let tcGlobals, tcImports, thisCcu, ccuSig, _builderOrSymbolUses, _topAttribs, _ilAssemRef, _ad, tcAssemblyExpr, _dependencyFiles, _projectOptions = getDetails() + let tcGlobals, tcImports, thisCcu, ccuSig, _builderOrSymbolUses, _topAttribs, _tcAssemblyData, _ilAssemRef, _ad, tcAssemblyExpr, _dependencyFiles, _projectOptions = getDetails() let mimpls = match tcAssemblyExpr with | None -> [] @@ -2266,7 +2271,7 @@ type FSharpCheckProjectResults // Not, this does not have to be a SyncOp, it can be called from any thread member _.GetUsesOfSymbol(symbol:FSharpSymbol, ?cancellationToken: CancellationToken) = - let _, _tcImports, _thisCcu, _ccuSig, builderOrSymbolUses, _topAttribs, _ilAssemRef, _ad, _tcAssemblyExpr, _dependencyFiles, _projectOptions = getDetails() + let _, _tcImports, _thisCcu, _ccuSig, builderOrSymbolUses, _topAttribs, _tcAssemblyData, _ilAssemRef, _ad, _tcAssemblyExpr, _dependencyFiles, _projectOptions = getDetails() let results = match builderOrSymbolUses with @@ -2297,7 +2302,7 @@ type FSharpCheckProjectResults // Not, this does not have to be a SyncOp, it can be called from any thread member _.GetAllUsesOfAllSymbols(?cancellationToken: CancellationToken) = - let tcGlobals, tcImports, thisCcu, ccuSig, builderOrSymbolUses, _topAttribs, _ilAssemRef, _ad, _tcAssemblyExpr, _dependencyFiles, _projectOptions = getDetails() + let tcGlobals, tcImports, thisCcu, ccuSig, builderOrSymbolUses, _topAttribs, _ilAssemRef, _tcAssemblyData, _ad, _tcAssemblyExpr, _dependencyFiles, _projectOptions = getDetails() let cenv = SymbolEnv(tcGlobals, thisCcu, Some ccuSig, tcImports) let tcSymbolUses = @@ -2328,18 +2333,18 @@ type FSharpCheckProjectResults yield FSharpSymbolUse(symbolUse.DisplayEnv, symbol, symbolUse.ItemWithInst.TyparInst, symbolUse.ItemOccurence, symbolUse.Range) |] member _.ProjectContext = - let tcGlobals, tcImports, thisCcu, _ccuSig, _tcSymbolUses, _topAttribs, _ilAssemRef, ad, _tcAssemblyExpr, _dependencyFiles, projectOptions = getDetails() + let tcGlobals, tcImports, thisCcu, _ccuSig, _tcSymbolUses, _topAttribs, _tcAssemblyData, _ilAssemRef, ad, _tcAssemblyExpr, _dependencyFiles, projectOptions = getDetails() let assemblies = tcImports.GetImportedAssemblies() |> List.map (fun x -> FSharpAssembly(tcGlobals, tcImports, x.FSharpViewOfMetadata)) FSharpProjectContext(thisCcu, assemblies, ad, projectOptions) member _.DependencyFiles = - let _tcGlobals, _tcImports, _thisCcu, _ccuSig, _tcSymbolUses, _topAttribs, _ilAssemRef, _ad, _tcAssemblyExpr, dependencyFiles, _projectOptions = getDetails() + let _tcGlobals, _tcImports, _thisCcu, _ccuSig, _tcSymbolUses, _topAttribs, _tcAssemblyData, _ilAssemRef, _ad, _tcAssemblyExpr, dependencyFiles, _projectOptions = getDetails() dependencyFiles member _.AssemblyFullName = - let _tcGlobals, _tcImports, _thisCcu, _ccuSig, _tcSymbolUses, _topAttribs, ilAssemRef, _ad, _tcAssemblyExpr, _dependencyFiles, _projectOptions = getDetails() + let _tcGlobals, _tcImports, _thisCcu, _ccuSig, _tcSymbolUses, _topAttribs, _tcAssemblyData, ilAssemRef, _ad, _tcAssemblyExpr, _dependencyFiles, _projectOptions = getDetails() ilAssemRef.QualifiedName override _.ToString() = "FSharpCheckProjectResults(" + projectFileName + ")" @@ -2409,7 +2414,7 @@ type FsiInteractiveChecker(legacyReferenceResolver, FSharpCheckProjectResults (filename, Some tcConfig, keepAssemblyContents, errors, Some(tcGlobals, tcImports, tcFileInfo.ThisCcu, tcFileInfo.CcuSigForFile, - (Choice2Of2 tcFileInfo.ScopeSymbolUses), None, mkSimpleAssemblyRef "stdin", + (Choice2Of2 tcFileInfo.ScopeSymbolUses), None, (fun () -> None), mkSimpleAssemblyRef "stdin", tcState.TcEnvFromImpls.AccessRights, None, dependencyFiles, projectOptions)) diff --git a/src/fsharp/service/FSharpCheckerResults.fsi b/src/fsharp/service/FSharpCheckerResults.fsi index 221a7a7dbca0..5bcf19314200 100644 --- a/src/fsharp/service/FSharpCheckerResults.fsi +++ b/src/fsharp/service/FSharpCheckerResults.fsi @@ -509,6 +509,7 @@ type public FSharpCheckProjectResults = ModuleOrNamespaceType * Choice * TopAttribs option * + (unit -> IRawFSharpAssemblyData option) * ILAssemblyRef * AccessorDomain * TypedImplFile list option * diff --git a/src/fsharp/service/ServiceParsedInputOps.fs b/src/fsharp/service/ServiceParsedInputOps.fs index 7e5177af5af3..bb7cad8ba014 100644 --- a/src/fsharp/service/ServiceParsedInputOps.fs +++ b/src/fsharp/service/ServiceParsedInputOps.fs @@ -1663,7 +1663,8 @@ module ParsedInput = if isImplicitTopLevelModule then 1 else ctx.Pos.Line else 1 | ScopeKind.Namespace -> - // for namespaces the start line is start line of the first nested entity + // For namespaces the start line is start line of the first nested entity + // If we are not on the first line, try to find opening namespace, and return line after it (in F# format) if ctx.Pos.Line > 1 then [0..ctx.Pos.Line - 1] |> List.mapi (fun i line -> i, getLineStr line) @@ -1674,7 +1675,14 @@ module ParsedInput = // move to the next line below "namespace" and convert it to F# 1-based line number | Some line -> line + 2 | None -> ctx.Pos.Line - else 1 + // If we are on 1st line in the namespace ctx, this line _should_ be the namespace declaration, check it and return next line. + // Otherwise, return first line (which theoretically should not happen). + else + let lineStr = getLineStr (ctx.Pos.Line - 1) + if lineStr.StartsWithOrdinal("namespace") then + ctx.Pos.Line + 1 + else + ctx.Pos.Line | _ -> ctx.Pos.Line mkPos line ctx.Pos.Column diff --git a/src/fsharp/service/service.fs b/src/fsharp/service/service.fs index 557c94acb5f9..a49e7aa36667 100644 --- a/src/fsharp/service/service.fs +++ b/src/fsharp/service/service.fs @@ -807,7 +807,7 @@ type BackgroundCompiler( | None -> return FSharpCheckProjectResults (options.ProjectFileName, None, keepAssemblyContents, creationDiags, None) | Some builder -> - let! tcProj, ilAssemRef, _, tcAssemblyExprOpt = builder.GetFullCheckResultsAndImplementationsForProject() + let! tcProj, ilAssemRef, tcAssemblyDataOpt, tcAssemblyExprOpt = builder.GetFullCheckResultsAndImplementationsForProject() let errorOptions = tcProj.TcConfig.errorSeverityOptions let fileName = DummyFileNameForRangesWithoutASpecificLocation @@ -822,6 +822,12 @@ type BackgroundCompiler( let diagnostics = [| yield! creationDiags; yield! DiagnosticHelpers.CreateDiagnostics (errorOptions, true, fileName, tcErrors, suggestNamesForErrors) |] + + let getAssemblyData() = + match tcAssemblyDataOpt with + | ProjectAssemblyDataResult.Available data -> Some data + | _ -> None + let results = FSharpCheckProjectResults (options.ProjectFileName, @@ -829,7 +835,7 @@ type BackgroundCompiler( keepAssemblyContents, diagnostics, Some(tcProj.TcGlobals, tcProj.TcImports, tcState.Ccu, tcState.CcuSig, - (Choice1Of2 builder), topAttribs, ilAssemRef, + (Choice1Of2 builder), topAttribs, getAssemblyData, ilAssemRef, tcEnvAtEnd.AccessRights, tcAssemblyExprOpt, Array.ofList tcDependencyFiles, options)) diff --git a/src/fsharp/symbols/Symbols.fs b/src/fsharp/symbols/Symbols.fs index ed1b773140b9..ed857c0db0bc 100644 --- a/src/fsharp/symbols/Symbols.fs +++ b/src/fsharp/symbols/Symbols.fs @@ -33,18 +33,18 @@ type FSharpAccessibility(a:Accessibility, ?isProtected) = match x with | CompPath(ILScopeRef.Local, []) -> true | _ -> false - + let (|Public|Internal|Private|) (TAccess p) = match p with | [] -> Public - | _ when List.forall isInternalCompPath p -> Internal + | _ when List.forall isInternalCompPath p -> Internal | _ -> Private - member _.IsPublic = not isProtected && match a with TAccess [] -> true | _ -> false + member _.IsPublic = not isProtected && (match a with TAccess [] -> true | _ -> false) - member _.IsPrivate = not isProtected && match a with Private -> true | _ -> false + member _.IsPrivate = not isProtected && (match a with Private -> true | _ -> false) - member _.IsInternal = not isProtected && match a with Internal -> true | _ -> false + member _.IsInternal = not isProtected && (match a with Internal -> true | _ -> false) member _.IsProtected = isProtected diff --git a/src/fsharp/xlf/FSComp.txt.cs.xlf b/src/fsharp/xlf/FSComp.txt.cs.xlf index d93fe9947662..0431b2cb8a42 100644 --- a/src/fsharp/xlf/FSComp.txt.cs.xlf +++ b/src/fsharp/xlf/FSComp.txt.cs.xlf @@ -289,7 +289,7 @@ The 'from the end slicing' feature requires language version 'preview'. - The 'from the end slicing' feature requires language version 'preview'. + Funkce vytváření průřezů od konce vyžaduje jazykovou verzi preview. @@ -407,11 +407,31 @@ Vytiskněte odvozená rozhraní všech kompilovaných souborů do přidružených souborů podpisu. + + Invalid use of emitting a reference assembly. Check the compiler options to not specify static linking, or using '--refonly' and '--refout' together. + Invalid use of emitting a reference assembly. Check the compiler options to not specify static linking, or using '--refonly' and '--refout' together. + + + + Invalid reference assembly path' + Invalid reference assembly path' + + Display the allowed values for language version, specify language version such as 'latest' or 'preview' Zobrazte si povolené hodnoty verze jazyka a pak zadejte požadovanou verzi, například latest nebo preview. + + Produce a reference assembly, instead of a full assembly, as the primary output + Produce a reference assembly, instead of a full assembly, as the primary output + + + + Produce a reference assembly with the specified file path. + Produce a reference assembly with the specified file path. + + Supported language versions: Podporované jazykové verze: @@ -434,7 +454,7 @@ The 'package management' feature requires language version 5.0 or above - The 'package management' feature requires language version 5.0 or above + Funkce správy balíčků vyžaduje jazykovou verzi 5.0 nebo vyšší. @@ -649,7 +669,7 @@ Invalid member declaration. The name of the member is missing or has parentheses. - Invalid member declaration. The name of the member is missing or has parentheses. + Neplatná deklarace člena. Jeho jméno chybí nebo obsahuje závorky. diff --git a/src/fsharp/xlf/FSComp.txt.de.xlf b/src/fsharp/xlf/FSComp.txt.de.xlf index 638a9a8de5dc..448cf3ac1b38 100644 --- a/src/fsharp/xlf/FSComp.txt.de.xlf +++ b/src/fsharp/xlf/FSComp.txt.de.xlf @@ -289,7 +289,7 @@ The 'from the end slicing' feature requires language version 'preview'. - The 'from the end slicing' feature requires language version 'preview'. + Für das Feature „Vom Ende ausgehende Slicing“ ist Sprachversion „Vorschau“ erforderlich. @@ -407,11 +407,31 @@ Drucken der abgeleiteten Schnittstellen aller Dateien an zugehörige Signaturdateien + + Invalid use of emitting a reference assembly. Check the compiler options to not specify static linking, or using '--refonly' and '--refout' together. + Invalid use of emitting a reference assembly. Check the compiler options to not specify static linking, or using '--refonly' and '--refout' together. + + + + Invalid reference assembly path' + Invalid reference assembly path' + + Display the allowed values for language version, specify language version such as 'latest' or 'preview' Zeigen Sie die zulässigen Werte für die Sprachversion an. Geben Sie die Sprachversion als "latest" oder "preview" an. + + Produce a reference assembly, instead of a full assembly, as the primary output + Produce a reference assembly, instead of a full assembly, as the primary output + + + + Produce a reference assembly with the specified file path. + Produce a reference assembly with the specified file path. + + Supported language versions: Unterstützte Sprachversionen: @@ -434,7 +454,7 @@ The 'package management' feature requires language version 5.0 or above - The 'package management' feature requires language version 5.0 or above + Für das „Paketverwaltungsfeature“ ist Sprachversion 5.0 oder höher erforderlich @@ -649,7 +669,7 @@ Invalid member declaration. The name of the member is missing or has parentheses. - Invalid member declaration. The name of the member is missing or has parentheses. + Ungültige Memberdeklaration. Der Name des Members fehlt oder ist in Klammern. diff --git a/src/fsharp/xlf/FSComp.txt.es.xlf b/src/fsharp/xlf/FSComp.txt.es.xlf index b7ced72c91b7..3bd6b38e8a63 100644 --- a/src/fsharp/xlf/FSComp.txt.es.xlf +++ b/src/fsharp/xlf/FSComp.txt.es.xlf @@ -289,7 +289,7 @@ The 'from the end slicing' feature requires language version 'preview'. - The 'from the end slicing' feature requires language version 'preview'. + La característica "desde el final del recorte" requiere la versión de lenguaje "preview" (vista previa). @@ -407,11 +407,31 @@ Imprimir las interfaces deducidas de todos los archivos de compilación en los archivos de signatura asociados + + Invalid use of emitting a reference assembly. Check the compiler options to not specify static linking, or using '--refonly' and '--refout' together. + Invalid use of emitting a reference assembly. Check the compiler options to not specify static linking, or using '--refonly' and '--refout' together. + + + + Invalid reference assembly path' + Invalid reference assembly path' + + Display the allowed values for language version, specify language version such as 'latest' or 'preview' Mostrar los valores permitidos para la versión de idioma, especificar la versión de idioma como "latest" "preview" + + Produce a reference assembly, instead of a full assembly, as the primary output + Produce a reference assembly, instead of a full assembly, as the primary output + + + + Produce a reference assembly with the specified file path. + Produce a reference assembly with the specified file path. + + Supported language versions: Versiones de lenguaje admitidas: @@ -434,7 +454,7 @@ The 'package management' feature requires language version 5.0 or above - The 'package management' feature requires language version 5.0 or above + La característica de "administración de paquetes" requiere la versión de lenguaje 5.0 o superior @@ -649,7 +669,7 @@ Invalid member declaration. The name of the member is missing or has parentheses. - Invalid member declaration. The name of the member is missing or has parentheses. + Declaración de miembro no válida. Falta el nombre del miembro o tiene paréntesis. diff --git a/src/fsharp/xlf/FSComp.txt.fr.xlf b/src/fsharp/xlf/FSComp.txt.fr.xlf index 52c3fdcea861..575166ffb4c5 100644 --- a/src/fsharp/xlf/FSComp.txt.fr.xlf +++ b/src/fsharp/xlf/FSComp.txt.fr.xlf @@ -289,7 +289,7 @@ The 'from the end slicing' feature requires language version 'preview'. - The 'from the end slicing' feature requires language version 'preview'. + La fonctionnalité « from the end slicing » nécessite la version de langage « preview ». @@ -407,11 +407,31 @@ Imprimer les interfaces inférées de tous les fichiers de compilation sur les fichiers de signature associés + + Invalid use of emitting a reference assembly. Check the compiler options to not specify static linking, or using '--refonly' and '--refout' together. + Invalid use of emitting a reference assembly. Check the compiler options to not specify static linking, or using '--refonly' and '--refout' together. + + + + Invalid reference assembly path' + Invalid reference assembly path' + + Display the allowed values for language version, specify language version such as 'latest' or 'preview' Afficher les valeurs autorisées pour la version du langage, spécifier la version du langage comme 'dernière' ou 'préversion' + + Produce a reference assembly, instead of a full assembly, as the primary output + Produce a reference assembly, instead of a full assembly, as the primary output + + + + Produce a reference assembly with the specified file path. + Produce a reference assembly with the specified file path. + + Supported language versions: Versions linguistiques prises en charge : @@ -434,7 +454,7 @@ The 'package management' feature requires language version 5.0 or above - The 'package management' feature requires language version 5.0 or above + La fonction « gestion des paquets » nécessite une version de langue 5.0 ou supérieure. @@ -649,7 +669,7 @@ Invalid member declaration. The name of the member is missing or has parentheses. - Invalid member declaration. The name of the member is missing or has parentheses. + Déclaration de membre non valide. Le nom du membre est manquant ou comporte des parenthèses. diff --git a/src/fsharp/xlf/FSComp.txt.it.xlf b/src/fsharp/xlf/FSComp.txt.it.xlf index 249887688fdb..ec8fc05495c9 100644 --- a/src/fsharp/xlf/FSComp.txt.it.xlf +++ b/src/fsharp/xlf/FSComp.txt.it.xlf @@ -289,7 +289,7 @@ The 'from the end slicing' feature requires language version 'preview'. - The 'from the end slicing' feature requires language version 'preview'. + La funzionalità 'sezionamento dalla fine' richiede la versione del linguaggio 'anteprima'. @@ -407,11 +407,31 @@ Stampare le interfacce derivate di tutti i file di compilazione nei file di firma associati + + Invalid use of emitting a reference assembly. Check the compiler options to not specify static linking, or using '--refonly' and '--refout' together. + Invalid use of emitting a reference assembly. Check the compiler options to not specify static linking, or using '--refonly' and '--refout' together. + + + + Invalid reference assembly path' + Invalid reference assembly path' + + Display the allowed values for language version, specify language version such as 'latest' or 'preview' Visualizza i valori consentiti per la versione del linguaggio. Specificare la versione del linguaggio, ad esempio 'latest' o 'preview' + + Produce a reference assembly, instead of a full assembly, as the primary output + Produce a reference assembly, instead of a full assembly, as the primary output + + + + Produce a reference assembly with the specified file path. + Produce a reference assembly with the specified file path. + + Supported language versions: Versioni del linguaggio supportate: @@ -434,7 +454,7 @@ The 'package management' feature requires language version 5.0 or above - The 'package management' feature requires language version 5.0 or above + La funzionalità 'gestione pacchetti' richiede la versione del linguaggio 5.0 o superiore @@ -649,7 +669,7 @@ Invalid member declaration. The name of the member is missing or has parentheses. - Invalid member declaration. The name of the member is missing or has parentheses. + Dichiarazione di membro non valida. Il nome del membro manca o contiene parentesi. diff --git a/src/fsharp/xlf/FSComp.txt.ja.xlf b/src/fsharp/xlf/FSComp.txt.ja.xlf index 15c5da75f0d2..4f28abfabdec 100644 --- a/src/fsharp/xlf/FSComp.txt.ja.xlf +++ b/src/fsharp/xlf/FSComp.txt.ja.xlf @@ -289,7 +289,7 @@ The 'from the end slicing' feature requires language version 'preview'. - The 'from the end slicing' feature requires language version 'preview'. + 'from the end slicing' (最後からのスライス) 機能には、言語バージョン 'preview' が必要です。 @@ -407,11 +407,31 @@ すべてのコンパイル ファイルの推定されたインターフェイスを関連する署名ファイルに印刷します + + Invalid use of emitting a reference assembly. Check the compiler options to not specify static linking, or using '--refonly' and '--refout' together. + Invalid use of emitting a reference assembly. Check the compiler options to not specify static linking, or using '--refonly' and '--refout' together. + + + + Invalid reference assembly path' + Invalid reference assembly path' + + Display the allowed values for language version, specify language version such as 'latest' or 'preview' 言語バージョンで許可された値を表示し、'最新' や 'プレビュー' などの言語バージョンを指定する + + Produce a reference assembly, instead of a full assembly, as the primary output + Produce a reference assembly, instead of a full assembly, as the primary output + + + + Produce a reference assembly with the specified file path. + Produce a reference assembly with the specified file path. + + Supported language versions: サポートされる言語バージョン: @@ -434,7 +454,7 @@ The 'package management' feature requires language version 5.0 or above - The 'package management' feature requires language version 5.0 or above + 'package management' (パッケージ管理) 機能には、言語バージョン 5.0 以降が必要です @@ -649,7 +669,7 @@ Invalid member declaration. The name of the member is missing or has parentheses. - Invalid member declaration. The name of the member is missing or has parentheses. + メンバーの宣言が無効です。メンバーの名前が見つからないか、かっこが含まれています。 diff --git a/src/fsharp/xlf/FSComp.txt.ko.xlf b/src/fsharp/xlf/FSComp.txt.ko.xlf index 8f28ff6bc5ad..ae5d5a74eefb 100644 --- a/src/fsharp/xlf/FSComp.txt.ko.xlf +++ b/src/fsharp/xlf/FSComp.txt.ko.xlf @@ -289,7 +289,7 @@ The 'from the end slicing' feature requires language version 'preview'. - The 'from the end slicing' feature requires language version 'preview'. + '끝에서부터 조각화' 기능을 사용하려면 언어 버전 '미리 보기'가 필요합니다. @@ -407,11 +407,31 @@ 모든 컴파일 파일의 유추된 인터페이스를 관련 서명 파일로 인쇄합니다. + + Invalid use of emitting a reference assembly. Check the compiler options to not specify static linking, or using '--refonly' and '--refout' together. + Invalid use of emitting a reference assembly. Check the compiler options to not specify static linking, or using '--refonly' and '--refout' together. + + + + Invalid reference assembly path' + Invalid reference assembly path' + + Display the allowed values for language version, specify language version such as 'latest' or 'preview' 언어 버전의 허용된 값을 표시하고 '최신' 또는 '미리 보기'와 같은 언어 버전을 지정합니다. + + Produce a reference assembly, instead of a full assembly, as the primary output + Produce a reference assembly, instead of a full assembly, as the primary output + + + + Produce a reference assembly with the specified file path. + Produce a reference assembly with the specified file path. + + Supported language versions: 지원되는 언어 버전: @@ -434,7 +454,7 @@ The 'package management' feature requires language version 5.0 or above - The 'package management' feature requires language version 5.0 or above + '패키지 관리' 기능을 사용하려면 언어 버전 5.0 이상이 필요합니다. @@ -649,7 +669,7 @@ Invalid member declaration. The name of the member is missing or has parentheses. - Invalid member declaration. The name of the member is missing or has parentheses. + 멤버 선언이 잘못되었습니다. 멤버 이름이 없거나 괄호가 있습니다. diff --git a/src/fsharp/xlf/FSComp.txt.pl.xlf b/src/fsharp/xlf/FSComp.txt.pl.xlf index 70627d2892bb..aaccee27ffa6 100644 --- a/src/fsharp/xlf/FSComp.txt.pl.xlf +++ b/src/fsharp/xlf/FSComp.txt.pl.xlf @@ -289,7 +289,7 @@ The 'from the end slicing' feature requires language version 'preview'. - The 'from the end slicing' feature requires language version 'preview'. + Funkcja „Przycinanie od końca” wymaga „podglądu” wersji językowej. @@ -407,11 +407,31 @@ Drukowanie wywnioskowanych interfejsów wszystkich plików kompilacji do skojarzonych plików sygnatur + + Invalid use of emitting a reference assembly. Check the compiler options to not specify static linking, or using '--refonly' and '--refout' together. + Invalid use of emitting a reference assembly. Check the compiler options to not specify static linking, or using '--refonly' and '--refout' together. + + + + Invalid reference assembly path' + Invalid reference assembly path' + + Display the allowed values for language version, specify language version such as 'latest' or 'preview' Wyświetl dozwolone wartości dla wersji językowej; określ wersję językową, np. „latest” lub „preview” + + Produce a reference assembly, instead of a full assembly, as the primary output + Produce a reference assembly, instead of a full assembly, as the primary output + + + + Produce a reference assembly with the specified file path. + Produce a reference assembly with the specified file path. + + Supported language versions: Obsługiwane wersje językowe: @@ -434,7 +454,7 @@ The 'package management' feature requires language version 5.0 or above - The 'package management' feature requires language version 5.0 or above + Funkcja „Zarządzanie pakietami” wymaga języka w wersji 5.0 lub nowszej @@ -649,7 +669,7 @@ Invalid member declaration. The name of the member is missing or has parentheses. - Invalid member declaration. The name of the member is missing or has parentheses. + Nieprawidłowa deklaracja elementu członkowskiego. Brak nazwy elementu członkowskiego lub ma ona nawiasy. diff --git a/src/fsharp/xlf/FSComp.txt.pt-BR.xlf b/src/fsharp/xlf/FSComp.txt.pt-BR.xlf index 26e583b87bf8..16496b3d78f1 100644 --- a/src/fsharp/xlf/FSComp.txt.pt-BR.xlf +++ b/src/fsharp/xlf/FSComp.txt.pt-BR.xlf @@ -289,7 +289,7 @@ The 'from the end slicing' feature requires language version 'preview'. - The 'from the end slicing' feature requires language version 'preview'. + O recurso 'da divisão final' requer a versão de idioma 'preview'. @@ -407,11 +407,31 @@ Imprimir as interfaces inferidas de todos os arquivos de compilação para os arquivos de assinatura associados + + Invalid use of emitting a reference assembly. Check the compiler options to not specify static linking, or using '--refonly' and '--refout' together. + Invalid use of emitting a reference assembly. Check the compiler options to not specify static linking, or using '--refonly' and '--refout' together. + + + + Invalid reference assembly path' + Invalid reference assembly path' + + Display the allowed values for language version, specify language version such as 'latest' or 'preview' Exibe os valores permitidos para a versão do idioma, especifica a versão do idioma, como 'mais recente ' ou 'prévia' + + Produce a reference assembly, instead of a full assembly, as the primary output + Produce a reference assembly, instead of a full assembly, as the primary output + + + + Produce a reference assembly with the specified file path. + Produce a reference assembly with the specified file path. + + Supported language versions: Versões de linguagens com suporte: @@ -434,7 +454,7 @@ The 'package management' feature requires language version 5.0 or above - The 'package management' feature requires language version 5.0 or above + O recurso 'gerenciamento de pacotes' requer a versão 5.0 ou superior do idioma @@ -649,7 +669,7 @@ Invalid member declaration. The name of the member is missing or has parentheses. - Invalid member declaration. The name of the member is missing or has parentheses. + Declaração de membro inválida. O nome do membro está ausente ou tem parênteses. diff --git a/src/fsharp/xlf/FSComp.txt.ru.xlf b/src/fsharp/xlf/FSComp.txt.ru.xlf index 8b2d5dcc6e3d..c3e3ce97be5d 100644 --- a/src/fsharp/xlf/FSComp.txt.ru.xlf +++ b/src/fsharp/xlf/FSComp.txt.ru.xlf @@ -289,7 +289,7 @@ The 'from the end slicing' feature requires language version 'preview'. - The 'from the end slicing' feature requires language version 'preview'. + Для функции конечного среза требуется "предварительная" версия языка. @@ -407,11 +407,31 @@ Печать определяемых интерфейсов всех файлов компиляции в связанные файлы подписей + + Invalid use of emitting a reference assembly. Check the compiler options to not specify static linking, or using '--refonly' and '--refout' together. + Invalid use of emitting a reference assembly. Check the compiler options to not specify static linking, or using '--refonly' and '--refout' together. + + + + Invalid reference assembly path' + Invalid reference assembly path' + + Display the allowed values for language version, specify language version such as 'latest' or 'preview' Отображение допустимых значений для версии языка. Укажите версию языка, например, "latest" или "preview". + + Produce a reference assembly, instead of a full assembly, as the primary output + Produce a reference assembly, instead of a full assembly, as the primary output + + + + Produce a reference assembly with the specified file path. + Produce a reference assembly with the specified file path. + + Supported language versions: Поддерживаемые языковые версии: @@ -434,7 +454,7 @@ The 'package management' feature requires language version 5.0 or above - The 'package management' feature requires language version 5.0 or above + Для функции управления пакетами требуется версия языка 5.0 или более поздняя @@ -649,7 +669,7 @@ Invalid member declaration. The name of the member is missing or has parentheses. - Invalid member declaration. The name of the member is missing or has parentheses. + Недопустимое объявление элемента. Имя элемента отсутствует или содержит скобки. diff --git a/src/fsharp/xlf/FSComp.txt.tr.xlf b/src/fsharp/xlf/FSComp.txt.tr.xlf index de3cedeb9381..5ad2de1bcd74 100644 --- a/src/fsharp/xlf/FSComp.txt.tr.xlf +++ b/src/fsharp/xlf/FSComp.txt.tr.xlf @@ -289,7 +289,7 @@ The 'from the end slicing' feature requires language version 'preview'. - The 'from the end slicing' feature requires language version 'preview'. + 'Uçtan dilimleme' özelliği, 'önizleme' dil sürümünü gerektirir. @@ -407,11 +407,31 @@ Tüm derleme dosyalarının çıkarsanan arabirimlerini ilişkili imza dosyalarına yazdır + + Invalid use of emitting a reference assembly. Check the compiler options to not specify static linking, or using '--refonly' and '--refout' together. + Invalid use of emitting a reference assembly. Check the compiler options to not specify static linking, or using '--refonly' and '--refout' together. + + + + Invalid reference assembly path' + Invalid reference assembly path' + + Display the allowed values for language version, specify language version such as 'latest' or 'preview' Dil sürümü için izin verilen değerleri görüntüleyin, dil sürümünü 'en son' veya 'önizleme' örneklerindeki gibi belirtin + + Produce a reference assembly, instead of a full assembly, as the primary output + Produce a reference assembly, instead of a full assembly, as the primary output + + + + Produce a reference assembly with the specified file path. + Produce a reference assembly with the specified file path. + + Supported language versions: Desteklenen dil sürümleri: @@ -434,7 +454,7 @@ The 'package management' feature requires language version 5.0 or above - The 'package management' feature requires language version 5.0 or above + ‘Paket yönetimi’ özelliği, dil sürümü 5.0 veya üstünü gerektirir @@ -649,7 +669,7 @@ Invalid member declaration. The name of the member is missing or has parentheses. - Invalid member declaration. The name of the member is missing or has parentheses. + Geçersiz üye bildirimi. Üyenin adı eksik veya parantez içeriyor. diff --git a/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf b/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf index b2a5c4075fd3..7fd15ff380d0 100644 --- a/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf +++ b/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf @@ -289,7 +289,7 @@ The 'from the end slicing' feature requires language version 'preview'. - The 'from the end slicing' feature requires language version 'preview'. + “从末尾切片”功能需要语言版本“预览”。 @@ -407,11 +407,31 @@ 将所有编译文件的推断接口打印到关联的签名文件 + + Invalid use of emitting a reference assembly. Check the compiler options to not specify static linking, or using '--refonly' and '--refout' together. + Invalid use of emitting a reference assembly. Check the compiler options to not specify static linking, or using '--refonly' and '--refout' together. + + + + Invalid reference assembly path' + Invalid reference assembly path' + + Display the allowed values for language version, specify language version such as 'latest' or 'preview' 显示语言版本的允许值,指定语言版本,如“最新”或“预览” + + Produce a reference assembly, instead of a full assembly, as the primary output + Produce a reference assembly, instead of a full assembly, as the primary output + + + + Produce a reference assembly with the specified file path. + Produce a reference assembly with the specified file path. + + Supported language versions: 支持的语言版本: @@ -434,7 +454,7 @@ The 'package management' feature requires language version 5.0 or above - The 'package management' feature requires language version 5.0 or above + “包管理”功能需要语言版本 5.0 或更高版本 @@ -649,7 +669,7 @@ Invalid member declaration. The name of the member is missing or has parentheses. - Invalid member declaration. The name of the member is missing or has parentheses. + 成员声明无效。成员的名称缺失或包含括号。 diff --git a/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf b/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf index 27dc0b276934..7070f0808361 100644 --- a/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf +++ b/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf @@ -289,7 +289,7 @@ The 'from the end slicing' feature requires language version 'preview'. - The 'from the end slicing' feature requires language version 'preview'. + 「從末端分割」功能需要語言版本「預覽」。 @@ -407,11 +407,31 @@ 將所有編譯檔案的推斷介面列印至相關聯的簽章檔案 + + Invalid use of emitting a reference assembly. Check the compiler options to not specify static linking, or using '--refonly' and '--refout' together. + Invalid use of emitting a reference assembly. Check the compiler options to not specify static linking, or using '--refonly' and '--refout' together. + + + + Invalid reference assembly path' + Invalid reference assembly path' + + Display the allowed values for language version, specify language version such as 'latest' or 'preview' 顯示語言版本允許的值,指定 'latest' 或 'preview' 等語言版本 + + Produce a reference assembly, instead of a full assembly, as the primary output + Produce a reference assembly, instead of a full assembly, as the primary output + + + + Produce a reference assembly with the specified file path. + Produce a reference assembly with the specified file path. + + Supported language versions: 支援的語言版本: @@ -434,7 +454,7 @@ The 'package management' feature requires language version 5.0 or above - The 'package management' feature requires language version 5.0 or above + 「套件管理」功能需要語言版本 5.0 或更新版本 @@ -649,7 +669,7 @@ Invalid member declaration. The name of the member is missing or has parentheses. - Invalid member declaration. The name of the member is missing or has parentheses. + 成員宣告無效。成員的名稱遺失或有括弧。 diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core.UnitTests.fsproj b/tests/FSharp.Core.UnitTests/FSharp.Core.UnitTests.fsproj index aa39265d2a0f..4602d100ff41 100644 --- a/tests/FSharp.Core.UnitTests/FSharp.Core.UnitTests.fsproj +++ b/tests/FSharp.Core.UnitTests/FSharp.Core.UnitTests.fsproj @@ -38,6 +38,7 @@ + diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core/RefStructs.fs b/tests/FSharp.Core.UnitTests/FSharp.Core/RefStructs.fs new file mode 100644 index 000000000000..8987d993bdb4 --- /dev/null +++ b/tests/FSharp.Core.UnitTests/FSharp.Core/RefStructs.fs @@ -0,0 +1,32 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace System.Runtime.CompilerServices + +#if NETCOREAPP +open System + +[] +type IsByRefLikeAttribute() = inherit Attribute() +#endif + +namespace FSharp.Core.UnitTests + +#if NETCOREAPP +open System +open System.Runtime.CompilerServices +open Xunit + +[] +type SpanWrapper(span: Span) = + member _.Span = span + +type CustomIsByRefLikeAttributeTests() = + [] + member _.TestSpanWrapper() = + let array = Array.init 5 id + let span = array.AsSpan() + let spanWrapper = SpanWrapper(span) + Assert.True(span.SequenceEqual(Span<_>.op_Implicit spanWrapper.Span)) + Assert.Equal(array, spanWrapper.Span.ToArray()) + () +#endif diff --git a/tests/FSharp.Test.Utilities/Compiler.fs b/tests/FSharp.Test.Utilities/Compiler.fs index 77f204b586b5..50f5e9b24dc1 100644 --- a/tests/FSharp.Test.Utilities/Compiler.fs +++ b/tests/FSharp.Test.Utilities/Compiler.fs @@ -16,6 +16,9 @@ open System.Collections.Immutable open System.IO open System.Text open System.Text.RegularExpressions +open System.Reflection +open System.Reflection.Metadata +open System.Reflection.PortableExecutable module rec Compiler = @@ -44,7 +47,8 @@ module rec Compiler = SourceKind: SourceKind Name: string option IgnoreWarnings: bool - References: CompilationUnit list } + References: CompilationUnit list + CompileDirectory: string option } override this.ToString() = match this.Name with | Some n -> n | _ -> (sprintf "%A" this) type CSharpCompilationSource = @@ -110,14 +114,15 @@ module rec Compiler = match source with | null -> failwith "Source cannot be null" | _ -> - { Source = Text source - Baseline = None - Options = defaultOptions - OutputType = Library - SourceKind = kind - Name = None - IgnoreWarnings = false - References = [] } + { Source = Text source + Baseline = None + Options = defaultOptions + OutputType = Library + SourceKind = kind + Name = None + IgnoreWarnings = false + References = [] + CompileDirectory = None } let private csFromString (source: string) : CSharpCompilationSource = match source with @@ -168,6 +173,20 @@ module rec Compiler = let FSharp (source: string) : CompilationUnit = fsFromString source SourceKind.Fs |> FS + let FSharpWithInputAndOutputPath (inputFilePath: string) (outputFilePath: string) : CompilationUnit = + let compileDirectory = Path.GetDirectoryName(outputFilePath) + let name = Path.GetFileName(outputFilePath) + { Source = Path(inputFilePath) + Baseline = None + Options = defaultOptions + OutputType = Library + SourceKind = SourceKind.Fs + Name = Some name + IgnoreWarnings = false + References = [] + CompileDirectory = Some compileDirectory } + |> FS + let CSharp (source: string) : CompilationUnit = csFromString source |> CS @@ -309,7 +328,12 @@ module rec Compiler = let references = processReferences fsSource.References - let compilation = Compilation.Create(source, sourceKind, output, options, references) + let compilation = + match fsSource.CompileDirectory with + | Some compileDirectory -> + Compilation.Create(source, sourceKind, output, options, references, compileDirectory) + | _ -> + Compilation.Create(source, sourceKind, output, options, references) compileFSharpCompilation compilation fsSource.IgnoreWarnings @@ -369,6 +393,27 @@ module rec Compiler = | CS cs -> compileCSharp cs | _ -> failwith "TODO" + let private getAssemblyInBytes (result: TestResult) = + match result with + | Success output -> + match output.OutputPath with + | Some filePath -> File.ReadAllBytes(filePath) + | _ -> failwith "Output path not found." + | _ -> + failwith "Compilation has errors." + + let compileGuid (cUnit: CompilationUnit) : Guid = + let bytes = + compile cUnit + |> shouldSucceed + |> getAssemblyInBytes + + use reader1 = new PEReader(bytes.ToImmutableArray()) + let reader1 = reader1.GetMetadataReader() + + reader1.GetModuleDefinition().Mvid |> reader1.GetGuid + + let private parseFSharp (fsSource: FSharpCompilationSource) : TestResult = let source = getSource fsSource.Source let fileName = if fsSource.SourceKind = SourceKind.Fsx then "test.fsx" else "test.fs" @@ -560,6 +605,8 @@ module rec Compiler = | Some p -> ILChecker.checkIL p il | Failure _ -> failwith "Result should be \"Success\" in order to get IL." + let verifyILBinary (il: string list) (dll: string)= ILChecker.checkIL dll il + let private verifyFSILBaseline (baseline: Baseline option) (result: Output) : unit = match baseline with | None -> failwith "Baseline was not provided." diff --git a/tests/FSharp.Test.Utilities/CompilerAssert.fs b/tests/FSharp.Test.Utilities/CompilerAssert.fs index 261e7cd57b88..49d037c62921 100644 --- a/tests/FSharp.Test.Utilities/CompilerAssert.fs +++ b/tests/FSharp.Test.Utilities/CompilerAssert.fs @@ -63,12 +63,12 @@ type CompilationReference = static member Create(cmpl: TestCompilation) = TestCompilationReference cmpl -and Compilation = private Compilation of source: string * SourceKind * CompileOutput * options: string[] * CompilationReference list * name: string option with +and Compilation = private Compilation of source: string * SourceKind * CompileOutput * options: string[] * CompilationReference list * name: string option * compileDirectory: string option with - static member Create(source, sourceKind, output, ?options, ?cmplRefs, ?name) = + static member Create(source, sourceKind, output, ?options, ?cmplRefs, ?name, ?compileDirectory) = let options = defaultArg options [||] let cmplRefs = defaultArg cmplRefs [] - Compilation(source, sourceKind, output, options, cmplRefs, name) + Compilation(source, sourceKind, output, options, cmplRefs, name, compileDirectory) [] type CompilerAssert private () = @@ -201,7 +201,7 @@ type CompilerAssert private () = static let rec compileCompilationAux outputPath (disposals: ResizeArray) ignoreWarnings (cmpl: Compilation) : (FSharpDiagnostic[] * string) * string list = let compilationRefs, deps = match cmpl with - | Compilation(_, _, _, _, cmpls, _) -> + | Compilation(_, _, _, _, cmpls, _, _) -> let compiledRefs = cmpls |> List.map (fun cmpl -> @@ -242,29 +242,29 @@ type CompilerAssert private () = let isScript = match cmpl with - | Compilation(_, kind, _, _, _, _) -> + | Compilation(_, kind, _, _, _, _, _) -> match kind with | Fs -> false | Fsx -> true let isExe = match cmpl with - | Compilation(_, _, output, _, _, _) -> + | Compilation(_, _, output, _, _, _, _) -> match output with | Library -> false | Exe -> true let source = match cmpl with - | Compilation(source, _, _, _, _, _) -> source + | Compilation(source, _, _, _, _, _, _) -> source let options = match cmpl with - | Compilation(_, _, _, options, _, _) -> options + | Compilation(_, _, _, options, _, _, _) -> options let nameOpt = match cmpl with - | Compilation(_, _, _, _, _, nameOpt) -> nameOpt + | Compilation(_, _, _, _, _, nameOpt, _) -> nameOpt let disposal, res = compileDisposable outputPath isScript isExe (Array.append options compilationRefs) nameOpt source disposals.Add disposal @@ -278,7 +278,14 @@ type CompilerAssert private () = res, (deps @ deps2) static let rec compileCompilation ignoreWarnings (cmpl: Compilation) f = - let compileDirectory = Path.Combine(Path.GetTempPath(), "CompilerAssert", Path.GetRandomFileName()) + let compileDirectory = + match cmpl with + | Compilation(compileDirectory=compileDirectory) -> + match compileDirectory with + | None -> + CompilerAssert.GenerateDllOutputPath() + | Some compileDirectory -> + compileDirectory let disposals = ResizeArray() try Directory.CreateDirectory(compileDirectory) |> ignore @@ -292,7 +299,14 @@ type CompilerAssert private () = // The reason behind is so we can compose verification of test runs easier. // TODO: We must not rely on the filesystem when compiling static let rec returnCompilation (cmpl: Compilation) ignoreWarnings = - let compileDirectory = Path.Combine(Path.GetTempPath(), "CompilerAssert", Path.GetRandomFileName()) + let compileDirectory = + match cmpl with + | Compilation(compileDirectory=compileDirectory) -> + match compileDirectory with + | None -> + CompilerAssert.GenerateDllOutputPath() + | Some compileDirectory -> + compileDirectory Directory.CreateDirectory(compileDirectory) |> ignore compileCompilationAux compileDirectory (ResizeArray()) ignoreWarnings cmpl @@ -353,10 +367,23 @@ type CompilerAssert private () = let exitCode, output, errors = Commands.executeProcess (Some filename) arguments (Path.GetDirectoryName(outputFilePath)) timeout (exitCode, output |> String.concat "\n", errors |> String.concat "\n") + static let CompilerAssertTempPath = Path.Combine(Path.GetTempPath(), "CompilerAssert") + static let CreateCompilerAssertTempPath() = + if not (FileSystem.DirectoryExistsShim CompilerAssertTempPath) then + FileSystem.DirectoryCreateShim CompilerAssertTempPath |> ignore + static member Checker = checker static member DefaultProjectOptions = defaultProjectOptions + static member GenerateFsInputPath() = + CreateCompilerAssertTempPath() + Path.Combine(CompilerAssertTempPath, Path.ChangeExtension(Path.GetRandomFileName(), ".fs")) + + static member GenerateDllOutputPath() = + CreateCompilerAssertTempPath() + Path.Combine(CompilerAssertTempPath, Path.ChangeExtension(Path.GetRandomFileName(), ".dll")) + static member CompileWithErrors(cmpl: Compilation, expectedErrors, ?ignoreWarnings) = let ignoreWarnings = defaultArg ignoreWarnings false compileCompilation ignoreWarnings cmpl (fun ((errors, _), _) -> diff --git a/tests/FSharp.Test.Utilities/ILChecker.fs b/tests/FSharp.Test.Utilities/ILChecker.fs index 6357af6102da..a2ff9e5035d6 100644 --- a/tests/FSharp.Test.Utilities/ILChecker.fs +++ b/tests/FSharp.Test.Utilities/ILChecker.fs @@ -48,7 +48,7 @@ module ILChecker = let unifyRuntimeAssemblyName ilCode = System.Text.RegularExpressions.Regex.Replace(ilCode, - "\[System.Runtime\]|\[System.Console\]|\[System.Runtime.Extensions\]|\[mscorlib\]","[runtime]", + "\[System\.Runtime\]|\[System\.Console\]|\[System\.Runtime\.Extensions\]|\[mscorlib\]|\[System\.Memory\]","[runtime]", System.Text.RegularExpressions.RegexOptions.Singleline) let raw = File.ReadAllText(ilFilePath) diff --git a/tests/FSharp.Test.Utilities/Xunit/Attributes/DirectoryAttribute.fs b/tests/FSharp.Test.Utilities/Xunit/Attributes/DirectoryAttribute.fs index facf0674bd7f..c44f1bd9f739 100644 --- a/tests/FSharp.Test.Utilities/Xunit/Attributes/DirectoryAttribute.fs +++ b/tests/FSharp.Test.Utilities/Xunit/Attributes/DirectoryAttribute.fs @@ -48,7 +48,8 @@ type DirectoryAttribute(dir: string) = SourceKind = SourceKind.Fsx Name = Some fs IgnoreWarnings = false - References = [] } |> FS + References = [] + CompileDirectory = None } |> FS member _.Includes with get() = includes and set v = includes <- v diff --git a/tests/fsharp/Compiler/CodeGen/EmittedIL/DeterministicTests.fs b/tests/fsharp/Compiler/CodeGen/EmittedIL/DeterministicTests.fs new file mode 100644 index 000000000000..fd8539ddab94 --- /dev/null +++ b/tests/fsharp/Compiler/CodeGen/EmittedIL/DeterministicTests.fs @@ -0,0 +1,530 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace FSharp.Compiler.UnitTests.CodeGen.EmittedIL + +open System.IO +open FSharp.Test +open FSharp.Test.Compiler +open NUnit.Framework + +[] +module DeterministicTests = + + [] + let ``Simple assembly should be deterministic``() = + let inputFilePath = CompilerAssert.GenerateFsInputPath() + let outputFilePath = CompilerAssert.GenerateDllOutputPath() + let src = + """ +module Assembly + +open System + +let test() = + Console.WriteLine("Hello World!") + """ + + File.WriteAllText(inputFilePath, src) + + let mvid1 = + FSharpWithInputAndOutputPath inputFilePath outputFilePath + |> withOptions ["--deterministic"] + |> compileGuid + let mvid2 = + FSharpWithInputAndOutputPath inputFilePath outputFilePath + |> withOptions ["--deterministic"] + |> compileGuid + + // Two identical compilations should produce the same MVID + Assert.AreEqual(mvid1, mvid2) + + [] + let ``Simple assembly with different platform should not be deterministic``() = + let inputFilePath = CompilerAssert.GenerateFsInputPath() + let outputFilePath = CompilerAssert.GenerateDllOutputPath() + let src = + """ +module Assembly + +open System + +let test() = + Console.WriteLine("Hello World!") + """ + + File.WriteAllText(inputFilePath, src) + + let mvid1 = + FSharpWithInputAndOutputPath inputFilePath outputFilePath + |> withOptions ["--deterministic"] + |> compileGuid + let mvid2 = + FSharpWithInputAndOutputPath inputFilePath outputFilePath + |> withOptions ["--deterministic";"--platform:Itanium"] + |> compileGuid + + // No two platforms should produce the same MVID + Assert.AreNotEqual(mvid1, mvid2) + + [] + let ``Simple reference assembly should be deterministic``() = + let inputFilePath = CompilerAssert.GenerateFsInputPath() + let outputFilePath = CompilerAssert.GenerateDllOutputPath() + let src = + """ +module ReferenceAssembly + +open System + +let private privTest() = + Console.WriteLine("Private Hello World!") + +let test() = + privTest() + Console.WriteLine("Hello World!") + """ + + File.WriteAllText(inputFilePath, src) + + let mvid1 = + FSharpWithInputAndOutputPath inputFilePath outputFilePath + |> withOptions ["--refonly";"--deterministic"] + |> compileGuid + let mvid2 = + FSharpWithInputAndOutputPath inputFilePath outputFilePath + |> withOptions ["--refonly";"--deterministic"] + |> compileGuid + + // Two identical compilations should produce the same MVID + Assert.AreEqual(mvid1, mvid2) + + [] + let ``Simple reference assembly with different platform should not be deterministic``() = + let inputFilePath = CompilerAssert.GenerateFsInputPath() + let outputFilePath = CompilerAssert.GenerateDllOutputPath() + let src = + """ +module ReferenceAssembly + +open System + +let private privTest() = + Console.WriteLine("Private Hello World!") + +let test() = + privTest() + Console.WriteLine("Hello World!") + """ + + File.WriteAllText(inputFilePath, src) + + let mvid1 = + FSharpWithInputAndOutputPath inputFilePath outputFilePath + |> withOptions ["--refonly";"--deterministic"] + |> compileGuid + let mvid2 = + FSharpWithInputAndOutputPath inputFilePath outputFilePath + |> withOptions ["--refonly";"--deterministic";"--platform:Itanium"] + |> compileGuid + + // No two platforms should produce the same MVID + Assert.AreNotEqual(mvid1, mvid2) + + + [] + let ``False-positive reference assemblies test, different aseemblies' mvid should not match`` () = + let inputFilePath = CompilerAssert.GenerateFsInputPath() + let outputFilePath = CompilerAssert.GenerateDllOutputPath() + let src = + """ +module ReferenceAssembly + +open System + +let test() = + Console.WriteLine("Hello World!") + """ + + File.WriteAllText(inputFilePath, src) + + let mvid1 = + FSharpWithInputAndOutputPath inputFilePath outputFilePath + |> withOptions ["--refonly";"--deterministic"] + |> compileGuid + + + let inputFilePath2 = CompilerAssert.GenerateFsInputPath() + let outputFilePath2 = CompilerAssert.GenerateDllOutputPath() + let src2 = + """ +module ReferenceAssembly + +open System + +let test2() = + Console.WriteLine("Hello World!") + """ + + File.WriteAllText(inputFilePath2, src2) + + let mvid2 = + FSharpWithInputAndOutputPath inputFilePath2 outputFilePath2 + |> withOptions ["--refonly";"--deterministic"] + |> compileGuid + + // Two different compilations should _not_ produce the same MVID + Assert.AreNotEqual(mvid1, mvid2) + + [] + let ``Reference assemblies should be deterministic when only private function name is different with the same function name length`` () = + let inputFilePath = CompilerAssert.GenerateFsInputPath() + let outputFilePath = CompilerAssert.GenerateDllOutputPath() + let src = + """ +module ReferenceAssembly + +open System + +let private privTest1() = + Console.WriteLine("Private Hello World!") + +let test() = + privTest1() + Console.WriteLine("Hello World!") + """ + + File.WriteAllText(inputFilePath, src) + + let mvid1 = + FSharpWithInputAndOutputPath inputFilePath outputFilePath + |> withOptions ["--refonly";"--deterministic"] + |> compileGuid + + + let inputFilePath2 = CompilerAssert.GenerateFsInputPath() + let outputFilePath2 = CompilerAssert.GenerateDllOutputPath() + let src2 = + """ +module ReferenceAssembly + +open System + +let private privTest2() = + Console.WriteLine("Private Hello World!") + +let test() = + privTest2() + Console.WriteLine("Hello World!") + """ + + File.WriteAllText(inputFilePath2, src2) + + let mvid2 = + FSharpWithInputAndOutputPath inputFilePath2 outputFilePath2 + |> withOptions ["--refonly";"--deterministic"] + |> compileGuid + + // Two compilations with changes only to private code should produce the same MVID + Assert.AreEqual(mvid1, mvid2) + + + [] + let ``Reference assemblies should be deterministic when only private function name is different with the different function name length`` () = + let inputFilePath = CompilerAssert.GenerateFsInputPath() + let outputFilePath = CompilerAssert.GenerateDllOutputPath() + let src = + """ +module ReferenceAssembly + +open System + +let private privTest1() = + Console.WriteLine("Private Hello World!") + +let test() = + privTest1() + Console.WriteLine("Hello World!") + """ + + File.WriteAllText(inputFilePath, src) + + let mvid1 = + FSharpWithInputAndOutputPath inputFilePath outputFilePath + |> withOptions ["--refonly";"--deterministic"] + |> compileGuid + + + let inputFilePath2 = CompilerAssert.GenerateFsInputPath() + let outputFilePath2 = CompilerAssert.GenerateDllOutputPath() + let src2 = + """ +module ReferenceAssembly + +open System + +let private privTest11() = + Console.WriteLine("Private Hello World!") + +let test() = + privTest11() + Console.WriteLine("Hello World!") + """ + + File.WriteAllText(inputFilePath2, src2) + + let mvid2 = + FSharpWithInputAndOutputPath inputFilePath2 outputFilePath2 + |> withOptions ["--refonly";"--deterministic"] + |> compileGuid + + // Two compilations with changes only to private code should produce the same MVID + Assert.AreEqual(mvid1, mvid2) + + [] + let ``Reference assemblies should be deterministic when only private function body is different`` () = + let inputFilePath = CompilerAssert.GenerateFsInputPath() + let outputFilePath = CompilerAssert.GenerateDllOutputPath() + let src = + """ +module ReferenceAssembly + +open System + +let private privTest1() = + Console.WriteLine("Private Hello World!") + +let test() = + privTest1() + Console.WriteLine("Hello World!") + """ + + File.WriteAllText(inputFilePath, src) + + let mvid1 = + FSharpWithInputAndOutputPath inputFilePath outputFilePath + |> withOptions ["--refonly";"--deterministic"] + |> compileGuid + + + let inputFilePath2 = CompilerAssert.GenerateFsInputPath() + let outputFilePath2 = CompilerAssert.GenerateDllOutputPath() + let src2 = + """ +module ReferenceAssembly + +open System + +let private privTest1() = + Console.Write("Private Hello World!") + +let test() = + privTest1() + Console.WriteLine("Hello World!") + """ + + File.WriteAllText(inputFilePath2, src2) + + let mvid2 = + FSharpWithInputAndOutputPath inputFilePath2 outputFilePath2 + |> withOptions ["--refonly";"--deterministic"] + |> compileGuid + + // Two compilations with changes only to private code should produce the same MVID + Assert.AreEqual(mvid1, mvid2) + + [] + let ``Reference assemblies should be deterministic when only private function return type is different`` () = + let inputFilePath = CompilerAssert.GenerateFsInputPath() + let outputFilePath = CompilerAssert.GenerateDllOutputPath() + let src = + """ +module ReferenceAssembly + +open System + +let private privTest1() : string = "Private Hello World!" + +let test() = + privTest1() |> ignore + Console.WriteLine() + """ + + File.WriteAllText(inputFilePath, src) + + let mvid1 = + FSharpWithInputAndOutputPath inputFilePath outputFilePath + |> withOptions ["--refonly";"--deterministic"] + |> compileGuid + + + let inputFilePath2 = CompilerAssert.GenerateFsInputPath() + let outputFilePath2 = CompilerAssert.GenerateDllOutputPath() + let src2 = + """ +module ReferenceAssembly + +open System + +let private privTest1() : int = 0 + +let test() = + privTest1() |> ignore + Console.WriteLine() + """ + + File.WriteAllText(inputFilePath2, src2) + + let mvid2 = + FSharpWithInputAndOutputPath inputFilePath2 outputFilePath2 + |> withOptions ["--refonly";"--deterministic"] + |> compileGuid + + // Two compilations with changes only to private code should produce the same MVID + Assert.AreEqual(mvid1, mvid2) + + [] + let ``Reference assemblies should be deterministic when only private function parameter count is different`` () = + let inputFilePath = CompilerAssert.GenerateFsInputPath() + let outputFilePath = CompilerAssert.GenerateDllOutputPath() + let src = + """ +module ReferenceAssembly + +open System + +let private privTest1 () : string = "Private Hello World!" + +let test() = + privTest1 () |> ignore + Console.WriteLine() + """ + + File.WriteAllText(inputFilePath, src) + + let mvid1 = + FSharpWithInputAndOutputPath inputFilePath outputFilePath + |> withOptions ["--refonly";"--deterministic"] + |> compileGuid + + + let inputFilePath2 = CompilerAssert.GenerateFsInputPath() + let outputFilePath2 = CompilerAssert.GenerateDllOutputPath() + let src2 = + """ +module ReferenceAssembly + +open System + +let private privTest1 () () : string = "Private Hello World!" + +let test() = + privTest1 () () |> ignore + Console.WriteLine() + """ + + File.WriteAllText(inputFilePath2, src2) + + let mvid2 = + FSharpWithInputAndOutputPath inputFilePath2 outputFilePath2 + |> withOptions ["--refonly";"--deterministic"] + |> compileGuid + + // Two compilations with changes only to private code should produce the same MVID + Assert.AreEqual(mvid1, mvid2) + + [] + let ``Reference assemblies should be deterministic when only private function parameter types are different`` () = + let inputFilePath = CompilerAssert.GenerateFsInputPath() + let outputFilePath = CompilerAssert.GenerateDllOutputPath() + let src = + """ +module ReferenceAssembly + +open System + +let private privTest1 () = "Private Hello World!" + +let test() = + privTest1() |> ignore + Console.WriteLine() + """ + + File.WriteAllText(inputFilePath, src) + + let mvid1 = + FSharpWithInputAndOutputPath inputFilePath outputFilePath + |> withOptions ["--refonly";"--deterministic"] + |> compileGuid + + + let inputFilePath2 = CompilerAssert.GenerateFsInputPath() + let outputFilePath2 = CompilerAssert.GenerateDllOutputPath() + let src2 = + """ +module ReferenceAssembly + +open System + +let private privTest1 (_: string) = "Private Hello World!" + +let test() = + privTest1 "" |> ignore + Console.WriteLine() + """ + + File.WriteAllText(inputFilePath2, src2) + + let mvid2 = + FSharpWithInputAndOutputPath inputFilePath2 outputFilePath2 + |> withOptions ["--refonly";"--deterministic"] + |> compileGuid + + // Two compilations with changes only to private code should produce the same MVID + Assert.AreEqual(mvid1, mvid2) + + [] + let ``Reference assemblies should be deterministic when private function is missing in one of them`` () = + let inputFilePath = CompilerAssert.GenerateFsInputPath() + let outputFilePath = CompilerAssert.GenerateDllOutputPath() + let src = + """ +module ReferenceAssembly + +open System + +let private privTest1 () = "Private Hello World!" + +let test() = + privTest1() |> ignore + Console.WriteLine() + """ + + File.WriteAllText(inputFilePath, src) + + let mvid1 = + FSharpWithInputAndOutputPath inputFilePath outputFilePath + |> withOptions ["--refonly";"--deterministic"] + |> compileGuid + + + let inputFilePath2 = CompilerAssert.GenerateFsInputPath() + let outputFilePath2 = CompilerAssert.GenerateDllOutputPath() + let src2 = + """ +module ReferenceAssembly + +open System + +let test() = + Console.WriteLine() + """ + + File.WriteAllText(inputFilePath2, src2) + + let mvid2 = + FSharpWithInputAndOutputPath inputFilePath2 outputFilePath2 + |> withOptions ["--refonly";"--deterministic"] + |> compileGuid + + // Two compilations with changes only to private code should produce the same MVID + Assert.AreEqual(mvid1, mvid2) \ No newline at end of file diff --git a/tests/fsharp/Compiler/CodeGen/EmittedIL/ReferenceAssemblyTests.fs b/tests/fsharp/Compiler/CodeGen/EmittedIL/ReferenceAssemblyTests.fs new file mode 100644 index 000000000000..762cea82bfb7 --- /dev/null +++ b/tests/fsharp/Compiler/CodeGen/EmittedIL/ReferenceAssemblyTests.fs @@ -0,0 +1,452 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace FSharp.Compiler.UnitTests.CodeGen.EmittedIL + +open FSharp.Test.Compiler +open NUnit.Framework +open FSharp.Compiler.IO + +[] +module ReferenceAssemblyTests = + + let referenceAssemblyAttributeExpectedIL = + """.custom instance void [runtime]System.Runtime.CompilerServices.ReferenceAssemblyAttribute::.ctor() = ( 01 00 00 00 )""" + + [] + let ``Simple reference assembly should have expected IL``() = + let src = + """ +module ReferenceAssembly + +open System + +let test() = + Console.WriteLine("Hello World!") + """ + + FSharp src + |> withOptions ["--refonly"] + |> compile + |> shouldSucceed + |> verifyIL [ + referenceAssemblyAttributeExpectedIL + """.class public abstract auto ansi sealed ReferenceAssembly + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .method public static void test() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: throw + } + + } + + .class private abstract auto ansi sealed ''.$ReferenceAssembly + extends [runtime]System.Object + { + }""" + ] + |> ignore + + [] + let ``Simple reference assembly should have expected IL without a private function``() = + let src = + """ +module ReferenceAssembly + +open System + +let private privTest() = + Console.WriteLine("Private Hello World!") + +let test() = + privTest() + Console.WriteLine("Hello World!") + """ + + FSharp src + |> withOptions ["--refonly"] + |> compile + |> shouldSucceed + |> verifyIL [ + referenceAssemblyAttributeExpectedIL + """.class public abstract auto ansi sealed ReferenceAssembly + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .method public static void test() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: throw + } + + } + + .class private abstract auto ansi sealed ''.$ReferenceAssembly + extends [runtime]System.Object + { + }""" + ] + |> ignore + + [] + let ``Simple reference assembly should have expected IL with anonymous record``() = + let src = + """ +module ReferenceAssembly + +open System + +let test(_x: {| a: int32 |}) = + Console.WriteLine("Hello World!") + """ + + FSharp src + |> withOptions ["--refonly"] + |> compile + |> shouldSucceed + |> verifyIL [ + referenceAssemblyAttributeExpectedIL + """.maxstack 8 + IL_0000: ldnull + IL_0001: throw + } + + } + + .class private abstract auto ansi sealed ''.$ReferenceAssembly + extends [runtime]System.Object + { + }""" + ] + |> ignore + + [] + let ``Simple reference assembly with nested module should have expected IL``() = + let src = + """ +module ReferenceAssembly + +open System + +module Nested = + + let test() = + Console.WriteLine("Hello World!") + """ + + FSharp src + |> withOptions ["--refonly"] + |> compile + |> shouldSucceed + |> verifyIL [ + referenceAssemblyAttributeExpectedIL + """.class public abstract auto ansi sealed ReferenceAssembly + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class abstract auto ansi sealed nested public Nested + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .method public static void test() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: throw + } + + } + + } + + .class private abstract auto ansi sealed ''.$ReferenceAssembly + extends [runtime]System.Object + { + }""" + ] + |> ignore + + [] + let ``Simple reference assembly with nested module with type should have expected IL``() = + let src = + """ +module ReferenceAssembly + +open System + +module Nested = + + type Test = { x: int } + + let test(_x: Test) = + Console.WriteLine("Hello World!") + """ + + FSharp src + |> withOptions ["--refonly"] + |> compile + |> shouldSucceed + |> verifyIL [ + referenceAssemblyAttributeExpectedIL + """.class public abstract auto ansi sealed ReferenceAssembly + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class abstract auto ansi sealed nested public Nested + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable sealed nested public Test + extends [runtime]System.Object + implements class [runtime]System.IEquatable`1, + [runtime]System.Collections.IStructuralEquatable, + class [runtime]System.IComparable`1, + [runtime]System.IComparable, + [runtime]System.Collections.IStructuralComparable + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 02 00 00 00 00 00 ) + .field assembly int32 x@ + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public hidebysig specialname + instance int32 get_x() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: throw + } + + .method public specialname rtspecialname + instance void .ctor(int32 x) cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: throw + } + + .method public strict virtual instance string + ToString() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldnull + IL_0001: throw + } + + .method public hidebysig virtual final + instance int32 CompareTo(class ReferenceAssembly/Nested/Test obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldnull + IL_0001: throw + } + + .method public hidebysig virtual final + instance int32 CompareTo(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldnull + IL_0001: throw + } + + .method public hidebysig virtual final + instance int32 CompareTo(object obj, + class [runtime]System.Collections.IComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldnull + IL_0001: throw + } + + .method public hidebysig virtual final + instance int32 GetHashCode(class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldnull + IL_0001: throw + } + + .method public hidebysig virtual final + instance int32 GetHashCode() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldnull + IL_0001: throw + } + + .method public hidebysig virtual final + instance bool Equals(object obj, + class [runtime]System.Collections.IEqualityComparer comp) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldnull + IL_0001: throw + } + + .method public hidebysig virtual final + instance bool Equals(class ReferenceAssembly/Nested/Test obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldnull + IL_0001: throw + } + + .method public hidebysig virtual final + instance bool Equals(object obj) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldnull + IL_0001: throw + } + + .property instance int32 x() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags, + int32) = ( 01 00 04 00 00 00 00 00 00 00 00 00 ) + .get instance int32 ReferenceAssembly/Nested/Test::get_x() + } + } + + .method public static void test(class ReferenceAssembly/Nested/Test _x) cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: throw + } + + } + + } + + .class private abstract auto ansi sealed ''.$ReferenceAssembly + extends [runtime]System.Object + { + }""" + ] + |> ignore + + [] + let ``--refout should produce both normal and reference assemblies``() = + // TODO: We probably want a built-in test framework functionality which will be taking care of comparing/verifying refout. + let refoutDllPath = FileSystem.GetTempPathShim() + "Test.ref.dll" + let src = + """ +module ReferenceAssembly + +open System + +let test() = + Console.WriteLine("Hello World!") + """ + + // This will produce normal assembly as well as ref in {refoutPath} + let result = + FSharp src + |> withOptions [$"--refout:{refoutDllPath}"] + |> compile + + // Should build successfully. + result |> shouldSucceed + // Verify that normal assembly has been produced. + |> verifyIL [""".class public abstract auto ansi sealed ReferenceAssembly + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .method public static void test() cil managed + { + + .maxstack 8 + IL_0000: ldstr "Hello World!" + IL_0005: call void [runtime]System.Console::WriteLine(string) + IL_000a: ret + } + + }""" + ] + |> ignore + + // Verify that ref assembly in custom path was produced. + if not (FileSystem.FileExistsShim refoutDllPath) then + failwith $"Can't find reference assembly {refoutDllPath}" + + refoutDllPath + |> verifyILBinary [ + referenceAssemblyAttributeExpectedIL + """.class public abstract auto ansi sealed ReferenceAssembly + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .method public static void test() cil managed + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: throw + } + + }""" + ] + + [] + let ``Can't use both --refonly and --staticlink``() = + let src = + """ +module ReferenceAssembly + +open System + +let test() = + Console.WriteLine("Hello World!") + """ + + FSharp src + |> withOptions ["--staticlink:foo"; "--refonly"] + |> compile + |> shouldFail + |> withSingleDiagnostic (Error 2030, Line 0, Col 1, Line 0, Col 1, "Invalid use of emitting a reference assembly. Check the compiler options to not specify static linking, or using '--refonly' and '--refout' together.") + |> ignore + + [] + let ``Can't use both --refoout and --staticlink``() = + let src = + """ +module ReferenceAssembly + +open System + +let test() = + Console.WriteLine("Hello World!") + """ + + FSharp src + |> withOptions ["--staticlink:foo"; "--refout:foo"] + |> compile + |> shouldFail + |> withSingleDiagnostic (Error 2030, Line 0, Col 1, Line 0, Col 1, "Invalid use of emitting a reference assembly. Check the compiler options to not specify static linking, or using '--refonly' and '--refout' together.") + |> ignore \ No newline at end of file diff --git a/tests/fsharp/Compiler/Language/SpanOptimizationTests.fs b/tests/fsharp/Compiler/Language/SpanOptimizationTests.fs index 6d155dc723eb..5345fbfd252a 100644 --- a/tests/fsharp/Compiler/Language/SpanOptimizationTests.fs +++ b/tests/fsharp/Compiler/Language/SpanOptimizationTests.fs @@ -11,7 +11,7 @@ module SpanOptimizationTests = [] let SpanForInDo() = - let source = + let source = """ module Test @@ -40,7 +40,7 @@ let test () = IL_0006: ldc.i4.0 IL_0007: stloc.1 IL_0008: br.s IL_0022 - + IL_000a: ldloca.s V_0 IL_000c: ldloc.1 IL_000d: call instance !0& valuetype [runtime]System.Span`1::get_Item(int32) @@ -56,14 +56,14 @@ let test () = IL_0023: ldloca.s V_0 IL_0025: call instance int32 valuetype [runtime]System.Span`1::get_Length() IL_002a: blt.s IL_000a - + IL_002c: ret }""" ]) [] let ReadOnlySpanForInDo() = - let source = + let source = """ module Test @@ -115,7 +115,7 @@ let test () = [] let ExplicitSpanTypeForInDo() = - let source = + let source = """ namespace System.Runtime.CompilerServices @@ -141,9 +141,7 @@ type Span<'T>(arr: 'T []) = static member Empty = Span<'T>([||]) - interface IEnumerable with - - member _.GetEnumerator() = null + member _.GetEnumerator() = arr.AsSpan().GetEnumerator() module Test = @@ -161,50 +159,45 @@ module Test = """ .method public static void test() cil managed { - + .maxstack 3 .locals init (valuetype System.Span`1 V_0, - class [runtime]System.Collections.IEnumerator V_1, - class [runtime]System.IDisposable V_2) + valuetype [runtime]System.Span`1/Enumerator V_1, + valuetype [runtime]System.Span`1 V_2, + object& V_3) IL_0000: call !!0[] [runtime]System.Array::Empty() IL_0005: newobj instance void valuetype System.Span`1::.ctor(!0[]) IL_000a: stloc.0 - IL_000b: ldloc.0 - IL_000c: box valuetype System.Span`1 - IL_0011: unbox.any [runtime]System.Collections.IEnumerable - IL_0016: callvirt instance class [runtime]System.Collections.IEnumerator [runtime]System.Collections.IEnumerable::GetEnumerator() - IL_001b: stloc.1 + IL_000b: ldloca.s V_0 + IL_000d: ldfld !0[] valuetype System.Span`1::arr + IL_0012: call valuetype [runtime]System.Span`1 [runtime]System.MemoryExtensions::AsSpan(!!0[]) + IL_0017: stloc.2 + IL_0018: ldloca.s V_2 + IL_001a: call instance valuetype [runtime]System.Span`1/Enumerator valuetype [runtime]System.Span`1::GetEnumerator() + IL_001f: stloc.1 .try { - IL_001c: ldloc.1 - IL_001d: callvirt instance bool [runtime]System.Collections.IEnumerator::MoveNext() - IL_0022: brfalse.s IL_0031 - - IL_0024: ldloc.1 - IL_0025: callvirt instance object [runtime]System.Collections.IEnumerator::get_Current() - IL_002a: call void [runtime]System.Console::WriteLine(object) - IL_002f: br.s IL_001c - - IL_0031: leave.s IL_0045 - - } + IL_0020: ldloca.s V_1 + IL_0022: call instance bool valuetype [runtime]System.Span`1/Enumerator::MoveNext() + IL_0027: brfalse.s IL_003e + + IL_0029: ldloca.s V_1 + IL_002b: call instance !0& valuetype [runtime]System.Span`1/Enumerator::get_Current() + IL_0030: stloc.3 + IL_0031: ldloc.3 + IL_0032: ldobj [runtime]System.Object + IL_0037: call void [runtime]System.Console::WriteLine(object) + IL_003c: br.s IL_0020 + + IL_003e: leave.s IL_0041 + + } finally { - IL_0033: ldloc.1 - IL_0034: isinst [runtime]System.IDisposable - IL_0039: stloc.2 - IL_003a: ldloc.2 - IL_003b: brfalse.s IL_0044 - - IL_003d: ldloc.2 - IL_003e: callvirt instance void [runtime]System.IDisposable::Dispose() - IL_0043: endfinally - IL_0044: endfinally - } - IL_0045: ret - } - - } + IL_0040: endfinally + } + IL_0041: ret + } """ ]) @@ -238,7 +231,7 @@ for i in 0 .. span.Length-1 do IL_0006: ldc.i4.0 IL_0007: stloc.1 IL_0008: br.s IL_0022 - + IL_000a: ldloca.s V_0 IL_000c: ldloc.1 IL_000d: call instance !0& valuetype [runtime]System.Span`1::get_Item(int32) @@ -254,7 +247,7 @@ for i in 0 .. span.Length-1 do IL_0023: ldloca.s V_0 IL_0025: call instance int32 valuetype [runtime]System.Span`1::get_Length() IL_002a: blt.s IL_000a - + IL_002c: ret }""" ]) diff --git a/tests/fsharp/Compiler/Language/SpanTests.fs b/tests/fsharp/Compiler/Language/SpanTests.fs index 009a69c15a9f..aef001deec2e 100644 --- a/tests/fsharp/Compiler/Language/SpanTests.fs +++ b/tests/fsharp/Compiler/Language/SpanTests.fs @@ -160,4 +160,19 @@ let f (x: TA) = () [| FSharpDiagnosticSeverity.Error, 3300, (6, 8, 6, 9), "The parameter 'x' has an invalid type 'TA'. This is not permitted by the rules of Common IL." |] + + [] + let ``A custom IsByRefLikeAttribute can define a ref struct``() = + CompilerAssert.TypeCheckWithErrors """ +namespace System.Runtime.CompilerServices + +open System + +[] +type IsByRefLikeAttribute() = inherit Attribute() + +[] +type T(span: Span) = struct end + """ + [| |] #endif \ No newline at end of file diff --git a/tests/fsharp/FSharpSuite.Tests.fsproj b/tests/fsharp/FSharpSuite.Tests.fsproj index 1ee6bf66a30c..731046e96d09 100644 --- a/tests/fsharp/FSharpSuite.Tests.fsproj +++ b/tests/fsharp/FSharpSuite.Tests.fsproj @@ -27,6 +27,7 @@ + @@ -36,6 +37,7 @@ + diff --git a/tests/fsharp/typecheck/sigs/neg107.bsl b/tests/fsharp/typecheck/sigs/neg107.bsl index 2fe7ea8251d7..30b24d25c592 100644 --- a/tests/fsharp/typecheck/sigs/neg107.bsl +++ b/tests/fsharp/typecheck/sigs/neg107.bsl @@ -100,9 +100,3 @@ neg107.fsx(66,34,66,38): typecheck error FS3232: Struct members cannot return th neg107.fsx(70,19,70,20): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL. neg107.fsx(70,14,70,18): typecheck error FS0437: A type would store a byref typed value. This is not permitted by Common IL. - -neg107.fsx(70,19,70,20): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL. - -neg107.fsx(70,19,70,20): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL. - -neg107.fsx(70,19,70,20): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL. diff --git a/tests/fsharp/typecheck/sigs/neg107.vsbsl b/tests/fsharp/typecheck/sigs/neg107.vsbsl index 2fe7ea8251d7..30b24d25c592 100644 --- a/tests/fsharp/typecheck/sigs/neg107.vsbsl +++ b/tests/fsharp/typecheck/sigs/neg107.vsbsl @@ -100,9 +100,3 @@ neg107.fsx(66,34,66,38): typecheck error FS3232: Struct members cannot return th neg107.fsx(70,19,70,20): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL. neg107.fsx(70,14,70,18): typecheck error FS0437: A type would store a byref typed value. This is not permitted by Common IL. - -neg107.fsx(70,19,70,20): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL. - -neg107.fsx(70,19,70,20): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL. - -neg107.fsx(70,19,70,20): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL. 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 853541eca4d5..7e7c4a13a997 100644 --- a/tests/fsharpqa/Source/CompilerOptions/fsc/help/help40.437.1033.bsl +++ b/tests/fsharpqa/Source/CompilerOptions/fsc/help/help40.437.1033.bsl @@ -1,4 +1,4 @@ -Microsoft (R) F# Compiler version 10.6.0.0 for F# 4.7 +Microsoft (R) F# Compiler version 12.0.0.0 for F# 6.0 Copyright (c) Microsoft Corporation. All Rights Reserved. @@ -39,6 +39,11 @@ Copyright (c) Microsoft Corporation. All Rights Reserved. signature files --nocopyfsharpcore Don't copy FSharp.Core.dll along the produced binaries +--refonly[+|-] Produce a reference assembly, + instead of a full assembly, as the + primary output +--refout: Produce a reference assembly with + the specified file path. - INPUT FILES - diff --git a/tests/service/ProjectAnalysisTests.fs b/tests/service/ProjectAnalysisTests.fs index 6f3c81e62bef..9012406bdc89 100644 --- a/tests/service/ProjectAnalysisTests.fs +++ b/tests/service/ProjectAnalysisTests.fs @@ -5664,6 +5664,7 @@ let checkContentAsScript content = [] let ``References from #r nuget are included in script project options`` () = let checkResults = checkContentAsScript """ +#i "nuget:https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json" #r "nuget: Dapper" """ let assemblyNames = diff --git a/tests/service/Symbols.fs b/tests/service/Symbols.fs index 2c3bf3112920..7ee0d0b8b704 100644 --- a/tests/service/Symbols.fs +++ b/tests/service/Symbols.fs @@ -1413,6 +1413,56 @@ type Foo = assertRange (5, 30) (5, 34) mWithKeyword | _ -> Assert.Fail "Could not get valid AST" + [] + let ``Range of attribute should be included in SynExceptionDefnRepr and SynExceptionSig`` () = + let parseResults = + getParseResultsOfSignatureFile + """ +module internal FSharp.Compiler.ParseHelpers + +/// The error raised by the parse_error_rich function, which is called by the parser engine +[] +exception SyntaxError of obj * range: range + + +""" + + match parseResults with + | ParsedInput.SigFile (ParsedSigFileInput (modules=[ + SynModuleOrNamespaceSig(decls=[ + SynModuleSigDecl.Exception( + SynExceptionSig(exnRepr=SynExceptionDefnRepr(range=mSynExceptionDefnRepr); range=mSynExceptionSig), mException) + ] ) ])) -> + assertRange (5, 0) (6, 43) mSynExceptionDefnRepr + assertRange (5, 0) (6, 43) mSynExceptionSig + assertRange (5, 0) (6, 43) mException + | _ -> Assert.Fail "Could not get valid AST" + + [] + let ``Range of members should be included in SynExceptionSig and SynModuleSigDecl.Exception`` () = + let parseResults = + getParseResultsOfSignatureFile + """ +module internal FSharp.Compiler.ParseHelpers + +exception SyntaxError of obj * range: range with + member Meh : string -> int + +open Foo +""" + + match parseResults with + | ParsedInput.SigFile (ParsedSigFileInput (modules=[ + SynModuleOrNamespaceSig(decls=[ + SynModuleSigDecl.Exception( + SynExceptionSig(exnRepr=SynExceptionDefnRepr(range=mSynExceptionDefnRepr); range=mSynExceptionSig), mException) + SynModuleSigDecl.Open _ + ] ) ])) -> + assertRange (4, 0) (4, 43) mSynExceptionDefnRepr + assertRange (4, 0) (5, 30) mSynExceptionSig + assertRange (4, 0) (5, 30) mException + | _ -> Assert.Fail "Could not get valid AST" + module SynMatchClause = [] let ``Range of single SynMatchClause`` () = diff --git a/vsintegration/src/FSharp.Editor/Options/EditorOptions.fs b/vsintegration/src/FSharp.Editor/Options/EditorOptions.fs index 578b675ae146..d7995bcf5091 100644 --- a/vsintegration/src/FSharp.Editor/Options/EditorOptions.fs +++ b/vsintegration/src/FSharp.Editor/Options/EditorOptions.fs @@ -94,7 +94,7 @@ type AdvancedOptions = type FormattingOptions = { FormatOnPaste: bool } static member Default = - { FormatOnPaste = true } + { FormatOnPaste = false } [] [)>] diff --git a/vsintegration/src/FSharp.UIResources/Strings.resx b/vsintegration/src/FSharp.UIResources/Strings.resx index 19f6d2658bc8..b0ceb57d47a0 100644 --- a/vsintegration/src/FSharp.UIResources/Strings.resx +++ b/vsintegration/src/FSharp.UIResources/Strings.resx @@ -226,7 +226,7 @@ Enter key behavior - Re-format indentation on paste + Re-format indentation on paste (Experimental) Suggest names for unresolved identifiers diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.cs.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.cs.xlf index da6e649a8ba8..eb4650c57ed0 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.cs.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.cs.xlf @@ -193,8 +193,8 @@ - Re-format indentation on paste - Přeformátovat odsazení při vložení + Re-format indentation on paste (Experimental) + Znovu naformátovat odsazení při vložení (experimentální) diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.de.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.de.xlf index 653c542d13f3..7db4ba605f3f 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.de.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.de.xlf @@ -193,8 +193,8 @@ - Re-format indentation on paste - Einzug beim Einfügen neu formatieren + Re-format indentation on paste (Experimental) + Einzug beim Einfügen erneut formatieren (experimentell) diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.es.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.es.xlf index 39c2877127c6..674c69434c29 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.es.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.es.xlf @@ -193,8 +193,8 @@ - Re-format indentation on paste - Cambiar formato de sangría al pegar + Re-format indentation on paste (Experimental) + Volver a aplicar formato a la sangría al pegar (experimental) diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.fr.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.fr.xlf index 3d73fe222b13..ec9bafbe8df0 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.fr.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.fr.xlf @@ -193,8 +193,8 @@ - Re-format indentation on paste - Remettre en forme le retrait au collage + Re-format indentation on paste (Experimental) + Formater de nouveau la mise en retrait lors du collage (expérimental) diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.it.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.it.xlf index 34d9ec67029c..9b2acf06d1b0 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.it.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.it.xlf @@ -193,8 +193,8 @@ - Re-format indentation on paste - Riformatta rientro dopo operazione Incolla + Re-format indentation on paste (Experimental) + Riformattar il rientro dopo operazione incolla (sperimentale) diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.ja.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.ja.xlf index 5771c8c5848e..8ab4c15b6e1f 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.ja.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.ja.xlf @@ -193,8 +193,8 @@ - Re-format indentation on paste - 貼り付け時にインデントを再フォーマットする + Re-format indentation on paste (Experimental) + 貼り付け時にインデントを再フォーマットする (試験段階) diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.ko.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.ko.xlf index dacb9996564b..4812b0acc99b 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.ko.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.ko.xlf @@ -193,8 +193,8 @@ - Re-format indentation on paste - 붙여넣을 때 들여쓰기 서식 다시 지정 + Re-format indentation on paste (Experimental) + 붙여넣을 때 들여쓰기 서식 다시 지정(실험적) diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.pl.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.pl.xlf index 4a205499f29f..c96168985ec2 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.pl.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.pl.xlf @@ -193,8 +193,8 @@ - Re-format indentation on paste - Ponownie formatuj wcięcia przy wklejaniu + Re-format indentation on paste (Experimental) + Ponowne formatowanie wcięcia przy wklejeniu (eksperymentalne) diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.pt-BR.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.pt-BR.xlf index 13cce041c991..076de7f90874 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.pt-BR.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.pt-BR.xlf @@ -193,8 +193,8 @@ - Re-format indentation on paste - Reformatar o recuo ao colar + Re-format indentation on paste (Experimental) + Reformatar o recuo na pasta (Experimental) diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.ru.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.ru.xlf index 579c059dcd62..690059925dff 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.ru.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.ru.xlf @@ -193,8 +193,8 @@ - Re-format indentation on paste - Повторно форматировать отступы при вставке + Re-format indentation on paste (Experimental) + Повторно форматировать отступы при вставке (экспериментальная функция) diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.tr.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.tr.xlf index 6ff42fad0e49..e05c403767ad 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.tr.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.tr.xlf @@ -193,8 +193,8 @@ - Re-format indentation on paste - Yapıştırırken girintiyi yeniden biçimlendir + Re-format indentation on paste (Experimental) + Yapıştırırken girintiyi yeniden biçimlendir (Deneysel) diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hans.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hans.xlf index 6b0a4cd7d073..b219edc12c0d 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hans.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hans.xlf @@ -193,8 +193,8 @@ - Re-format indentation on paste - 粘贴时重新设置缩进格式 + Re-format indentation on paste (Experimental) + 粘贴时重新设置缩进格式(实验) diff --git a/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hant.xlf b/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hant.xlf index acbacbce0817..0b6b964edda5 100644 --- a/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hant.xlf +++ b/vsintegration/src/FSharp.UIResources/xlf/Strings.zh-Hant.xlf @@ -193,8 +193,8 @@ - Re-format indentation on paste - 在貼上時重設縮排格式 + Re-format indentation on paste (Experimental) + 在貼上時重新格式化縮排 (實驗性)