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

Documentation request about int #12552

Open
m-holger opened this issue Oct 29, 2019 · 3 comments · May be fixed by #24250
Open

Documentation request about int #12552

m-holger opened this issue Oct 29, 2019 · 3 comments · May be fixed by #24250

Comments

@m-holger
Copy link

m-holger commented Oct 29, 2019

Would it be possible to document when int behaves as a type and when int
behaves as a type class.

The differences between the two have some profound and perhaps unexpected
implications for Nim programs.

For the casual reader it is difficult if not impossible to find an answer to
the question in the documentation.

Consider the following examples:

let
    x = 1'i8


proc foo(n : int) =
    echo "foo : ", n, " is of type ",  typeof(n)

proc bar[T : int] (n : T) =
    echo "bar : ", n, " is of type ",  typeof(n)


foo(x)          # outputs :  foo : 1 is of type int
                # int behaves like a type

bar(x)          # outputs :  bar : 1 is of type int8
                # int behaves like a type class 
                # C code has distinct procedures for each intxx type (except int64)

i.e. in proc bar[T : int] (n : T), int behaves like int | int8 | int16 | int32 (with some magic - see barfoo and barfoofoo below)

However, this behaviour does not carry through to overloading resolution

generic match :
f is a generic type and a matches, for instance a is int and
f is a generic (constrained) parameter type (like in [T] or [T: int|char]

Likewise for generic matches the most specialized generic type (that still matches) is preferred

proc foofoobar[T] (n : T) =
    echo "foofoobar[T] : ", n, " is of type ",  typeof(n)

proc foofoobar[T : int] (n : T) =
    echo "foofoobar[int] : ", n, " is of type ",  typeof(n)

foofoobar(x)    # outputs : foofoobar[T] : 1 is of type int8
                # for purposes of overloading resolution
                # int behaves like a type

or when int appears as part of a type expression

proc foobar[T : int | string] (n : T) =
    echo "foobar : ", n, " is of type ",  typeof(n)

foobar(x)       # Error: type mismatch: required type for n: T: int or string  but expression 'x' is of type: int8
                # in expressions, 
                # int behaves like a type 

The fact that int is int | int8 | int16 | int32 "with magic" is demonstrated by the fact that

proc barfoo[T : SomeUnsignedInt] (n : T) =
    echo "barfoo[SomeUnsignedInt] : ", n, " is of type ",  typeof(n)

proc barfoo[T : SomeSignedInt] (n : T) =
    echo  "barfoo[SomeSignedInt] : ", n, " is of type ",  typeof(n)

barfoo(1)       # Error: ambiguous call  (see my comment to request #12513)
                # NB  SomeSignedInt and SomeUnsignedInt are non-overlapping

fails, while

proc barfoofoo[T : uint] (n : T) =
    echo "barfoofoo[uint] : ", n, " is of type ",  typeof(n)

proc barfoofoo[T : int] (n : T) =
    echo  "barfoofoo[int] : ", n, " is of type ",  typeof(n)

barfoofoo(1)    # outputs : barfoofoo[int] : 1 is of type int
barfoofoo(x)    # outputs : barfoofoo[int] : 1 is of type int8

works as one would expect, but obviously not for int64 :

barfoofoo(1'i64) # Error: type mismatch: got <int64> required type for n: T: int but expression '1'i64' is of type: int64
@Araq
Copy link
Member

Araq commented Oct 30, 2019

I'm not sure the documentation is to blame here, looks to me like a compiler bug.

@m-holger
Copy link
Author

This may be a bug, but I think it is also a, or rather two, documentation issues.

The first issue is that to my reading of the documentation the compiler follows the letter,
but probably not the spirit, of what is documented. This makes it difficult to report the issue
as a bug. If it helps, I can summarise how I read the documentation and you can decide whether
my interpretation is what was intended, and if not, whether my misinterpretation is a result
of unclear thinking on my part (in which case some pointers would be appreciated) or unclear
documentation.

The second issue is the lack of a link to the RFCs on the documentation home page, which
would have helped me to find RFC #36 "Change int literal to number literal". This RFC
would have led me to report the issue as a likely bug, rather than a documentation request.

Part of the issue seems to be the int literal problem described by GULPF on 3 Apr 2018 in RFC #36.
The wider issue appears to be the interaction between the implicit conversion of int literals to
smaller int types and the overloading resolution rules. It looks to me that GULPF's "default order" suggestion would probably fix the most important issue, but not all issues. (Would the topic be worth a RFC?)

One of the practical implications of the problem is that refactoring of a compile-time dispatch
table

proc blah[T](x : T) =
when x is SomeSignedInt:
    blahInt(x)
elif x is SomeUnsignedInt:
    blahUint(x)
elif ...

into overloaded procedures [or any other use of proc blah[T : SomeSignedInt](...] require work-arounds.

[Newbie question: is there any advantage to using the dispatch table approach in Nim that I am missing?]

@ghost ghost added the Documentation Content Related to documentation content (not generation). label Jul 27, 2020
@metagn
Copy link
Collaborator

metagn commented Jun 24, 2023

I would say this is a bug. The call to bar should create a conversion to int (and likely does), and typeof(n) should be int (i.e. T should be matched as the type of the conversion result).

The behavior is correct for converters:

converter foo(x: int): string = $x

proc bar[T: string](n: T) =
  echo "bar: ", n, " is of type ", typeof(n)

bar(123)
# bar: 123 is of type string

But not floats with literals (although this might require a separate fix):

proc bar[T: float](n: T) =
  echo "bar: ", n, " is of type ", typeof(n)

bar(123)
# bar: 123 is of type int

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