~mna/snow unlisted

5d441107081a0c21867fd367b9c2484207a3ba72 — Martin Angers 9 months ago a1f9b24
pkg/semantic: test generic interfaces
M pkg/parser/parser.go => pkg/parser/parser.go +3 -0
@@ 807,6 807,9 @@ func (p *parser) parseInterfaceDecl() *ast.InterfaceDecl {
		if fn.Ref.IsValid() {
			p.error(fn.Pos(), "interface method cannot be marked as ref")
		}
		if fn.GenericParams != nil {
			p.error(fn.Pos(), "interface method cannot have a generic clause (the interface itself can)")
		}
		if fn.Body != nil {
			p.error(fn.Pos(), "interface method cannot have a body")
		}

M pkg/parser/testdata/invalid_interface.snow => pkg/parser/testdata/invalid_interface.snow +2 -0
@@ 5,4 5,6 @@ interface I {
  fn bar() {
    foo()
  }

  fn quz[$T](t: $T)
}

M pkg/parser/testdata/invalid_interface.snow.err => pkg/parser/testdata/invalid_interface.snow.err +1 -0
@@ 1,2 1,3 @@
testdata/invalid_interface.snow:2:3: interface method cannot have attributes
testdata/invalid_interface.snow:5:3: interface method cannot have a body
testdata/invalid_interface.snow:9:3: interface method cannot have a generic clause (the interface itself can)

M pkg/parser/testdata/invalid_interface.snow.want => pkg/parser/testdata/invalid_interface.snow.want +11 -2
@@ 1,5 1,5 @@
file [1, #0] [0:80]
  interface [2] [0:80]
file [1, #0] [0:101]
  interface [3] [0:101]
    ident [I] [10:11]
    fn [16:50]
      @ [2] [16:39]


@@ 19,3 19,12 @@ file [1, #0] [0:80]
        expr [69:74]
          call [0] [69:74]
            ident [foo] [69:72]
    fn [82:99]
      ident [quz] [85:88]
      generic [88:92]
        param [89:91]
          ident [$T] [89:91]
      sig [1->0] [92:99]
        param [93:98]
          ident [t] [93:94]
          ident [$T] [96:98]

A pkg/semantic/testdata/check/fn_generic_interface.snow.err => pkg/semantic/testdata/check/fn_generic_interface.snow.err +1 -0
@@ 0,0 1,1 @@
testdata/fn_generic_interface.snow:23:14: cannot assign type struct G[bool] to variable of type interface I[int]

A pkg/semantic/testdata/check/fn_generic_interface.snow.want => pkg/semantic/testdata/check/fn_generic_interface.snow.want +82 -0
@@ 0,0 1,82 @@
file testdata/fn_generic_interface.snow [0, 1, 2, 1]
  fn main [let: () -> void]
    block [10]
      var:= ifaceInt [var: interface I[int]]
        generic inst [1] [type: interface I[int]]
          ident I [type: interface I]
          ident int [type: int]
        implicit conv [value: interface I[int]]
          call [0] [value: struct S]
            ident S [type: struct S]
      var= res [var: int]
        call [1] [value: int]
          select [let: (int) -> int]
            ident ifaceInt [var: interface I[int]]
            ident foo [let: (int) -> int]
          int [1] [const: int]
      var: gInt [var: struct G[int]]
        generic inst [1] [type: struct G[int]]
          ident G [type: struct G]
          ident int [type: int]
      var= gres [var: int]
        call [1] [value: int]
          select [let: (int) -> int]
            ident gInt [var: struct G[int]]
            ident foo [let: (int) -> int]
          int [1] [const: int]
      assign
        ident ifaceInt [var: interface I[int]]
        implicit conv [value: interface I[int]]
          call [0] [value: struct G[int]]
            generic inst [1] [type: struct G[int]]
              ident G [type: struct G]
              ident int [type: int]
      assign
        ident res [var: int]
        call [1] [value: int]
          select [let: (int) -> int]
            ident ifaceInt [var: interface I[int]]
            ident foo [let: (int) -> int]
          int [2] [const: int]
      assign
        ident ifaceInt [var: interface I[int]]
        call [0] [value: struct G[bool]]
          generic inst [1] [type: struct G[bool]]
            ident G [type: struct G]
            ident bool [type: bool]
      var: ifaceString [var: interface I[string]]
        generic inst [1] [type: interface I[string]]
          ident I [type: interface I]
          ident string [type: string]
      assign
        ident ifaceString [var: interface I[string]]
        implicit conv [value: interface I[string]]
          call [0] [value: struct G[string]]
            generic inst [1] [type: struct G[string]]
              ident G [type: struct G]
              ident string [type: string]
      expr
        call [1] [value: string]
          select [let: (string) -> string]
            ident ifaceString [var: interface I[string]]
            ident foo [let: (string) -> string]
          string ["a"] [const: string]
  struct S [0, 1, 0, 0] [type: struct S]
    fn foo [let: (int) -> int]
      let: i [let: int]
        ident int [type: int]
      ident int [type: int]
      block [0]
  struct G [0, 1, 0, 0, $1] [type: struct G]
    generic type $T [type: $T]
    fn foo [let: ($T) -> $T]
      let: t [let: $T]
        ident $T [type: $T]
      ident $T [type: $T]
      block [0]
  interface I [1, $1] [type: interface I]
    generic type $T [type: $T]
    fn foo [let: ($T) -> $T]
      let: t [let: $T]
        ident $T [type: $T]
      ident $T [type: $T]

A pkg/semantic/testdata/fn_generic_interface.snow => pkg/semantic/testdata/fn_generic_interface.snow +29 -0
@@ 0,0 1,29 @@
interface I[$T] {
  fn foo(t: $T) -> $T
}

struct S {
  fn foo(i: int) -> int {}
}

struct G[$T] {
  fn foo(t: $T) -> $T {}
}

fn main() {
  var ifaceInt: I[int] = S()
  var res = ifaceInt.foo(1)
  var gInt: G[int]
  var gres = gInt.foo(1)

  ifaceInt = G[int]()
  res = ifaceInt.foo(2)

  # this should fail
  ifaceInt = G[bool]()

  # this should work
  var ifaceString: I[string]
  ifaceString = G[string]()
  ifaceString.foo("a")
}

A pkg/semantic/testdata/scopes/fn_generic_interface.snow.err => pkg/semantic/testdata/scopes/fn_generic_interface.snow.err +0 -0

A pkg/semantic/testdata/scopes/fn_generic_interface.snow.want => pkg/semantic/testdata/scopes/fn_generic_interface.snow.want +61 -0
@@ 0,0 1,61 @@
1 *semantic.Unit {
.  bool
.  extern
.  f32
.  f64
.  false
.  float
.  i16
.  i32
.  i64
.  i8
.  int
.  string
.  true
.  u16
.  u32
.  u64
.  u8
.  uint
.  void
.  2 *semantic.Struct {
.  .  import
.  .  pkg
.  .  symbol
.  }
.  3 *semantic.File {
.  .  G
.  .  I
.  .  S
.  .  main
.  .  4 *semantic.Interface {
.  .  .  $T
.  .  .  foo
.  .  .  5 *semantic.Fn {
.  .  .  .  t
.  .  .  }
.  .  }
.  .  6 *semantic.Struct {
.  .  .  foo
.  .  .  7 *semantic.Fn {
.  .  .  .  i
.  .  .  .  self
.  .  .  }
.  .  }
.  .  8 *semantic.Struct {
.  .  .  $T
.  .  .  foo
.  .  .  9 *semantic.Fn {
.  .  .  .  self
.  .  .  .  t
.  .  .  }
.  .  }
.  .  10 *semantic.Fn {
.  .  .  gInt
.  .  .  gres
.  .  .  ifaceInt
.  .  .  ifaceString
.  .  .  res
.  .  }
.  }
}

A pkg/semantic/testdata/static/fn_generic_interface.snow.err => pkg/semantic/testdata/static/fn_generic_interface.snow.err +1 -0
@@ 0,0 1,1 @@
testdata/fn_generic_interface.snow:23:14: cannot assign type struct G[bool] to variable of type interface I[int]

A pkg/semantic/testdata/static/fn_generic_interface.snow.want => pkg/semantic/testdata/static/fn_generic_interface.snow.want +15 -0
@@ 0,0 1,15 @@
testdata/fn_generic_interface.snow:14:26: S
testdata/fn_generic_interface.snow:15:13: ifaceInt
testdata/fn_generic_interface.snow:15:22: foo
testdata/fn_generic_interface.snow:17:14: gInt
testdata/fn_generic_interface.snow:17:19: foo
testdata/fn_generic_interface.snow:19:14: G
testdata/fn_generic_interface.snow:19:16: int
testdata/fn_generic_interface.snow:20:9: ifaceInt
testdata/fn_generic_interface.snow:20:18: foo
testdata/fn_generic_interface.snow:23:14: G
testdata/fn_generic_interface.snow:23:16: bool
testdata/fn_generic_interface.snow:27:17: G
testdata/fn_generic_interface.snow:27:19: string
testdata/fn_generic_interface.snow:28:3: ifaceString
testdata/fn_generic_interface.snow:28:15: foo

A pkg/semantic/testdata/types/fn_generic_interface.snow.err => pkg/semantic/testdata/types/fn_generic_interface.snow.err +0 -0

A pkg/semantic/testdata/types/fn_generic_interface.snow.want => pkg/semantic/testdata/types/fn_generic_interface.snow.want +79 -0
@@ 0,0 1,79 @@
file testdata/fn_generic_interface.snow [0, 1, 2, 1]
  fn main [let: () -> void]
    block [10]
      var:= ifaceInt [var: interface I[int]]
        generic inst [1] [type: interface I[int]]
          ident I [type: interface I]
          ident int [type: int]
        call [0] [value: struct S]
          ident S [type: struct S]
      var= res [var: int]
        call [1] [value: int]
          select [let: (int) -> int]
            ident ifaceInt [var: interface I[int]]
            ident foo [let: (int) -> int]
          int [1] [const: int]
      var: gInt [var: struct G[int]]
        generic inst [1] [type: struct G[int]]
          ident G [type: struct G]
          ident int [type: int]
      var= gres [var: int]
        call [1] [value: int]
          select [let: (int) -> int]
            ident gInt [var: struct G[int]]
            ident foo [let: (int) -> int]
          int [1] [const: int]
      assign
        ident ifaceInt [var: interface I[int]]
        call [0] [value: struct G[int]]
          generic inst [1] [type: struct G[int]]
            ident G [type: struct G]
            ident int [type: int]
      assign
        ident res [var: int]
        call [1] [value: int]
          select [let: (int) -> int]
            ident ifaceInt [var: interface I[int]]
            ident foo [let: (int) -> int]
          int [2] [const: int]
      assign
        ident ifaceInt [var: interface I[int]]
        call [0] [value: struct G[bool]]
          generic inst [1] [type: struct G[bool]]
            ident G [type: struct G]
            ident bool [type: bool]
      var: ifaceString [var: interface I[string]]
        generic inst [1] [type: interface I[string]]
          ident I [type: interface I]
          ident string [type: string]
      assign
        ident ifaceString [var: interface I[string]]
        call [0] [value: struct G[string]]
          generic inst [1] [type: struct G[string]]
            ident G [type: struct G]
            ident string [type: string]
      expr
        call [1] [value: string]
          select [let: (string) -> string]
            ident ifaceString [var: interface I[string]]
            ident foo [let: (string) -> string]
          string ["a"] [const: string]
  struct S [0, 1, 0, 0] [type: struct S]
    fn foo [let: (int) -> int]
      let: i [let: int]
        ident int [type: int]
      ident int [type: int]
      block [0]
  struct G [0, 1, 0, 0, $1] [type: struct G]
    generic type $T [type: $T]
    fn foo [let: ($T) -> $T]
      let: t [let: $T]
        ident $T [type: $T]
      ident $T [type: $T]
      block [0]
  interface I [1, $1] [type: interface I]
    generic type $T [type: $T]
    fn foo [let: ($T) -> $T]
      let: t [let: $T]
        ident $T [type: $T]
      ident $T [type: $T]