nim-lang / Nim

Nim is a statically typed compiled systems programming language. It combines successful concepts from mature languages like Python, Ada and Modula. Its design focuses on efficiency, expressiveness, and elegance (in that order of priority).
https://nim-lang.org
Other
16.59k stars 1.47k forks source link

Cannot infer the value of static param #10220

Open mratsim opened 5 years ago

mratsim commented 5 years ago

Sorry for the long repro code, it's quite tricky to extract it from my codebase and keep the issue reproducible as 3 differents procs/statements need to be present

This is a follow-up on my Go playing bot project which triggered many bugs last April every time I tried to avoid one:

With this new example I get:

cannot_infer.nim(90, 15) template/generic instantiation of `search_best_move` from here
cannot_infer.nim(81, 7) template/generic instantiation of `run_rollout` from here
cannot_infer.nim(19, 42) Error: cannot infer the value of the static param 'N'
import hashes, tables

type
  ################################ Coordinates ###################################
  GoInt* = int32

  Point*[N: static[GoInt]] = distinct range[-1.GoInt .. (N+2) * (N+2) - 1]
    # Can't use plain static[GoInt]: https://github.com/nim-lang/Nim/issues/7609

  ################################ Coordinates ###################################

  ################################ Color & Moves ###################################

  Intersection* = enum
    Empty, Black, White, Border

  ################################ Board  ###################################

  Board*[N: static[GoInt]] = array[(N+2) * (N+2), Intersection]

  BoardState*[N: static[GoInt]] = ref object
    board*: Board[N]

  ################################ Monte-Carlo ###################################

  Zobrist* = Hash
  Node*[N: static[GoInt]] = object
  NodeTable*[N: static[GoInt]] = Table[Zobrist, Node[N]]

  MCTS_Context*[N: static[GoInt]] = object
    nodes*: NodeTable[N]

################################ Procedures ###################################

func newBoardState*(size: static[GoInt]): BoardState[size] =
  new result

# Remove for no crash
func `$`*[N: static[GoInt]](board: Board[N]): string =
  # Display a go board - Triggers crash <------------------------------
  result = "foo"

proc run_rollout[N: static[GoInt]](
        self: var MCTS_Context[N],
        board_state: BoardState[N]) =

  var
    amaf_color_map: array[(N+2)*(N+2), Intersection]

  # Comment the following out and the project compiles:
  echo amaf_color_map # Triggers crash <------------------------------

proc search_best_move*[N: static[GoInt]](
  self: var MCTS_Context[N], board_state: BoardState[N],
  nb_simulations: Natural): Point[N] =

  self.run_rollout(board_state)

################################ Bug ###################################

var a = newBoardState(GoInt 19) # Triggers crash <------------------------------
# var a: BoardState[GoInt 19] # This is another possible fix

var ctx: MCTS_Context[GoInt 19]

let move = ctx.search_best_move(a, 10)
stale[bot] commented 4 years ago

This issue has been automatically marked as stale because it has not had recent activity. If you think it is still a valid issue, write a comment below; otherwise it will be closed. Thank you for your contributions.

narimiran commented 3 years ago

var a = newBoardState(GoInt 19) # Triggers crash <------------------------------

This doesn't trigger crash anymore.

echo amaf_color_map # Triggers crash <------------------------------

This doesn't crash, but it produces:

Error: type mismatch: got <array[0..440, Intersection]>
but expected one of:
proc echo(x: varargs[typed, `$`])
  first type mismatch at position: 1
  required type for x: varargs[typed]
  but expression 'amaf_color_map' is of type: array[0..440, Intersection]
metagn commented 1 month ago

The compiler, I think rightfully, can't infer the N in Board[N] when an arbitrary array type is given. With #24098, this stops the $ overload with Board[N] from matching, and uses the $ overload for arrays instead. Would this be considered correct?

Giving amaf_color_map the type Board[N] does make it use the Board[N] overload, which is an interesting test IMO because an alternative implementation of the language arguably wouldn't support it.