mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-21 23:05:27 +00:00
fixes #17630 ## Recursive Concept Cycle Detection - Track (conceptId, typeId) pairs during matching to detect cycles - Changed marker from IntSet to HashSet[ConceptTypePair] - Removed unused depthCount field - Added recursive concepts documentation to manual - Added tests for recursive concepts, distinct chains, and co-dependent concepts ## Fix Flaky `tasyncclosestall` Test The macOS ARM64 CI jobs were failing due to a flaky async socket test (unrelated to concepts). The test only accepted `EBADF` as a valid error code when closing a socket with pending writes. However, depending on timing, the kernel may report `ECONNRESET` or `EPIPE` instead: - **EBADF**: Socket was closed locally before kernel detected remote state - **ECONNRESET**: Remote peer sent RST packet (detected first) - **EPIPE**: Socket is no longer connected (broken pipe) All three are valid disconnection errors. The fix accepts any of them, making the test reliable across platforms. --------- Co-authored-by: Andreas Rumpf <araq4k@proton.me>
This commit is contained in:
@@ -3025,6 +3025,44 @@ If neither of them are subsets of one another, then the disambiguation proceeds
|
||||
and the concept with the most definitions wins, if any. No definite winner is an ambiguity error at
|
||||
compile time.
|
||||
|
||||
Recursive concepts
|
||||
------------------
|
||||
|
||||
Concepts can reference themselves in their definitions, enabling recursive type constraints.
|
||||
This is useful for matching `distinct` types that should inherit traits from their base type:
|
||||
|
||||
```nim
|
||||
import std/typetraits
|
||||
|
||||
type
|
||||
PrimitiveBase = SomeNumber | bool | ptr | pointer | enum
|
||||
|
||||
# Matches PrimitiveBase directly, or any distinct type whose base is Primitive
|
||||
Primitive = concept x
|
||||
x is PrimitiveBase or distinctBase(x) is Primitive
|
||||
|
||||
# Application: a handle type that should be treated like a primitive
|
||||
Handle = distinct int
|
||||
SpecialHandle = distinct Handle
|
||||
|
||||
assert int is Primitive
|
||||
assert Handle is Primitive
|
||||
assert SpecialHandle is Primitive # works through 2 levels
|
||||
assert not (string is Primitive)
|
||||
```
|
||||
|
||||
Concepts can also be mutually recursive (co-dependent):
|
||||
|
||||
```nim
|
||||
type
|
||||
Serializable = concept
|
||||
proc serialize(s: Self; writer: var Writer)
|
||||
Writer = concept
|
||||
proc write(w: var Self; data: Serializable)
|
||||
```
|
||||
|
||||
The compiler uses cycle detection to handle these cases without infinite recursion.
|
||||
|
||||
Statements and expressions
|
||||
==========================
|
||||
|
||||
|
||||
Reference in New Issue
Block a user