Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More struct tuple inference #18194

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/Compiler/Checking/CheckIncrementalClasses.fs
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ let TcImplicitCtorInfo_Phase2A(cenv: cenv, env, tpenv, tcref: TyconRef, vis, att
let env = AddDeclaredTypars CheckForDuplicateTypars copyOfTyconTypars env

// Type check arguments by processing them as 'simple' patterns
let ctorArgNames, patEnv, SynSimplePats.SimplePats(spats, _, _) = TcSimplePatsOfUnknownType cenv true CheckCxs env tpenv pat
let ctorArgNames, patEnv, SynSimplePats.SimplePats(pats= spats) = TcSimplePatsOfUnknownType cenv true CheckCxs env tpenv pat

let rec reportGeneratedPattern spat =
match spat with
Expand Down
2 changes: 1 addition & 1 deletion src/Compiler/Checking/CheckPatterns.fs
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ and TcSimplePats (cenv: cenv) optionalArgsOK checkConstraints ty env patEnv synS
[v], patEnv

| SynSimplePats.SimplePats (ps, _, m) ->
let ptys = UnifyRefTupleType env.eContextInfo cenv env.DisplayEnv m ty ps
let _, ptys = UnifyTupleTypeAndInferCharacteristics env.eContextInfo cenv env.DisplayEnv m ty true ps
let ps', patEnvR = (patEnv, List.zip ptys ps) ||> List.mapFold (fun patEnv (ty, pat) -> TcSimplePat optionalArgsOK checkConstraints cenv ty env patEnv pat [])
ps', patEnvR

Expand Down
2 changes: 1 addition & 1 deletion src/Compiler/Checking/Expressions/CheckExpressions.fs
Original file line number Diff line number Diff line change
Expand Up @@ -5795,7 +5795,7 @@ and TcExprUndelayed (cenv: cenv) (overallTy: OverallTy) env tpenv (synExpr: SynE
let unaryArg = mkSynId trivia.UnderscoreRange (cenv.synArgNameGenerator.New())
let svar = mkSynCompGenSimplePatVar unaryArg
let pushedExpr = pushUnaryArg synExpr unaryArg
let lambda = SynExpr.Lambda(false, false, SynSimplePats.SimplePats([ svar ],[], svar.Range), pushedExpr, None, m, SynExprLambdaTrivia.Zero)
let lambda = SynExpr.Lambda(false, false, SynSimplePats.SimplePats([ svar ], [], svar.Range), pushedExpr, None, m, SynExprLambdaTrivia.Zero)
TcIteratedLambdas cenv true env overallTy Set.empty tpenv lambda
| SynExpr.Lambda _ ->
TcIteratedLambdas cenv true env overallTy Set.empty tpenv synExpr
Expand Down
4 changes: 2 additions & 2 deletions src/Compiler/SyntaxTree/SyntaxTreeOps.fs
Original file line number Diff line number Diff line change
Expand Up @@ -372,9 +372,9 @@ let rec SimplePatsOfPat synArgNameGenerator p =
match p with
| SynPat.FromParseError(p, _) -> SimplePatsOfPat synArgNameGenerator p

| SynPat.Tuple(false, ps, commas, m)
| SynPat.Tuple(isStruct, ps, commas, m)

| SynPat.Paren(SynPat.Tuple(false, ps, commas, _), m) ->
| SynPat.Paren(SynPat.Tuple(isStruct, ps, commas, _), m) ->
let sps = List.map (SimplePatOfPat synArgNameGenerator) ps

let ps2, laterF =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@
<Compile Include="Language\StateMachineTests.fs" />
<Compile Include="Language\DynamicAssignmentOperatorTests.fs" />
<Compile Include="Language\CastingTests.fs" />
<Compile Include="Language\TupleTests.fs" />
<Compile Include="Language\NameofTests.fs" />
<Compile Include="Language\DiscriminatedUnionTests.fs" />
<Compile Include="Language\DotLambdaTests.fs" />
Expand Down
243 changes: 243 additions & 0 deletions tests/FSharp.Compiler.ComponentTests/Language/TupleTests.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,243 @@
// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.

namespace Language

open Xunit
open FSharp.Test.Compiler

module TupleTests =

[<Fact>]
let ``Simple reference tuple`` () =
FSharp """
let x, y = 1, 2
"""
|> ignoreWarnings
|> typecheck
|> shouldSucceed

[<Fact>]
let ``Simple reference tuple destructuring with match`` () =
FSharp """
match 1, 2 with
| x, y -> x + y
"""
|> ignoreWarnings
|> typecheck
|> shouldSucceed

[<Fact>]
let ``Simple reference tuple destructuring with for-loop`` () =
FSharp """
for x, y in [1, 2] do ()
"""
|> ignoreWarnings
|> typecheck
|> shouldSucceed

// [<Fact>]
// let ``Simple reference tuple destructuring in a lambda`` () =
// FSharp """
// type Class() =
// member _.Method(x:(int*int)[]) =
// x |> Array.iter (fun (a, b) -> ())
// """
// |> ignoreWarnings
// |> typecheck
// |> shouldSucceed

[<Fact>]
let ``Function - Simple tuple destructuring in a lambda`` () =
FSharp """
let f (a: (int * int) list) =
a |> List.map fst
"""
|> ignoreWarnings
|> typecheck
|> shouldSucceed

module StructTupleTests =

[<Fact>]
let ``Simple struct tuple`` () =
FSharp """
let struct(x, y) = struct(1, 2)
"""
|> ignoreWarnings
|> typecheck
|> shouldSucceed

[<Fact>]
let ``Simple struct tuple destructuring with match`` () =
FSharp """
match struct(1, 2) with
| x, y -> x + y

match struct(1, 2) with
| struct(x, y) -> x + y
"""
|> ignoreWarnings
|> typecheck
|> shouldSucceed

[<Fact>]
let ``Simple struct tuple destructuring with for-loop`` () =
FSharp """
let structTuples = [ struct(1, 2) ]
for x, y in structTuples do ()
for struct(x, y) in structTuples do ()
"""
|> ignoreWarnings
|> typecheck
|> shouldSucceed

[<Fact>]
let ``Class - Simple struct tuple destructuring in a lambda`` () =
FSharp """
type Class() =
member _.Method(x:struct(int*int)[]) =
x |> Array.iter (fun (a, b) -> ())
"""
|> ignoreWarnings
|> typecheck
|> shouldSucceed

[<Fact>]
let ``Class - Simple struct tuple destructuring in a lambda AppExpr`` () =
FSharp """
type Class() =
member _.Method(x:struct(int*int)[]) =
x |> Array.iter (fun struct (a, b) -> ())

"""
|> ignoreWarnings
|> typecheck
|> shouldSucceed

[<Fact>]
let ``Class - Simple struct tuple destructuring in a match lambda AppExpr`` () =
FSharp """
type Class() =
member _.Method(x:struct(int*int)[]) =
x |> Array.iter (function (a, b) -> ())
x |> Array.iter (function struct (a, b) -> ())

"""
|> ignoreWarnings
|> typecheck
|> shouldSucceed

[<Fact>]
let ``Class - Simple struct tuple destructuring in a struct lambda argument`` () =
FSharp """
type Class() =
member _.Method2(x:struct(int*int)) =
x |> fun (a, b) -> ()
x |> fun struct(a, b) -> ()
"""
|> ignoreWarnings
|> typecheck
|> shouldSucceed

[<Fact>]
let ``Class - calling a method with struct tuple parameter`` () =
FSharp """
type Class() =
member _.Method2(x:struct(int*int)) =
x |> fun struct(a, b) -> ()

let c = Class()
c.Method2((1, 2))
c.Method2(struct(1, 2))

struct(1, 2)
|> c.Method2
"""
|> ignoreWarnings
|> typecheck
|> shouldSucceed

[<Fact>]
let ``Class - Error when calling a method with struct tuple parameter(Piping)`` () =
FSharp """
type Class() =
member _.Method2(x:struct(int*int)) =
x |> fun struct(a, b) -> ()

let c = Class()
(1, 2)
|> c.Method2
"""
|> ignoreWarnings
|> typecheck
|> shouldFail
|> withDiagnostics [
(Error 193, Line 8, Col 4, Line 8, Col 13, "Type constraint mismatch. The type
'int * int'
is not compatible with type
'struct (int * int)'
")
]

[<Fact>]
let ``Function - Simple struct tuple destructuring in a struct lambda with parenthesis`` () =
FSharp """
let f (a: struct (int * int)) =
a |> (fun ((x, y)) -> x + y)
a |> (fun (struct(x, y)) -> x + y)
"""
|> ignoreWarnings
|> typecheck
|> shouldSucceed

// [<Fact>]
// let ``Function - Simple struct tuple destructuring in a lambda`` () =
// FSharp """
// let f (a: struct (int * int) list) =
// a |> List.map fst
// """
// |> ignoreWarnings
// |> typecheck
// |> shouldSucceed

[<Fact>]
let ``Function - Simple struct tuple destructuring in a match lambda AppExpr`` () =
FSharp """
let f (x: struct (int * int) []) =
x |> Array.iter (function (a, b) -> ())
x |> Array.iter (function struct (a, b) -> ())

"""
|> ignoreWarnings
|> typecheck
|> shouldSucceed

[<Fact>]
let ``Function - Simple struct tuple destructuring in a struct lambda`` () =
FSharp """
let f (a: struct (int * int)) =
a |> (fun (x, y) -> x + y)
a |> (fun struct(x, y) -> x + y)
"""
|> ignoreWarnings
|> typecheck
|> shouldSucceed

[<Fact>]
let ``Function - struct tuple destructuring in a CE`` () =
FSharp """
let doSomething() =
async {
return struct (1, 2)
}

let consumeSomething() =
task {
let! x, y = doSomething()
let! struct (a, b) = doSomething()
return x + y + a + b
}
"""
|> ignoreWarnings
|> typecheck
|> shouldSucceed
Loading