Nim icon indicating copy to clipboard operation
Nim copied to clipboard

compiler bug about generic type, dot operators

Open retsyo opened this issue 3 years ago • 2 comments

The following code runs on windows only, and requires

when nim compiles the code

import sugar
import winim/clr

var
    mscor* = load("mscorlib")
    NPOIOOXML* = clr.load("NPOI.OOXML.dll")

var
    File* = mscor.GetType("System.IO.File")
    WorkbookFactory* = NPOIOOXML.GetType("NPOI.SS.UserModel.WorkbookFactory")

# proc fn(fnExcel: string, sthSheet: int|string): int = # error too
proc fn(fnExcel: string, sthSheet: int|string=0): int = # error
    var stream= @File.OpenRead(fnExcel)
    var workbook = @WorkbookFactory.Create(stream);
    return workbook.NumberOfSheets

var fnExcel = "testR.xlsx"

dump fn(fnExcel, 0)
#~ dump fn(fnExcel, "Sheet1")

it says

........................................................................................................................
D:\tmp\compareexcel\b.nim(19, 6) template/generic instantiation of `dump` from here
E:\msys64\home\USER\_nim\nim\lib\pure\sugar.nim(171, 12) template/generic instantiation of `fn` from here
D:\tmp\compareexcel\b.nim(14, 36) Error: type mismatch: got <CLRType, CLRVariant>
but expected one of:
proc Create(self: ptr IPropertySetStorage; rfmtid: REFFMTID; pclsid: ptr CLSID;
            grfFlags: DWORD; grfMode: DWORD; ppprstg: ptr ptr IPropertyStorage): HRESULT
  first type mismatch at position: 1
  required type for self: ptr IPropertySetStorage
  but expression '@WorkbookFactory' is of type: CLRType
proc Create(self: ptr IShellImageStore; dwMode: DWORD; pdwLock: ptr DWORD): HRESULT
  first type mismatch at position: 1
  required type for self: ptr IShellImageStore
  but expression '@WorkbookFactory' is of type: CLRType

expression: Create(@WorkbookFactory, stream)

however, the following 2 codes can be compiled and run without problem

# good code 1
import sugar
import winim/clr

var
    mscor* = load("mscorlib")
    NPOIOOXML* = clr.load("NPOI.OOXML.dll")

var
    File* = mscor.GetType("System.IO.File")
    WorkbookFactory* = NPOIOOXML.GetType("NPOI.SS.UserModel.WorkbookFactory")

proc fn(fnExcel: string, intSheet: int=0): int =
    var stream= @File.OpenRead(fnExcel)
    var workbook = @WorkbookFactory.Create(stream);
    return workbook.NumberOfSheets

var fnExcel = "testR.xlsx"

dump fn(fnExcel, 0)

and

# good code 2
import sugar
import winim/clr

var
    mscor* = load("mscorlib")
    NPOIOOXML* = clr.load("NPOI.OOXML.dll")

var
    File* = mscor.GetType("System.IO.File")
    WorkbookFactory* = NPOIOOXML.GetType("NPOI.SS.UserModel.WorkbookFactory")

proc fn(fnExcel: string, strSheet: string="Sheet1"): int =
    var stream= @File.OpenRead(fnExcel)
    var workbook = @WorkbookFactory.Create(stream);
    return workbook.NumberOfSheets

var fnExcel = "testR.xlsx"

dump fn(fnExcel, "Sheet1")

Since it is a simplified version, the parameter strSheet/intSheet/sthSheet is not used here, however in my real code, it is need and can not be omitted.

retsyo avatar Jan 09 '22 03:01 retsyo

Minimized:

{.experimental: "dotOperators".}

type Foo = object
  x: int

proc bar(a, b: int): int = a + b

template `.`(a: Foo, b): untyped = a.x

proc generic[T]() =
  echo Foo(x: 3).bar

generic[void]()

So dot operators don't work with overloaded symbols inside generic procs. int | string in your fn proc makes it generic. The workaround is

proc fn(fnExcel: string, sthSheet: int|string=0): int =
    var stream= @File.OpenRead(fnExcel)
    var workbook = `.`(@WorkbookFactory, Create, stream)
    return workbook.NumberOfSheets

metagn avatar Jan 09 '22 13:01 metagn

Fwiw dot operators are known to not work well with generics. Which is why they were declared "experimental". But finding a design for them that actually works would be nice.

Araq avatar Jan 10 '22 15:01 Araq