diff --git a/docs/release-notes/.FSharp.Compiler.Service/8.0.300.md b/docs/release-notes/.FSharp.Compiler.Service/8.0.300.md index 6a4d44d2aec..672209d2ed1 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/8.0.300.md +++ b/docs/release-notes/.FSharp.Compiler.Service/8.0.300.md @@ -6,9 +6,11 @@ * Graph Based Checking doesn't throw on invalid parsed input so it can be used for IDE scenarios ([PR #16575](https://github.com/dotnet/fsharp/pull/16575), [PR #16588](https://github.com/dotnet/fsharp/pull/16588), [PR #16643](https://github.com/dotnet/fsharp/pull/16643)) * Various parenthesization API fixes. ([PR #16578](https://github.com/dotnet/fsharp/pull/16578), [PR #16666](https://github.com/dotnet/fsharp/pull/16666)) * Keep parens for problematic exprs (`if`, `match`, etc.) in `$"{(…):N0}"`, `$"{(…),-3}"`, etc. ([PR #16578](https://github.com/dotnet/fsharp/pull/16578)) -* Fix crash in DOTNET_SYSTEM_GLOBALIZATION_INVARIANT mode ([PR #16471](https://github.com/dotnet/fsharp/pull/16471)) +* Fix crash in DOTNET_SYSTEM_GLOBALIZATION_INVARIANT mode [#PR 16471](https://github.com/dotnet/fsharp/pull/16471)) +* Fix16572 - Fixed the preview feature enabling Is properties for union case did not work correctly with let .rec and .fsi files ([PR #16657](https://github.com/dotnet/fsharp/pull/16657)) * `[]` member should not produce property symbol. ([Issue #16640](https://github.com/dotnet/fsharp/issues/16640), [PR #16658](https://github.com/dotnet/fsharp/pull/16658)) * Fix discriminated union initialization. ([#PR 16661](https://github.com/dotnet/fsharp/pull/16661)) +* Allow calling method with both Optional and ParamArray. ([#PR 16688](https://github.com/dotnet/fsharp/pull/16688), [suggestions #1120](https://github.com/fsharp/fslang-suggestions/issues/1120)) ### Added diff --git a/src/Compiler/Checking/CheckDeclarations.fs b/src/Compiler/Checking/CheckDeclarations.fs index ef59411179e..fc2e5e9d19b 100644 --- a/src/Compiler/Checking/CheckDeclarations.fs +++ b/src/Compiler/Checking/CheckDeclarations.fs @@ -4727,7 +4727,6 @@ module TcDeclarations = let env = List.foldBack (AddLocalVal g cenv.tcSink scopem) idvs envForDecls env) - /// Bind a collection of mutually recursive declarations in a signature file let TcMutRecSignatureDecls (cenv: cenv) envInitial parent typeNames tpenv m scopem mutRecNSInfo (mutRecSigs: MutRecSigsInitialData) = let mutRecSigsAfterSplit = mutRecSigs |> MutRecShapes.mapTycons SplitTyconSignature @@ -4739,6 +4738,18 @@ module TcDeclarations = // Updates the types of the modules to contain the contents so far, which now includes values and members MutRecBindingChecking.TcMutRecDefns_UpdateModuleContents mutRecNSInfo mutRecDefnsAfterCore + // Generate the union augmentation values for all tycons. + let mutable vals = List.empty + (envMutRec, mutRecDefnsAfterCore) + ||> MutRecShapes.iterTyconsWithEnv (fun envForDecls ((tyconCore, _, _), tyconOpt, _, _, _) -> + let (MutRecDefnsPhase1DataForTycon (isAtOriginalTyconDefn=isAtOriginalTyconDefn)) = tyconCore + match tyconOpt with + | Some tycon when isAtOriginalTyconDefn -> + if tycon.IsUnionTycon && AddAugmentationDeclarations.ShouldAugmentUnion cenv.g tycon then + let vspecs = AddAugmentationDeclarations.AddUnionAugmentationValues cenv envForDecls tycon + vals <- vspecs @ vals + | _ -> ()) + // By now we've established the full contents of type definitions apart from their // members and any fields determined by implicit construction. We know the kinds and // representations of types and have established them as valid. @@ -4747,28 +4758,19 @@ module TcDeclarations = // // Note: This environment reconstruction doesn't seem necessary. We're about to create Val's for all members, // which does require type checking, but no more information than is already available. - let envMutRecPrelimWithReprs, withEnvs = + + let envMutRecPrelimWithReprs, withEnvs = (envInitial, MutRecShapes.dropEnvs mutRecDefnsAfterCore) - ||> MutRecBindingChecking.TcMutRecDefns_ComputeEnvs - (fun (_, tyconOpt, _, _, _) -> tyconOpt) - (fun _binds -> [ (* no values are available yet *) ]) - cenv true scopem m + ||> MutRecBindingChecking.TcMutRecDefns_ComputeEnvs + (fun (_, tyconOpt, _, _, _) -> tyconOpt) + (fun _binds -> vals) + cenv true scopem m let mutRecDefnsAfterVals = TcMutRecSignatureDecls_Phase2 cenv scopem envMutRecPrelimWithReprs withEnvs // Updates the types of the modules to contain the contents so far, which now includes values and members MutRecBindingChecking.TcMutRecDefns_UpdateModuleContents mutRecNSInfo mutRecDefnsAfterVals - // Generate the union augmentation values for all tycons. - (envMutRec, mutRecDefnsAfterCore) ||> MutRecShapes.iterTyconsWithEnv (fun envForDecls ((tyconCore, _, _), tyconOpt, _, _, _) -> - let (MutRecDefnsPhase1DataForTycon (isAtOriginalTyconDefn=isAtOriginalTyconDefn)) = tyconCore - match tyconOpt with - | Some tycon when isAtOriginalTyconDefn -> - if tycon.IsUnionTycon && AddAugmentationDeclarations.ShouldAugmentUnion cenv.g tycon then - let vspecs = AddAugmentationDeclarations.AddUnionAugmentationValues cenv envForDecls tycon - ignore vspecs - | _ -> ()) - envMutRec //------------------------------------------------------------------------- diff --git a/src/Compiler/Checking/MethodCalls.fs b/src/Compiler/Checking/MethodCalls.fs index 5aed55cba08..5f60bfce120 100644 --- a/src/Compiler/Checking/MethodCalls.fs +++ b/src/Compiler/Checking/MethodCalls.fs @@ -556,6 +556,12 @@ type CalledMeth<'T> let nUnnamedCalledArgs = unnamedCalledArgs.Length if allowOutAndOptArgs && nUnnamedCallerArgs < nUnnamedCalledArgs then let unnamedCalledArgsTrimmed, unnamedCalledOptOrOutArgs = List.splitAt nUnnamedCallerArgs unnamedCalledArgs + + // take the last ParamArray arg out, make it not break the optional/out params check + let unnamedCalledArgsTrimmed, unnamedCalledOptOrOutArgs = + match List.rev unnamedCalledOptOrOutArgs with + | h :: t when h.IsParamArray -> unnamedCalledArgsTrimmed @ [h], List.rev t + | _ -> unnamedCalledArgsTrimmed, unnamedCalledOptOrOutArgs let isOpt x = x.OptArgInfo.IsOptional let isOut x = x.IsOutArg && isByrefTy g x.CalledArgumentType diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/MethodResolution.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/MethodResolution.fs index 613001af658..3ac3d49ce4b 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/MethodResolution.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/MethodResolution.fs @@ -262,3 +262,34 @@ let _, _ = Thing.Do() (Error 501, Line 6, Col 12, Line 6, Col 22, "The member or object constructor 'Do' takes 1 argument(s) but is here given 0. The required signature is 'static member Thing.Do: [] i: outref -> bool'.") ] + [] + let ``optional and ParamArray parameter resolves correctly `` () = + Fsx """ +open System.Runtime.InteropServices + +type Thing = + static member Do( + [] something: string, + [] args: obj[]) = something, args + static member Do2( + [] something: string, + outvar: outref, + [] args: obj[]) = + + outvar <- 1 + something, args +let _, _ = Thing.Do() +let _, _ = Thing.Do("123") +let _, _ = Thing.Do("123", 1, 2, 3, 4) + +let _, _ = Thing.Do2() +let _, _ = Thing.Do2("123") +let _ = + let mutable x = 0 + Thing.Do2("123", &x) +let _ = + let mutable x = 0 + Thing.Do2("123", &x, 1, 2, 3, 4) + """ + |> typecheck + |> shouldSucceed diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/Types/UnionTypes/UnionTypes.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/Types/UnionTypes/UnionTypes.fs index e30a31edacf..948ae405822 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/Types/UnionTypes/UnionTypes.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/Types/UnionTypes/UnionTypes.fs @@ -610,6 +610,66 @@ module UnionTypes = (Warning 42, Line 11, Col 12, Line 11, Col 24, "This construct is deprecated: it is only for use in the F# library") ] + [] + [] + [] + let ``UnionCaseIsTester inlined and SignatureData`` userec = + + let kwrec = if userec then "rec" else "" + let myLibraryFsi = + SourceCodeFileKind.Create( + "myLibrary.fsi", + $""" +module {kwrec} MyLibrary + + [] + type PrimaryAssembly = + | Mscorlib + | System_Runtime + | NetStandard""") + + let myLibraryFs = + SourceCodeFileKind.Create( + "myLibrary.fs", + $""" +module {kwrec} MyLibrary + + [] + type PrimaryAssembly = + | Mscorlib + | System_Runtime + | NetStandard + """) + + let myFileFs = + SourceCodeFileKind.Create( + "myFile.fs", + $""" +module {kwrec} FileName + + open MyLibrary + let inline getAssemblyType () = PrimaryAssembly.NetStandard + let inline isNetStandard () = (PrimaryAssembly.NetStandard).IsNetStandard + """) + + let myLibrary = + (fsFromString myLibraryFsi) |> FS + |> withAdditionalSourceFiles [myLibraryFs; myFileFs] + |> asLibrary + |> withLangVersionPreview + |> withName "MyLibrary" + + Fs """ +let x = FileName.getAssemblyType().IsNetStandard +let y = FileName.getAssemblyType() +let z = FileName.isNetStandard() +printfn "%b %A %b" x y z + """ + |> asExe + |> withReferences [myLibrary] + |> withLangVersionPreview + |> compileAndRun + |> shouldSucceed //SOURCE=W_UnionCaseProduction01.fsx SCFLAGS="-a --test:ErrorRanges" # W_UnionCaseProduction01.fsx [] diff --git a/tests/FSharp.Compiler.ComponentTests/Language/DiscriminatedUnionTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/DiscriminatedUnionTests.fs index d7de4c35cd2..6d2d0d24c28 100644 --- a/tests/FSharp.Compiler.ComponentTests/Language/DiscriminatedUnionTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Language/DiscriminatedUnionTests.fs @@ -2,10 +2,12 @@ namespace Language +open Xunit open FSharp.Test.Compiler module DiscriminatedUnionTests = - [] + + [] let ``Simple Is* discriminated union properties are visible, proper values are returned`` () = Fsx """ type Foo = | Foo of string | Bar @@ -17,7 +19,7 @@ if foo.IsBar then failwith "Should not be Bar" |> compileExeAndRun |> shouldSucceed - [] + [] let ``Simple Is* discriminated union properties are not visible for a single case union`` () = Fsx """ type Foo = Bar of string @@ -31,7 +33,7 @@ if not foo.IsBar then failwith "Should be Bar" |> withDiagnostics [Error 39, Line 4, Col 12, Line 4, Col 17, "The type 'Foo' does not define the field, constructor or member 'IsBar'. Maybe you want one of the following: Bar"] - [] + [] let ``Simple Is* discriminated union property satisfies SRTP constraint`` () = Fsx """ type X = @@ -47,7 +49,7 @@ X.A "a" |> test |> compileExeAndRun |> shouldSucceed - [] + [] let ``Lowercase Is* discriminated union properties are visible, proper values are returned`` () = Fsx """ [] @@ -63,7 +65,7 @@ if foo.IsA then failwith "Should not be A" |> compileExeAndRun |> shouldSucceed - [] + [] let ``Is* discriminated union properties with backticks are visible, proper values are returned`` () = Fsx """ type Foo = | Foo of string | ``Mars Bar`` @@ -79,7 +81,7 @@ if not marsbar.``IsMars Bar`` then failwith "Should be ``Mars Bar``" |> compileExeAndRun |> shouldSucceed - [] + [] let ``Is* discriminated union properties are visible, proper values are returned in recursive namespace, before the definition`` () = FSharp """ namespace rec Hello @@ -102,7 +104,7 @@ type Foo = |> shouldSucceed - [] + [] let ``Is* discriminated union properties are visible, proper values are returned in recursive namespace, in SRTP`` () = FSharp """ namespace Hello @@ -130,7 +132,7 @@ module Main = |> compileExeAndRun |> shouldSucceed - [] + [] let ``Is* discriminated union properties are unavailable with DefaultAugmentation(false)`` () = Fsx """ [] @@ -144,19 +146,40 @@ let isFoo = foo.IsFoo |> withErrorMessage "The type 'Foo' does not define the field, constructor or member 'IsFoo'. Maybe you want one of the following: Foo" - [] - let ``Is* discriminated union properties are unavailable on voption`` () = + [] + let ``Is* discriminated union properties are unavailable on union case with lang version 8`` () = Fsx """ -let x = (ValueSome 1).IsSome -let y = ValueOption.None.IsValueNone +[] +type PrimaryAssembly = +| Mscorlib +| System_Runtime +| NetStandard + +let x = (PrimaryAssembly.Mscorlib).IsMscorlib """ - |> withLangVersionPreview + |> withLangVersion80 |> typecheck |> shouldFail - |> withErrorMessage "The type 'ValueOption<_>' does not define the field, constructor or member 'IsValueNone'. Maybe you want one of the following: - ValueNone" + |> withErrorMessage "The type 'PrimaryAssembly' does not define the field, constructor or member 'IsMscorlib'. Maybe you want one of the following: + Mscorlib" + + + [] + let ``Is* discriminated union properties are available on union case after lang version 8`` () = + Fsx """ +[] +type PrimaryAssembly = +| Mscorlib +| System_Runtime +| NetStandard + +let x = (PrimaryAssembly.Mscorlib).IsMscorlib + """ + |> withLangVersionPreview + |> compileExeAndRun + |> shouldSucceed - [] + [] let ``Is* discriminated union properties work with UseNullAsTrueValue`` () = Fsx """ []