diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 618a642e48..5820fde4b2 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -42,14 +42,14 @@ - + https://github.com/dotnet/arcade - 4a7d983f833d6b86365ea1b2b4d6ee72fbdbf944 + 2c829550b968e29389ce8392244da2b006d71301 - + https://github.com/dotnet/arcade - 4a7d983f833d6b86365ea1b2b4d6ee72fbdbf944 + 2c829550b968e29389ce8392244da2b006d71301 diff --git a/eng/common/core-templates/job/publish-build-assets.yml b/eng/common/core-templates/job/publish-build-assets.yml index d99a1a3b28..3d3356e319 100644 --- a/eng/common/core-templates/job/publish-build-assets.yml +++ b/eng/common/core-templates/job/publish-build-assets.yml @@ -113,38 +113,19 @@ jobs: Add-Content -Path $filePath -Value "$(DefaultChannels)" Add-Content -Path $filePath -Value $(IsStableBuild) - - template: /eng/common/core-templates/steps/publish-build-artifacts.yml - parameters: - is1ESPipeline: ${{ parameters.is1ESPipeline }} - args: - displayName: Publish ReleaseConfigs Artifact - pathToPublish: '$(Build.StagingDirectory)/ReleaseConfigs' - publishLocation: Container - artifactName: ReleaseConfigs - - - task: powershell@2 - displayName: Check if SymbolPublishingExclusionsFile.txt exists - inputs: - targetType: inline - script: | $symbolExclusionfile = "$(Build.SourcesDirectory)/eng/SymbolPublishingExclusionsFile.txt" - if(Test-Path -Path $symbolExclusionfile) + if (Test-Path -Path $symbolExclusionfile) { Write-Host "SymbolExclusionFile exists" - Write-Host "##vso[task.setvariable variable=SymbolExclusionFile]true" - } - else{ - Write-Host "Symbols Exclusion file does not exist" - Write-Host "##vso[task.setvariable variable=SymbolExclusionFile]false" + Copy-Item -Path $symbolExclusionfile -Destination "$(Build.StagingDirectory)/ReleaseConfigs" } - template: /eng/common/core-templates/steps/publish-build-artifacts.yml parameters: is1ESPipeline: ${{ parameters.is1ESPipeline }} args: - displayName: Publish SymbolPublishingExclusionsFile Artifact - condition: eq(variables['SymbolExclusionFile'], 'true') - pathToPublish: '$(Build.SourcesDirectory)/eng/SymbolPublishingExclusionsFile.txt' + displayName: Publish ReleaseConfigs Artifact + pathToPublish: '$(Build.StagingDirectory)/ReleaseConfigs' publishLocation: Container artifactName: ReleaseConfigs @@ -162,9 +143,10 @@ jobs: scriptType: ps scriptLocation: scriptPath scriptPath: $(Build.SourcesDirectory)/eng/common/post-build/publish-using-darc.ps1 - arguments: -BuildId $(BARBuildId) + arguments: > + -BuildId $(BARBuildId) -PublishingInfraVersion 3 - -AzdoToken '$(publishing-dnceng-devdiv-code-r-build-re)' + -AzdoToken '$(System.AccessToken)' -WaitPublishingFinish true -ArtifactsPublishingAdditionalParameters '${{ parameters.artifactsPublishingAdditionalParameters }}' -SymbolPublishingAdditionalParameters '${{ parameters.symbolPublishingAdditionalParameters }}' diff --git a/eng/common/core-templates/job/source-index-stage1.yml b/eng/common/core-templates/job/source-index-stage1.yml index 945c1c19e8..205fb5b3a3 100644 --- a/eng/common/core-templates/job/source-index-stage1.yml +++ b/eng/common/core-templates/job/source-index-stage1.yml @@ -34,10 +34,12 @@ jobs: pool: ${{ if eq(variables['System.TeamProject'], 'public') }}: name: $(DncEngPublicBuildPool) - image: windows.vs2022.amd64.open + image: 1es-windows-2022-open + os: windows ${{ if eq(variables['System.TeamProject'], 'internal') }}: name: $(DncEngInternalBuildPool) - image: windows.vs2022.amd64 + image: 1es-windows-2022 + os: windows steps: - ${{ if eq(parameters.is1ESPipeline, '') }}: diff --git a/eng/common/core-templates/post-build/post-build.yml b/eng/common/core-templates/post-build/post-build.yml index 20924366b8..454fd75c7a 100644 --- a/eng/common/core-templates/post-build/post-build.yml +++ b/eng/common/core-templates/post-build/post-build.yml @@ -307,9 +307,10 @@ stages: scriptType: ps scriptLocation: scriptPath scriptPath: $(Build.SourcesDirectory)/eng/common/post-build/publish-using-darc.ps1 - arguments: -BuildId $(BARBuildId) + arguments: > + -BuildId $(BARBuildId) -PublishingInfraVersion ${{ parameters.publishingInfraVersion }} - -AzdoToken '$(publishing-dnceng-devdiv-code-r-build-re)' + -AzdoToken '$(System.AccessToken)' -WaitPublishingFinish true -ArtifactsPublishingAdditionalParameters '${{ parameters.artifactsPublishingAdditionalParameters }}' -SymbolPublishingAdditionalParameters '${{ parameters.symbolPublishingAdditionalParameters }}' diff --git a/eng/common/core-templates/steps/get-federated-access-token.yml b/eng/common/core-templates/steps/get-federated-access-token.yml index c8c49cc0e8..3a4d4410c4 100644 --- a/eng/common/core-templates/steps/get-federated-access-token.yml +++ b/eng/common/core-templates/steps/get-federated-access-token.yml @@ -3,6 +3,14 @@ parameters: type: string - name: outputVariableName type: string +- name: is1ESPipeline + type: boolean +- name: stepName + type: string + default: 'getFederatedAccessToken' +- name: condition + type: string + default: '' # Resource to get a token for. Common values include: # - '499b84ac-1321-427f-aa17-267ca6975798' for Azure DevOps # - 'https://storage.azure.com/' for storage @@ -10,10 +18,16 @@ parameters: - name: resource type: string default: '499b84ac-1321-427f-aa17-267ca6975798' +- name: isStepOutputVariable + type: boolean + default: false steps: - task: AzureCLI@2 displayName: 'Getting federated access token for feeds' + name: ${{ parameters.stepName }} + ${{ if ne(parameters.condition, '') }}: + condition: ${{ parameters.condition }} inputs: azureSubscription: ${{ parameters.federatedServiceConnection }} scriptType: 'pscore' @@ -25,4 +39,4 @@ steps: exit 1 } Write-Host "Setting '${{ parameters.outputVariableName }}' with the access token value" - Write-Host "##vso[task.setvariable variable=${{ parameters.outputVariableName }};issecret=true]$accessToken" \ No newline at end of file + Write-Host "##vso[task.setvariable variable=${{ parameters.outputVariableName }};issecret=true;isOutput=${{ parameters.isStepOutputVariable }}]$accessToken" \ No newline at end of file diff --git a/eng/common/core-templates/steps/publish-logs.yml b/eng/common/core-templates/steps/publish-logs.yml index 8c5ea77b58..80788c5231 100644 --- a/eng/common/core-templates/steps/publish-logs.yml +++ b/eng/common/core-templates/steps/publish-logs.yml @@ -32,7 +32,6 @@ steps: '$(MaestroAccessToken)' '$(dn-bot-all-orgs-artifact-feeds-rw)' '$(akams-client-id)' - '$(akams-client-secret)' '$(microsoft-symbol-server-pat)' '$(symweb-symbol-server-pat)' '$(dn-bot-all-orgs-build-rw-code-rw)' diff --git a/eng/common/cross/build-rootfs.sh b/eng/common/cross/build-rootfs.sh index eb1a908046..4b5e8d7166 100755 --- a/eng/common/cross/build-rootfs.sh +++ b/eng/common/cross/build-rootfs.sh @@ -72,7 +72,7 @@ __AlpinePackages+=" krb5-dev" __AlpinePackages+=" openssl-dev" __AlpinePackages+=" zlib-dev" -__FreeBSDBase="13.2-RELEASE" +__FreeBSDBase="13.3-RELEASE" __FreeBSDPkg="1.17.0" __FreeBSDABI="13" __FreeBSDPackages="libunwind" @@ -605,18 +605,18 @@ elif [[ "$__CodeName" == "illumos" ]]; then fi echo "Building binutils. Please wait.." if [[ "$__hasWget" == 1 ]]; then - wget -O- https://ftp.gnu.org/gnu/binutils/binutils-2.33.1.tar.bz2 | tar -xjf - + wget -O- https://ftp.gnu.org/gnu/binutils/binutils-2.42.tar.xz | tar -xJf - else - curl -SL https://ftp.gnu.org/gnu/binutils/binutils-2.33.1.tar.bz2 | tar -xjf - + curl -SL https://ftp.gnu.org/gnu/binutils/binutils-2.42.tar.xz | tar -xJf - fi mkdir build-binutils && cd build-binutils - ../binutils-2.33.1/configure --prefix="$__RootfsDir" --target="${__illumosArch}-sun-solaris2.10" --program-prefix="${__illumosArch}-illumos-" --with-sysroot="$__RootfsDir" + ../binutils-2.42/configure --prefix="$__RootfsDir" --target="${__illumosArch}-sun-solaris2.11" --program-prefix="${__illumosArch}-illumos-" --with-sysroot="$__RootfsDir" make -j "$JOBS" && make install && cd .. echo "Building gcc. Please wait.." if [[ "$__hasWget" == 1 ]]; then - wget -O- https://ftp.gnu.org/gnu/gcc/gcc-8.4.0/gcc-8.4.0.tar.xz | tar -xJf - + wget -O- https://ftp.gnu.org/gnu/gcc/gcc-13.3.0/gcc-13.3.0.tar.xz | tar -xJf - else - curl -SL https://ftp.gnu.org/gnu/gcc/gcc-8.4.0/gcc-8.4.0.tar.xz | tar -xJf - + curl -SL https://ftp.gnu.org/gnu/gcc/gcc-13.3.0/gcc-13.3.0.tar.xz | tar -xJf - fi CFLAGS="-fPIC" CXXFLAGS="-fPIC" @@ -624,7 +624,7 @@ elif [[ "$__CodeName" == "illumos" ]]; then CFLAGS_FOR_TARGET="-fPIC" export CFLAGS CXXFLAGS CXXFLAGS_FOR_TARGET CFLAGS_FOR_TARGET mkdir build-gcc && cd build-gcc - ../gcc-8.4.0/configure --prefix="$__RootfsDir" --target="${__illumosArch}-sun-solaris2.10" --program-prefix="${__illumosArch}-illumos-" --with-sysroot="$__RootfsDir" --with-gnu-as \ + ../gcc-13.3.0/configure --prefix="$__RootfsDir" --target="${__illumosArch}-sun-solaris2.11" --program-prefix="${__illumosArch}-illumos-" --with-sysroot="$__RootfsDir" --with-gnu-as \ --with-gnu-ld --disable-nls --disable-libgomp --disable-libquadmath --disable-libssp --disable-libvtv --disable-libcilkrts --disable-libada --disable-libsanitizer \ --disable-libquadmath-support --disable-shared --enable-tls make -j "$JOBS" && make install && cd .. @@ -632,7 +632,7 @@ elif [[ "$__CodeName" == "illumos" ]]; then if [[ "$__UseMirror" == 1 ]]; then BaseUrl=https://pkgsrc.smartos.skylime.net fi - BaseUrl="$BaseUrl/packages/SmartOS/trunk/${__illumosArch}/All" + BaseUrl="$BaseUrl/packages/SmartOS/2019Q4/${__illumosArch}/All" echo "Downloading manifest" if [[ "$__hasWget" == 1 ]]; then wget "$BaseUrl" diff --git a/eng/common/native/init-compiler.sh b/eng/common/native/init-compiler.sh index 62900e12b2..9a0e1f2b45 100644 --- a/eng/common/native/init-compiler.sh +++ b/eng/common/native/init-compiler.sh @@ -19,11 +19,9 @@ case "$compiler" in # clangx.y or clang-x.y version="$(echo "$compiler" | tr -d '[:alpha:]-=')" majorVersion="${version%%.*}" - [ -z "${version##*.*}" ] && minorVersion="${version#*.}" - if [ -z "$minorVersion" ] && [ -n "$majorVersion" ] && [ "$majorVersion" -le 6 ]; then - minorVersion=0; - fi + # LLVM based on v18 released in early 2024, with two releases per year + maxVersion="$((18 + ((($(date +%Y) - 2024) * 12 + $(date +%-m) - 3) / 6)))" compiler=clang ;; @@ -31,7 +29,9 @@ case "$compiler" in # gccx.y or gcc-x.y version="$(echo "$compiler" | tr -d '[:alpha:]-=')" majorVersion="${version%%.*}" - [ -z "${version##*.*}" ] && minorVersion="${version#*.}" + + # GCC based on v14 released in early 2024, with one release per year + maxVersion="$((14 + ((($(date +%Y) - 2024) * 12 + $(date +%-m) - 3) / 12)))" compiler=gcc ;; esac @@ -49,12 +49,10 @@ check_version_exists() { desired_version=-1 # Set up the environment to be used for building with the desired compiler. - if command -v "$compiler-$1.$2" > /dev/null; then - desired_version="-$1.$2" - elif command -v "$compiler$1$2" > /dev/null; then - desired_version="$1$2" - elif command -v "$compiler-$1$2" > /dev/null; then - desired_version="-$1$2" + if command -v "$compiler-$1" > /dev/null; then + desired_version="-$1" + elif command -v "$compiler$1" > /dev/null; then + desired_version="$1" fi echo "$desired_version" @@ -75,7 +73,7 @@ set_compiler_version_from_CC() { fi # gcc and clang often display 3 part versions. However, gcc can show only 1 part in some environments. - IFS=. read -r majorVersion minorVersion _ < /dev/null; then - echo "Error: No usable version of $compiler found." + echo "Error: No compatible version of $compiler was found within the range of $minVersion to $maxVersion. Please upgrade your toolchain or specify the compiler explicitly using CLR_CC and CLR_CXX environment variables." exit 1 fi CC="$(command -v "$compiler" 2> /dev/null)" CXX="$(command -v "$cxxCompiler" 2> /dev/null)" set_compiler_version_from_CC - else - if [ "$compiler" = "clang" ] && [ "$majorVersion" -lt 5 ] && { [ "$build_arch" = "arm" ] || [ "$build_arch" = "armel" ]; }; then - # If a major version was provided explicitly, and it was too old, find a newer compiler instead - if ! command -v "$compiler" > /dev/null; then - echo "Error: Found clang version $majorVersion which is not supported on arm/armel architectures, and there is no clang in PATH." - exit 1 - fi - - CC="$(command -v "$compiler" 2> /dev/null)" - CXX="$(command -v "$cxxCompiler" 2> /dev/null)" - set_compiler_version_from_CC - fi fi else - desired_version="$(check_version_exists "$majorVersion" "$minorVersion")" + desired_version="$(check_version_exists "$majorVersion")" if [ "$desired_version" = "-1" ]; then - echo "Error: Could not find specific version of $compiler: $majorVersion $minorVersion." + echo "Error: Could not find specific version of $compiler: $majorVersion." exit 1 fi fi diff --git a/eng/common/post-build/publish-using-darc.ps1 b/eng/common/post-build/publish-using-darc.ps1 index 4ff587ca46..90b58e32a8 100644 --- a/eng/common/post-build/publish-using-darc.ps1 +++ b/eng/common/post-build/publish-using-darc.ps1 @@ -42,6 +42,7 @@ try { --azdev-pat "$AzdoToken" ` --bar-uri "$MaestroApiEndPoint" ` --ci ` + --verbose ` @optionalParams if ($LastExitCode -ne 0) { diff --git a/global.json b/global.json index 214f7c1bd4..4023209fd0 100644 --- a/global.json +++ b/global.json @@ -17,7 +17,7 @@ "perl": "5.38.2.2" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "9.0.0-beta.24352.2", + "Microsoft.DotNet.Arcade.Sdk": "9.0.0-beta.24405.1", "Microsoft.DotNet.Helix.Sdk": "8.0.0-beta.23255.2" } } diff --git a/src/Compiler/Checking/Expressions/CheckExpressions.fs b/src/Compiler/Checking/Expressions/CheckExpressions.fs index be64b075e2..585939038f 100644 --- a/src/Compiler/Checking/Expressions/CheckExpressions.fs +++ b/src/Compiler/Checking/Expressions/CheckExpressions.fs @@ -7119,12 +7119,14 @@ and CheckSuperType (cenv: cenv) ty m = and TcObjectExpr (cenv: cenv) env tpenv (objTy, realObjTy, argopt, binds, extraImpls, mObjTy, mNewExpr, mWholeExpr) = let g = cenv.g - match tryTcrefOfAppTy g objTy with | ValueNone -> error(Error(FSComp.SR.tcNewMustBeUsedWithNamedType(), mNewExpr)) | ValueSome tcref -> let isRecordTy = tcref.IsRecordTycon - if not isRecordTy && not (isInterfaceTy g objTy) && isSealedTy g objTy then errorR(Error(FSComp.SR.tcCannotCreateExtensionOfSealedType(), mNewExpr)) + let isInterfaceTy = isInterfaceTy g objTy + let isFSharpObjModelTy = isFSharpObjModelTy g objTy + let isOverallTyAbstract = HasFSharpAttribute g g.attrib_AbstractClassAttribute tcref.Attribs + if not isRecordTy && not isInterfaceTy && isSealedTy g objTy then errorR(Error(FSComp.SR.tcCannotCreateExtensionOfSealedType(), mNewExpr)) CheckSuperType cenv objTy mObjTy @@ -7135,14 +7137,14 @@ and TcObjectExpr (cenv: cenv) env tpenv (objTy, realObjTy, argopt, binds, extraI let env = EnterFamilyRegion tcref env let ad = env.AccessRights - if // record construction ? + if // record construction ? e.g { A = 1; B = 2 } isRecordTy || - // object construction? - (isFSharpObjModelTy g objTy && not (isInterfaceTy g objTy) && argopt.IsNone) then + // object construction? e.g. new A() { ... } + (isFSharpObjModelTy && not isInterfaceTy && argopt.IsNone) then if argopt.IsSome then error(Error(FSComp.SR.tcNoArgumentsForRecordValue(), mWholeExpr)) if not (isNil extraImpls) then error(Error(FSComp.SR.tcNoInterfaceImplementationForConstructionExpression(), mNewExpr)) - if isFSharpObjModelTy g objTy && GetCtorShapeCounter env <> 1 then + if isFSharpObjModelTy && GetCtorShapeCounter env <> 1 then error(Error(FSComp.SR.tcObjectConstructionCanOnlyBeUsedInClassTypes(), mNewExpr)) let fldsList = binds |> List.map (fun b -> @@ -7152,8 +7154,9 @@ and TcObjectExpr (cenv: cenv) env tpenv (objTy, realObjTy, argopt, binds, extraI TcRecordConstruction cenv objTy true env tpenv None objTy fldsList mWholeExpr else + // object expression construction e.g. { new A() with ... } or { new IA with ... } let ctorCall, baseIdOpt, tpenv = - if isInterfaceTy g objTy then + if isInterfaceTy then match argopt with | None -> BuildObjCtorCall g mWholeExpr, None, tpenv @@ -7162,7 +7165,7 @@ and TcObjectExpr (cenv: cenv) env tpenv (objTy, realObjTy, argopt, binds, extraI else let item = ForceRaise (ResolveObjectConstructor cenv.nameResolver env.DisplayEnv mObjTy ad objTy) - if isFSharpObjModelTy g objTy && GetCtorShapeCounter env = 1 then + if isFSharpObjModelTy && GetCtorShapeCounter env = 1 then error(Error(FSComp.SR.tcObjectsMustBeInitializedWithObjectExpression(), mNewExpr)) match item, argopt with @@ -7193,14 +7196,6 @@ and TcObjectExpr (cenv: cenv) env tpenv (objTy, realObjTy, argopt, binds, extraI overridesAndVirts |> List.iter (fun (m, implTy, dispatchSlots, dispatchSlotsKeyed, availPriorOverrides, overrides) -> let overrideSpecs = overrides |> List.map fst let hasStaticMembers = dispatchSlots |> List.exists (fun reqdSlot -> not reqdSlot.MethodInfo.IsInstance) - let isOverallTyAbstract = - match tryTcrefOfAppTy g objTy with - | ValueNone -> false - | ValueSome tcref -> HasFSharpAttribute g g.attrib_AbstractClassAttribute tcref.Attribs - - if overrideSpecs.IsEmpty && not (isInterfaceTy g objTy) then - errorR (Error(FSComp.SR.tcInvalidObjectExpressionSyntaxForm (), mWholeExpr)) - if hasStaticMembers then errorR(Error(FSComp.SR.chkStaticMembersOnObjectExpressions(), mObjTy)) @@ -7240,8 +7235,11 @@ and TcObjectExpr (cenv: cenv) env tpenv (objTy, realObjTy, argopt, binds, extraI let objtyR, overrides' = allTypeImpls.Head assert (typeEquiv g objTy objtyR) let extraImpls = allTypeImpls.Tail + + if not isInterfaceTy && (isOverallTyAbstract && overrides'.IsEmpty) && extraImpls.IsEmpty then + errorR (Error(FSComp.SR.tcInvalidObjectExpressionSyntaxForm (), mWholeExpr)) - // 7. Build the implementation + // 4. Build the implementation let expr = mkObjExpr(objtyR, baseValOpt, ctorCall, overrides', extraImpls, mWholeExpr) let expr = mkCoerceIfNeeded g realObjTy objtyR expr expr, tpenv diff --git a/src/Compiler/Checking/Expressions/CheckSequenceExpressions.fs b/src/Compiler/Checking/Expressions/CheckSequenceExpressions.fs index 09de598b18..31be49131a 100644 --- a/src/Compiler/Checking/Expressions/CheckSequenceExpressions.fs +++ b/src/Compiler/Checking/Expressions/CheckSequenceExpressions.fs @@ -444,20 +444,12 @@ let TcSequenceExpressionEntry (cenv: TcFileState) env (overallTy: OverallTy) tpe match RewriteRangeExpr comp with | Some replacementExpr -> TcExpr cenv overallTy env tpenv replacementExpr | None -> - let implicitYieldEnabled = cenv.g.langVersion.SupportsFeature LanguageFeature.ImplicitYield let validateObjectSequenceOrRecordExpression = not implicitYieldEnabled match comp with - | SynExpr.New _ -> - try - TcExprUndelayed cenv overallTy env tpenv comp |> ignore - with RecoverableException e -> - errorRecovery e m - - errorR (Error(FSComp.SR.tcInvalidObjectExpressionSyntaxForm (), m)) | SimpleSemicolonSequence cenv false _ when validateObjectSequenceOrRecordExpression -> errorR (Error(FSComp.SR.tcInvalidObjectSequenceOrRecordExpression (), m)) | _ -> () diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/Expressions/ObjectExpressions/ObjectExpressions.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/Expressions/ObjectExpressions/ObjectExpressions.fs index 0a3eb93cf5..33fc4582f2 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/Expressions/ObjectExpressions/ObjectExpressions.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/Expressions/ObjectExpressions/ObjectExpressions.fs @@ -33,6 +33,93 @@ let implementer() ={ new IFirst } |> withLangVersion80 |> typecheck |> shouldSucceed + + [] + let ``Object expression can construct an abstract class and also implement interfaces with and without abstract members.`` () = + Fsx """ +type IFirst = interface end + +type ISecond = + abstract member M : unit -> unit + +[] +type MyClass() = class end + +{ new MyClass() with + member x.ToString() = "OK" + + interface IFirst + + interface ISecond with + member this.M() = () } |> ignore + """ + |> withLangVersion80 + |> typecheck + |> shouldSucceed + + [] + let ``Object expression can construct an abstract class(missing with...) and also implement interfaces with and without abstract members.`` () = + Fsx """ +type IFirst = interface end + +type ISecond = + abstract member M : unit -> unit + +[] +type MyClass() = class end + +{ new MyClass() interface IFirst + + interface ISecond with + member this.M() = () } |> ignore + """ + |> withLangVersion80 + |> typecheck + |> shouldSucceed + + [] + let ``Object expression can construct an abstract class(missing with... and interface in the next line) and also implement interfaces with and without abstract members.`` () = + Fsx """ +type IFirst = interface end + +type ISecond = + abstract member M : unit -> unit + +[] +type MyClass() = class end + +{ new MyClass() + interface IFirst + + interface ISecond with + member this.M() = () } |> ignore + """ + |> withLangVersion80 + |> typecheck + |> shouldSucceed + + [] + let ``Verifies that the object expression built type has the interface.`` () = + Fsx """ +type IFirst = interface end + +type ISecond = + abstract member M : unit -> unit + +[] +type MyClass() = + interface ISecond with + member this.M() = printfn "It works" + +let expr = { new MyClass() interface IFirst } +(expr:> ISecond).M() + """ + |> withLangVersion80 + |> compileExeAndRun + |> shouldSucceed + |> withStdOutContainsAllInOrder [ + "It works" + ] [] let ``Parameterized object expression implementing an interface with members`` () = diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/RealInternalSignature/RealInternalSignature.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/RealInternalSignature/RealInternalSignature.fs index b0b12e502d..d40a8b5484 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/RealInternalSignature/RealInternalSignature.fs +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/RealInternalSignature/RealInternalSignature.fs @@ -1253,3 +1253,56 @@ module Test6 |> asLibrary |> compile |> shouldSucceed + + [] + let ``Calling protected static base member from `static do` does not raise MethodAccessException when --realsig+`` () = + FSharp """ +#nowarn "44" // using Uri.EscapeString just because it's protected static + +type C(str : string) = + inherit System.Uri(str) + + static do + System.Uri.EscapeString("http://www.myserver.com") |> ignore + printfn "Hello, World" + +module M = + [] + let main args = + let res = C("http://www.myserver.com") + 0 + """ + |> withLangVersionPreview + |> withRealInternalSignature true + |> asLibrary + |> compile + |> compileExeAndRun + |> shouldSucceed + |> withStdOutContainsAllInOrder [ + "Hello, World" + ] + + [] + let ``Calling protected static base member from `static do` raises MethodAccessException with --realsig-`` () = + FSharp """ +#nowarn "44" // using Uri.EscapeString just because it's protected static + +type C(str : string) = + inherit System.Uri(str) + + static do + System.Uri.EscapeString("http://www.myserver.com") |> ignore + printfn "Hello, World" + +module M = + [] + let main args = + let res = C("http://www.myserver.com") + 0 + """ + |> withLangVersionPreview + |> withRealInternalSignature false + |> asLibrary + |> compile + |> compileExeAndRun + |> shouldFail \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj index 3cbbe3ef3c..0509d424f8 100644 --- a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj +++ b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj @@ -250,6 +250,8 @@ + + diff --git a/tests/FSharp.Compiler.ComponentTests/Interop/ParamArray.fs b/tests/FSharp.Compiler.ComponentTests/Interop/ParamArray.fs new file mode 100644 index 0000000000..3864857d96 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Interop/ParamArray.fs @@ -0,0 +1,107 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace Interop + +open Xunit +open FSharp.Test +open FSharp.Test.Compiler + +module ParamArray = + + [] + let ``C# 13 params enhancements`` () = + let csharp = + CSharp """ +using System; +using System.Collections.Generic; + +namespace CSharpAssembly; + +public class CS13ParamArray +{ + public static void WriteNames(params string[] names) + => Console.WriteLine("First: " + string.Join(" + ", names)); + + public static void WriteNames(params List names) + => Console.WriteLine("Second: " + string.Join(" + ", names)); + + public static void WriteNames(params IEnumerable names) + => Console.WriteLine("Third: " + string.Join(" + ", names)); +}""" + |> withCSharpLanguageVersionPreview + + FSharp """ +open System.Collections.Generic; +open CSharpAssembly + +CS13ParamArray.WriteNames("Petr", "Jana") +CS13ParamArray.WriteNames(List["Petr"; "Jana"]) +CS13ParamArray.WriteNames(["Petr"; "Jana"]) +""" + |> withReferences [csharp] + |> compileExeAndRun + |> shouldSucceed + |> withStdOutContainsAllInOrder [ + "First: Petr + Jana" + "Second: Petr + Jana" + "Third: Petr + Jana" + ] + + [] + let ``C# 13 params enhancements - ReadOnlySpan`` () = + let csharp = + CSharp """ +using System; + +namespace CSharpAssembly; + +public class CS13ParamArray +{ + public static void WriteNames(params ReadOnlySpan names) + => Console.WriteLine(string.Join(" + ", names)); +}""" + |> withCSharpLanguageVersionPreview + + FSharp """ +open System +open CSharpAssembly + +CS13ParamArray.WriteNames(ReadOnlySpan([|"Petr"; "Jana"|])) +""" + |> withReferences [csharp] + |> compileExeAndRun + |> shouldSucceed + |> withStdOutContainsAllInOrder [ "Petr + Jana" ] + + [] + let ``C# 13 params enhancements - error when no matching overload is available`` () = + let csharp = + CSharp """ +using System; +using System.Collections.Generic; + +namespace CSharpAssembly; + +public class CS13ParamArray +{ + public static void WriteNames(params List names) + => Console.WriteLine("Second: " + string.Join(" + ", names)); + + public static void WriteNames(params IEnumerable names) + => Console.WriteLine("Third: " + string.Join(" + ", names)); +}""" + |> withCSharpLanguageVersionPreview + + FSharp """ +open CSharpAssembly + +CS13ParamArray.WriteNames("Petr", "Jana") +""" + |> withReferences [csharp] + |> asExe + |> compile + |> shouldFail + |> withDiagnostics [ + (Error 503, Line 4, Col 1, Line 4, Col 42, + "A member or object constructor 'WriteNames' taking 2 arguments is not accessible from this code location. All accessible versions of method 'WriteNames' take 1 arguments.") + ] \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Interop/ParamArrayMigrated.fs b/tests/FSharp.Compiler.ComponentTests/Interop/ParamArrayMigrated.fs new file mode 100644 index 0000000000..0906682d6d --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Interop/ParamArrayMigrated.fs @@ -0,0 +1,110 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace Interop + +open Xunit +open FSharp.Test.Compiler + +module ParamArrayMigrated = + + let csharp = + CSharp """ +using System; + +namespace CSharpAssembly +{ + [AttributeUsage(AttributeTargets.All)] + public class AttributeWithParamArray : Attribute + { + public object[] Parameters; + + public AttributeWithParamArray(params object[] x) + { + + Parameters = x; + } + } + + public class CSParamArray + { + public static int Method(params int[] allArgs) + { + int total = 0; + foreach (int i in allArgs) + total += i; + + return total; + } + + public static int Method(params T[] args) + { + return args.Length; + } + } +}""" + + [] + let ``Valid params call`` () = + FSharp """ +open System +open CSharpAssembly + +// Apply the attribute +[ obj) |])>] +type Foo() = + [ obj); ("bar" :> obj) |])>] + override this.ToString() = "Stuff" + +let callCSGenericMethod (a: 't[]) = CSParamArray.Method(a) + +[] +do + let getTestAttribute (t : Type) = + let tyAttributes = t.GetCustomAttributes(false) + let attrib = tyAttributes |> Array.find (fun attrib -> match attrib with :? AttributeWithParamArray -> true | _ -> false) + (attrib :?> AttributeWithParamArray) + + let tyFoo = typeof + let testAtt = getTestAttribute tyFoo + if testAtt.Parameters <> [| (0 :> obj) |] then + failwith "Attribute parameters not as expected" + + let directCallWorks = + CSParamArray.Method(9, 8, 7) + CSParamArray.Method(1, 2) + CSParamArray.Method() = (9 + 8 + 7) + (1 + 2) + if not directCallWorks then + failwith "Calling C# param array method gave unexpected result" + + let callParamArray (x : int array) = CSParamArray.Method(x) + let asArrayCallWorks = (callParamArray [| 9; 8; 7 |]) = (9 + 8 + 7) + if not asArrayCallWorks then + failwith "Calling C# param array method, passing args as an array, gave unexpected result" + + if callCSGenericMethod [|"1";"2";"3"|] <> 3 then + failwith "Calling C# generic param array method gave unexpected result" + + if CSParamArray.Method("1", "2", "3") <> CSParamArray.Method([|"1"; "2"; "3"|]) then + failwith "Calling C# generic param array in normal and expanded method gave unexpected result" +""" + |> withReferences [csharp] + |> compileExeAndRun + |> shouldSucceed + + [] + let ``Invalid params call`` () = + FSharp """ +open CSharpAssembly + +[] +type Foo() = + override this.ToString() = "Stuff" +""" + |> withReferences [csharp] + |> asExe + |> compile + |> shouldFail + |> withDiagnostics [ + (Error 13, Line 4, Col 29, Line 4, Col 37, + "The static coercion from type\n int \nto \n 'a \n involves an indeterminate type based on information prior to this program point. Static coercions are not allowed on some types. Further type annotations are needed.") + (Error 267, Line 4, Col 29, Line 4, Col 37, + "This is not a valid constant expression or custom attribute value") + ] diff --git a/tests/FSharp.Test.Utilities/Compiler.fs b/tests/FSharp.Test.Utilities/Compiler.fs index 9fb050b09d..1edd5ef548 100644 --- a/tests/FSharp.Test.Utilities/Compiler.fs +++ b/tests/FSharp.Test.Utilities/Compiler.fs @@ -585,6 +585,9 @@ module rec Compiler = | CS cs -> CS { cs with LangVersion = ver } | _ -> failwith "Only supported in C#" + let withCSharpLanguageVersionPreview = + withCSharpLanguageVersion CSharpLanguageVersion.Preview + let withOutputType (outputType : CompileOutput) (cUnit: CompilationUnit) : CompilationUnit = match cUnit with | FS x -> FS { x with OutputType = outputType } diff --git a/tests/fsharpqa/Source/Misc/ConsumeParamArray.fsscript b/tests/fsharpqa/Source/Misc/ConsumeParamArray.fsscript deleted file mode 100644 index 188c6459f3..0000000000 --- a/tests/fsharpqa/Source/Misc/ConsumeParamArray.fsscript +++ /dev/null @@ -1,56 +0,0 @@ -// #Regression #Misc -#light - -// Test that F# can consume C# param arrays. (Can't use variable number of arguments, rather -// arguments will just be exposed as taking an array.) -// FSB 1105, params attributes not supported -// This is also regression test for FSHARP1.0:3817 -open System - -#r "ParamArray.dll" -open CSharpAssembly - -// Apply the attribute -[ obj) |])>] -type Foo() = - [ obj); ("bar" :> obj) |])>] - override this.ToString() = "Stuff" - -let callCSGenericMethod (a: 't[]) = CSParamArray.Method(a) - -[] -do - let getTestAttribute (t : Type) = - let tyAttributes = t.GetCustomAttributes(false) - let attrib = tyAttributes |> Array.find (fun attrib -> match attrib with :? AttributeWithParamArray -> true | _ -> false) - (attrib :?> AttributeWithParamArray) - - let tyFoo = typeof - let testAtt = getTestAttribute tyFoo - if testAtt.Parameters <> [| (0 :> obj) |] then - printfn "Attribute parameters not as expected" - exit 1 - - let directCallWorks = - CSParamArray.Method(9, 8, 7) + CSParamArray.Method(1, 2) + CSParamArray.Method() = (9 + 8 + 7) + (1 + 2) - if not directCallWorks then - printfn "Calling C# param array method gave unexpected result" - exit 1 - - let callParamArray (x : int array) = CSParamArray.Method(x) - let asArrayCallWorks = (callParamArray [| 9; 8; 7 |]) = (9 + 8 + 7) - if not asArrayCallWorks then - printfn "Calling C# param array method, passing args as an array, gave unexpected result" - exit 1 - - if callCSGenericMethod [|"1";"2";"3"|] <> 3 then - printfn "Calling C# generic param array method gave unexpected result" - exit 1 - - if CSParamArray.Method("1", "2", "3") <> CSParamArray.Method([|"1"; "2"; "3"|]) then - printfn "Calling C# generic param array in normal and expanded method gave unexpected result" - exit 1 - - exit 0 - - \ No newline at end of file diff --git a/tests/fsharpqa/Source/Misc/E_ConsumeParamArray.fsscript b/tests/fsharpqa/Source/Misc/E_ConsumeParamArray.fsscript deleted file mode 100644 index 8e6a7a1473..0000000000 --- a/tests/fsharpqa/Source/Misc/E_ConsumeParamArray.fsscript +++ /dev/null @@ -1,35 +0,0 @@ -// #Regression #Misc -#light - -// This test used to be the regression test for FSHARP1.0:1105. -// This code is expected to fail compilation, yet it was able to detect FSHARP1.0:3817 -// so I am promoting it to negative testcases. -//The static coercion from type -open System - -#r "ParamArray.dll" -open CSharpAssembly - -// Apply the attribute -[] -type Foo() = - [] - override this.ToString() = "Stuff" - -[] -do - let testPassed = - let getTestAttribute (t : Type) = - let tyAttributes = t.GetCustomAttributes(false) - let attrib = tyAttributes |> Array.find (fun attrib -> match attrib with :? AttributeWithParamArray -> true | _ -> false) - (attrib :?> AttributeWithParamArray) - - let tyFoo = typeof - let testAtt = getTestAttribute tyFoo - if testAtt.Parameters <> [|upcast 0|] then - false - else - true - - if not testPassed then exit 1 - exit 0 diff --git a/tests/fsharpqa/Source/Misc/ParamArray.cs b/tests/fsharpqa/Source/Misc/ParamArray.cs deleted file mode 100644 index 6c7ae6108d..0000000000 --- a/tests/fsharpqa/Source/Misc/ParamArray.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System; - -namespace CSharpAssembly -{ - [AttributeUsage(AttributeTargets.All)] - public class AttributeWithParamArray : Attribute - { - public object[] Parameters; - - public AttributeWithParamArray(params object[] x) - { - - Parameters = x; - } - } - - public class CSParamArray - { - public static int Method(params int[] allArgs) - { - int total = 0; - foreach (int i in allArgs) - total += i; - - return total; - } - - public static int Method(params T[] args) - { - return args.Length; - } - } -} \ No newline at end of file diff --git a/tests/fsharpqa/Source/Misc/env.lst b/tests/fsharpqa/Source/Misc/env.lst index b2b236cb7f..ada01d097f 100644 --- a/tests/fsharpqa/Source/Misc/env.lst +++ b/tests/fsharpqa/Source/Misc/env.lst @@ -1,6 +1,3 @@ - PRECMD="\$CSC_PIPE /target:library ParamArray.cs" SOURCE=ConsumeParamArray.fsscript # ConsumeParamArray.fsscript - PRECMD="\$CSC_PIPE /target:library ParamArray.cs" SOURCE=E_ConsumeParamArray.fsscript # E_ConsumeParamArray.fsscript - SOURCE=E_productioncoverage01.fs # E_productioncoverage01.fs SOURCE=E_productioncoverage02.fs # E_productioncoverage02.fs SOURCE=E_productioncoverage03.fs SCFLAGS="--test:ErrorRanges" # E_productioncoverage03.fs