Repository: go
Issue: proposal: spec: expression to create pointer to simple types
Labels: LanguageChange,Proposal,LanguageChangeReview

This notion was addressed in #9097, which was shut down rather summarily. Rather than reopen it, let me take another approach.

When `&S{}` was added to the language as a way to construct a pointer to a composite literal, it didn't quite feel right to me. The allocation was semi-hidden, magical. But I have gotten used to it, and of course now use it often.

But it still bothers me some, because it is a special case. Why is it only valid for composite literals? There are reasons for this, which we'll get back to, but it still feels wrong that it's easier to create a pointer to a struct:

```
p := &S{a:3}
```

than to create a pointer to a simple type:

```
a := 3
p := &a
```

I would like to propose two different solutions to this inconsistency.
Now it has been repeatedly suggested that we allow pointers to constants, as in

```
p := &3
```

but that has the nasty problem that 3 does not have a type, so that just won't work.

There are two ways forward that could work, though.

*Option 1: new*

We can add an optional argument to `new`. If you think about it,

```
p := &S{a:3}
```

can be considered to be shorthand for

```
p := new(S)
*p = S{a:3}
```

or

```
var _v = S{a:3}
p := &_v
```

That's two steps either way. If we focus first on the `new` version, we could reduce it to one line by allowing a second, optional argument to the builtin:

```
p := new(S, S{a:3})
```

That of course doesn't add much, and the stuttering is annoying, but it enables this form, making a number of previously clumsy pointer builds easy:

```
p1 := new(int, 3)
p2 := new(rune, 10)
p3 := new(Weekday, Tuesday)
p4 := new(Name, "unspecified")
... and so on
```

Seen in this light, this construct redresses the fact that it's harder to build a pointer to a simple type than to a compound one.

This construct creates an addressible form from a non-addressible one by explicitly allocating the storage for the expression.
It could be applied to lots of places, including function returns:

```
p := new(T, f())
```


Moreover, although we could leave out this step (but see Option 2) we could now redefine the `&` operator applied to a non-addressible typed expression to be,

```
new(typeOfExpression, Expression)
```

That is,

```
p := &expression 
```

where `expr` is not an existing memory location is now just defined to be shorthand for

```
p := new(typeOfExpression, expression)
```


*Option 2*

I am more of a fan of the `new` builtin than most. It's regular and easy to use, just a little verbose.
But a lot of people don't like it, for some reason.
So here's an approach that doesn't change new.
Instead, we define that conversions (and perhaps type assertions, but let's not worry about them here) are addressible.
This gives us another mechanism to define the type of that constant 3:

```
p := &int(3)
```

This works because a conversion must always create new storage.
By definition, a conversion changes the type of the result, so it must create a location of that type to hold the value.
We cannot say `&3` because there is no type there, but by making the operation apply to a conversion, there is always a defined type.

Here are the examples above, rewritten in this form:

```
p1 := &int(3)
p2 := &rune(10)
p3 := &Weekday(Tuesday)
p4 := &Name("unspecified")
```

*Discussion*

Personally, I find both of these mechanisms attractive, although either one would scratch the itch.
I propose therefore that we do both, but of course the discussion may end up selecting only one.

*Template*

_Would you consider yourself a novice, intermediate, or experienced Go programmer?_

I have some experience.

_What other languages do you have experience with?_

Fortran, C, Forth, Basic, C, C++, Java, Python, and probably more. Just not JavaScript

_Would this change make Go easier or harder to learn, and why?_

Perhaps a little easier, but it's a niche problem.

_Has this idea, or one like it, been proposed before?_

Yes, in issue #9097 and probably elsewhere.

_If so, how does this proposal differ?_

A different justification and a new approach, with an extension of `new`.

_Who does this proposal help, and why?_

People annoyed by the difficulty of allocating pointers to simple values.

_What is the proposed change?_

See above.

_Please describe as precisely as possible the change to the language._

See above.

_What would change in the language spec?_

The `new` operator would get an optional second argument, and/or conversions would become addressible.

_Please also describe the change informally, as in a class teaching Go._

See above.

_Is this change backward compatible? Breaking the Go 1 compatibility guarantee is a large cost and requires a large benefit._

Yes. Don't worry.

_Show example code before and after the change._

See above.

_What is the cost of this proposal? (Every language change has a cost)._

Fairly small compiler update compared to some others underway. Will need to touch documentation, spec, perhaps some examples.

_How many tools (such as vet, gopls, gofmt, goimports, etc.) would be affected?_

Perhaps none? Not sure.

_What is the compile time cost?_

Nothing measurable.

_What is the run time cost?_

Nothing measurable.

_Can you describe a possible implementation?_

Yes.


_Do you have a prototype? (This is not required.)_

No.


_How would the language spec change?_

Answered above. Why is this question here twice?

_Orthogonality: how does this change interact or overlap with existing features?_

It is orthogonal.

_Is the goal of this change a performance improvement?_

No.


_If so, what quantifiable improvement should we expect?_

More regularity for this case, removing a restriction and making some (not terribly common, but irritating) constructs shorter.

_How would we measure it?_

Eyeballing.

_Does this affect error handling?_

No.

_If so, how does this differ from previous error handling proposals?_

N/A

_Is this about generics?_

No.

_If so, how does this differ from the the current design draft and the previous generics proposals?_

N/A