mirror of
https://github.com/nim-lang/Nim.git
synced 2026-09-17 18:44:53 +00:00
Fix and tests for issues #26147 case A. See individual commit messages. Checked on the full test suite: no new failure with respect to devel as baseline.
47 lines
1.4 KiB
Nim
47 lines
1.4 KiB
Nim
discard """
|
|
action: run
|
|
"""
|
|
|
|
# The choice between a routine declared over a concept and a concrete overload
|
|
# must not depend on how many requirements the concept happens to declare.
|
|
#
|
|
# `sumGeneric` ranks concepts by requirement count, and concrete types by
|
|
# structural nesting depth, which makes sense within each category but not
|
|
# between one another. So we must make sure we don't fall through that case
|
|
# accidentally picking ambiguous calls arbitrarily (see GitHub issue #26147).
|
|
|
|
type
|
|
Small[T] = concept
|
|
proc `[]`(a: Self; index: int): T
|
|
proc len(a: Self): int
|
|
|
|
Large[T] = concept
|
|
proc `[]`(a: Self; index: int): T
|
|
proc len(a: Self): int
|
|
proc extra1(a: Self): int
|
|
proc extra2(a: Self): int
|
|
proc extra3(a: Self): int
|
|
|
|
Box[T] = ref object
|
|
data: seq[T]
|
|
|
|
proc `[]`[T](b: Box[T], i: int): T = b.data[i]
|
|
proc len[T](b: Box[T]): int = b.data.len
|
|
proc extra1[T](b: Box[T]): int = 0
|
|
proc extra2[T](b: Box[T]): int = 0
|
|
proc extra3[T](b: Box[T]): int = 0
|
|
|
|
proc pickSmall[T](x: Small[T]): string = "concept"
|
|
proc pickSmall[T](x: Box[T]): string = "concrete"
|
|
|
|
proc pickLarge[T](x: Large[T]): string = "concept"
|
|
proc pickLarge[T](x: Box[T]): string = "concrete"
|
|
|
|
let b = Box[int](data: @[1, 2, 3])
|
|
|
|
# `Box` satisfies both concepts, so both calls must select the concrete
|
|
# overload, and must agree with each other.
|
|
doAssert pickSmall(b) == "concrete"
|
|
doAssert pickLarge(b) == "concrete"
|
|
doAssert pickSmall(b) == pickLarge(b)
|