Skip to content

Problems with struct unions in typed AST: "unhandled construct in AST" #756

@alfonsogarciacaro

Description

@alfonsogarciacaro

Reference fable-compiler/Fable#816

When traversing the typed AST generated by the following code:

type Foo =
    | Foo of Result<int, string>

let foo (a: Foo): bool =
    match a with
    | Foo(Ok(_)) -> true
    | _ -> false

The following exception is raised:

ERROR: unhandled construct in AST at /home/pauan/Programming/fsharp/fable-getting-started/src/fs/Main.fs (7,10--7,11) IsSynthetic=false (/home/pauan/Programming/fsharp/fable-getting-started/src/fs/Main.fs)
   at Microsoft.FSharp.Compiler.SourceCodeServices.ExprTranslationImpl.wfail[a](String msg, range m)
   at Microsoft.FSharp.Compiler.SourceCodeServices.FSharpExprConvert.ConvExprPrim(cenv cenv, ExprTranslationEnv env, Expr expr)
   at Microsoft.FSharp.Compiler.SourceCodeServices.FSharpExprConvert.ConvDecisionTreePrim@980.Invoke(DecisionTreeCase _arg2, E acc)
   at Microsoft.FSharp.Compiler.SourceCodeServices.FSharpExprConvert.ConvExprPrimLinear(cenv cenv, ExprTranslationEnv env, Expr expr, FSharpFunc`2 contf)
   at Microsoft.FSharp.Compiler.SourceCodeServices.FSharpExprConvert.ConvExprOnDemand@1036.Invoke(Unit unitVar0)
   at Microsoft.FSharp.Compiler.SourceCodeServices.FSharpExpr.get_E()
   at Microsoft.FSharp.Compiler.SourceCodeServices.BasicPatterns.|ILFieldGet|_|(FSharpExpr e)
   at Fable.FSharp2Fable.Compiler.|SpecialValue|_|(IFableCompiler com, Context ctx, FSharpExpr _arg1)
   at Fable.FSharp2Fable.Compiler.transformExpr(IFableCompiler com, Context ctx, FSharpExpr fsExpr)
   at Fable.FSharp2Fable.Compiler.addMethod@950(IFableCompiler com, Context ctx, DeclInfo declInfo, SourceLocation range, FSharpOption`1 import, FSharpMemberOrFunctionOrValue meth, FSharpList`1 args, FSharpExpr body)
   at Fable.FSharp2Fable.Compiler.transformMemberDecl(IFableCompiler com, Context ctx, DeclInfo declInfo, FSharpMemberOrFunctionOrValue meth, FSharpList`1 args, FSharpExpr body)
   at Microsoft.FSharp.Collections.ListModule.loop@219-29[T,TState](FSharpFunc`3 f, TState s, FSharpList`1 xs)
   at Fable.FSharp2Fable.Compiler.transformDeclarations(IFableCompiler com, Context ctx, FSharpList`1 decls)
   at Fable.FSharp2Fable.Compiler.transformFile(ICompiler com, ICompilerState state, FSharpCheckProjectResults checkedProject, String fileName)

It seems the problem is caused by struct unions, if I redefine Result on top the problem disappears:

type Result<'a,'b> = Ok of ResultValue:'a | Error of ErrorValue:'b

However it happens again if I add the [<Struct>] attribute to my custom Result.

Another way to "solve" the problem is to avoid the nested pattern matching:

let foo (a: Foo): bool =
    match a with
    | Foo body ->
        match body with
        | Ok _ -> true
        | _ -> false

Note this is not happening only because of BasicPatterns.|ILFieldGet|_|, if I remove those lines from Fable and build again, the error just happens in another place:

ERROR: unhandled construct in AST at C:\Users\Alfonso\Documents\GitHub\Fable\src\tools\QuickTest.fs (40,10--40,11) IsSynthetic=false (C:/Users/Alfonso/Documents/GitHub/Fable/src/tools/QuickTest.fs)
   at Microsoft.FSharp.Compiler.SourceCodeServices.ExprTranslationImpl.wfail[a](String msg, range m)
   at Microsoft.FSharp.Compiler.SourceCodeServices.FSharpExprConvert.ConvDecisionTreePrim@980.Invoke(DecisionTreeCase _arg2, E acc)
   at Microsoft.FSharp.Compiler.SourceCodeServices.FSharpExprConvert.ConvExprPrimLinear(cenv cenv, ExprTranslationEnv env, Expr expr, FSharpFunc`2 contf) in C:\Users\Alfonso\Documents\GitHub\FSharp.Compiler.Service\src\fsharp\vs\Exprs.fs:line 362
   at Microsoft.FSharp.Compiler.SourceCodeServices.FSharpExprConvert.ConvExprOnDemand@1036.Invoke(Unit unitVar0) in C:\Users\Alfonso\Documents\GitHub\FSharp.Compiler.Service\src\fsharp\vs\Exprs.fs:line 126
   at Microsoft.FSharp.Compiler.SourceCodeServices.FSharpExpr.get_E()
   at Microsoft.FSharp.Compiler.SourceCodeServices.BasicPatterns.|Let|_|(FSharpExpr e) in C:\Users\Alfonso\Documents\GitHub\FSharp.Compiler.Service\src\fsharp\vs\Exprs.fs:line 199
   at Fable.FSharp2Fable.Patterns.|ForOf|_|(FSharpExpr _arg1) in c:\Users\Alfonso\Documents\GitHub\Fable\src\dotnet\Fable.Compiler\FSharp2Fable.Util.fs:line 606
   at Fable.FSharp2Fable.Compiler.transformExpr(IFableCompiler com, Context ctx, FSharpExpr fsExpr)
   at Fable.FSharp2Fable.Compiler.addMethod@961(IFableCompiler com, Context ctx, DeclInfo declInfo, SourceLocation range, FSharpOption`1 import, FSharpMemberOrFunctionOrValue meth, FSharpList`1 args, FSharpExpr body)
   at Fable.FSharp2Fable.Compiler.transformMemberDecl(IFableCompiler com, Context ctx, DeclInfo declInfo, FSharpMemberOrFunctionOrValue meth, FSharpList`1 args, FSharpExpr body)
   at Fable.FSharp2Fable.Compiler.transformDeclarations@1067-1.Invoke(FSharpImplementationFileDeclaration decl)
   at Microsoft.FSharp.Collections.ListModule.loop@219-29[T,TState](FSharpFunc`3 f, TState s, FSharpList`1 xs)
   at Fable.FSharp2Fable.Compiler.transformDeclarations(IFableCompiler com, Context ctx, FSharpList`1 decls)
   at Fable.FSharp2Fable.Compiler.transformFile(ICompiler com, ICompilerState state, FSharpCheckProjectResults checkedProject, String fileName)

Any hints why this may be happening? @dsyme @forki

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions