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.
This commit is contained in:
ringabout
2026-03-30 21:09:11 +08:00
committed by GitHub
parent 78282b241f
commit 7a82c5920c
2 changed files with 26 additions and 3 deletions

View File

@@ -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

View File

@@ -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