diff options
Diffstat (limited to 'compiler/parampatterns.nim')
-rw-r--r-- | compiler/parampatterns.nim | 25 |
1 files changed, 16 insertions, 9 deletions
diff --git a/compiler/parampatterns.nim b/compiler/parampatterns.nim index 3f67005b9..978583c14 100644 --- a/compiler/parampatterns.nim +++ b/compiler/parampatterns.nim @@ -178,18 +178,21 @@ type arDiscriminant, # is a discriminant arStrange # it is a strange beast like 'typedesc[var T]' -proc isAssignable*(owner: PSym, n: PNode): TAssignableResult = +proc isAssignable*(owner: PSym, n: PNode; isUnsafeAddr=false): TAssignableResult = ## 'owner' can be nil! result = arNone case n.kind of nkSym: - # don't list 'skLet' here: - if n.sym.kind in {skVar, skResult, skTemp}: + let kinds = if isUnsafeAddr: {skVar, skResult, skTemp, skParam, skLet} + else: {skVar, skResult, skTemp} + if n.sym.kind in kinds: if owner != nil and owner.id == n.sym.owner.id and sfGlobal notin n.sym.flags: result = arLocalLValue else: result = arLValue + elif n.sym.kind == skParam and n.sym.typ.kind == tyVar: + result = arLValue elif n.sym.kind == skType: let t = n.sym.typ.skipTypes({tyTypeDesc}) if t.kind == tyVar: result = arStrange @@ -198,7 +201,7 @@ proc isAssignable*(owner: PSym, n: PNode): TAssignableResult = {tyVar, tyPtr, tyRef}: result = arLValue else: - result = isAssignable(owner, n.sons[0]) + result = isAssignable(owner, n.sons[0], isUnsafeAddr) if result != arNone and sfDiscriminant in n.sons[1].sym.flags: result = arDiscriminant of nkBracketExpr: @@ -206,23 +209,27 @@ proc isAssignable*(owner: PSym, n: PNode): TAssignableResult = {tyVar, tyPtr, tyRef}: result = arLValue else: - result = isAssignable(owner, n.sons[0]) + result = isAssignable(owner, n.sons[0], isUnsafeAddr) 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.sons[1]) + result = isAssignable(owner, n.sons[1], isUnsafeAddr) elif compareTypes(n.typ, n.sons[1].typ, dcEqIgnoreDistinct): # types that are equal modulo distinction preserve l-value: - result = isAssignable(owner, n.sons[1]) + result = isAssignable(owner, n.sons[1], isUnsafeAddr) of nkHiddenDeref, nkDerefExpr, nkHiddenAddr: result = arLValue of nkObjUpConv, nkObjDownConv, nkCheckedFieldExpr: - result = isAssignable(owner, n.sons[0]) + result = isAssignable(owner, n.sons[0], isUnsafeAddr) of nkCallKinds: # builtin slice keeps lvalue-ness: - if getMagic(n) == mSlice: result = isAssignable(owner, n.sons[1]) + if getMagic(n) in {mArrGet, mSlice}: + result = isAssignable(owner, n.sons[1], isUnsafeAddr) + of nkStmtList, nkStmtListExpr: + if n.typ != nil: + result = isAssignable(owner, n.lastSon, isUnsafeAddr) else: discard |