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

Depickling assertion followed by nullref internal errors in units-of-measure case #362

Closed
latkin opened this issue Apr 13, 2015 · 3 comments
Labels
Milestone

Comments

@latkin
Copy link
Contributor

latkin commented Apr 13, 2015

Came across this while poking around this SO question. Have reduced code to more minimal example.

Use the F# 3.1 compiler to create a library from the following:

// test.fs
namespace Test

type Vector2<[<Measure>]'T> =
    { X : float<'T>
      Y : float<'T> }

    static member (*) (v:Vector2<'a>, f:float<'b>) : Vector2<'a * 'b> =
        { X = v.X * f; Y = v.Y * f }

Then try to consume the Vector2 type from a console app like so, with F# 4.0 compiler:

// program.fs
open Test
open Microsoft.FSharp.Data.UnitSystems.SI.UnitSymbols

{ X = 1.<m>; Y = 1.<m>} |> printfn "%A"
> [3.1] fsc.exe -a test.fs
> [4.0] fsc.exe -r:test.dll program.fs

Assuming debug build of 4.0 compiler you will get the following assert then a series of nullrefs (below).

  • Using 3.1 compiler for both steps results in same errors
  • Using 4.0 compiler for both steps results in successful compile

So it seems like this was a bad pickling behavior in 3.1 that is now corrected, but when consuming bad format we are not handling it gracefully.

---------------------------
Assertion Failed: Abort=Quit, Retry=Debug, Ignore=Continue
---------------------------
*** unpickle: osgn 10 in table itypars with IL scope test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null had no matching declaration (was not fixed up)
Please report this warning. (Note for compiler developers: to get information about which item this index relates to, enable the conditional in Pickle.p_osgn_ref to refer to the given index number and recompile an identical copy of the source for the DLL containing the data being unpickled.  A message will then be printed indicating the name of the item.
   at Microsoft.FSharp.Compiler.Pickle.check[a,b](ILScopeRef ilscope, NodeInTable`2 inMap)
   at Microsoft.FSharp.Compiler.Pickle.unpickleObjWithDanglingCcus[T](String file, ILScopeRef viewedScope, ILModuleDef ilModule, FSharpFunc`2 u, Byte[] phase2bytes)
   at Microsoft.FSharp.Compiler.Build.GetSignatureData(String file, ILScopeRef ilScopeRef, ILModuleDef ilModule, FSharpFunc`2 byteReader)
   at Microsoft.FSharp.Compiler.Build.ccuRawDataAndInfos@4013.Invoke(Tuple`2 tupledArg)
   at Microsoft.FSharp.Primitives.Basics.List.map[T,TResult](FSharpFunc`2 mapping, FSharpList`1 x)
   at Microsoft.FSharp.Collections.ListModule.Map[T,TResult](FSharpFunc`2 mapping, FSharpList`1 list)
   at Microsoft.FSharp.Compiler.Build.TcImports.PrepareToImportReferencedFSharpDll(FSharpList`1 tpApprovals, range m, String filename, FSharpOption`1 displayPSTypeProviderSecurityDialogBlockingUI, ImportedBinary dllinfo)
   <snip>

-------

Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object.
   at Microsoft.FSharp.Compiler.Tast.Typar.get_Solution()
   at Microsoft.FSharp.Compiler.Tast.Typar.get_IsSolved()
   at Microsoft.FSharp.Compiler.Tast.stripUnitEqnsAux(Boolean canShortcut, MeasureExpr unt)
   at Microsoft.FSharp.Compiler.Tastops.stripUnitEqnsFromMeasureAux(Boolean canShortcut, MeasureExpr unt)
   at Microsoft.FSharp.Compiler.Tastops.stripUnitEqnsFromMeasure(MeasureExpr m)
   at Microsoft.FSharp.Compiler.Tastops.gather@434-2.Invoke(FSharpList`1 acc, MeasureExpr unt)
   at Microsoft.FSharp.Compiler.Tastops.gather@434-2.Invoke(FSharpList`1 acc, MeasureExpr unt)
   at Microsoft.FSharp.Compiler.Tastops.gather@434-2.Invoke(FSharpList`1 acc, MeasureExpr unt)
   at Microsoft.FSharp.Compiler.Tastops.isDimensionless(TcGlobals g, TType tyarg)
   at Microsoft.FSharp.Primitives.Basics.List.forall[T](FSharpFunc`2 predicate, FSharpList`1 xs1)
   at Microsoft.FSharp.Collections.ListModule.ForAll[T](FSharpFunc`2 predicate, FSharpList`1 list)
   at Microsoft.FSharp.Compiler.Tastops.stripTyEqnsA(TcGlobals g, Boolean canShortcut, TType ty)
   at Microsoft.FSharp.Compiler.Tastops.stripTyEqns(TcGlobals g, TType ty)
   at Microsoft.FSharp.Compiler.Tastops.stripTyEqnsAndErase(Boolean eraseFuncAndTuple, TcGlobals g, TType ty)
   at Microsoft.FSharp.Compiler.Tastops.stripTyEqnsWrtErasure(Erasure erasureFlag, TcGlobals g, TType ty)
   at Microsoft.FSharp.Compiler.Tastops.typeAEquivAux(Erasure erasureFlag, TcGlobals g, TypeEquivEnv aenv, TType ty1, TType ty2)
   at Microsoft.FSharp.Collections.ListModule.forall2aux[a,b](FSharpFunc`3 f, FSharpList`1 list1, FSharpList`1 list2)
   at Microsoft.FSharp.Collections.ListModule.ForAll2[T1,T2](FSharpFunc`2 predicate, FSharpList`1 list1, FSharpList`1 list2)
   at Microsoft.FSharp.Collections.ListModule.forall2aux[a,b](FSharpFunc`3 f, FSharpList`1 list1, FSharpList`1 list2)
   at Microsoft.FSharp.Collections.ListModule.ForAll2[T1,T2](FSharpFunc`2 predicate, FSharpList`1 list1, FSharpList`1 list2)
   at Microsoft.FSharp.Collections.ListModule.TryFind[T](FSharpFunc`2 predicate, FSharpList`1 list)
   at Microsoft.FSharp.Compiler.Tast.ValRef.get_Deref()
   at Microsoft.FSharp.Compiler.Tast.ValRef.get_IsIncrClassConstructor()
   at Microsoft.FSharp.Compiler.TypeChecker.TcRecordConstruction@5830.Invoke(ValRef v)
   <snip>
@latkin latkin added the Bug label Apr 13, 2015
@dsyme
Copy link
Contributor

dsyme commented Apr 23, 2015

I'm not entirely sure there's going to be a nice fix for this, do you think it's a must fix for F# 4.0?

@latkin
Copy link
Contributor Author

latkin commented Apr 23, 2015

Can we at least issue a proper error instead of nullrefing? "Corrupt F# metadata encountered" or something like that?

@dsyme
Copy link
Contributor

dsyme commented Apr 23, 2015

Yes, to do that take the this code out of #if DEBUG and surface the error as a reported exception. I don't think there is any file location with which to associate the error though, so it won't be seen in the IDE, and you'll have to use Range.range0 I think

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants