mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-29 17:34:43 +00:00
split again from #24038, fixes
https://github.com/status-im/nimbus-eth2/pull/6554#issuecomment-2354977102
`var`/pointer types are no longer implicitly convertible to each other
if their element types either:
* require an int conversion or another conversion operation as long as
it's not to `openarray`,
* are subtypes with pointer indirection,
Previously any conversion below a subrange match would match if the
element type wasn't a pointer type, then it would error later in
`analyseIfAddressTaken`.
Different from #24038 in that the preview define that made subrange
matches also fail to match is removed for a simpler diff so that it can
be backported.
(cherry picked from commit 1660ddf98a)
146 lines
3.9 KiB
Nim
146 lines
3.9 KiB
Nim
import
|
|
std/[macros, tables, hashes]
|
|
|
|
export
|
|
macros
|
|
|
|
type
|
|
FieldDescription* = object
|
|
name*: NimNode
|
|
isPublic*: bool
|
|
isDiscriminator*: bool
|
|
typ*: NimNode
|
|
pragmas*: NimNode
|
|
caseField*: NimNode
|
|
caseBranch*: NimNode
|
|
|
|
{.push raises: [].}
|
|
|
|
func isTuple*(t: NimNode): bool =
|
|
t.kind == nnkBracketExpr and t[0].kind == nnkSym and eqIdent(t[0], "tuple")
|
|
|
|
macro isTuple*(T: type): untyped =
|
|
newLit(isTuple(getType(T)[1]))
|
|
|
|
proc collectFieldsFromRecList(result: var seq[FieldDescription],
|
|
n: NimNode,
|
|
parentCaseField: NimNode = nil,
|
|
parentCaseBranch: NimNode = nil,
|
|
isDiscriminator = false) =
|
|
case n.kind
|
|
of nnkRecList:
|
|
for entry in n:
|
|
collectFieldsFromRecList result, entry,
|
|
parentCaseField, parentCaseBranch
|
|
of nnkRecWhen:
|
|
for branch in n:
|
|
case branch.kind:
|
|
of nnkElifBranch:
|
|
collectFieldsFromRecList result, branch[1],
|
|
parentCaseField, parentCaseBranch
|
|
of nnkElse:
|
|
collectFieldsFromRecList result, branch[0],
|
|
parentCaseField, parentCaseBranch
|
|
else:
|
|
doAssert false
|
|
|
|
of nnkRecCase:
|
|
collectFieldsFromRecList result, n[0],
|
|
parentCaseField,
|
|
parentCaseBranch,
|
|
isDiscriminator = true
|
|
|
|
for i in 1 ..< n.len:
|
|
let branch = n[i]
|
|
case branch.kind
|
|
of nnkOfBranch:
|
|
collectFieldsFromRecList result, branch[^1], n[0], branch
|
|
of nnkElse:
|
|
collectFieldsFromRecList result, branch[0], n[0], branch
|
|
else:
|
|
doAssert false
|
|
|
|
of nnkIdentDefs:
|
|
let fieldType = n[^2]
|
|
for i in 0 ..< n.len - 2:
|
|
var field: FieldDescription
|
|
field.name = n[i]
|
|
field.typ = fieldType
|
|
field.caseField = parentCaseField
|
|
field.caseBranch = parentCaseBranch
|
|
field.isDiscriminator = isDiscriminator
|
|
|
|
if field.name.kind == nnkPragmaExpr:
|
|
field.pragmas = field.name[1]
|
|
field.name = field.name[0]
|
|
|
|
if field.name.kind == nnkPostfix:
|
|
field.isPublic = true
|
|
field.name = field.name[1]
|
|
|
|
result.add field
|
|
|
|
of nnkSym:
|
|
result.add FieldDescription(
|
|
name: n,
|
|
typ: getType(n),
|
|
caseField: parentCaseField,
|
|
caseBranch: parentCaseBranch,
|
|
isDiscriminator: isDiscriminator)
|
|
|
|
of nnkNilLit, nnkDiscardStmt, nnkCommentStmt, nnkEmpty:
|
|
discard
|
|
|
|
else:
|
|
doAssert false, "Unexpected nodes in recordFields:\n" & n.treeRepr
|
|
|
|
proc collectFieldsInHierarchy(result: var seq[FieldDescription],
|
|
objectType: NimNode) =
|
|
var objectType = objectType
|
|
|
|
objectType.expectKind {nnkObjectTy, nnkRefTy}
|
|
|
|
if objectType.kind == nnkRefTy:
|
|
objectType = objectType[0]
|
|
|
|
objectType.expectKind nnkObjectTy
|
|
|
|
var baseType = objectType[1]
|
|
if baseType.kind != nnkEmpty:
|
|
baseType.expectKind nnkOfInherit
|
|
baseType = baseType[0]
|
|
baseType.expectKind nnkSym
|
|
baseType = getImpl(baseType)
|
|
baseType.expectKind nnkTypeDef
|
|
baseType = baseType[2]
|
|
baseType.expectKind {nnkObjectTy, nnkRefTy}
|
|
collectFieldsInHierarchy result, baseType
|
|
|
|
let recList = objectType[2]
|
|
collectFieldsFromRecList result, recList
|
|
|
|
proc recordFields*(typeImpl: NimNode): seq[FieldDescription] =
|
|
if typeImpl.isTuple:
|
|
for i in 1 ..< typeImpl.len:
|
|
result.add FieldDescription(typ: typeImpl[i], name: ident("Field" & $(i - 1)))
|
|
return
|
|
|
|
let objectType = case typeImpl.kind
|
|
of nnkObjectTy: typeImpl
|
|
of nnkTypeDef: typeImpl[2]
|
|
else:
|
|
macros.error("object type expected", typeImpl)
|
|
return
|
|
|
|
collectFieldsInHierarchy(result, objectType)
|
|
|
|
macro field*(obj: typed, fieldName: static string): untyped =
|
|
newDotExpr(obj, ident fieldName)
|
|
|
|
proc skipPragma*(n: NimNode): NimNode =
|
|
if n.kind == nnkPragmaExpr: n[0]
|
|
else: n
|
|
|
|
|
|
{.pop.}
|