From 7a82c5920c46fa7a3393ebdecc54716cb1015366 Mon Sep 17 00:00:00 2001 From: ringabout <43030857+ringabout@users.noreply.github.com> Date: Mon, 30 Mar 2026 21:09:11 +0800 Subject: [PATCH] fixes #25677; fixes #25678; typeAllowedAux to improve flag handling (#25684) fixes #25677; fixes #25678 This pull request introduces both a bug fix to the type checking logic in the compiler and new test cases for lent types involving procedures and tables. The most significant change is a refinement in how type flags are handled for procedure and function types in the compiler, which improves correctness in type allowance checks. Additionally, the test suite is expanded to cover more complex scenarios with lent types and table lookups. **Compiler improvements:** * Refined the handling of type flags in `typeAllowedAux` for procedure and function types by introducing `innerFlags`, which removes certain flags (`taObjField`, `taTupField`, `taIsOpenArray`) before recursing into parameter and return types. This ensures more accurate type checking and prevents inappropriate flag propagation. **Testing enhancements:** * Added new test blocks in `tests/lent/tlents.nim` to cover lent procedure types stored in objects and used as table values, including a function that retrieves such procedures from a table by key. * Introduced a test case for an object containing a lent procedure field, ensuring correct behavior when accessing and using these fields. --- compiler/typeallowed.nim | 7 ++++--- tests/lent/tlents.nim | 22 ++++++++++++++++++++++ 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/compiler/typeallowed.nim b/compiler/typeallowed.nim index 80b532371c..05584341b6 100644 --- a/compiler/typeallowed.nim +++ b/compiler/typeallowed.nim @@ -99,12 +99,13 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind, if isInlineIterator(typ) and kind in {skVar, skLet, skConst, skParam, skResult}: # only closure iterators may be assigned to anything. result = t - let f = if kind in {skProc, skFunc}: flags+{taNoUntyped} else: flags + let innerFlags = flags - {taObjField, taTupField, taIsOpenArray} + let f = if kind in {skProc, skFunc}: innerFlags+{taNoUntyped} else: innerFlags for _, a in t.paramTypes: if result != nil: break - result = typeAllowedAux(marker, a, skParam, c, f-{taIsOpenArray}) + result = typeAllowedAux(marker, a, skParam, c, f) if result.isNil and t.returnType != nil: - result = typeAllowedAux(marker, t.returnType, skResult, c, flags) + result = typeAllowedAux(marker, t.returnType, skResult, c, innerFlags) of tyTypeDesc: if kind in {skVar, skLet, skConst} and taProcContextIsNotMacro in flags: result = t diff --git a/tests/lent/tlents.nim b/tests/lent/tlents.nim index 28fe0602ed..1b14972239 100644 --- a/tests/lent/tlents.nim +++ b/tests/lent/tlents.nim @@ -23,3 +23,25 @@ block: doAssert x(a) == 1 doAssert y(a) == 1 + +import std/tables + +block: + type + R = proc(): lent O {.nimcall.} + F = object + schema: R + O = object + fields: Table[string, F] + + func f(o: O, key: string): R = + if key in o.fields: o.fields[key].schema + else: nil + +block: + type + R = proc(): lent O + O = object + r: R + + func f(o: O): int = 42