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

spec: inconsistency about allowable conversions of numeric constants to strings #24745

Open
mdempsky opened this issue Apr 7, 2018 · 8 comments

Comments

@mdempsky
Copy link
Member

commented Apr 7, 2018

In section "Conversions", the Go spec says:

A constant value x can be converted to type T if x is representable by a value of T. As a special case, an integer constant x can be converted to a string type using the same rule as for non-constant x.

Note that "integer constants" are distinct from "rune constants", "float constants", etc.

However, the spec also includes two examples of conversions of rune literals to type string: string('x') and string('a').

cmd/compile and go/types allow these conversions. I assume gccgo does too, as utf8.RuneError is an untyped rune constant, and string(utf8.RuneError) appears a few times in the standard library.

I think the wording should be tweaked to "an integer or rune constant x".

Aside: I'd think we should relax it further to allow any integer value. We allow make([]byte, 1.0), so it seems inconsistent to not allow string(1.0).

/cc @griesemer

@mdempsky mdempsky added this to the Go1.11 milestone Apr 7, 2018

@mdempsky mdempsky changed the title spec: inconsistency about converting numeric constants to strings spec: inconsistency about allowable conversions of numeric constants to strings Apr 7, 2018

@mdempsky

This comment has been minimized.

Copy link
Member Author

commented Apr 7, 2018

Somewhat related: #21982.

@mdempsky

This comment has been minimized.

Copy link
Member Author

commented Apr 7, 2018

If the left operand of a constant shift expression is an untyped constant, the result is an integer constant;

This suggests in the code below that 'a' << 1 should be an integer constant, so x should be given the default type int, and the blank assignment should succeed.

var x = 'a' << 1
var _ int = x

However, cmd/compile and go/types both give x the type rune, so the assignment is rejected.

@go101

This comment has been minimized.

Copy link

commented Apr 7, 2018

doesn't integer constants include rune constants?

@cznic

This comment has been minimized.

Copy link
Contributor

commented Apr 7, 2018

I also think 'x' is an integer constant. It's just its default type is rune.

@mdempsky

This comment has been minimized.

Copy link
Member Author

commented Apr 7, 2018

rune is an alias for int32, which is defined as an integer type. But there doesn't appear to be any wording to suggest that "rune constants" are a subclass of "integer constants."

@cznic

This comment has been minimized.

Copy link
Contributor

commented Apr 7, 2018

I think that 'x' is not (yet) a rune constant, but an untyped integer constant. In certain contexts, like in foo := 'x' it becomes a rune. In string('x') its default type (rune) is IMO not relevant. I think that it's in the later case actually (due to context) first converted to int, not rune, like in the (IMHO) equivalent string(120).

@mdempsky

This comment has been minimized.

Copy link
Member Author

commented Apr 8, 2018

I think that 'x' is not (yet) a rune constant, but an untyped integer constant.

That's not what the Go spec says (emphasis added):

A rune literal represents a rune constant, an integer value identifying a Unicode code point.

Rune constants are integer values, but not integer constants.

@griesemer griesemer self-assigned this Apr 9, 2018

@griesemer

This comment has been minimized.

Copy link
Contributor

commented Apr 9, 2018

I agree with @mdempsky that there is at least some imprecision if not inconsistency in the spec in this area. We use mildly similar terminology for different purposes (integer value vs integer constant vs integer vs int type, etc.) and these terms are vaguely defined if at all.

I think we need to clearly define these terms in one place (consistent with existing use) and then this issue (and related ones) should become clear.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
5 participants
You can’t perform that action at this time.