From 7ccc7d7e93e0fdfcf72aed239cf8b5d4c04e7de5 Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Sat, 30 May 2020 15:32:31 +0200 Subject: [PATCH] fixes #14498 [backport:1.2] (#14503) --- compiler/parampatterns.nim | 12 +++++++++--- compiler/semexprs.nim | 2 +- tests/lent/tnot_allowed_lent.nim | 4 ++-- tests/lent/tnot_allowed_lent2.nim | 14 ++++++++++++++ 4 files changed, 26 insertions(+), 6 deletions(-) create mode 100644 tests/lent/tnot_allowed_lent2.nim diff --git a/compiler/parampatterns.nim b/compiler/parampatterns.nim index 486f8ff544..33881a7b30 100644 --- a/compiler/parampatterns.nim +++ b/compiler/parampatterns.nim @@ -176,6 +176,7 @@ type arLocalLValue, # is an l-value, but local var; must not escape # its stack frame! arDiscriminant, # is a discriminant + arLentValue, # lent value arStrange # it is a strange beast like 'typedesc[var T]' proc exprRoot*(n: PNode): PSym = @@ -260,9 +261,14 @@ proc isAssignable*(owner: PSym, n: PNode; isUnsafeAddr=false): TAssignableResult # types that are equal modulo distinction preserve l-value: result = isAssignable(owner, n[1], isUnsafeAddr) of nkHiddenDeref: - if isUnsafeAddr and n[0].typ.kind == tyLent: result = arLValue - elif n[0].typ.kind == tyLent: result = arDiscriminant - else: result = arLValue + let n0 = n[0] + if n0.typ.kind == tyLent: + if isUnsafeAddr or (n0.kind == nkSym and n0.sym.kind == skResult): + result = arLValue + else: + result = arLentValue + else: + result = arLValue of nkDerefExpr, nkHiddenAddr: result = arLValue of nkObjUpConv, nkObjDownConv, nkCheckedFieldExpr: diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index e29101385e..c5b864d1fb 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -1712,7 +1712,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 != tyVar and - isAssignable(c, a) == arNone) or + isAssignable(c, a) in {arNone, arLentValue}) or skipTypes(le, abstractVar).kind in {tyOpenArray, tyVarargs}: # Direct assignment to a discriminant is allowed! localError(c.config, a.info, errXCannotBeAssignedTo % diff --git a/tests/lent/tnot_allowed_lent.nim b/tests/lent/tnot_allowed_lent.nim index b144ce36b8..2de18d4afa 100644 --- a/tests/lent/tnot_allowed_lent.nim +++ b/tests/lent/tnot_allowed_lent.nim @@ -7,10 +7,10 @@ type proc mytest1(s: MyObject, i: int): lent string = ## works fine - if i < s.x.len - 1 and s.x[i] != "": + if i < s.x.len - 1 and s.x[i] != "": result = s.x[i] else: raise newException(KeyError, "err1") - + proc mytest2(s: MyObject, i: int): lent string = ## reject due to if expr if i < s.x.len - 1 and s.x[i] != "": s.x[i] diff --git a/tests/lent/tnot_allowed_lent2.nim b/tests/lent/tnot_allowed_lent2.nim new file mode 100644 index 0000000000..e61cae9227 --- /dev/null +++ b/tests/lent/tnot_allowed_lent2.nim @@ -0,0 +1,14 @@ +discard """ + errmsg: "'x' cannot be assigned to" + line: 10 +""" + +proc bug14498 = + var a = @['a', 'b', 'c', 'd', 'e', 'f'] + + for x in a: + x = 'c' + + echo a + +bug14498()