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

proposal: Go 2: change len, cap to return untyped ints if result is constant #31795

Closed
griesemer opened this issue May 2, 2019 · 12 comments
Closed
Labels
FrozenDueToAge LanguageChange NeedsDecision Feedback is required from experts, contributors, and/or the community before a change can be made. Proposal v2 A language change or incompatible library change
Milestone

Comments

@griesemer
Copy link
Contributor

Reminder issue.

Can we change len, cap, etc. to return an untyped value rather than an int if they are constant expressions? Investigate if this is possible in a backward-compatible way.

@griesemer griesemer added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label May 2, 2019
@griesemer griesemer added this to the Go1.14 milestone May 2, 2019
@griesemer griesemer self-assigned this May 2, 2019
@ianlancetaylor ianlancetaylor added the v2 A language change or incompatible library change label May 7, 2019
@bradfitz
Copy link
Contributor

bradfitz commented May 7, 2019

And unsafe.Sizeof etc.

@ianlancetaylor ianlancetaylor changed the title spec: built-ins such as len to return untyped result for constant expressions (investigation) proposal: Go 2: change len, cap, unsafe.Sizeof, unsafe.OffsetOf to return untyped constants May 14, 2019
@ianlancetaylor ianlancetaylor changed the title proposal: Go 2: change len, cap, unsafe.Sizeof, unsafe.OffsetOf to return untyped constants proposal: Go 2: change len, cap, unsafe.Sizeof, unsafe.OffsetOf to return untyped constants if constant May 14, 2019
@ianlancetaylor ianlancetaylor added NeedsDecision Feedback is required from experts, contributors, and/or the community before a change can be made. and removed NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. labels May 14, 2019
@MichaelTJones
Copy link
Contributor

Yes, this meets every use case that has frustrated me in code.

@griesemer griesemer changed the title proposal: Go 2: change len, cap, unsafe.Sizeof, unsafe.OffsetOf to return untyped constants if constant proposal: Go 2: change len, cap, unsafe.AlignOf, unsafe.Sizeof, unsafe.OffsetOf to return untyped constants if constant May 29, 2019
@griesemer griesemer changed the title proposal: Go 2: change len, cap, unsafe.AlignOf, unsafe.Sizeof, unsafe.OffsetOf to return untyped constants if constant proposal: Go 2: change len, cap, unsafe.Alignof, unsafe.Sizeof, unsafe.OffsetOf to return untyped constants if constant May 29, 2019
@gopherbot
Copy link

Change https://golang.org/cl/179184 mentions this issue: go/types: change cap, len to return untyped int if result is constant (experiment)

@griesemer
Copy link
Contributor Author

It turns out that per the spec, unsafe.Sizeof (and its siblings unsafe.Offsetof, unsafe.Alignof) return a uintptr rather than an int, which makes it impossible to change these in a backward-compatible way: even though they always return a constant, if that were an untyped int it would not default to uintptr. A place where this is causing problems is for instance in file https://golang.org/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin.go on line 353 where n is supposed to be of type uintptr.

But we should be able to do it for len and cap without problems - and indeed there aren't any in the stdlib as a type-checking it via a modified type checker shows (apply CL 179184 and run go test go/types which will run the go/types over all packages of the std lib, among other tests).

@griesemer griesemer changed the title proposal: Go 2: change len, cap, unsafe.Alignof, unsafe.Sizeof, unsafe.OffsetOf to return untyped constants if constant proposal: Go 2: change len, cap to return untyped constants if constant May 29, 2019
@griesemer griesemer changed the title proposal: Go 2: change len, cap to return untyped constants if constant proposal: Go 2: change len, cap to return untyped ints if result is constant May 29, 2019
@griesemer
Copy link
Contributor Author

As an aside, changing len and cap as described is in the spirit of the built-ins complex, real and imag which also return an untyped result if the argument(s) are untyped.

@gopherbot gopherbot removed the NeedsDecision Feedback is required from experts, contributors, and/or the community before a change can be made. label Aug 16, 2019
@gopherbot gopherbot added the NeedsDecision Feedback is required from experts, contributors, and/or the community before a change can be made. label Sep 3, 2019
@mdempsky
Copy link
Member

mdempsky commented Sep 7, 2019

Rather than make cap and len only evaluate to untyped when their arguments are constant, why not just always make them untyped?

Non-constant comparisons are still untyped bool when their operands are typed.

Edit: To answer my own question, because if we allowed var x byte = len(s) where s is a non-constant string, then we'd have to define what to do for strings over 255 bytes long. Would we silently truncate? Would we panic?

It turns out that per the spec, unsafe.Sizeof (and its siblings unsafe.Offsetof, unsafe.Alignof) return a uintptr rather than an int, which makes it impossible to change these in a backward-compatible way: even though they always return a constant, if that were an untyped int it would not default to uintptr.

We could make them evaluate to "untyped uintptr" lol.

@MichaelTJones
Copy link
Contributor

MichaelTJones commented Sep 7, 2019 via email

@griesemer
Copy link
Contributor Author

@mdempsky As you noted, the problem with making len always untyped is the size of the result. For booleans (and also strings) the size is known, no matter what kind of boolean (or string).

@go101
Copy link

go101 commented Oct 9, 2019

Will this change allow const X = len("Go") + 2i and complex(len("Go"), 2)?

@griesemer
Copy link
Contributor Author

yes

@rsc rsc modified the milestones: Go1.14, Backlog Oct 9, 2019
@rsc
Copy link
Contributor

rsc commented Oct 11, 2019

I am not sure the costs here are worth the benefit. Today there is a simple rule: len(x) has type int. Changing the type to depend on what x is will interact in non-orthogonal ways with various code changes. For example, under the proposed semantics, this code compiles:

const x string = "hello"
func f(uintptr)
...
f(len(x))

but suppose then someone comes along and wants to be able to modify x for testing or something like that, so they s/const/var/. That's usually fairly safe, but now the f(len(x)) call fails to type-check, and it will be mysterious why it ever worked.

This change seems like it might add more rough edges than it removes.

@griesemer
Copy link
Contributor Author

Agreeing with @rsc here. While this seems like an easy win at first glance, it's not clear that the corner cases are worth the extra complexity. I am retracting this proposal.

@golang golang locked and limited conversation to collaborators Dec 2, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge LanguageChange NeedsDecision Feedback is required from experts, contributors, and/or the community before a change can be made. Proposal v2 A language change or incompatible library change
Projects
None yet
Development

No branches or pull requests

8 participants