-
Notifications
You must be signed in to change notification settings - Fork 802
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
WIP RFC FS-1092: Anonymous Type-tagged Union types #10896
Conversation
…rce as current F# spec
…e order while pretty print
…Solver.fs? Fix minor issue in type relation
I set up auto-flow from |
Can we get the "Candidate for F# vNext" here? |
The base of this is still an experiment (for example: it's a draft) and nowhere near the quality of other vNext-style PRs. Once design quirks are worked out I think we can proceed with labeling it as such. I expect quite a bit of churn in both places until we get at something that's considered reviewable. |
@Swoorup I updated this by merging in the base branch |
…ature/erased-unions Merge feature/auto-widen to feature/erased-unions
…ature/erased-unions Merge feature/auto-widen to feature/erased-unions
…ature/erased-unions Merge feature/auto-widen to feature/erased-unions
…ature/erased-unions Merge feature/auto-widen to feature/erased-unions
…o-feature/erased-unions
…ature/erased-unions Merge feature/auto-widen to feature/erased-unions
…ature/erased-unions Merge feature/auto-widen to feature/erased-unions
…o-feature/erased-unions
…ature/erased-unions Merge feature/auto-widen to feature/erased-unions
Looks like there is an issue when a function type is used as one of the union types: > type IntOrFn = (int | unit -> int);;
type IntOrFn = (int | (unit -> int))
> let foo :IntOrFn = 5;;
val foo : IntOrFn = 5
> let foo :IntOrFn = fun () -> 5;;
let foo :IntOrFn = fun () -> 5;;
-------------------^^^^^^^^^^^
stdin(6,20): error FS0002: This function takes too many arguments, or is used in a context where a function is not expected |
Also, flexible types seem to work for > type IntOrStr = (int | string);;
type IntOrStr = (int | string)
> let mer (fn : unit -> #IntOrStr) = fn();;
val mer : fn:(unit -> 'a) -> 'a when 'a :> IntOrStr
> type Foof = static member Boom(fn : unit -> #IntOrStr) = fn();;
Process terminated. Assertion failed.
Unexpected exception raised in compiler: buildGenParam: multiple base types
System.Exception: buildGenParam: multiple base types
at FSharp.Compiler.AbstractIL.ILRuntimeWriter.buildGenParamsPass1b@1405.Invoke(Int32 i, ILGenericParameterDef gp) in /fsharp/src/fsharp/absil/ilreflect.fs:line 1414
at FSharp.Compiler.AbstractIL.ILRuntimeWriter.buildGenParamsPass1b(cenv cenv, emEnv emEnv, Type[] genArgs, FSharpList`1 gps) in /fsharp/src/fsharp/absil/ilreflect.fs:line 1405
at FSharp.Compiler.AbstractIL.ILRuntimeWriter.buildMethodPass2(cenv cenv, ILTypeRef tref, TypeBuilder typB, emEnv emEnv, ILMethodDef mdef) in /fsharp/src/fsharp/absil/ilreflect.fs:line 1544
at FSharp.Compiler.AbstractIL.ILRuntimeWriter.emEnv@1819-2.Invoke(emEnv emEnv, ILMethodDef mdef) in /fsharp/src/fsharp/absil/ilreflect.fs:line 1819
at Microsoft.FSharp.Collections.ArrayModule.Fold[T,TState](FSharpFunc`2 folder, TState state, T[] array) in /fsharp/src/fsharp/FSharp.Core/array.fs:line 901
at FSharp.Compiler.AbstractIL.ILRuntimeWriter.buildTypeDefPass2(cenv cenv, FSharpList`1 nesting, emEnv emEnv, ILTypeDef tdef) in /fsharp/src/fsharp/absil/ilreflect.fs:line 1819
at FSharp.Compiler.AbstractIL.ILRuntimeWriter.emEnv@1825-5.Invoke(emEnv emEnv, ILTypeDef tdef) in /fsharp/src/fsharp/absil/ilreflect.fs:line 1825
at Microsoft.FSharp.Collections.ListModule.Fold[T,TState](FSharpFunc`2 folder, TState state, FSharpList`1 list) in /fsharp/src/fsharp/FSharp.Core/list.fs:line 221
at FSharp.Compiler.AbstractIL.ILRuntimeWriter.buildTypeDefPass2(cenv cenv, FSharpList`1 nesting, emEnv emEnv, ILTypeDef tdef) in /fsharp/src/fsharp/absil/ilreflect.fs:line 1825
at FSharp.Compiler.AbstractIL.ILRuntimeWriter.buildModuleTypePass2(cenv cenv, emEnv emEnv, ILTypeDef tdef) in /fsharp/src/fsharp/absil/ilreflect.fs:line 2019
at FSharp.Compiler.AbstractIL.ILRuntimeWriter.emEnv@2032-9.Invoke(emEnv emEnv, ILTypeDef tdef) in /fsharp/src/fsharp/absil/ilreflect.fs:line 2032
at Microsoft.FSharp.Collections.ListModule.Fold[T,TState](FSharpFunc`2 folder, TState state, FSharpList`1 list) in /fsharp/src/fsharp/FSharp.Core/list.fs:line 221
at FSharp.Compiler.AbstractIL.ILRuntimeWriter.buildModuleFragment(cenv cenv, emEnv emEnv, AssemblyBuilder asmB, ModuleBuilder modB, ILModuleDef m) in /fsharp/src/fsharp/absil/ilreflect.fs:line 2032
at FSharp.Compiler.AbstractIL.ILRuntimeWriter.emitModuleFragment(ILGlobals ilg, Boolean emitTailcalls, emEnv emEnv, AssemblyBuilder asmB, ModuleBuilder modB, ILModuleDef modul, Boolean debugInfo, FSharpFunc`2 resolveAssemblyRef, FSharpFunc`2 tryFindSysILTypeRef) in /fsharp/src/fsharp/absil/ilreflect.fs:line 2103
at FSharp.Compiler.Interactive.Shell.FsiDynamicCompiler.ProcessCodegenResults(CompilationThreadToken ctok, ErrorLogger errorLogger, FsiDynamicCompilerState istate, IncrementalOptimizationEnv optEnv, TcState tcState, TcConfig tcConfig, FSharpList`1 prefixPath, Boolean showTypes, Boolean isIncrementalFragment, String fragName, FSharpList`1 declaredImpls, IlxAssemblyGenerator ilxGenerator, IlxGenResults codegenResults) in /fsharp/src/fsharp/fsi/fsi.fs:line 1159
at FSharp.Compiler.Interactive.Shell.FsiDynamicCompiler.ProcessInputs(CompilationThreadToken ctok, ErrorLogger errorLogger, FsiDynamicCompilerState istate, FSharpList`1 inputs, Boolean showTypes, Boolean isIncrementalFragment, Boolean isInteractiveItExpr, FSharpList`1 prefixPath) in /fsharp/src/fsharp/fsi/fsi.fs:line 1257
at FSharp.Compiler.Interactive.Shell.FsiDynamicCompiler.EvalParsedDefinitions(CompilationThreadToken ctok, ErrorLogger errorLogger, FsiDynamicCompilerState istate, Boolean showTypes, Boolean isInteractiveItExpr, FSharpList`1 defs) in /fsharp/src/fsharp/fsi/fsi.fs:line 1390
at FSharp.Compiler.Interactive.Shell.clo@2212-597.Invoke(FsiDynamicCompilerState istate) in /fsharp/src/fsharp/fsi/fsi.fs:line 2224
at FSharp.Compiler.Interactive.Shell.FsiInteractionProcessor.InteractiveCatch[a](ErrorLogger errorLogger, FSharpFunc`2 f, a istate) in /fsharp/src/fsharp/fsi/fsi.fs:line 2122
at FSharp.Compiler.ErrorLogger.ErrorLoggerExtensions.ErrorLogger.EmitDiagnostic(ErrorLogger x, Exception exn, FSharpDiagnosticSeverity severity) in /fsharp/src/fsharp/ErrorLogger.fs:line 372
at FSharp.Compiler.ErrorLogger.ErrorLoggerExtensions.ErrorLogger.ErrorRecovery(ErrorLogger x, Exception exn, Range m) in /fsharp/src/fsharp/ErrorLogger.fs:line 408
at FSharp.Compiler.ErrorLogger.ErrorLoggerExtensions.ErrorLogger.StopProcessingRecovery(ErrorLogger x, Exception exn, Range m) in /fsharp/src/fsharp/ErrorLogger.fs:line 422
at FSharp.Compiler.ErrorLogger.stopProcessingRecovery(Exception exn, Range m) in /fsharp/src/fsharp/ErrorLogger.fs:line 482
at FSharp.Compiler.Interactive.Shell.FsiInteractionProcessor.InteractiveCatch[a](ErrorLogger errorLogger, FSharpFunc`2 f, a istate) in /fsharp/src/fsharp/fsi/fsi.fs:line 2122
at FSharp.Compiler.Interactive.Shell.FsiInteractionProcessor.ExecInteraction(CompilationThreadToken ctok, TcConfig tcConfig, FsiDynamicCompilerState istate, ParsedScriptInteraction action, ErrorLogger errorLogger) in /fsharp/src/fsharp/fsi/fsi.fs:line 2212
at FSharp.Compiler.Interactive.Shell.FsiInteractionProcessor.execParsedInteractions(CompilationThreadToken ctok, TcConfig tcConfig, FsiDynamicCompilerState istate, FSharpOption`1 action, ErrorLogger errorLogger, FSharpOption`1 lastResult, CancellationToken cancellationToken) in /fsharp/src/fsharp/fsi/fsi.fs:line 2357
at FSharp.Compiler.Interactive.Shell.FsiInteractionProcessor.executeParsedInteractions(CompilationThreadToken ctok, TcConfig tcConfig, FsiDynamicCompilerState istate, FSharpOption`1 action, ErrorLogger errorLogger, FSharpOption`1 lastResult, CancellationToken cancellationToken) in /fsharp/src/fsharp/fsi/fsi.fs:line 2368
at FSharp.Compiler.Interactive.Shell.clo@2398-599.Invoke(CompilationThreadToken ctok, TcConfig tcConfig, FsiDynamicCompilerState istate) in /fsharp/src/fsharp/fsi/fsi.fs:line 2399
at FSharp.Compiler.Interactive.Shell.FsiInteractionProcessor.mainThreadProcessAction[a,b](a ctok, FSharpFunc`2 action, b istate) in /fsharp/src/fsharp/fsi/fsi.fs:line 2381
at FSharp.Compiler.Interactive.Shell.FsiInteractionProcessor.mainThreadProcessParsedInteractions(CompilationThreadToken ctok, ErrorLogger errorLogger, FSharpOption`1 action, FsiDynamicCompilerState istate, CancellationToken cancellationToken) in /fsharp/src/fsharp/fsi/fsi.fs:line 2398
at FSharp.Compiler.Interactive.Shell.res@2458-60.Invoke(CompilationThreadToken ctok, FsiDynamicCompilerState istate) in /fsharp/src/fsharp/fsi/fsi.fs:line 2458
at FSharp.Compiler.Interactive.Shell.clo@2102-596.Invoke(Unit unitVar0) in /fsharp/src/fsharp/fsi/fsi.fs:line 2111
at <StartupCode$FSharp-Compiler-Interactive-Settings>.$Fsiaux.FSharp-Compiler-Interactive-IEventLoop-Invoke@50-1.Invoke(Unit x) in /fsharp/src/fsharp/fsiaux.fs:line 50
at <StartupCode$FSharp-Compiler-Interactive-Settings>.$Fsiaux.run@41-4.Invoke(FSharpFunc`2 f) in /fsharp/src/fsharp/fsiaux.fs:line 41
at <StartupCode$FSharp-Compiler-Interactive-Settings>.$Fsiaux.run@39.Invoke(Unit unitVar0) in /fsharp/src/fsharp/fsiaux.fs:line 41
at FSharp.Compiler.Interactive.SimpleEventLoop.FSharp.Compiler.Interactive.IEventLoop.Run() in /fsharp/src/fsharp/fsiaux.fs:line 48
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
at FSharp.Compiler.Interactive.Shell.Utilities.callInstanceMethod0[a](Object obj, Type[] typeArgs, String nm) in /fsharp/src/fsharp/fsi/fsi.fs:line 131
at Sample.FSharp.Compiler.Interactive.Main.evaluateSession@228-4.EventLoopRun() in /fsharp/src/fsharp/fsi/fsimain.fs:line 246
at FSharp.Compiler.Interactive.Shell.runLoop@2707.Invoke(Unit unitVar0) in /fsharp/src/fsharp/fsi/fsi.fs:line 2712
at FSharp.Compiler.Interactive.Shell.DriveFsiEventLoop(FsiEvaluationSessionHostConfig fsi, FsiConsoleOutput fsiConsoleOutput) in /fsharp/src/fsharp/fsi/fsi.fs:line 2728
at FSharp.Compiler.Interactive.Shell.FsiEvaluationSession.Run() in /fsharp/src/fsharp/fsi/fsi.fs:line 3182
at Sample.FSharp.Compiler.Interactive.Main.evaluateSession(String[] argv) in /fsharp/src/fsharp/fsi/fsimain.fs:line 298
at Sample.FSharp.Compiler.Interactive.Main.MainMain(String[] argv) in /fsharp/src/fsharp/fsi/fsimain.fs:line 342
Abort trap: 6 |
I doubt flexible type should be used that way. I can't see it making sense, at least not right now, as generics wouldn't be supported in this feature. |
@Swoorup this is the problem I'm trying to solve: > type IntOrStr = (int | string);;
type IntOrStr = (int | string)
> let fn = fun () -> 5;;
val fn : unit -> int
> // with flexible types
- let foo (fn : unit -> #IntOrStr) = fn();;
val foo : fn:(unit -> 'a) -> 'a when 'a :> IntOrStr
> foo fn;;
val it : int = 5
> // without flexible types
- let bar (fn : unit -> IntOrStr) = fn();;
val bar : fn:(unit -> IntOrStr) -> IntOrStr
> bar fn;;
bar fn;;
----^^
stdin(6,5): error FS0001: Type mismatch. Expecting a
'unit -> IntOrStr'
but given a
'unit -> int'
The type 'IntOrStr' does not match the type 'int' |
@chkn It looks more like a problem for auto-widening (as future improvements). Ideally you shouldn't need flexible type for this case. |
if not (ResizeArray.exists (isObjTy g) list) then | ||
if isObjTy g pt then | ||
list.Clear() | ||
list.Add(pt) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This creates a compatibility consideration for libraries that publish erased union types. It might not be a concern, but I think it's important to be aware of:
Library1
type Foo = obj
Library2 (references Library1)
type Bar = (* ... *)
type Problematic = (Foo | Bar) // where `Foo` is from Library1
Due to this conditional, the Bar
part of Problematic
will be discarded, keeping only obj
aliased through Foo
. But if Library1 is later updated to change the type of Foo
, any code compiled against the updated Library1 and old Library2 will find that the Problematic
type no longer accepts Bar
s.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't that be same issue as the following:
Library1
type Foo = int
Library2 (references Library1)
let handle (foo: Foo) =
foo + 1
Later Library1 is updated to so that Foo
is aliased to String
? handle
doesn't handle string. I don't know enough about how .net handles transitive dependencies in depth.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah you'd definitely expect that sort of breakage with the Foo
type. But I wouldn't expect that using Problematic
with Bar
would also be broken in that case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But you would just recompile the code no in that case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, if you could. But it might be a dependency you don't have the source for
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see, how this is different to other issues that arise out of dependency version mismatch. You'd only have the issue if you publish a package using a version and then republish it using the same version, causing the breakage.
Pattern matching, (giving out warnings when matches are incomplete or overmatching) is an area that needs to be looked after. At the moment, it is just based on :? pattern match which doesn't do much. There are other tickets which are addressing areas of pattern matching, so probably best holding for now. |
Any reasons for this being closed? @dsyme |
Hmm looks like it got auto-closed when the branch it was targeting got deleted. I'll retarget to main |
Actually looks like |
Replaces #10566.
Implements RFC https://github.com/fsharp/fslang-design/blob/master/RFCs/FS-1092-anonymous-type-tagged-unions.md
Builds on #10884
Wet paint