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

Problems with dot syntax and private symbols used within templates #7223

Closed
zah opened this issue Feb 15, 2018 · 0 comments · Fixed by #22111
Closed

Problems with dot syntax and private symbols used within templates #7223

zah opened this issue Feb 15, 2018 · 0 comments · Fixed by #22111

Comments

@zah
Copy link
Member

zah commented Feb 15, 2018

In this issue we'll discuss some unexpected differences that arise when you switch between procs and templates in the presence of multiple modules and private helper procs. Consider the following multi-module program:

ptr_arith.nim:

proc baseAddr*[T](x: openarray[T]): pointer =
  cast[pointer](x)

proc shift*(p: pointer, delta: int): pointer =
  cast[pointer](cast[int](p) + delta)

ranges.nim

import
  ptr_arith

type
  Bytes* = seq[byte]
  
  BytesRange* = object
    bytes*: Bytes
    ibegin*, iend*: int

proc privateProc(r: BytesRange): int = r.ibegin

template rangeBeginAddr*(r: BytesRange): pointer =
  ptr_arith.shift(baseAddr(r.bytes), r.ibegin)

usage.nim

import
  ranges

var r = BytesRange(bytes: @[1.byte, 2, 3], ibegin: 0, iend: 2)
var a = r.rangeBeginAddr

The code above compiles and runs fine, but it will fail to compile if we make any of the following innocent changes:

Replace r.ibegin with r.privateProc

The error will be "undeclared field: 'privateProc'"

To fix the code, you can either turn the template into a proc or you can turn r.privateProc to privateProc(r) while still using a template.

Rewrite rangeBeginAddr using the dot syntax

template rangeBeginAddr*(r: BytesRange): pointer =
  r.bytes.baseAddr.shift(r.ibegin)

The code will now fail with undeclared field: 'baseAddr'. To fix it, you can turn the template into a proc.

Both problems will manifest only when rangeBeginAddr is used from another module. Local usages will be compiled correctly. Since templates are otherwise allowed to mediate access to private symbols, the expected behavior here is that there won't be any differences in the behavior of procs and templates and the local vs non-local usages of a template.

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

Successfully merging a pull request may close this issue.

3 participants