diff options
author | flywind <xzsflywind@gmail.com> | 2022-03-01 14:46:08 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-03-01 07:46:08 +0100 |
commit | d6d36093b18dfa1e2b8b6325016f1def015250b4 (patch) | |
tree | a5b4acd79bcaf5c6851e8bf3d6714d76d10ecd4c | |
parent | 207237cec229171eafbd3357dcf128bdd270332a (diff) | |
download | Nim-d6d36093b18dfa1e2b8b6325016f1def015250b4.tar.gz |
apply changes from #18017 and some fixes (#19571)
* implements https://github.com/nim-lang/RFCs/issues/369 * deprecate unsafeAddr; extend addr addr is now available for all addressable locations, unsafeAddr is deprecated and become an alias for addr * follow @Vindaar's advice * change the signature of addr * unsafeAddr => addr (stdlib) * Update changelog.md * unsafeAddr => addr (tests) * Revert "unsafeAddr => addr (stdlib)" This reverts commit ab83c99c507048a8396e636bf22d55fdd84d7d1c. * doc changes; thanks to @konsumlamm Co-authored-by: konsumlamm <44230978+konsumlamm@users.noreply.github.com> * merge * remove * fix bug Co-authored-by: Araq <rumpf_a@web.de> Co-authored-by: konsumlamm <44230978+konsumlamm@users.noreply.github.com>
-rw-r--r-- | compiler/parampatterns.nim | 60 | ||||
-rw-r--r-- | compiler/semexprs.nim | 14 | ||||
-rw-r--r-- | compiler/semmagic.nim | 6 | ||||
-rw-r--r-- | lib/system.nim | 3 |
4 files changed, 42 insertions, 41 deletions
diff --git a/compiler/parampatterns.nim b/compiler/parampatterns.nim index bfbc72675..cceb236ae 100644 --- a/compiler/parampatterns.nim +++ b/compiler/parampatterns.nim @@ -179,6 +179,7 @@ type arLocalLValue, # is an l-value, but local var; must not escape # its stack frame! arDiscriminant, # is a discriminant + arAddressableConst, # an addressable const arLentValue, # lent value arStrange # it is a strange beast like 'typedesc[var T]' @@ -212,7 +213,7 @@ proc exprRoot*(n: PNode): PSym = else: break -proc isAssignable*(owner: PSym, n: PNode; isUnsafeAddr=false): TAssignableResult = +proc isAssignable*(owner: PSym, n: PNode): TAssignableResult = ## 'owner' can be nil! result = arNone case n.kind @@ -220,20 +221,20 @@ proc isAssignable*(owner: PSym, n: PNode; isUnsafeAddr=false): TAssignableResult if n.typ != nil and n.typ.kind in {tyVar}: result = arLValue of nkSym: - let kinds = if isUnsafeAddr: {skVar, skResult, skTemp, skParam, skLet, skForVar} - else: {skVar, skResult, skTemp} - if n.sym.kind == skParam and n.sym.typ.kind in {tyVar, tySink}: - result = arLValue - elif isUnsafeAddr and n.sym.kind == skParam: - result = arLValue - elif isUnsafeAddr and n.sym.kind == skConst and dontInlineConstant(n, n.sym.ast): - result = arLValue + const kinds = {skVar, skResult, skTemp, skParam, skLet, skForVar} + if n.sym.kind == skParam: + result = if n.sym.typ.kind in {tyVar, tySink}: arLValue else: arAddressableConst + elif n.sym.kind == skConst and dontInlineConstant(n, n.sym.ast): + result = arAddressableConst elif n.sym.kind in kinds: - if owner != nil and owner == n.sym.owner and - sfGlobal notin n.sym.flags: - result = arLocalLValue + if n.sym.kind in {skParam, skLet, skForVar}: + result = arAddressableConst else: - result = arLValue + if owner != nil and owner == n.sym.owner and + sfGlobal notin n.sym.flags: + result = arLocalLValue + else: + result = arLValue elif n.sym.kind == skType: let t = n.sym.typ.skipTypes({tyTypeDesc}) if t.kind in {tyVar}: result = arStrange @@ -241,10 +242,10 @@ proc isAssignable*(owner: PSym, n: PNode; isUnsafeAddr=false): TAssignableResult let t = skipTypes(n[0].typ, abstractInst-{tyTypeDesc}) if t.kind in {tyVar, tySink, tyPtr, tyRef}: result = arLValue - elif isUnsafeAddr and t.kind == tyLent: - result = arLValue + elif t.kind == tyLent: + result = arAddressableConst else: - result = isAssignable(owner, n[0], isUnsafeAddr) + result = isAssignable(owner, n[0]) if result != arNone and n[1].kind == nkSym and sfDiscriminant in n[1].sym.flags: result = arDiscriminant @@ -252,23 +253,23 @@ proc isAssignable*(owner: PSym, n: PNode; isUnsafeAddr=false): TAssignableResult let t = skipTypes(n[0].typ, abstractInst-{tyTypeDesc}) if t.kind in {tyVar, tySink, tyPtr, tyRef}: result = arLValue - elif isUnsafeAddr and t.kind == tyLent: - result = arLValue + elif t.kind == tyLent: + result = arAddressableConst else: - result = isAssignable(owner, n[0], isUnsafeAddr) + result = isAssignable(owner, n[0]) of nkHiddenStdConv, nkHiddenSubConv, nkConv: # Object and tuple conversions are still addressable, so we skip them # XXX why is 'tyOpenArray' allowed here? if skipTypes(n.typ, abstractPtrs-{tyTypeDesc}).kind in {tyOpenArray, tyTuple, tyObject}: - result = isAssignable(owner, n[1], isUnsafeAddr) + result = isAssignable(owner, n[1]) elif compareTypes(n.typ, n[1].typ, dcEqIgnoreDistinct): # types that are equal modulo distinction preserve l-value: - result = isAssignable(owner, n[1], isUnsafeAddr) + result = isAssignable(owner, n[1]) of nkHiddenDeref: let n0 = n[0] if n0.typ.kind == tyLent: - if isUnsafeAddr or (n0.kind == nkSym and n0.sym.kind == skResult): + if n0.kind == nkSym and n0.sym.kind == skResult: result = arLValue else: result = arLentValue @@ -277,18 +278,19 @@ proc isAssignable*(owner: PSym, n: PNode; isUnsafeAddr=false): TAssignableResult of nkDerefExpr, nkHiddenAddr: result = arLValue of nkObjUpConv, nkObjDownConv, nkCheckedFieldExpr: - result = isAssignable(owner, n[0], isUnsafeAddr) + result = isAssignable(owner, n[0]) of nkCallKinds: # builtin slice keeps lvalue-ness: if getMagic(n) in {mArrGet, mSlice}: - result = isAssignable(owner, n[1], isUnsafeAddr) - elif n.typ != nil and n.typ.kind in {tyVar}: - result = arLValue - elif isUnsafeAddr and n.typ != nil and n.typ.kind == tyLent: - result = arLValue + result = isAssignable(owner, n[1]) + elif n.typ != nil: + case n.typ.kind + of tyVar: result = arLValue + of tyLent: result = arLentValue + else: discard of nkStmtList, nkStmtListExpr: if n.typ != nil: - result = isAssignable(owner, n.lastSon, isUnsafeAddr) + result = isAssignable(owner, n.lastSon) of nkVarTy: # XXX: The fact that this is here is a bit of a hack. # The goal is to allow the use of checks such as "foo(var T)" diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index c593efe55..5f3d065b6 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -650,8 +650,8 @@ proc fixAbstractType(c: PContext, n: PNode) = changeType(c, it[1], s, check=true) n[i] = it[1] -proc isAssignable(c: PContext, n: PNode; isUnsafeAddr=false): TAssignableResult = - result = parampatterns.isAssignable(c.p.owner, n, isUnsafeAddr) +proc isAssignable(c: PContext, n: PNode): TAssignableResult = + result = parampatterns.isAssignable(c.p.owner, n) proc isUnresolvedSym(s: PSym): bool = result = s.kind == skGenericParam @@ -1658,9 +1658,11 @@ proc takeImplicitAddr(c: PContext, n: PNode; isLent: bool): PNode = # `proc fun(a: var int): var int = a` discard else: discard - let valid = isAssignable(c, n, isLent) + let valid = isAssignable(c, n) if valid != arLValue: - if valid == arLocalLValue: + if valid in {arAddressableConst, arLentValue} and isLent: + discard "ok" + elif valid == arLocalLValue: localError(c.config, n.info, errXStackEscape % renderTree(n, {renderNoComments})) else: localError(c.config, n.info, errExprHasNoAddress) @@ -1784,7 +1786,7 @@ proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode = if le == nil: localError(c.config, a.info, "expression has no type") elif (skipTypes(le, {tyGenericInst, tyAlias, tySink}).kind notin {tyVar} and - isAssignable(c, a) in {arNone, arLentValue}) or ( + isAssignable(c, a) in {arNone, arLentValue, arAddressableConst}) or ( skipTypes(le, abstractVar).kind in {tyOpenArray, tyVarargs} and views notin c.features): # Direct assignment to a discriminant is allowed! localError(c.config, a.info, errXCannotBeAssignedTo % @@ -2267,7 +2269,7 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode = markUsed(c, n.info, s) checkSonsLen(n, 2, c.config) result[0] = newSymNode(s, n[0].info) - result[1] = semAddrArg(c, n[1], s.name.s == "unsafeAddr") + result[1] = semAddrArg(c, n[1]) result.typ = makePtrType(c, result[1].typ) of mTypeOf: markUsed(c, n.info, s) diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim index c7fc75620..ed1826fd4 100644 --- a/compiler/semmagic.nim +++ b/compiler/semmagic.nim @@ -10,11 +10,11 @@ # This include file implements the semantic checking for magics. # included from sem.nim -proc semAddrArg(c: PContext; n: PNode; isUnsafeAddr = false): PNode = +proc semAddrArg(c: PContext; n: PNode): PNode = let x = semExprWithType(c, n) if x.kind == nkSym: x.sym.flags.incl(sfAddrTaken) - if isAssignable(c, x, true) notin {arLValue, arLocalLValue}: + if isAssignable(c, x) notin {arLValue, arLocalLValue, arAddressableConst, arLentValue}: localError(c.config, n.info, errExprHasNoAddress) result = x @@ -466,7 +466,7 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode, of mAddr: checkSonsLen(n, 2, c.config) result = n - result[1] = semAddrArg(c, n[1], n[0].sym.name.s == "unsafeAddr") + result[1] = semAddrArg(c, n[1]) result.typ = makePtrType(c, result[1].typ) of mTypeOf: result = semTypeOf(c, n) diff --git a/lib/system.nim b/lib/system.nim index 56a6e2887..572768de2 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -202,9 +202,6 @@ proc `addr`*[T](x: T): ptr T {.magic: "Addr", noSideEffect.} = ## ## Cannot be overloaded. ## - ## See also: - ## * `unsafeAddr <#unsafeAddr,T>`_ - ## ## .. code-block:: Nim ## var ## buf: seq[char] = @['a','b','c'] |