dotnet / fsharp

The F# compiler, F# core library, F# language service, and F# tooling integration for Visual Studio
https://dotnet.microsoft.com/languages/fsharp
MIT License
3.93k stars 788 forks source link

error FS0193: internal error: GenericArguments[0], 'TWidget', on 'Eto.StyleHandler`1[THandler]' violates the constraint of type 'THandler'. #2411

Closed smoothdeveloper closed 7 years ago

smoothdeveloper commented 7 years ago

I'm trying to call https://github.com/picoe/Eto/blob/develop/Source/Eto/Style.cs#L154 but I'm getting internal error

#load ".paket/load/eto.platform.wpf.fsx"
#r "PresentationFramework"
#r "WindowsBase"
#r "PresentationCore"
open Eto

Style.Add<Eto.Wpf.Forms.FormHandler>(null, fun (handler: Wpf.Forms.FormHandler) -> System.Windows.Media.TextOptions.SetTextFormattingMode(handler.Control, System.Windows.Media.TextFormattingMode.Display))
Style.Add<Eto.Wpf.Forms.DialogHandler>(null, fun (handler: Wpf.Forms.DialogHandler) -> System.Windows.Media.TextOptions.SetTextFormattingMode(handler.Control, System.Windows.Media.TextFormattingMode.Display))

error FS0193: internal error: GenericArguments[0], 'TWidget', on 'Eto.StyleHandler`1[THandler]' violates the constraint of type 'THandler'.

Note that for some reason, I need to state the type of handler in the lambda which is strange because the parameter type is meant to be the same as the one I gave as explicit type parameter to Style.Add

Attaching the script + dependencies for reproducing the error (rename it as .7z as it is not a zip file) etofsharp.7z.zip

I don't know a work around for that issue if anyone has an idea?

smoothdeveloper commented 7 years ago

Bringing a stack trace, from master:

error FS0193: internal error: GenericArguments[0], 'TWidget', on 'Eto.StyleHandler`1[THandler]' violates the constraint of type 'THandler'.
Stack Trace
System.ArgumentException: GenericArguments[0], 'TWidget', on 'Eto.StyleHandler`1[THandler]' violates the constraint of type 'THandler'. ---> System.TypeLoadException: GenericArguments[0], 'TWidget', on 'Eto.StyleHandler`
1[THandler]' violates the constraint of type parameter 'THandler'.
   at System.RuntimeTypeHandle.Instantiate(RuntimeTypeHandle handle, IntPtr* pInst, Int32 numGenericArgs, ObjectHandleOnStack type)
   at System.RuntimeTypeHandle.Instantiate(Type[] inst)
   at System.RuntimeType.MakeGenericType(Type[] instantiation)
   --- End of inner exception stack trace ---
   at System.RuntimeType.ValidateGenericArguments(MemberInfo definition, RuntimeType[] genericArguments, Exception e)
   at System.RuntimeType.MakeGenericType(Type[] instantiation)
   at Microsoft.FSharp.Compiler.AbstractIL.ILRuntimeWriter.convTypeSpec(cenv cenv, emEnv emEnv, Boolean preferCreated, ILTypeSpec tspec) in C:\dev\visualfsharp\src\absil\ilreflect.fs:line 523
   at Microsoft.FSharp.Compiler.AbstractIL.ILRuntimeWriter.convTypeAux(cenv cenv, emEnv emEnv, Boolean preferCreated, ILType typ) in C:\dev\visualfsharp\src\absil\ilreflect.fs:line 542
   at Microsoft.FSharp.Primitives.Basics.List.mapToFreshConsTail[a,b](FSharpList`1 cons, FSharpFunc`2 f, FSharpList`1 x) in C:\dev\visualfsharp\src\fsharp\FSharp.Core\local.fs:line 243
   at Microsoft.FSharp.Primitives.Basics.List.map[T,TResult](FSharpFunc`2 mapping, FSharpList`1 x) in C:\dev\visualfsharp\src\fsharp\FSharp.Core\local.fs:line 253
   at Microsoft.FSharp.Collections.ListModule.Map[T,TResult](FSharpFunc`2 mapping, FSharpList`1 list) in C:\dev\visualfsharp\src\fsharp\FSharp.Core\list.fs:line 75
   at Microsoft.FSharp.Compiler.AbstractIL.ILRuntimeWriter.select@680.Invoke(MethodInfo methInfo) in C:\dev\visualfsharp\src\absil\ilreflect.fs:line 684
   at Microsoft.FSharp.Collections.ListModule.TryFind[T](FSharpFunc`2 predicate, FSharpList`1 list) in C:\dev\visualfsharp\src\fsharp\FSharp.Core\list.fs:line 384
   at Microsoft.FSharp.Compiler.AbstractIL.ILRuntimeWriter.queryableTypeGetMethodBySearch(cenv cenv, emEnv emEnv, Type parentT, ILMethodRef mref) in C:\dev\visualfsharp\src\absil\ilreflect.fs:line 697
   at Microsoft.FSharp.Compiler.AbstractIL.ILRuntimeWriter.convMethodSpec(cenv cenv, emEnv emEnv, ILMethodSpec mspec) in C:\dev\visualfsharp\src\absil\ilreflect.fs:line 761
   at Microsoft.FSharp.Compiler.AbstractIL.ILRuntimeWriter.emitInstrCall@862.Invoke(Unit unitVar0) in C:\dev\visualfsharp\src\absil\ilreflect.fs:line 869
   at Microsoft.FSharp.Compiler.AbstractIL.ILRuntimeWriter.emitInstrTail(ILGenerator ilG, ILTailcall tail, FSharpFunc`2 emitTheCall) in C:\dev\visualfsharp\src\absil\ilreflect.fs:line 850
   at Microsoft.FSharp.Compiler.AbstractIL.ILRuntimeWriter.emitCode(cenv cenv, ModuleBuilder modB, emEnv emEnv, ILGenerator ilG, ILCode code) in C:\dev\visualfsharp\src\absil\ilreflect.fs:line 1249
   at Microsoft.FSharp.Compiler.AbstractIL.ILRuntimeWriter.emitILMethodBody(cenv cenv, ModuleBuilder modB, emEnv emEnv, ILGenerator ilG, ILMethodBody ilmbody) in C:\dev\visualfsharp\src\absil\ilreflect.fs:line 1266
   at Microsoft.FSharp.Compiler.AbstractIL.ILRuntimeWriter.emitMethodBody[a,b](cenv cenv, ModuleBuilder modB, emEnv emEnv, FSharpFunc`2 ilG, b _name, ILLazyMethodBody mbody) in C:\dev\visualfsharp\src\absil\ilreflect.fs:
line 1271
   at Microsoft.FSharp.Compiler.AbstractIL.ILRuntimeWriter.buildMethodPass3(cenv cenv, ILTypeRef tref, ModuleBuilder modB, TypeBuilder typB, emEnv emEnv, ILMethodDef mdef) in C:\dev\visualfsharp\src\absil\ilreflect.fs:li
ne 1521
   at Microsoft.FSharp.Compiler.AbstractIL.ILRuntimeWriter.buildTypeDefPass3@1780.Invoke(ILMethodDef mdef) in C:\dev\visualfsharp\src\absil\ilreflect.fs:line 1780
   at Microsoft.FSharp.Collections.SeqModule.Iterate[T](FSharpFunc`2 action, IEnumerable`1 source) in C:\dev\visualfsharp\src\fsharp\FSharp.Core\seq.fs:line 880
   at Microsoft.FSharp.Compiler.AbstractIL.ILRuntimeWriter.buildTypeDefPass3(cenv cenv, FSharpList`1 nesting, ModuleBuilder modB, emEnv emEnv, ILTypeDef tdef) in C:\dev\visualfsharp\src\absil\ilreflect.fs:line 1780
   at Microsoft.FSharp.Compiler.AbstractIL.ILRuntimeWriter.buildModuleTypePass3(cenv cenv, ModuleBuilder modB, emEnv emEnv, ILTypeDef tdef) in C:\dev\visualfsharp\src\absil\ilreflect.fs:line 1927
   at Microsoft.FSharp.Compiler.AbstractIL.ILRuntimeWriter.emEnv@1946-10.Invoke(emEnv emEnv, ILTypeDef tdef) in C:\dev\visualfsharp\src\absil\ilreflect.fs:line 1946
   at Microsoft.FSharp.Collections.ListModule.loop@220-16.Invoke(TState s, FSharpList`1 xs) in C:\dev\visualfsharp\src\fsharp\FSharp.Core\list.fs:line 222
   at Microsoft.FSharp.Compiler.AbstractIL.ILRuntimeWriter.buildModuleFragment(cenv cenv, emEnv emEnv, AssemblyBuilder asmB, ModuleBuilder modB, ILModuleDef m) in C:\dev\visualfsharp\src\absil\ilreflect.fs:line 1946
   at Microsoft.FSharp.Compiler.AbstractIL.ILRuntimeWriter.emitModuleFragment(ILGlobals ilg, emEnv emEnv, AssemblyBuilder asmB, ModuleBuilder modB, ILModuleDef modul, Boolean debugInfo, FSharpFunc`2 resolveAssemblyRef, F
SharpFunc`2 tryFindSysILTypeRef) in C:\dev\visualfsharp\src\absil\ilreflect.fs:line 2009
   at Microsoft.FSharp.Compiler.Interactive.Shell.FsiDynamicCompiler.ProcessInputs(CompilationThreadToken ctok, ErrorLogger errorLogger, FsiDynamicCompilerState istate, FSharpList`1 inputs, Boolean showTypes, Boolean isI
ncrementalFragment, Boolean isInteractiveItExpr, FSharpList`1 prefixPath) in C:\dev\visualfsharp\src\fsharp\fsi\fsi.fs:line 1047
   at Microsoft.FSharp.Compiler.Interactive.Shell.FsiDynamicCompiler.EvalParsedDefinitions(CompilationThreadToken ctok, ErrorLogger errorLogger, FsiDynamicCompilerState istate, Boolean showTypes, Boolean isInteractiveItE
xpr, FSharpList`1 defs) in C:\dev\visualfsharp\src\fsharp\fsi\fsi.fs:line 1135
   at Microsoft.FSharp.Compiler.Interactive.Shell.clo@1859-48.Invoke(FsiDynamicCompilerState istate) in C:\dev\visualfsharp\src\fsharp\fsi\fsi.fs:line 1866
   at Microsoft.FSharp.Compiler.Interactive.Shell.FsiInteractionProcessor.InteractiveCatch[b](ErrorLogger errorLogger, FSharpFunc`2 f, b istate) in C:\dev\visualfsharp\src\fsharp\fsi\fsi.fs:line 1813

in ilreflect.fs:

let rec convTypeSpec cenv emEnv preferCreated (tspec:ILTypeSpec) =
    let typT   = convTypeRef cenv emEnv preferCreated tspec.TypeRef 
    let tyargs = List.map (convTypeAux cenv emEnv preferCreated) tspec.GenericArgs
    match isNil tyargs,typT.IsGenericType with
    | _   ,true  -> typT.MakeGenericType(List.toArray tyargs)   |> nonNull "convTypeSpec: generic" 
    | true,false -> typT                                          |> nonNull "convTypeSpec: non generic" 
    | _   ,false -> failwithf "- convTypeSpec: non-generic type '%O' has type instance of length %d?" typT tyargs.Length 

typT.MakeGenericType throws because the types given aren't matching the second overload for Add (https://github.com/picoe/Eto/blob/135ce25fb34866493a8c44355fd5bfd25795e644/Source/Eto/Style.cs#L179), although when I dig the inheritance chain for Eto.Wpf.Forms.FormHandler it seems to satisfy the requirements where THandler: class, Widget.IHandler

FormHandler is a class, and implements Widget.IHandler.

What seems to happen is that both overload gets mixed, trying to resolve the first one with constraints defined for second one:

image

Notice TWidget for type parameter name in tyargs, while typT seems to refer to the overload with StyleHandler<THandler>

smoothdeveloper commented 7 years ago

This bug is specific to fsi AFAICS, fsc compiles same code fine.

Minimum repro:

// lib.cs
using System;
public delegate void FooHandler<T>(T obj) where T : IFoo;
public delegate void BarHandler<T>(T obj) where T : IBar;
public interface IFoo { }
public interface IBar { }
public class Foo
{
    public static void Do<T>(string s, FooHandler<T>a) where T : IFoo { System.Console.WriteLine("dooifoo"); }
    public static void Do<T>(string s, BarHandler<T> b) where T : IBar { System.Console.WriteLine("dooibar"); }
}

csc -t:library lib.cs

// app.fsx
#r "lib.dll"
type FooImpl() =
  interface IFoo
type BarImpl() =
  interface IBar
Foo.Do<FooImpl>("", (fun _ -> ()))
Foo.Do<BarImpl>("", (fun _ -> ()))
> fsi app.fsx
error FS0193: internal error: GenericArguments[0], 'T', on 'BarHandler`1[T]' violates the constraint of type 'T'.
>fsc app.fsx
Microsoft (R) F# Compiler version 4.1
Copyright (c) Microsoft Corporation. All Rights Reserved.

>app
dooifoo
dooibar
smoothdeveloper commented 7 years ago

In queryableTypeGetMethodBySearch, there is a test for generic method arity, but there is no check on type constraints.

if mtyargTIs.Length <> mref.GenericArity then false (* method generic arity mismatch *)

I think adding a check there before going into the else branch would solve the problem, I'm trying to figure out if everything is at hand to issue such check.

smoothdeveloper commented 7 years ago

closed via #2590