diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index 0fce7b417128..448f0178a723 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -10,7 +10,7 @@ # this module does the semantic checking of type declarations # included from sem.nim -import math +import std/math const errStringOrIdentNodeExpected = "string or ident node expected" @@ -1171,6 +1171,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode, else: discard proc semParamType(c: PContext, n: PNode, constraint: var PNode): PType = + ## Semchecks the type of parameters. if n.kind == nkCurlyExpr: result = semTypeNode(c, n[0], nil) constraint = semNodeKindConstraints(n, c.config, 1) @@ -1226,9 +1227,13 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode, if hasType: typ = semParamType(c, a[^2], constraint) # TODO: Disallow typed/untyped in procs in the compiler/stdlib - if kind == skProc and (typ.kind == tyTyped or typ.kind == tyUntyped): - if not isMagic(getCurrOwner(c)): - localError(c.config, a[^2].info, "'" & typ.sym.name.s & "' is only allowed in templates and macros or magic procs") + if kind in {skProc, skFunc}: + if (typ.kind == tyTyped or typ.kind == tyUntyped) and not isMagic(getCurrOwner(c)): + localError(c.config, a[^2].info, "'" & typ.sym.name.s & + "' is only allowed in templates and macros or magic procs") + elif typ.kind == tyLent: + localError(c.config, a[^2].info, "`lent` is only allowed in return type") + if hasDefault: def = a[^1] diff --git a/tests/lent/t16898.nim b/tests/lent/t16898.nim new file mode 100644 index 000000000000..9115f2d04cb3 --- /dev/null +++ b/tests/lent/t16898.nim @@ -0,0 +1,31 @@ +discard """ + errormsg: "lent is only allowed in return type" +""" + +# bug #16898 +type + Fp[N: static int, T] = object + big: array[N, T] + +type + QuadraticExt* = concept x + ## Quadratic Extension concept (like complex) + type BaseField = auto + x.c0 is BaseField + x.c1 is BaseField + +{.experimental:"views".} + +func prod(r: var QuadraticExt, a, b: lent QuadraticExt) = + discard + +type + Fp2[N: static int, T] = object + c0, c1: Fp[N, T] + +# This should be passed by reference, +# but concepts do not respect the 24 bytes rule +# or `byref` pragma. +var r, a, b: Fp2[6, uint64] + +prod(r, a, b) diff --git a/tests/lent/t17621.nim b/tests/lent/t17621.nim new file mode 100644 index 000000000000..005d7fe25b5b --- /dev/null +++ b/tests/lent/t17621.nim @@ -0,0 +1,15 @@ +discard """ + errormsg: "lent is only allowed in return type" +""" + +# bug #17621 +{.experimental: "views".} + +type Test = ref object + foo: int + +proc modify(self: lent Test) = + self.foo += 1 + +let test = Test(foo: 12) +modify(test)