-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
make
var
/pointer types not match if base type has to be converted (#…
…24130) split again from #24038, fixes status-im/nimbus-eth2#6554 (comment) `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.
- Loading branch information
Showing
7 changed files
with
394 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,9 @@ | ||
discard """ | ||
errormsg: "for a 'var' type a variable needs to be passed; but 'uint16(x)' is immutable" | ||
errormsg: "type mismatch: got <uint8>" | ||
""" | ||
|
||
proc toUInt16(x: var uint16) = | ||
discard | ||
|
||
var x = uint8(1) | ||
toUInt16 x | ||
toUInt16 x |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
discard """ | ||
action: reject | ||
nimout: ''' | ||
but expression 'int(a)' is immutable, not 'var' | ||
''' | ||
""" | ||
|
||
proc `++`(n: var int) = | ||
n += 1 | ||
|
||
var a: int32 = 15 | ||
|
||
++int(a) #[tt.Error | ||
^ type mismatch: got <int>]# | ||
|
||
echo a |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
proc `++`(n: var int) = | ||
n += 1 | ||
|
||
var a: int32 = 15 | ||
|
||
++a #[tt.Error | ||
^ type mismatch: got <int32>]# | ||
|
||
echo a |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
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.} |
Oops, something went wrong.