parent
cb9d554ac9
commit
6e358e3187
4 changed files with 58 additions and 5 deletions
|
|
@ -89,6 +89,7 @@ type
|
||||||
errMainModuleMustBeSpecified,
|
errMainModuleMustBeSpecified,
|
||||||
errXExpected,
|
errXExpected,
|
||||||
errTIsNotAConcreteType,
|
errTIsNotAConcreteType,
|
||||||
|
errCastToANonConcreteType,
|
||||||
errInvalidSectionStart, errGridTableNotImplemented, errGeneralParseError,
|
errInvalidSectionStart, errGridTableNotImplemented, errGeneralParseError,
|
||||||
errNewSectionExpected, errWhitespaceExpected, errXisNoValidIndexFile,
|
errNewSectionExpected, errWhitespaceExpected, errXisNoValidIndexFile,
|
||||||
errCannotRenderX, errVarVarTypeNotAllowed, errInstantiateXExplicitly,
|
errCannotRenderX, errVarVarTypeNotAllowed, errInstantiateXExplicitly,
|
||||||
|
|
@ -326,6 +327,7 @@ const
|
||||||
errMainModuleMustBeSpecified: "please, specify a main module in the project configuration file",
|
errMainModuleMustBeSpecified: "please, specify a main module in the project configuration file",
|
||||||
errXExpected: "\'$1\' expected",
|
errXExpected: "\'$1\' expected",
|
||||||
errTIsNotAConcreteType: "\'$1\' is not a concrete type.",
|
errTIsNotAConcreteType: "\'$1\' is not a concrete type.",
|
||||||
|
errCastToANonConcreteType: "cannot cast to a non concrete type: \'$1\'",
|
||||||
errInvalidSectionStart: "invalid section start",
|
errInvalidSectionStart: "invalid section start",
|
||||||
errGridTableNotImplemented: "grid table is not implemented",
|
errGridTableNotImplemented: "grid table is not implemented",
|
||||||
errGeneralParseError: "general parse error",
|
errGeneralParseError: "general parse error",
|
||||||
|
|
|
||||||
|
|
@ -218,13 +218,16 @@ proc semConv(c: PContext, n: PNode): PNode =
|
||||||
proc semCast(c: PContext, n: PNode): PNode =
|
proc semCast(c: PContext, n: PNode): PNode =
|
||||||
## Semantically analyze a casting ("cast[type](param)")
|
## Semantically analyze a casting ("cast[type](param)")
|
||||||
checkSonsLen(n, 2)
|
checkSonsLen(n, 2)
|
||||||
|
let targetType = semTypeNode(c, n.sons[0], nil)
|
||||||
|
let castedExpr = semExprWithType(c, n.sons[1])
|
||||||
|
if tfHasMeta in targetType.flags:
|
||||||
|
localError(n.sons[0].info, errCastToANonConcreteType, $targetType)
|
||||||
|
if not isCastable(targetType, castedExpr.typ):
|
||||||
|
localError(n.info, errExprCannotBeCastToX, $targetType)
|
||||||
result = newNodeI(nkCast, n.info)
|
result = newNodeI(nkCast, n.info)
|
||||||
result.typ = semTypeNode(c, n.sons[0], nil)
|
result.typ = targetType
|
||||||
addSon(result, copyTree(n.sons[0]))
|
addSon(result, copyTree(n.sons[0]))
|
||||||
addSon(result, semExprWithType(c, n.sons[1]))
|
addSon(result, castedExpr)
|
||||||
if not isCastable(result.typ, result.sons[1].typ):
|
|
||||||
localError(result.info, errExprCannotBeCastToX,
|
|
||||||
typeToString(result.typ))
|
|
||||||
|
|
||||||
proc semLowHigh(c: PContext, n: PNode, m: TMagic): PNode =
|
proc semLowHigh(c: PContext, n: PNode, m: TMagic): PNode =
|
||||||
const
|
const
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ type
|
||||||
preferName, preferDesc, preferExported, preferModuleInfo, preferGenericArg
|
preferName, preferDesc, preferExported, preferModuleInfo, preferGenericArg
|
||||||
|
|
||||||
proc typeToString*(typ: PType; prefer: TPreferedDesc = preferName): string
|
proc typeToString*(typ: PType; prefer: TPreferedDesc = preferName): string
|
||||||
|
template `$`*(typ: PType): string = typeToString(typ)
|
||||||
|
|
||||||
proc base*(t: PType): PType =
|
proc base*(t: PType): PType =
|
||||||
result = t.sons[0]
|
result = t.sons[0]
|
||||||
|
|
|
||||||
47
tests/errmsgs/tnon_concrete_cast.nim
Normal file
47
tests/errmsgs/tnon_concrete_cast.nim
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
discard """
|
||||||
|
errormsg: "cannot cast to a non concrete type: 'ptr SomeNumber'"
|
||||||
|
line: 36
|
||||||
|
"""
|
||||||
|
|
||||||
|
# https://github.com/nim-lang/Nim/issues/5428
|
||||||
|
|
||||||
|
type
|
||||||
|
MemFile = object
|
||||||
|
mem: pointer
|
||||||
|
|
||||||
|
proc memfileopen(filename: string, newFileSize: int): MemFile =
|
||||||
|
# just a memfile mock
|
||||||
|
return
|
||||||
|
|
||||||
|
type
|
||||||
|
MyData = object
|
||||||
|
member1: seq[int]
|
||||||
|
member2: int
|
||||||
|
|
||||||
|
type
|
||||||
|
MyReadWrite = object
|
||||||
|
memfile: MemFile
|
||||||
|
offset: int
|
||||||
|
|
||||||
|
# Here, SomeNumber is bound to a concrete type, and that's OK
|
||||||
|
proc write(rw: var MyReadWrite; value: SomeNumber): void =
|
||||||
|
(cast[ptr SomeNumber](cast[uint](rw.memfile.mem) + rw.offset.uint))[] = value
|
||||||
|
rw.offset += sizeof(SomeNumber)
|
||||||
|
|
||||||
|
# Here, we try to use SomeNumber without binding it to a type. This should
|
||||||
|
# produce an error message for now. It's also possible to relax the rules
|
||||||
|
# and allow for type-class based type inference in such situations.
|
||||||
|
proc write[T](rw: var MyReadWrite; value: seq[T]): void =
|
||||||
|
rw.write value.len
|
||||||
|
let dst = cast[ptr SomeNumber](cast[uint](rw.memfile.mem) + uint(rw.offset))
|
||||||
|
let src = cast[pointer](value[0].unsafeAddr)
|
||||||
|
let size = sizeof(T) * value.len
|
||||||
|
copyMem(dst, src, size)
|
||||||
|
rw.offset += size
|
||||||
|
|
||||||
|
proc saveBinFile(arg: var MyData, filename: string): void =
|
||||||
|
var rw: MyReadWrite
|
||||||
|
rw.memfile = memfileOpen(filename, newFileSize = rw.offset)
|
||||||
|
rw.offset = 0
|
||||||
|
rw.write arg.member1
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue