basic 'lent T' test works
This commit is contained in:
parent
7adf3bf476
commit
c99f952dfb
4 changed files with 36 additions and 16 deletions
|
|
@ -414,7 +414,7 @@ proc genDeepCopy(p: BProc; dest, src: TLoc) =
|
||||||
else:
|
else:
|
||||||
linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src))
|
linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src))
|
||||||
of tyPointer, tyChar, tyBool, tyEnum, tyCString,
|
of tyPointer, tyChar, tyBool, tyEnum, tyCString,
|
||||||
tyInt..tyUInt64, tyRange, tyVar:
|
tyInt..tyUInt64, tyRange, tyVar, tyLent:
|
||||||
linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src))
|
linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src))
|
||||||
else: internalError("genDeepCopy: " & $ty.kind)
|
else: internalError("genDeepCopy: " & $ty.kind)
|
||||||
|
|
||||||
|
|
@ -699,7 +699,7 @@ proc genDeref(p: BProc, e: PNode, d: var TLoc; enforceDeref=false) =
|
||||||
case typ.kind
|
case typ.kind
|
||||||
of tyRef:
|
of tyRef:
|
||||||
d.storage = OnHeap
|
d.storage = OnHeap
|
||||||
of tyVar:
|
of tyVar, tyLent:
|
||||||
d.storage = OnUnknown
|
d.storage = OnUnknown
|
||||||
if tfVarIsPtr notin typ.flags and p.module.compileToCpp and
|
if tfVarIsPtr notin typ.flags and p.module.compileToCpp and
|
||||||
e.kind == nkHiddenDeref:
|
e.kind == nkHiddenDeref:
|
||||||
|
|
@ -1359,9 +1359,9 @@ proc genOf(p: BProc, x: PNode, typ: PType, d: var TLoc) =
|
||||||
var r = rdLoc(a)
|
var r = rdLoc(a)
|
||||||
var nilCheck: Rope = nil
|
var nilCheck: Rope = nil
|
||||||
var t = skipTypes(a.t, abstractInst)
|
var t = skipTypes(a.t, abstractInst)
|
||||||
while t.kind in {tyVar, tyPtr, tyRef}:
|
while t.kind in {tyVar, tyLent, tyPtr, tyRef}:
|
||||||
if t.kind != tyVar: nilCheck = r
|
if t.kind notin {tyVar, tyLent}: nilCheck = r
|
||||||
if t.kind != tyVar or not p.module.compileToCpp:
|
if t.kind notin {tyVar, tyLent} or not p.module.compileToCpp:
|
||||||
r = rfmt(nil, "(*$1)", r)
|
r = rfmt(nil, "(*$1)", r)
|
||||||
t = skipTypes(t.lastSon, typedescInst)
|
t = skipTypes(t.lastSon, typedescInst)
|
||||||
if not p.module.compileToCpp:
|
if not p.module.compileToCpp:
|
||||||
|
|
@ -1723,7 +1723,7 @@ proc genRangeChck(p: BProc, n: PNode, d: var TLoc, magic: string) =
|
||||||
rope(magic)]), a.storage)
|
rope(magic)]), a.storage)
|
||||||
|
|
||||||
proc genConv(p: BProc, e: PNode, d: var TLoc) =
|
proc genConv(p: BProc, e: PNode, d: var TLoc) =
|
||||||
let destType = e.typ.skipTypes({tyVar, tyGenericInst, tyAlias, tySink})
|
let destType = e.typ.skipTypes({tyVar, tyLent, tyGenericInst, tyAlias, tySink})
|
||||||
if sameBackendType(destType, e.sons[1].typ):
|
if sameBackendType(destType, e.sons[1].typ):
|
||||||
expr(p, e.sons[1], d)
|
expr(p, e.sons[1], d)
|
||||||
else:
|
else:
|
||||||
|
|
@ -1799,7 +1799,7 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||||
"$# = #subInt64($#, $#);$n"]
|
"$# = #subInt64($#, $#);$n"]
|
||||||
const fun: array[mInc..mDec, string] = ["$# = #addInt($#, $#);$n",
|
const fun: array[mInc..mDec, string] = ["$# = #addInt($#, $#);$n",
|
||||||
"$# = #subInt($#, $#);$n"]
|
"$# = #subInt($#, $#);$n"]
|
||||||
let underlying = skipTypes(e.sons[1].typ, {tyGenericInst, tyAlias, tySink, tyVar, tyRange})
|
let underlying = skipTypes(e.sons[1].typ, {tyGenericInst, tyAlias, tySink, tyVar, tyLent, tyRange})
|
||||||
if optOverflowCheck notin p.options or underlying.kind in {tyUInt..tyUInt64}:
|
if optOverflowCheck notin p.options or underlying.kind in {tyUInt..tyUInt64}:
|
||||||
binaryStmt(p, e, d, opr[op])
|
binaryStmt(p, e, d, opr[op])
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -222,7 +222,10 @@ proc isAssignable*(owner: PSym, n: PNode; isUnsafeAddr=false): TAssignableResult
|
||||||
elif compareTypes(n.typ, n.sons[1].typ, dcEqIgnoreDistinct):
|
elif compareTypes(n.typ, n.sons[1].typ, dcEqIgnoreDistinct):
|
||||||
# types that are equal modulo distinction preserve l-value:
|
# types that are equal modulo distinction preserve l-value:
|
||||||
result = isAssignable(owner, n.sons[1], isUnsafeAddr)
|
result = isAssignable(owner, n.sons[1], isUnsafeAddr)
|
||||||
of nkHiddenDeref, nkDerefExpr, nkHiddenAddr:
|
of nkHiddenDeref:
|
||||||
|
if n[0].typ.kind == tyLent: result = arDiscriminant
|
||||||
|
else: result = arLValue
|
||||||
|
of nkDerefExpr, nkHiddenAddr:
|
||||||
result = arLValue
|
result = arLValue
|
||||||
of nkObjUpConv, nkObjDownConv, nkCheckedFieldExpr:
|
of nkObjUpConv, nkObjDownConv, nkCheckedFieldExpr:
|
||||||
result = isAssignable(owner, n.sons[0], isUnsafeAddr)
|
result = isAssignable(owner, n.sons[0], isUnsafeAddr)
|
||||||
|
|
|
||||||
|
|
@ -951,7 +951,7 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode =
|
||||||
else:
|
else:
|
||||||
result = semMacroExpr(c, n, n, s, flags)
|
result = semMacroExpr(c, n, n, s, flags)
|
||||||
of skTemplate:
|
of skTemplate:
|
||||||
if efNoEvaluateGeneric in flags and s.ast[genericParamsPos].len > 0 or
|
if efNoEvaluateGeneric in flags and s.ast[genericParamsPos].len > 0 or
|
||||||
sfCustomPragma in sym.flags:
|
sfCustomPragma in sym.flags:
|
||||||
markUsed(n.info, s, c.graph.usageSym)
|
markUsed(n.info, s, c.graph.usageSym)
|
||||||
styleCheckUse(n.info, s)
|
styleCheckUse(n.info, s)
|
||||||
|
|
@ -1296,7 +1296,7 @@ proc propertyWriteAccess(c: PContext, n, nOrig, a: PNode): PNode =
|
||||||
#fixAbstractType(c, result)
|
#fixAbstractType(c, result)
|
||||||
#analyseIfAddressTakenInCall(c, result)
|
#analyseIfAddressTakenInCall(c, result)
|
||||||
|
|
||||||
proc takeImplicitAddr(c: PContext, n: PNode): PNode =
|
proc takeImplicitAddr(c: PContext, n: PNode; isLent: bool): PNode =
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkHiddenAddr, nkAddr: return n
|
of nkHiddenAddr, nkAddr: return n
|
||||||
of nkHiddenDeref, nkDerefExpr: return n.sons[0]
|
of nkHiddenDeref, nkDerefExpr: return n.sons[0]
|
||||||
|
|
@ -1307,7 +1307,7 @@ proc takeImplicitAddr(c: PContext, n: PNode): PNode =
|
||||||
if valid != arLValue:
|
if valid != arLValue:
|
||||||
if valid == arLocalLValue:
|
if valid == arLocalLValue:
|
||||||
localError(n.info, errXStackEscape, renderTree(n, {renderNoComments}))
|
localError(n.info, errXStackEscape, renderTree(n, {renderNoComments}))
|
||||||
else:
|
elif not isLent:
|
||||||
localError(n.info, errExprHasNoAddress)
|
localError(n.info, errExprHasNoAddress)
|
||||||
result = newNodeIT(nkHiddenAddr, n.info, makePtrType(c, n.typ))
|
result = newNodeIT(nkHiddenAddr, n.info, makePtrType(c, n.typ))
|
||||||
result.add(n)
|
result.add(n)
|
||||||
|
|
@ -1315,9 +1315,9 @@ proc takeImplicitAddr(c: PContext, n: PNode): PNode =
|
||||||
proc asgnToResultVar(c: PContext, n, le, ri: PNode) {.inline.} =
|
proc asgnToResultVar(c: PContext, n, le, ri: PNode) {.inline.} =
|
||||||
if le.kind == nkHiddenDeref:
|
if le.kind == nkHiddenDeref:
|
||||||
var x = le.sons[0]
|
var x = le.sons[0]
|
||||||
if x.typ.kind == tyVar and x.kind == nkSym and x.sym.kind == skResult:
|
if x.typ.kind in {tyVar, tyLent} and x.kind == nkSym and x.sym.kind == skResult:
|
||||||
n.sons[0] = x # 'result[]' --> 'result'
|
n.sons[0] = x # 'result[]' --> 'result'
|
||||||
n.sons[1] = takeImplicitAddr(c, ri)
|
n.sons[1] = takeImplicitAddr(c, ri, x.typ.kind == tyLent)
|
||||||
x.typ.flags.incl tfVarIsPtr
|
x.typ.flags.incl tfVarIsPtr
|
||||||
#echo x.info, " setting it for this type ", typeToString(x.typ), " ", n.info
|
#echo x.info, " setting it for this type ", typeToString(x.typ), " ", n.info
|
||||||
|
|
||||||
|
|
@ -1473,18 +1473,18 @@ proc semYieldVarResult(c: PContext, n: PNode, restype: PType) =
|
||||||
if t.kind == tyVar: t.flags.incl tfVarIsPtr # bugfix for #4048, #4910, #6892
|
if t.kind == tyVar: t.flags.incl tfVarIsPtr # bugfix for #4048, #4910, #6892
|
||||||
if n.sons[0].kind in {nkHiddenStdConv, nkHiddenSubConv}:
|
if n.sons[0].kind in {nkHiddenStdConv, nkHiddenSubConv}:
|
||||||
n.sons[0] = n.sons[0].sons[1]
|
n.sons[0] = n.sons[0].sons[1]
|
||||||
n.sons[0] = takeImplicitAddr(c, n.sons[0])
|
n.sons[0] = takeImplicitAddr(c, n.sons[0], t.kind == tyLent)
|
||||||
of tyTuple:
|
of tyTuple:
|
||||||
for i in 0..<t.sonsLen:
|
for i in 0..<t.sonsLen:
|
||||||
var e = skipTypes(t.sons[i], {tyGenericInst, tyAlias, tySink})
|
var e = skipTypes(t.sons[i], {tyGenericInst, tyAlias, tySink})
|
||||||
if e.kind in {tyVar, tyLent}:
|
if e.kind in {tyVar, tyLent}:
|
||||||
if e.kind == tyVar: e.flags.incl tfVarIsPtr # bugfix for #4048, #4910, #6892
|
if e.kind == tyVar: e.flags.incl tfVarIsPtr # bugfix for #4048, #4910, #6892
|
||||||
if n.sons[0].kind == nkPar:
|
if n.sons[0].kind == nkPar:
|
||||||
n.sons[0].sons[i] = takeImplicitAddr(c, n.sons[0].sons[i])
|
n.sons[0].sons[i] = takeImplicitAddr(c, n.sons[0].sons[i], e.kind == tyLent)
|
||||||
elif n.sons[0].kind in {nkHiddenStdConv, nkHiddenSubConv} and
|
elif n.sons[0].kind in {nkHiddenStdConv, nkHiddenSubConv} and
|
||||||
n.sons[0].sons[1].kind == nkPar:
|
n.sons[0].sons[1].kind == nkPar:
|
||||||
var a = n.sons[0].sons[1]
|
var a = n.sons[0].sons[1]
|
||||||
a.sons[i] = takeImplicitAddr(c, a.sons[i])
|
a.sons[i] = takeImplicitAddr(c, a.sons[i], false)
|
||||||
else:
|
else:
|
||||||
localError(n.sons[0].info, errXExpected, "tuple constructor")
|
localError(n.sons[0].info, errXExpected, "tuple constructor")
|
||||||
else: discard
|
else: discard
|
||||||
|
|
|
||||||
17
tests/lent/tbasic_lent_check.nim
Normal file
17
tests/lent/tbasic_lent_check.nim
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
discard """
|
||||||
|
cmd: "nim c --newRuntime $file"
|
||||||
|
output: "1"
|
||||||
|
"""
|
||||||
|
|
||||||
|
proc viewInto(a: array[4, string]): lent string =
|
||||||
|
result = a[0]
|
||||||
|
|
||||||
|
proc passToVar(x: var string) =
|
||||||
|
discard
|
||||||
|
|
||||||
|
proc main =
|
||||||
|
let x = ["1", "2", "3", "4"]
|
||||||
|
echo viewInto(x)
|
||||||
|
doAssert(not compiles(passToVar(viewInto(x))))
|
||||||
|
|
||||||
|
main()
|
||||||
Loading…
Add table
Add a link
Reference in a new issue