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

make var/pointer types not match if base type has to be converted #24130

Merged
merged 8 commits into from
Sep 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions compiler/sigmatch.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1017,9 +1017,21 @@ proc inferStaticsInRange(c: var TCandidate,
doInferStatic(lowerBound, getInt(upperBound) + 1 - lengthOrd(c.c.config, concrete))

template subtypeCheck() =
if result <= isSubrange and f.last.skipTypes(abstractInst).kind in {
tyRef, tyPtr, tyVar, tyLent, tyOwned}:
case result
of isIntConv:
result = isNone
of isSubrange:
discard # XXX should be isNone with preview define, warnings
of isConvertible:
if f.last.skipTypes(abstractInst).kind != tyOpenArray:
# exclude var openarray which compiler supports
result = isNone
of isSubtype:
if f.last.skipTypes(abstractInst).kind in {
tyRef, tyPtr, tyVar, tyLent, tyOwned}:
# compiler can't handle subtype conversions with pointer indirection
result = isNone
else: discard

proc isCovariantPtr(c: var TCandidate, f, a: PType): bool =
# this proc is always called for a pair of matching types
Expand Down
2 changes: 1 addition & 1 deletion testament/important_packages.nim
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ pkg "ssostrings"
pkg "stew"
pkg "stint", "nim c stint.nim"
pkg "strslice"
pkg "strunicode", "nim c -r --mm:refc src/strunicode.nim"
pkg "strunicode", "nimble uninstall -i -y normalize; nimble install -y normalize@#HEAD; nimble install --depsOnly -y; nim c -r --mm:refc src/strunicode.nim"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've asked @nitely to bump normalize's version, in hopes this hack won't be needed anymore.

pkg "supersnappy"
pkg "synthesis"
pkg "taskpools"
Expand Down
4 changes: 2 additions & 2 deletions tests/errmsgs/t22097.nim
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
16 changes: 16 additions & 0 deletions tests/int/twrongexplicitvarconv.nim
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
9 changes: 9 additions & 0 deletions tests/int/twrongvarconv.nim
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
145 changes: 145 additions & 0 deletions tests/overload/mvaruintconv.nim
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.}
Loading
Loading