Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bugs with new-style concepts #18225

Open
timotheecour opened this issue Jun 10, 2021 · 2 comments
Open

bugs with new-style concepts #18225

timotheecour opened this issue Jun 10, 2021 · 2 comments
Labels

Comments

@timotheecour
Copy link
Member

timotheecour commented Jun 10, 2021

Example

sample of 8 bugs with new style concepts:

when defined case1:
  #[
  BUG:D20210609T174202:here doesn't honor func
  ]#
  type Foo = concept
    func bar(x: Self): Self
  proc bar(a: int): int = (echo "asdf"; 1)
  doAssert int isnot Foo # assert fails, but should succeed because bar has sideeffects

when defined case2:
  #[
  BUG:D20210609T174206:here doesn't work with auto
  ]#
  type Foo = concept
    proc bar(x: Self): Self
  proc bar(a: int | float): auto = a
  doAssert int is Foo # fails

when defined case3:
  #[
  BUG: D20210609T175144:here doesn't work with overloaded symbols
  ]#
  type Foo = concept
    proc bar(x: Self): int
  proc bar(a: int | float): int = 1
  proc bar(a: string): int = 1
  doAssert string is Foo # fails

when defined case4:
  #[
  BUG: D20210609T180457:here doesn't generic constraints
  ]#
  type Foo = concept
    proc bar[T: SomeInteger](x: Self, b: T): T
  proc bar[T: SomeInteger](x: string, b: T): T = discard
  doAssert string is Foo # fails

when defined case5:
  #[
  BUG:D20210609T182307:here doesn't work with var
  ]#
  type Foo = concept
    proc bar(a: seq[Self])
  proc bar(a: var seq[string]) = discard
  echo string is Foo # prints true, should print false
  proc fn(a: Foo) = bar(@[a])
  echo compiles(fn("x")) # prints false as expected because '@[a]' is immutable, not 'var'

when defined case6:
  #[
  BUG: D20210609T183337:here doesn't work with static params
  ]#
  type Foo = concept
    proc bar(a: Self, b: static int) = discard
  proc bar(a: string, b: static int) = discard
  doAssert string is Foo # fails

when defined case7:
  #[
  BUG: D20210609T183337:here doesn't work with static params
  ]#
  type Foo = concept
    proc bar(a: Self, b: typedesc) = discard
  proc bar(a: string, b: typedesc) = discard
  doAssert string is Foo # fails

when defined case8:
  #[
  BUG: D20210609T190543:here doesn't work with called iterators (iterables)
  ]#
  type Summable = concept
    template sum(a: iterable[Self]): int = discard # doesn't help
    # proc sum(a: iterable[Self]): int # doesn't help
  iterator iota(n: int): int = (for i in 0..<n: yield i)
  template sum[T](a: iterable[T]): T =
    var ret: T
    for ai in a: ret += ai
    ret
  doAssert sum(iota(3)) == 0 + 1 + 2
  template sum2(a: Summable): untyped = sum(a) * 2
  echo sum2(iota(3)) # Error: attempting to call routine: 'iota'

not to mention all the other concept issues already reported: Concepts (currently 42 open issues)

Current Output

all those cases fail

Expected Output

those cases should pass

Possible Solution

{.enableif.}, which I implemented in #12048 (which i will rename as {.where.}) , was wrongly closed.

It doesn't have any of the problems of concepts (whether old style or new style), is more flexible and is a much simpler solution leveraging the compiler's existing expression evaluator; it's also the solution adopted by these:

In short, enableif is the obvious, simpler, more flexible approach and we should use it.

Note that we could even define concepts on top of enableif (enableif subsumes concepts):
type Foo = concept x {.enableif: bar(x) is int.} on top of {.enableif.}, to allow the same syntax where needed, eg:

type Foo = concept x {.enableif: bar(x) is int.}
proc fn(a: Foo)
proc fn(a: auto) {.enableif: bar(a) is int.}
proc fn[T](a, b: auto, c: int, d: T) {.enableif: bar(a, b, T).} # not possible with concepts

Additional Information

1.5.1 21f3b85

@Araq
Copy link
Member

Araq commented Jun 10, 2021

enableif subsumes concepts

But it doesn't, concepts allow for type variable inference (container of T; infer the T) and enableif doesn't. Rust has traits and Swift protocols, comparable to concepts. They have both where and concepts!

@Araq
Copy link
Member

Araq commented Jun 10, 2021

Cases 2 and 5 are not bugs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants