proposal: Go 2: operator functions

The only issue that I could find about operator overloading currently #19770, although it's currently closed and doesn't have many details.
Goal
Operator overloading should be used to create datatypes that represent things that already exist in Go. They should not represent anything else, and should ideally have no other function.
New operators should not be allowed to defined, we should only be able to define currently existing operators. If you look at languages that let you define your own operators (Scala, looking at you!) the code becomes extremely messy and hard to read. It almost requires an IDE because operator overloading is very heavily used.
Using an operator for anything other than it's purpose is a bad idea. We should not be making data structures with fancy looking + operators to add things to the structure. Overloading the + operator in Go should only be used for defining addition/concatenation operators for non-builtin types. Also, as per Go spec, binary operators should only be used for operating on two values of the same type.
Operators should only operate on and return a single type. This keeps things consistent with how operators currently work in Go. We shouldn't allow any type1 + string -> type1 stuff.
Operators should only be defined in the same package as the type they are defined on. Same rule as methods. You can't define methods for structs outside your package, and you shouldn't be able to do this with operators either.
 This should be a contract that should be listed in the Go spec. This makes operator functions predictable, which is how they should be.
Unary operators should not need to be overloaded.
+x                          is 0 + x
-x    negation              is 0 - x
^x    bitwise complement    is m ^ x  with m = "all bits set to 1" for unsigned x
                                      and  m = -1 for signed x

This part of the spec should always remain true, and should also remain true for anything using these operators. Perhaps ^x may need to have it's own, as there's no good way to define "all bits set to 1" for an arbitrary type, although defining a .Invert() function is no less readable IMO.
Unary operations on structs would then therefore be Type{} + t or Type{} - t, and pointers would be nil + t and nil - t. These may have to be special cases in the implementation of operator functions on pointers to types.
Assignment operators should also never be overloaded.
An assignment operation x op= y where op is a binary arithmetic operator is equivalent to x = x op (y) but evaluates x only once. The op= construct is a single token.

This should remain the same just as unary operators.
If we do not permit overloading the ^x unary operator, this means that we only need to define binary operations.
Issues/Projects aided by operator overloading
#19787 - Decimal floating point (IEEE 754-2008)
#26699 - Same proposal, more detail
#19623 - Changing int to be arbitrary precision
#9455 - Adding int128 and uint128
this code - Seriously it's gross
really anything that uses math/big that isn't micro-optimized
If I went searching for longer, there'd probably be a few more that pop up
Syntax
What's a proposal without proposed syntaxes?
// A modular integer.
type Int struct {
	Val int
	Mod int
}

// ==============
// each of the functions would have the following function body:
//
//    	if a == Int{} { // handle unary +
//		a.Mod = b.Mod
//	}
//
//	checkMod(a, b)
//	nextInt = Int{Val: a.Val + b.Val, Mod: a.Mod}
//	nextInt.Reduce()
//
//	return nextInt
//
// ==============

// In all of these, it would result in a compile error if the types of the arguments
// do not match each other and the return type.

// My new favorite. This makes for a simple grammar. It allows
// people who prefer function calls can instead use the `Add` function.
operator (Int + Int) Add
func Add(a, b Int) Int { ... }

// My old favorite. Abandoning the `func` construct clarifies
// that these should not be used like a standard function, and is much
// more clear that all arguments and the return type must be equal.
op(Int) (a + b) { ... }
operator(Int) (a + b) { ... }      // <- I like this better

// My old second favorite, although this looks a lot like a standard method definition.
// Maybe a good thing?
func (a + b Int) Int { ... }

// It can be fixed with adding an "op" to signify it's an operator function, although
// I do not like it because it just reads wrong. Also, looks like we're defining a package-level
// function named `op`... which is not what we are doing.
func op (a + b Int) Int { ... }

// Although at the same time, I don't like having words
// before the `func`... I feel that all function declarations should begin with `func`
op func (a + b Int) Int { ... }

// Another idea could just be to define a method named "Plus", although this
// would cause confusion between functions like `big.Int.Plus` vs `big.Int.Add`.
// We probably need to preserve `big.Int.Add` for microoptimization purposes.
func (a Int) Plus(b Int) Int { ... }

Considering other languages' implementations.
C++
// there's several ways to declare, but we'll use this one
Type operator+(Type a, Type b)

I think C++ isn't a bad language, but there are a lot of new programmers who use it and think it's "super cool" to implement operator functions for everything they make, including stuff like overloading the = operator (which I have seen before).
I also have a couple friends from college who really enjoyed defining operator functions for everything... no bueno.
It gives too much power to the programmer to do everything that they want to do. Doing this creates messy code.
Swift
static func +(a: Type, b: Type) -> Type

Note that custom operators may be defined, and you can define stuff like the operator's precedence. I have not looked much into how these operators end up being used, though.
C#
public static Type operator+ (Type a, Type b)

Operator functions in C# end up being massively overused in my experience. People define all of the operators for all of their data structures. Might just be a consequence of using a language with many features, though.
Kotlin
operator fun plus(b: Type): Type // use "this" for left hand side

https://kotlinlang.org/docs/reference/operator-overloading.html, actually a really nice read.
Operator functions get used everywhere, and even the standard library is littered with them. Using them leads to unreadable code. For instance, what does mutableList + elem mean? Does it mutate mutableList? Does it return a new MutableList instance? No one knows without looking at the documentation.
Also, defining it as a method instead of a separate function just begs it to mutate this. We do not want to encourage this.
Open Questions
Which operators should be allowed to be overridden?
So, the mathematical operators +, -, *, /, % are pretty clear that if this gets implemented, we'd want to overload these operators.
List of remaining operators that should be considered for overloading:

<< and >> (I do not think this is a good idea)
|, &, and &^ (also do not think this is a good idea)
<, >, <=, >=, ==, != (maybe a good idea?)

If we include <, we should include == to prevent the confusing case of x <= y && y >= x but x != y.

Overloading equality may be a good thing. big.Int suffers because the only way to test equality is with a.Cmp(b) == 0 which is not readable at all.
I have left out || and && because they should be reserved exclusively for bool or types based on bool (has anyone ever even based a type on bool?) and see no reason to override them.
Should we even allow operator overloading on pointer types?
Allowing operator overloading on a pointer type means the possibility of mutating, which we do not want. On the other hand, allowing pointer types means less copying, especially for large structures such as matrices. This question would be resolved if the read only types proposal is accepted.
Disallowing pointer types

Does not allow mutation
No need for nil checks in operator implementation

Allowing pointer types

Allows operators to be consistent with the rest of the type's methods.

ie *big.Int is *big.Int everywhere else, it would be good for consistiency

Since it's consistent, it makes it easier to pass into other functions.

ie Can't pass big.Int into a function that takes *big.Int

Perhaps it should be a compile-time error to mutate a pointer in an operator function. If read-only types were added then we could require the parameters to be read-only.
Should it reference/dereference as needed?
Methods currently do this with their receivers. For instance:
// Because the receiver for `NewInt` is `*big.Int`,
// the second line is equivalent to `(&num).NewInt(....)`

var num big.Int
num.NewInt(5000000000000000000)

So should the same logic apply to operator functions?

I'm aware that this will probably not be added to Go 2, but I figured it would be a good thing to make an issue for, since the current issue for Operator Functions is quite small and, well, it's closed.

Edits:

Added #9455 to list of proposals which could be solved using this instead
Fixed a clarity issue
Changed examples to use a modular integer rather than a *big.Int since the math/big package is designed to be used in an efficient way, and added that read-only types would benefit this proposal

I do not like this idea. Because:

It increase the complexity of syntax, compilers, tools that read the language.
It decrease the readable of the code. It is much more difficult to answer the question "where is the code defined?"

It increase the complexity of syntax, compilers, tools that read the language.

Of course it does, it's a new feature. All features inevatibly will do this. Although if we're worrying about complicating anything, it should be the spec. Luckily a lot of the rules remain the same, the only things that change are allowing more things to be "operated" together with arithmetic operators.

It also increase the learning cost of the language.

Again, so does every new feature, and I'd say the learning cost is very small. People typically don't need to write operator functions anyway, as there are meant to be used much more than they are written.

It decrease the readable of the code. It is much more difficult to answer the question "where is the code defined?"

That is a valid critique, but ideally you should not be worried about what it does. It doesn't matter how 1+2 works, you care that it adds properly and you get a 3 in return. Operator functions should not do anything other than what you expect the operator to do.
I'd say it actually increases readability as well. Again, look at literally anything that uses math/big like this quick example. People who need stuff like math/big or a future decimal64 library can take advantage of this. Honestly, APIs for these things are quite terrible, and need to be because we need workarounds for these operators.

Also, it's defined the same place that methods are. In the package! So really the question "where is it defined" is a question that we already have the tools to answer.

It also increase the learning cost of the language.

I would argue the opposite. The current implementation of the math/big package is confusing and very hard to use. A very big improvement would be if it would just support operators and would act like the base number types. That would make it very easy to learn and use.

It decrease the readable of the code. It is much more difficult to answer the question "where is the code defined?"

The code readability is greatly improved. Again, math/big clearly illustrates that. As for "where is the code defined", that has little to do with readability, and the answer, as is right now, is of course: https://godoc.org/math/big

Another area that may be improved with such operator functions is the current generics proposal.
As it stands right now, writing a function to add 2 numbers would only be limited to the current numeric types. A hypothetical Sum generic function will never be able to work with big.Int, for example, or say, a custom rational number type.

I disagree. Only a small percentage of the math/big api can be replaced with the small set of binary operators defined in the language.

On 11 Sep 2018, at 17:47, Viktor Kojouharov<EMAIL_ADDRESS>wrote:
It also increase the learning cost of the language.
I would argue the opposite. The current implementation of the math/big package is confusing and very hard to use. A very big improvement would be if it would just support operators and would act like the base number types. That would make it very easy to learn and use.
It decrease the readable of the code. It is much more difficult to answer the question "where is the code defined?"
The code readability is greatly improved. Again, math/big clearly illustrates that. As for "where is the code defined", that has little to do with readability, and the answer, as is right now, is of course: https://godoc.org/math/big
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub, or mute the thread.

// each of the functions would have the following function body:
{
    return new(big.Int).Add(a, b)
}

I would prefer not to allocate a potentially large amount of memory for every arithmetic operation, especially if that operation looks like a normal arithmetic operation.
The package math/big is both well-designed and has a learning curve. The two qualifiers are conflated in some of the examples and comments here. The stated goal of this package was to provide efficient manipulation of big numbers. The current proposal should perform no worse than the current state of affairs.

I disagree. Only a small percentage of the math/big api can be replaced with the small set of binary operators defined in the language.

Yes, only a small percentage can be replaced, but what about how often those are used? (Also, this really isn't only for math/big, I mainly used it as an example because it has a very steep learning curve, and the code resulting from it is typically very messy and can be hard to maintain.

I would prefer not to allocate a potentially large amount of memory for every arithmetic operation, especially if that operation looks like a normal arithmetic operation.
The package math/big is both well-designed and has a learning curve. The two qualifiers are conflated in some of the examples and comments here. The stated goal of this package was to provide efficient manipulation of big numbers. The current proposal should perform no worse than the current state of affairs.

This is a good critique as well, but when all you want to do is to add numbers without having to worry about overflow, it could be extremely useful.
There could also be a separate type defined somewhere else with a less steep learning curve. After all, there is a pretty popular issue (#19623) to make int arbitrary precision. This could instead be a third party library (or in golang.org/x/) with operator functions defined for it.

Just as a quick demo as to how this could be implemented outside of math/big, which was a bad example (since it's designed to be efficient).
// A modular integer.
//
// `Reduce` should be called if you ever modify `Val` or `Mod` directly.
// As long as this is done, the `==` operator will work properly.
type Int struct {
	Val int
	Mod int
}

// Adds two modular integers and reduces.
// Panics if a and b do not have the same modulus
operator(Int) (a + b) {
	checkMod(a, b)
	nextInt = Int{Val: a.Val + b.Val, Mod: a.Mod}
	nextInt.Reduce()

	return nextInt
}

// Subtracts a modular integer from another and reduces.
// Panics if a and b do not have the same modulus.
operator(Int) (a - b) {
	checkMod(a, b)
	nextInt = Int{Val: a.Val - b.Val, Mod: a.Mod}
	nextInt.Reduce()

	return nextInt
}

// Multiplies two modular integers and reduces.
// Panics if a and b do not have the same modulus
operator(Int) (a * b) {
	checkMod(a, b)
	nextInt = Int{Val: a.Val * b.Val, Mod: a.Mod}
	nextInt.Reduce()

	return nextInt
}

// sets i.Val to its least nonnegative residue
func (i *Int) Reduce() {
	if (i.Val >= 0 && i.Val < i.Mod) {
		return
	}
	i.Val = (i.Val%i.Mod + i.Mod)%i.Mod
}

// makes sure a and b have the same modulus.
// if not, it panics.
func checkMod(a, b Int) {
	if (a.Mod != b.Mod) {
		panic(fmt.Errorf("mod is not equal: a(%d) b(%d)", a.Mod, b.Mod))
	}
}

This could also of course be used for other mathematical constructs such as matrices, vectors, etc. Also for arbitrary-precision integers, a bigdecimals, a elliptical-point, etc.

With operators there are 5 goals:

Disallow operating on different types
Not wildly exported to other packages, force re-declaring
Disallow mutating input args
Interact with generics well
Only one function that returns integer for operators <,>,<=,>=,==,!= negative positive and equal (zero)

I propose the following.  Operators should be a function calls with functions that are in general:
type T struct{}
func MyCustomAdd(*T , *T) *T {...}
func MyCustomSub(*T , *T) *T {...}
func MyCustomMul(*T , *T) *T {...}
func MyCustomMod(*T , *T) *T {...}
func MyCustomShr(*T , uint) *T {...}
func MyCustomShl(*T , uint) *T {...}
func MyCustomBwAnd(*T , *T) *T {...}
func MyCustomBwOr(*T , *T) *T {...}
func MyCustomBwClr(*T , *T) *T {...}
func MyCustomCompare(*T , *T) int {...}
Comparison is special, it is the "default operator", and maps all of the operators <,>,<=,>=,==,!=
Comparison is written like:
op default MyCustomCompare
Next the user can define also the other operators:
op + MyCustomAdd
If MyCustomAdd does not match the generic signature func (* , ) () this would be a compile time error. This satisfies point 1. Also, defining operator on a type that already has it would be a compile time error.
If the function is capitalized then the operator can be exported but must be also declared in the remote package, like so:
op + otherpackage.MyCustomAdd
This satisfies point 2.
All functions linked to operator will go thru additional type checking, to detect cases where you write to args and where you return something else than pointer to your own variable (this rule bans returning nil, also bans returning a and b):
func MyCustomAdd(a *MyInt ,b *MyInt) *MyInt {
var foo T // this must exist
a.x = 7 // cannot write to arg
if (yadda yadda) {
return nil // this cannot exist
} else {
return b // this cannot exist
}
return &foo // this must exist
return //this cannot exist
}
Operators that passed the additional type checking, will be internally optimized to something like
func(a *, b *,ret *).
Those who did not won't.
Next, generic function Maximum:
func Maximum (compare func (*, *)bool, ... things) (out *) {...}
Can be specially written as:
func Maximum2 (compare op default, ... things) (out *) {...}
Now comes the main point: Maximum requires either plain generic function or auto-passed "unoptimized operator".
Maximum2 requires optimized operator. If you pass optimized operator to function that requires unoptimized one, a wrapper  code will be generated and the wrapper passed.
Operators can be auto passed, like this:
Maximum(, T{},T{},T{},T{} )
Maximum2(, T{},T{},T{},T{} )
And used inside the generic function:
func Maximum2 (compare op default, things ... ) (out *) {
if things[1] > things[0] {
return &things[1]
}
return &things[0]
}
And the best part: compiler takes care of the boring details.
Like: promoting values to pointers when passing to operator functions. Creating wrappers for operators. Typechecking operator functions and returning compile time errors when you pass unoptimizable operator function to a generic function that has op param.

Could you edit to have your examples in code fences?
like this

would be
```
like this
```

Maybe a simpler syntax is also okay?
func (a int) +(b int) (int)

Just like a normal method, but with an operator rune as name.

Okay, I think you're micro-optimizing a bit here. The syntax should be simple.
Also, as a minor point, you don't need to dereference before using the . operator. The compiler does that for you since it's part of the spec.
I'd also like to add that read-only types (I'd link the proposal if I weren't on my phone) would work well with this proposal, as operator functions could require that all inputs are read-only.

I think forcing redeclaration of operators may lead to an "operator poisoning" of sorts... It would be especially inconvenient for people who use Go for mathematics to use a matrix, vector, and arbitrary-size int, and need to redeclare 50 operators.
Calling the comparison operators "default" doesn't make any sense to me.
I like the rest of the first part of your proposal, though. The second part not-so-much.

I am not merely speculating, I have a very serious intention to add operator overloading to my experimental language, named go-li. In fact I plan to do it next week, exactly how I propose.
Comparisons: Calling them default is wrong you're right. IMHO Most people would want to map all of them to the same function, in the C language tradition that returns negative int when a<b, zero when a==b, and positive int when a>b.
take look at this line:
func Foo(op comparison) {...}

How do you know that it is operator comparison, rather than parameter named op of type comparison? You don't know. Backwards compatibility is not 100% bulletproof. For this reason at least one of the words has to be reserved keyword, I propose:
func Foo(op default) {...}

or something like this:
op <=> MyComparison
func Foo(op <=>) {...}

or, alternatively, not using "op" but the "map" keyword to map operators.
map + MyAddition
func Foo(map +, map -, map comparison) {...}

alternatively, not using any arg names:
map + MyAddition
map <=> MyComparison
func Foo( +,  -, <=>, actual_parameter int) {...}

To prove it, here is example of code that uses generics, and would benefit from operator overloading. Fenwick tree (a data-structure that allows you to quickly sum a continuous sub-sequence of a large array.).
Fenwick tree in go-li language
Fenwick tree in folang
Fenwick tree example on folang playground
It needs the addition operator and negation operator , currently implemented using those callback functions.
The thing you probably disliked, is how we pass operators to generic functions. Trust me this is needed, otherwise people who don't prefer operators will have no way to call into generic functions that use operators. In this way they can, by passing the required concrete function that matches the callback signature as the parameter the way it is.
If we don't do this, the use of operators would spread like a disease:
i need package A
package A uses operators
therefore I define operators in my package so A can use them
since i defined operators i start using them (why not? they're already here)
suddenly my code is full of operators
other people need my package
therefore they define operators ... and so on

I'm 100% okay with binding operators to existing function calls. What I don't like is redeclaring the operators in every package that's going to use them.
I really would like a new "op" or "operator" TLD. It would make sure source code stays readable. It could still be backward-compatible as it is a TLD and would only be used as one.
I think the best syntax would be something like
op + CustomAdd

func CustomAdd(*T, *T) *T { ... }

The only issue is that this would allow
op + func (*T, *T) *T { ... }

Sure, you could say "just don't allow inlining here", but I feel like that'd be against Go's simplistic design. Perhaps instead preventing that should just be a go vet check.

TL;DR
Dear "go community", please read how its implemented in C++, then come back to this proposal. Also, you will probably need generics. And this is not trolling. @go-li has actually already brought up many valid points from that ecosystem in this thread.
Long list of comments:

Operator overloading beyond "i can do this" brings us to value semantics and abstract algebra, and requires several levels of constraints on types of the arguments to be done right. But it also allows to radically simplify all code dealing with Number-like object (i.e: the ones that have conceptual arithmetic operations available upon. E.g.: ints, floats, bigInts, matrices, complex numbers, quaternions, currency), and also provide convenience for things like Set operations (s1 + s2 == s1.union(s2)).
without equality (==) and its siblings (ordering / comparison) operator overloading turns into weak syntax sugar at best. Comparison operator definitions are a quite wordy, and so C++ plans to introduce <=> (starship) operator to simplify them.
while forcing totality on types (A, A)=>A sounds logical and cool, it will not let you implement [even such a simple thing as] multiplying matrix by scalar
regarding developer ergonomics, if operators are defined on types, then only packages using those types will have new semantics, and so developers would not be surprised by behavior of the operator.

I also don't like the idea of re-declaration. If I import a package that defines operators on its types then I don't have access to those operators? That kinda makes them useless. The whole point of operator overloading is to give them to library consumers. I, as a library implementer, don't care about them and don't really need them.
Also, I don't think we should look at C++. It has too much complexity that's very specific to C++ - value semantics, rvalue/lvalue, move semantics etc etc etc. It looks, frankly, ridiculous how it works rights now and committee understands that. <=>  tries to make it slightly better. There're better examples on how it can be done.

I would like to add some new insights to this topic:

when reading the original design goals of GO I thought this (operator overloading) would never happen
when going forward with this I would not reflect upon how other languages do it (see end of text why)
when implementing this we will quickly run into secondary decisions as operator overloading is closely linked to function overloading (same function name, different function argument types) and that is also something that GO was supposed to never implement

Proposed method for function overloading is via function names that SHOW both the operator and the position of the arguments.
Example 1:
func "_+_"(a,b int) (sum int) {
	sum = a + b
	return
}

Example 2:
func "_++"(a *int) (result int) {
	result = *a
	*a = result+1
	return
}

Example 3:
func "++_"(a *int) (result int) {
	result = *a + 1
	*a = result
	return
}

Example 4:
func "_[_]=_"(arr map[int]string, idx string, value string){
	...
}

Example 5:
func "_._"(arr map[string]int, value string) int {
	return arr[value]
}

As you see this opens much wider possibilities than old-style operator overloading but (and I have implemented this in an compiler/bytecode-interpreter language so I know) this is bothersome and if I would face it again I would not go for operator overloading at all.
The only thing why you want to do this is that GO currently is lacking some of the more excotic data containers but francly. I do not think that GO needs this.  It would change the language profoundly in a manner that makes it less distinct and less systematic (readable/predictable).
It also must be implemented on a low level in the parser and compiler so this change would be affect a large part of the code-base of the language.

I reflect on other languages to learn from them by their mistakes. We should avoid the _[_] = _ operator and such similar operators which do not reflect arithmetic types - this proposal is strictly for creating a way to represent arithmetic types in Go. The syntax you provide is intriguing though. I may draft a new proposal in the near future which is less about overloading operators. It's hard to explain in a quick comment but hopefully it should still be simple.

There is an important but implicit (and probably slightly hidden) trade-off in operator overloading, which is visible if you compare the proposed functions/methods signatures with the methods of math/big:
it is not possible to pass among the arguments a pointer where the result will be stored.
For example, let's consider addition between user-defined types: the syntax is not very relevant, it can be any of the existing proposals:
operator (*big.Int + *big.Int) Add
func Add(a, b *big.Int) *big.Int { /* must allocate a new big.Int and return its address */ }

or
operator(*big.Int) (a + b) {
  // idem, must allocate a new big.Int and return its address
}

or anything else.
In all cases, as highlighted in the comments above, the operator implementation must allocate a (possibly large) object where the result is stored. I used pointers *big.Int instead of values to make the issue more obvious.
On the other hand, math/big methods solve this issue by accepting an additional argument where they store the result - currently the receiver:
package big

// Add sets z to the sum x+y and returns z.
func (z *Int) Add(x, y *Int) *Int {
  // store the result in z: if its internal buffer is large enough, no allocation is needed.
}

Now, one may argue that the approach taken by math/big is a micro-optimization.
I am not really interested in discussing whether it's a "micro" optimization or not, but I think it's a very important optimization:
Imagine, instead of integers or floats, a library for linear algebra on arbitrary size matrices - for example "gonum.org/v1/gonum/mat":
if operator overloading is part of Go, authors and users of such library will be tempted to support it.
At the moment, they have methods similar in spirit to math/big, for example:
package mat

// Add adds a and b element-wise, placing the result in the receiver
func (m *Dense) Add(a, b Matrix) {
  // store the result in m: also here, if its internal buffer is large enough, no allocation is needed.
}

but operator overloading will not have the third argument, forcing to allocate it:
operator (Matrix + Matrix) Add
func Add(a, b Matrix) *Dense { /* must allocate a new Dense and return its address */ }

If you then write something like a + b + c + d on matrices, each + will allocate its result, which will need to be garbage collected at the end of the expression (except for the last one) - I expect it will be much slower than the (micro?) optimized
var Dense a, b, c, d, z
// initialize a, b, c, d and z. Then:
z.Add(a, b)
z.Add(z, c)
z.Add(z, d)

So my question is about the following trade-off:
the (hopefully) improved readability and simplicity of operator overloading (if used correctly and not abused) is worth the slowdown it causes due to multiple allocations and subsequent garbage collection?
P.S. one may attempt to solve this issue by adding an extra parameter also to overloaded operators, as for example:
operator (*big.Int + *big.Int) Add
func (z *big.Int) Add(a, b *big.Int) *big.Int {
  // fill z with the result of a + b and return z
}

but this only moves the problem from method declaration to method use, because when invoking such operator+ in many cases there is no receiver:
var a, b, c, z big.Int
// initialize a, b, c, d and z. Then:

z = a + b // a clever compiler may use z as receiver of operator+

z = a + b + c // z can be the receiver of the second addition.
                    // but who is the receiver of the first addition, i.e. a + b ?

@cosmos72 You make an excellent point, but I note that that compiler can convert z = a + b + c into z = a + b; z = z + c.  Any expression no matter how complex is just a sequence of unary and binary operations.  So the question is whether and when the compiler can reliably turn
t1 = a + b
z = t1 + c

into
z = a + b
z = z + c

That is, when is it safe to replace a compiler-introduced temporary variable with the final result of the expression, and, similarly, when it is safe to combine compiler-introduced temporaries?  It's a problem not dissimilar to register allocation with an unbounded number of registers, although it's possible that there are cases where there is some additional aliasing that must be considered.
Anyhow, I think the main point is, if we have operator functions, when writing the implementation there needs to be a way to express not just the operands but also the destination aka receiver.

Thanks @ianlancetaylor
Sorry for the second long post in a row - the analysis of "compiler-introduced temporary variables" and aliasing contains some subtle points and, if operator overloading is added to the language, they are going to affect Go programmers and compilers writers for a long time.
It is thus important to fully understand the consequences in detail, as they are non-trivial - I hope you agree it's the only way to make an informed decision.
Let's start from a concrete example:
package main
import (
  "math/big"
)
var _2 = big.NewRat(2, 1)

// compute z = ax^2 + 2bxy + cy^2 + 2dx + 2fy + g
func QuadraticCurve(z, x, y, a, b, c, d, f, g *big.Rat) *big.Rat {
  z = a*x*x + _2*b*y + c*y*y + _2*d*x + _2*f*y + g
  return z
}

The implementation surely looks enticingly similar to the mathematical formula.
Without operator overloading, the equivalent code is ugly, difficult to read
and requires some thought to write:
// compute z = ax^2 + 2bxy + cy^2 + 2dx + 2fy + g
func QuadraticCurve(z, x, y, a, b, c, d, f, g *big.Rat) *big.Rat {
  var t big.Rat

  z.Mul(a, x).Mul(z, x)               // z = a*x*x

  t.Mul(_2, b).Mul(&t, x).Mul(&t, y)  // t = 2*b*x*y
  z.Add(z, &t)                        // we can now reuse t

  t.Mul(c, y).Mul(&t, y)              // t = c*y*y
  z.Add(z, &t)                        // we can now reuse t

  t.Mul(_2, d).Mul(&t, x)             // t = 2*d*x
  z.Add(z, &t)                        // we can now reuse t

  t.Mul(_2, f).Mul(&t, y)             // t = 2*f*y
  z.Add(z, &t)                        // we can now reuse t

  return z.Add(z, g)
}

There is no need to highlight the advantages of the first version and the disadvantages of the second.
I will just say that the first seems a high-level language, while the second has an assembler-like look,
where variables take the place of CPU registers and are managed explicitly one by one - including temporary variables.
The disadvantages of the first version can be summarized in a question:
can the compiler be sufficiently smart that both compiled versions run equally fast?
(without artificially penalizing the second, obviously)
Let's see what a sufficiently smart compiler should do.

compute how many temporary variables are needed.

This is somewhat similar to register allocation, as you pointed out.
It can be visualized as a tree coloring problem, where the tree is the Abstract Syntax Tree (AST):
      z
      =
      +
     / \________
    *           +
   / \         / \________
  a   *       *           +
     / \     / \         / \________
    x   x   2   *       *           +
               / \     / \         / \________
              b   *   c   *       *           +
                 / \     / \     / \         / \
                x   y   y   y   2   *       *   g
                                   / \     / \
                                  d   x   2   *
                                             / \
                                            f   y

The tree coloring problem can be stated as follows:

All leaves have no color - nothing to allocate there, as the values are stored in existing variables.
All internal nodes (the + and *) must be colored i.e. their result must be stored
in some temporary variable. Each color is a different temporary variable.
The immediate children of an internal node must all have different colors:
you cannot store two (or more) partial computations into the same temporary variable.

Also, the compiler cannot take advantage of any mathematical property of the operators,
such as neutral element e op x == x, commutativity a * b == b * a,
associativity (a * b) * c == a * (b * c) and distributivity (a + b) * c == a * c + b * c
because the user-defined operators may not have such properties.
For example, matrix or quaternion multiplication is not commutative
and octonion multiplication is neither commutative nor associative.
In this case, the AST is quite simple and needs only two colors, i.e. two temporary variables:

a*x*x is blue (i.e. all its internal nodes are blue)
2*b*x*y is red (i.e. all its internal nodes are red)
c*y*y is red
2*d*x is red
2*f*y is red
and all other internal nodes (the +) are blue

analyze aliasing

What's aliasing actually?
One can attempt to define it as follows: if two values are aliased, they may reference the same data.
Thus modifying the content of one value may modify the other.
In our example, the "sufficiently smart" compiler should realize that z
is only used to store the final result, and thus, if it demonstrates that z
is not aliased to any other variable, it can directly use z
as one of the temporary variables.
This is a tricky point, both for programmers and for the compiler:
if z is aliased to some other variable passed to QuadraticCurve(),
the second version of the function will not behave as expected, i.e. it will produce
a different result.
Maybe it's a bug, maybe it's intentional (and hopefully documented), but in any case
there is no way to inform the compiler of such peculiarity. I.e. there is currently no
Go syntax to tell the compiler which variables may alias each other and which variables
are guaranteed not to alias each other.
C (not C++) has the 'restrict' keyword to annotate a pointer as "it will not alias
anything else", but a single mistake using it will introduce subtle and hard-to-find bugs.
Not something I would recommend for Go.
In Go, analyzing aliasing at compile time can probably be analogous to escape analysis:
when a function is compiled, its callers may not be known yet, so the compiler cannot
assume anything about the aliasing among its arguments, but it can analyze the aliasing
created or destroyed by the function body.
When local variables are created, they are not aliased to anything:
aliasing can only be introduced by storing shared data inside them,
or by storing the same slice, map or address into multiple places.
(Note: what about closures?)
In short, aliases analysis will probably be able to produce a proof "these two variables are not aliases"
only for local variables, and only if the compiler performs an aliasing analysis on each function
while compiling it, similarly to how it currently performs escape analysis.

actually creating "compiler-introduced temporary variables"

There is currently no uniform syntax for this.
Many types guarantee in their documentation (which a compiler cannot read) that the zero value is valid and useful,
but other types give no such guarantee.
Also, in many cases operator overloading will accept pointers to named types,
as the *big.Int used in the example above, and the "compiler-introduced temporary variables"
of type *big.Int must be a non-nil pointer to big.Int.
In general, if the compiler needs to introduce a temporary variable of type *T, should it call new(T)?
What happens if the zero value of T is not the right thing to use?
The solution I am currently experimenting with (for generics, which have a similar need for "user-introduced temporary variables") is the following:

a compiler-generated temporary variable of type T (which must not be a pointer)
is the value returned by 'zero.New()below, provided that the code compiles andzero.New()returns aT`
var zero T
zero.New()

if T is a pointer i.e. it is *U, a compiler-generated temporary variable of type *U
is the value returned by 'zero.New()below, provided that the code compiles andzero.New()returns a*Ui.e. aT`
var zero U
zero.New()

This is a way to introduce C++-style constructors in Go - New() becomes equivalent to a zero-argument constructor,
but I could not find a better way.
And it certainly has the disadvantage that Go code using operator overloading becomes harder to reason about: the compiler will invisibly insert calls to T.New()

@cosmos72 much work, chapou.
But the main point is just to have operator methods, like introduced by Mr. Griesemer in 2016. This is absolutely needed for a usable decimal implementation or other useful number formats. And for minimizing the core of Go. For example complex numbers could be implemented in a separate package.
Overloading is not needed or wanted.
That this works, can be seen here  https://youtu.be/vLxX3yZmw5Q and here https://github.com/griesemer/dotGo2016?files=1
Maybe I missed the point. For it seems quiet simple. Here is the proposal and the solution.
Motivation is business calculations: invoices, taxes, ... This is not possible without a good decimal implementation with usual operators.

@maj-o I was not discussing the syntax to define operator on new types - it can be operator overloading, operator methods, annotations, or any other proposal.
My work above analyzes the amount of garbage (temporary values) produced by operators on user-defined types, the techniques to minimize the garbage, and the limits of such techniques.
The reason is simple: less garbage means fewer allocations and fewer garbage collections, which translates to faster execution (provided the algorithm is not changed in other ways)

i would be a healthier person if "math/big" had operator overloading plz do soon :)

@deanveloper: oh yes, this (#35307) takes the wind out cosmos72 long posts. if simd, misd ... would work, then the compiler could perfectly optimize
a+b+c
of any type. That would be much better then internal variables or how old peaple would solve this problem stack pushes and pops.

My (very) long posts were meant to analyze the performance implications of operator functions on large and variable-size objects, as for example math/big.Int.
I perfectly agree that operator functions on fixed-size SIMD data (AVX/NEON etc.) would be very useful and do not need all that machinery - especially because they can (and should) be stored in CPU registers as much as possible

I'm kind of a newbie to Go but it ocurred to me if we already have the interface block, would it not make sense to define operators in there since interfaces define behaviour?

i’m not sure how you would go about doing it with an interface, since interfaces only describe already existing structures.

It think the definition of unary operators in the OP is a can of worms. For instance, taken literally it seams it opens up +"abc" to mean same as ""+"abc".
Ostensively this is because string concatenation is fundamentally different from mathematical addition (and it could be argued they shouldn't share an operation), but such is life.
IMO, while I appreciate the attempts at simplification, trying to ensure operators are only applied to "math", and making a minimal set of sane assumptions about their usage, to ensure we don't end up with C++, it should be noted that even many typical "math" notations will go against some of the more restrictive rules, because some algebras have different ideas about "zero", "unit", etc.
For example, unifying comparisons is a nice effort, but it should not be lost that many types will might have defined equality, but not defined order.
For another, the SO3 space of 3D rotations, typically represented by unit quaternions usually uses binary * for composition, and unary - for the conjugate/inverse (which as "wrong" as string concatenarion, and similarly violates the OP rules by defining unary - but not binary -).

I'm fairly new to go, and from what i saw i like this idea
i was reading through here and thought maybe changing this:
operator (Int + Int) Add
func Add(a, b Int) Int { ... }

to this:
operator (Int + Int) Add
func (a int) Add(b Int) Int { ... }

using the first operand in the func definition as a receiver, i don't have much to argue for it other then it looks better to me personally

That would actually be possible to write with the initial syntax using a neat trick!
operator (Int + Int) Int.Add
func (a Int) Add(b Int) Int { ... }

The Int.Add syntax takes what we would traditionally call func (a Int) Add(b Int) and instead evaluates it as func Add(a Int, b Int). See method expressions

Any update on this?

@k06a No updates.
The next big language change is going to be generics.  If the generics proposal is adopted and implemented, I doubt we will make another big language for some time.  So honestly I would not anticipate a change along these lines happening for some years (if ever).

Why not just declare it in the function's export comment? I'm pretty new to golang too but one thing I admire is how it makes comments an important part of the coding process. Something as simple as
// Add defines an addition operator for datatype
//go:operator (Int + Int) Add
func (a int) Add(b Int) Int { ... }
It seems like most of the problems people have with this proposal are the effects this has on gc or abuse. Both can be mitigated by just making sure the user is informed by forcing documentation.
I really hope this makes it into the language since it just make sense for us that do mathematical operations on matrices or vectors daily. It's about readability for me. Types with mathematical operations should follow mathematical syntax whenever possible so hand written arithmetic can better translate. This:
m1 := Matrix4x4{...}
m2 := Matrix4x4{...}
m3 := Matrix4x4{...}
m4 := m1.Add(m2.Mult(m3))
is just not as clear or readable as this:
m1 := Matrix4x4{...}
m2 := Matrix4x4{...}
m3 := Matrix4x4{...}
m4 := m1 + m2 * m3

I think @vwxyzjn's idea is solid, but would be more appropriate (and ergonomically friendly for those of us using QWERTY keyboards) if the prefix were . instead, partly for the reason that it helps clarify that it's a (slightly disguised) method call, and doesn't conflict with existing syntax when spaces are omitted.
Proposal
Operators may be optionally prefixed with .. For binary operators, this permits calling an identical method from the lhs(left-hand side), with the rhs (right-hand side) passed as an argument. Unary operators (obviously) call the method from the rhs. For all intents and purposes, these are normal method calls and definitions, and have no special requirements imposed upon them. They may accept any type a method accepts, and return any type a method may return.
Example:
package main
import "fmt"

type MyInt int
func (lhs MyInt) +(rhs MyInt) MyInt {
    return lhs+rhs
}

func main() {
    fmt.Println(MyInt(1) .+ MyInt(2)) // Prints 3
}

The key here is that the + operator is not overloaded by the normal definition, but supplemented with syntax that is reminiscent of a method call, because it is a method call.
Translated to current Go, the above example would be:
package main
import "fmt"

type MyInt int
func (lhs MyInt) Plus(rhs MyInt) MyInt {
        return lhs+rhs
}

func main() {
        fmt.Println(MyInt(1).Plus(MyInt(2)))
}

Overloaded operators would follow the exact same syntax rules as their normal counterparts, and would simply expand to rhs.Operator(lhs). I would like to think this could work well with the pending generics proposals, and involves relatively minimal syntax changes.
The language definition would require the following changes:
binary_op = ["."] ("||" | "&&" | rel_op | add_op | mul_op) .
unary_op  = ["."] ("+" | "-" | "!" | "^" | "*" | "&" | "<-") .

MethodName = identifier | binary_op | unary_op .

Commentary
I disagree with the original proposal, in that we should not assume what users need with regards to operators available for overloading; outside of the Go-sphere, symbols have any number of different uses and interpretations. An example I like to use is a Lua library called LPeg, which uses operator overloading to create something entirely new by reusing existing syntax.
Problems

(As above) It is not clear whether or not pointer receivers should be permitted.
It may be confusing that the method is defined as +, but used as .+. This may be at least partly remedied by drawing attention to the parallels between normal methods and the operators.
I am not 100% well-versed in the generics proposal(s), so I may be mistaken in my assessment of compatibility.

Nice! really an interesting idea :)
I think there's another, not so obvious, drawback: there is no way to specify where the result should be stored.
For example, math/big.Int defines addition as follows:
// Add sets z to the sum x+y and returns z.
func (z *Int) Add(x, y *Int) *Int

and is used as: result.Add(x, y).
This gives control over allocation to the caller which, if he/she wants, can avoid allocating a new big.Int for every arithmetic operation.
In the proposal above, one has to write instead x .+ y which is conceptually equivalent to x.Add(y).
If the representation of x and y are not fixed-size, it forces the implementation of Add
to allocate memory where to store the result before returning it.

I think there's another, not so obvious, drawback: there is no way to specify where the result should be stored.

This is intentional, in order to enforce that mathematical operators do not mutate their “arguments”. I had initially used math/big as an example in the proposal, but ended up removing it, because of the fact that all of math/big‘s struct’s methods mutate their members.
The main reason behind this is the same reason that types with a pointer as its underlying type are discouraged (and cannot have methods!). It gets very confusing when it doesn’t look like a function call looks like it isn’t going to mutate, and then something gets mutated without the user realizing it.

So, math operators for immutable objects only. Surely easier to implement.
My guess is it would not be a good fit for high-performance vector/matrix operations, or arbitrary precision numbers (math/big.Int, math/big.Rat, math/big.Float etc), or for anything that may require significant memory allocations.
On the other hand, at least in Python and Lisp, arithmetic on arbitrary precision numbers (Python long and Lisp bignum, ratio) is implemented exactly as you propose:
arbitrary precision numbers are immutable and operations on them always allocate new memory where to store the result.

Correct. The intended use case (for this proposal at least) is not for large matrices or anything like that. While I would like to improve this proposal to allow it, I can’t think of a good way of doing it without making it not feel like Go.
Possibly something along the lines of:
package big // import “math/big”

operator (*Int + *Int) addOp

// i is the memory address of the assigned variable
// a and b are the operands
func (i *Int) addOp(a, b *Int) {
    i.Add(a, b)
}

// usage:
// var sum big.Int
// sum = &sum + big.NewInt(100)
// var add = big.NewInt(6)
// sum = &sum + add

This way we can reuse pointers and avoid copying. I think the cognitive overhead might be a bit high though.

I wrote a proposal some time ago - it should still be somewhere in this thread - about operator overload with receiver used as (mutable) result.
The idea was something like
package big

operator +(*Int, *Int) = (*Int).Add

// Add computes x + y and stores result in z. also returns z.
func (z *Int) Add(x *Int, y *Int) *Int {
    // ...
    return z
}

and then teach the compiler that it should translate
var a, b ,c *big.Int
fmt.Println(a + b)
fmt.Println(a + b + c)

into
var a, b ,c *big.Int
fmt.Println(  new(big.Int).Add(a, b) )
fmt.Println(  new(big.Int).Add(a, b).Add(c) )

i.e. to inject compiler-generated temporaries to store the results, and reuse them where possible.
Definitely more complicated to implement than your (first) proposal, but more efficient at runtime.

This may be at least partly remedied by drawing attention to the parallels between normal methods and the operators.

I'm not sure the parallel with method calls is such a good thing: x .+ y .* z would be equivalent to x.Add(y.Mul(z)) while x .+ y .+ z would be equivalent to x.Add(y).Add(z)

I disagree with the original proposal, in that we should not assume what users need with regards to operators available for overloading; outside of the Go-sphere, symbols have any number of different uses and interpretations. An example I like to use is a Lua library called LPeg, which uses operator overloading to create something entirely new by reusing existing syntax.

I think this is exactly what we should try to avoid.
Except for + on strings, arithmetic operators should not lose their meaning, IMO.
There's probably a widespread need for "real world" types such as decimal types ("big decimal", fixed point, floating point, or just bigger ints).
This is what we (humans) read and write.
We have them in UIs, SQL databases, literals in our own code, and, most importantly, our paper notes.
These types would naturally use the same operators as int and float, with same precedence rules and same meaning.
(talking about + - * / % and all comparisons)
Vectors and matrices are out of scope IMHO.
I also think we don't need mutable receivers.
I would be more than happy if I had a decimal128 with operators but had to use method calls on a big decimal type, just like big.Int Vs. int64. And the cost of copying a decimal128 would rarely matter.

While I like the idea, it gets a little more complicated... first of all with operator +(...) = (*Int).Add
The Add method both returns a value and mutates its receiver (which it also returns). This causes a couple complications when we aren’t talking about math/big. For instance, if the returned value is different than the receiver, then we run into a predicament with translating a = b .+ c. Instead, I propose the “signature” of operator would look like operator (T <op> T) = func (*T, T, T).
To get this to work with pointer arguments, you would use a double-pointer as the first argument. This is because the operator function needs to be able to assign to the lvalue, which is a pointer. This would allow flexibility between usages for value-types and pointer-types being used as operands.
operator (*Int + *Int) = func (lvalue **Int, a, b *Int) {
    (*lvalue).Add(a, b)
}

The signature is a bit more confusing for pointer types... although I think that operators for pointer types should be pretty niche. Also it’s not super confusing when essentially all it means is “we allow ourselves to change where an lvalue points to”.
Usage on the “calling” side of the operators remains the same and much less confusing:
var a, b, c *big.Int

a = b + c

fmt.Println(a + b + c)

translates to
var a, b, c *big.Int

a.+(b, c)

var _temp = new(big.Int)
_temp.+(a, b)
_temp.+(_temp, c)
fmt.Println(_temp)

Typed this on a phone, apologies for any typos

I see a lot of "we don't need this (implicit: for the use I have in mind)"
and very few general proposals that try to cover all reasonable cases where other languages use operators or operator overloading, namely:

arithmetic on arbitrary precision numbers
arithmetic on bound-checked or saturating numbers
arithmetic on elements of finite fields
arithmetic on vectors and matrices
arithmetic on quaternions, octonions...

and surely there are more reasonable cases I do not know about.
Some of them require large and variable-sized representations, which means memory allocation and usually involves pointers.
Some of them will/would be used in situations where performance matters, possibly a lot.
Some other will be used in situations where ease of writing the code (and source code readability) is instead the most important consideration.
Yes, it's possible to write a proposal that intentionally addresses a subset of the use cases.
But that would close the door for a very long time to the use cases that are left out - so in my opinion
the author would better have (and describe) a very good reason to leave out such use cases.
That's why I came up with a proposal that internally uses explicit receivers, and modifies and returns them:
the syntax and readability of overloaded operators is not changed, but internally it allows for a more efficient implementation, especially if the things being added/multiplied/etc. are large and may need to allocate memory.
Surely, it's more complicated to implement - both inside the compiler and for programmers that want to add operator overloading to their types - but it's not more complicated to use: one still writes a + b + c or a .+ b .+ c or whatever the chosen syntax will be.
I wrote my opinion, and I will now stop flooding this thread :)

Operators should only operate on and return a single type

It would be nice to be able to write e.g.
time.Now() + time.Hour

As sugar for
time.Now().Add(time.Hour)

While I somewhat agree that it looks nice, by the communative property of addition, we would also infer that time.Hour + time.Now() would be valid. That would either translate to something like time.Hour.Add(time.Now()) which doesn't make sense, or time.Now().Add(time.Hour), which is confusing since it's out of order. Or we could throw a compiler error, but that'd mean that addition is no longer communative, which may also be confusing.
Also, while it might look good for times, what about the following:
var i pkg.Uint
var j pkg.Int

k := (i + j*i) / j

If they were all the same type, this would make a lot of sense. However, because they are different types, it isn't clear what is going on here. What is the type of k? the type of (i + j*i)? What if j is negative, but the numerator resolves as pkg.Uint? Since the type of each expression is not clear, how do we address overflow/underflow bugs?
Not to mention, it's not going to be easy to separate the values:
k := j*i
k = i + k // possible compiler error
k = k / j // another possible compiler error

Moral of the story, which we have learned from several languages in the past: we should not allow operators over different types. It gets extremely confusing.

@deanveloper:
To illustrate @evrimoztamur's point, there's already precedent for non-commutative operators in Go: String concatenation. "a" + "b" is very much not the same thing as "b" + "a". I see no particular reason that user-created operator meanings would have to follow that rule, either.
That being said, I agree that operators over differing types would be a bad idea. I'm not particularly in favor of operator overloading in general, but if it was added I would want it added in a limited capacity. User-defined operator overloads should get no special privileges over the built-in ones in my opinion, and outside of interfaces, which are very different from all other types in Go, I can't think of any regular binary operator that takes multiple types simultaneously.

Not sure of how to partake in the conversation. Should probably start by reading everything. But on the off shot that you'd forgive a hasty post: couldn't the lexer take a + b and map it to the standard work-around a.Add(b). I've only just picked Go up, but am hoping that this would be as agreeable as some of the other pragmatic solutions such as the ambidexterity of the dot operator between pointer and direct struct values....

Am I understanding the gist of the resistance to this point correctly:
The community is against the change because of the complexity and confusion of implicit type checking and the unbounded depth that could reach in users hands. The users expect that they'd be able to write multiple overloads for the various combinations that the infix notation could be called upon, or write a generic subset that would require some kind of hierarchical type inheritance and smarts in order for the expected types to be inferred etc.
Couldn't we do away with the majority of the complexity, and inhibit any confusion, by keeping the language's limit to a single function definition (no actual overloading), and just implementing the syntactic replacement (a + b to a.Add(b)). Thusly the one definition (specified by the infix arguments' types) would have a clear return type and definition. The intermediate values would be explicated, the function definition singular, and the sugar gained. Complex chains of the infix sugar would possibly need inline conversions or field-referencing, but that's just upholding the specificity criterion of clear code.
This might only cut back on the expectations of the users, but this limited/restricted option seems like it would be inline with the community's goals for the language. Happy to learn from your responses!

It's not the same.
1*2+3=6
1.mul(2.add(3)).=5
Main reason for this is to have a decimal type.
Perfectly arbitrary precision decimals, search.

@RocketRoss

This might only cut back on the expectations of the users, but this limited/restricted option seems like it would be inline with the community's goals for the language. Happy to learn from your responses!

Generally, part of the requirement for language changes is that they must the needs of everyone who has the problem. (This is why all of the error handling proposals to date have been rejected, for example.) Limiting user operators to a single argument type does not meet the needs of people who want them for linear algebra, as a broad use case, because it does not allow one to distinguish between matrix and scalar multiplication. So, I don't think this approach can be considered acceptable.

Generally, part of the requirement for language changes is that they must the needs of everyone who has the problem.

Doesn't that make this problem intractable? Some participants (in both error handling and operator overloading) have mutually exclusive needs.

The folks doing linear algebra may want to define signatures for all manners of different matrix shapes and operand types.
Those looking to write vector operations may want to define totally new operators i.e. for dot or cross products.
Those who want code to be predictable may want only one operator signature per type, all following predictable integer semantics.
Those who don't want the + operator to be able to panic may not want any of this at all.
And I want to define DSLs using operator overloading in unusual (some would say "wrong") ways.

Each and every one of these is a valid viewpoint that's been presented in this thread. 1, 2, and 5 conflict with 3 and 4. 2 even conflicts with the language design, as infix operators are limited, and changing that would likely require major language specification, lexer, and parser changes.

@maj-o 1*2+3 is always 5. But taking your point as 2*1+3, the sugar substitution would follow the operator precedence, avoiding any increase in confusion:
playground
2*1+3 = 5
2.Mul(1).Add(3) = 5
2.Mul(1.Add(3)) = 8 // this would not be the result of sugar substitution following precedence
2+1*3 = 5
2.Add(1.Mul(3)) = 5
2.Add(1).Mul(3) = 9 // this would not be the result of sugar substitution following precedence

Regarding the intractability.. I'm wondering if the following reduced implementation wouldn't be just a minor lexer change, and less so a language alteration, hopefully reducing the number of benefactors' boxes that need to be checked for justification:
Let's start with the most basic extension to Go-Lang towards achieving something in this direction:

Mathematical operators (a subset at least) between user-defined types (particularly structs) are replaced with a corresponding named function (+ -> .Add etc.).
The replacement follows the operator precedence.
It will be expected that the named function return a value (of whatever type the author deems reasonable), so that chains of operators are applicable.

We would not be considering:

adding carte-blanche for new operator definitions (tough on the dot vs cross product, but I imagine some inline conversion to a wrapper struct, with the alternative .Mul definition, could be a more suitable work around than the current named functions, see the attached playground)
implementing function overloading (cannot define T.Add(U) and T.Add(V)... I imagine some more expansive sugar substitution would handle T.AddU(U), T.AddV(V) etc...). Thus all operator substitution candidates that are created will likely have homogenous operands, and be scoped to the author's source code.

I don't see any room for ambiguity arising so far, and I do see a simple improvement to the language being achieved: time.Now() + time.Hour and similarly for user-defined types that are purposed for math or numerical analysis...
What am I missing in the considerations? I don't mind a hard no if I can understand why not. I'm viewing this as a lexer capability that is on par with the (&v). substitution to invoke pointer-receiver definitions. Am I wrong?

One thing missing from your proposal is consideration of memory allocations:
if a and b are types that contain heap-allocated data, for example because they are vectors, matrices or arbitrary precision numbers (see math/big),
then translating a+b into a.Add(b) means the returned value will have to be created from scratch,  including allocation of its data in the heap.
That's why types in math/big define arithmetic operations differently: z = a + b is written as
z.Add(a, b)

which stores the result into an existing z: if its internal heap-allocated data is large enough, it will be reused, avoiding any allocation.
There's also a general principle for it: receive buffers from the caller and use them (write your result there), do not allocate them yourself and return them.

Nice point... Let me know if my interpretation is off:
Pointers are the perfect mechanism for specifying 'buffers' to the callee. Indeed my understanding is that is there sole effective purpose.
a+b written anywhere needs to occupy some new memory, right? if a+b > x etc, so the z.Add(a, b) seems quite gross to me, unless it's more specifically to minimise allocations during chained additions, e.g. z.Add(a, b).Add(c).. I mean is that allowed? Surely not because that would be overloaded... I don't think I'm understanding the z.Add(a, b) design decision. I also think that z := a + b is far more in line with Go than var z Big; z.Add(a, b)...? (not trying to derail to conversation on Big's decisions, just hoping to learn from reactions)
In critical positions, one could exercise heap pedanticism with z := Big(0); z += a; z += b; z += c;. There asides maybe this is the point where some more smarts need to come to play (i.e. I concede):
it would be nice to have  a + b + c not produce 2 allocations, but instead to have the second addition be more of a += operation on the first allocation. I'm not sure of the contemporary approach to this, but surely other languages have either mitigated it or deemed it acceptable. Maybe the

z.Add(a, b) may be gross, but we got there because experience showed us that memory allocation is the dominant cost of using types like big.Int.  People writing efficient code with math/big have to be able to control the memory allocation of every operation in order to avoid unnecessary allocations.
This is definitely a concern with operator overloading, if we want to be able to use operators with types like big.Int.  And since big.Int is more or less a poster child for operator overloading, I think that some solution is required.  That solution could perhaps mean writing down rules for how the compiler is required to combine assignment with operators.  I'm not sure.

@ianlancetaylor can contradict me if he wants,
but I think the three-argument methods to perform arithmetic on arbitrary types (z.Add(a,b) etc.) are really the only reasonable way to go.
Self-assignment operators z += a; z *= b; z /= c certainly help keeping allocations under control, but fail short of the (in my opinion) first main goal of operator overloading:

source readability and expressiveness: write simple, naturally-looking high-level source using operators, and let the compiler figure out the details

In other words, if operator overloading is ever implemented in Go, it would really better allow writing things like
z = a + b * c / d

The second goal (still in my opinion) of operator overloading is:

Go toolchain should compile such high-level source to reasonably efficient machine code - i.e. something that minimizes heap-allocation of temporaries, not code that heap-allocates one temporary for each operation.

Some time ago I wrote in this thread an analysis about how to reach both goals at once.
It's somewhat complicated but feasible - it starts from three-argument methods z.Add(a, b) and analyzes what the compiler must do to minimize the number of temporaries.
I'm afraid anything simpler than that will fall short in at least one of these two (somewhat competing) goals. i.e. source readability/expressiveness and runtime efficiency.

Hi all, because we now have generic, can we utilize it?
for example,
we can define + and * as built-in function
func OpAdd[T interface{ OpAdd(T) T }](a, b T) T { return a.OpAdd(b) }
func OpMul[T interface{ OpMul(T) T }](a, b T) T { return a.OpMul(b) }

and also add OpAdd and OpMul method to basic types like
func (a int) OpAdd(b int) int { /* compiler intrinsic of a + b to avoid recursive call */ }
func (a int) OpMul(b int) int { /* compiler intrinsic of a * b to avoid recursive call */ }

and then we can convert the expression
a * b + c * d

into
OpAdd(OpMul(a, b), OpMul(c, d))

with that in place, we can easily implement an operator for a custom type like this one https://go.dev/play/p/h_SVp8-Gjl8
In summary:

adding built-in function Op*** into language spec
adding built-in method Op*** into language spec
we need to change the compiler to convert the normal binary expressions into function calls into the built-in Op*** function (honoring the operator precedence)
we need to change the compiler to generate all the built-in Op*** methods to the basic types

This, or something more or less similar, can be implemented without language changes now that we have generics.
The language changes are "only" needed to be able to write
a * b + c * d

instead of the more cumbersome (but explicit)
OpAdd(OpMul(a, b), OpMul(c ,d))

(although I'd still recommend three-argument operations, with the receiver being used to store the result, to avoid unnecessary memory allocations for large objects).
Clearly, this issue is a proposal for operator functions, so the OpAdd, OpMul and friends alone would not address it.

It has been fairly well established that the Go developers do not want operator overloading in the language, and I'm inclined to agree with the reasoning given, namely that it can disguise an expensive operation as though it was just addition or something, and there's no way to know what it's really doing at the call-site anymore. With the exception of string + string, all operators in Go currently are O(1), which is actually very nice. While operator overloading could certainly be convenient in some situations, such as math/big, I don't think that it's worth the complication that it introduces.
Maybe infix functions would be a better approach, so that you could do a plus b. I don't think that it really gains much over a.Plus(b), though.

Maybe infix functions would be a better approach, so that you could do a plus b. I don't think that it really gains much over a.Plus(b), though.

what do you suggest to handling precedence @DeedleFake ?

It was just a random thought, not an actual suggestion, but probably just simple left-to-right would be the least surprising.

(although I'd still recommend three-argument operations, with the receiver being used to store the result, to avoid unnecessary memory allocations for large objects).

I think for big.Int, we would only have Op***Assign family (with pointer receiver), but not OpAdd or OpMul (with non-pointer reciever)

If being O(1) is an issue, we should probably remove operators from floats, as I'm pretty sure most people are not familiar with the fact that operations on some floats can be more than two orders of magnitude slower that operations on other floats.
Operator overloading, if added, will be abused. Not adding it and also not making types that'd benefit greatly from it (decimal, vec3, mat4, quaternion, big.Int…) native so that they could use them makes Go less useful in fields that need it.
There's no avoiding the trade off.

many say that operator overloading will be abused to the point that the code is hard to understand.
but from what I learned from Haskell (I'm not saying I'm an expert on it), as long they form semigroup (in other words, the types must always be the same), I don't see how it will be abused.
so *T will only be addable to another *T but not T, and vice versa T is only addable to another T but not *T
operator overloading in other languages like C++, where you can define multiple of it and the types are not the same, of course, will make the code harder to understand
can someone give an example of how it is abused?

In Go today a * b always executes in roughly constant time, never allocates memory, and never panics.  If we permit operator overloading none of those will be the case.

My understanding is that it is common to prohibit the use of operator overloading on large projects where code complexity is a concern, for example in game development (allowed for simple implementations) and mars rover environments (strict prohibition).
My experience: I have worked on several numerical libraries that deal with quat, vector and matrix operations, the whole lot of it. There has been only one case where I regretted the fact there was no operator overloading in Go, it was when I had to work with the big.Int type. This was early on in my Go career and today I think the reason I felt this was bad API design of the big package. Having functions for operations instead of methods does so much more for readability.
So I'd rather not have operator overloading. It seems to be a language feature undesirable by those who practice software engineering and I don't have a need for it to develop numerical libraries. There are other more pressing issues regarding Go in a numerical setting than the lack of syntactic sugar.

All I want is generic support in operator overloading, with full support for all operations, with generics support.
Let me overload any operator that is supported; Type constraints as I have seen theme in go don't define these well enough because we are missing critical binary and logical operations, and are not able to do things like using constraints.Unsigned to write generic code that leverages operator overloading.
Let me do that!

operator overloading introduces a huge complexity, either in compiler implementation and code maintaibility, which is also the root of the expansion of C++ complexity IMHO.

I would love to be able to write code that can simply be leveraged with type sets that I've previously defined. Let me use the composition of objects to define what they are.
You can't tell me that you want to enable composition over inheritance as a core design constraint, and then tell me that I can't compose objects without begging the question if that violates the design by making custom composition harder.  Not to mention, it seems kind of contradictory.. and unfair. The fact is, while operator overloading for things like (+) and (-) might seem odd, for distinct sets of data and various models in some very distinct domains, it makes a lot of sense and enables separation of concerns and DRYing that leads to cleaner code.
For example,  I should be able to add a Money type to another Money type with (a + b).  I'm possibly going to have to make sure the two currencies are the same, or I can enable functionality around exchange rates through. But the fact remains, no matter what I choose to do, it's kind of important that I have full control... if only for compliance and auditing.
I fully understand that people shouldn't be messing with operators in ways that could create bad code; But the community can't even agree on what that is half the time. I'm sure we can all point to tech that just seems wrong, but trying to design against bad code will only get you so far. And in many ways, it'll force people to create bad code to get around the artificial constraint that you imposed with good intentions that got in their way while they were just trying to do their jobs.
All I'm asking is that, if golang is truly about composition, that we truly go into and enable composition.   Let me compose my objects. Not just to define the methods that are a part of an interface, let me define the operators that must be enabled for the interfaces used in the process I have defined.
The current solution only enables half of the problem.

That operator overloading will never happen in GO was one of the very first design strategies.
If you as GO user feel that you are missing something then you can not resist the temptation to produce unreadable code (and should switch back to one of the plenty languages in which such is possible and customary).
Sorry I don't want to be rude but operator overloading was one of the worst mistakes in computer history.
I'm a senior programmer with 40 years of experience in about any programming language and system that exists(ed) including multiple self created scripting languages and I'm also the person who ported Python to the VAX/VMS platform.
Just take my word for it, operator overloading in GO may never happen and that is one of the foundations of GO.
This ongoing conversation ONLY exists to prevent future users from creating duplicate proposals here.

I apologize, but as respectfully as possible, I have no idea who you are,  and I do not believe that your opinion alone is worthy of accepting as fact.  I'm bringing you data and examples and asking questions; you are replying with insults and accusations.
The unproven personal attacks against me and others who simply disagree and have data to show for it are unprofessional; It's fine for you to have opinions, and I welcome your opinions and that data you want to share to back them up, but you should be willing to admit when you don't have data to back them up.
I'm actually a big fan of DRY and SOLID and personally enforce these in my projects; So your incorrect assertion that this would generate bad code 100% of the time is flat out wrong. I gave you a great example above: and I explicitly defined the concerned boundaries.  I respectfully understand that if you disagree with me,  that's one thing, But you shouldn't be making random arguments without data either, because with all respect, I'm bringing examples and data to you... and all you're doing is replying with opinion and insults.
Your 40 year of experience is great, but it's not the sort of thing that can end an argument without data.   Where is the data?

Looks like you have not tired the complex expression!

Given the power of the fmt.Stringer interface in golang, its important to consider that effectively this is another perfect example of why you would want type conversion that you can inject your own code into as a form of operator overloading; in this case it's simply of a string composed of a Strategy taking the prior typed instance as input and returning a string.
What's important here is that we can inject that strategy ourselves. The value is that we have control over the code in the resulting callback; and the fact that it's used by so many things gives it more utility.

I propose a comprehensive package of enhancements for Go, which includes operator overloading, lambda functions, as well as getter and setter methods similar to C#.
In order to control potential side effects - a prevalent concern with these features - my suggestion is to implement operator overloading, and getter/setter methods through lambda functions in Go. These lambda functions should only allow conditional expressions, effectively preventing side effects. This approach could provide a layer of control not currently available in Python due to possible side effects with lambda functions.
Furthermore, within these lambda functions in Go, I would suggest disallowing function calls. We should only permit further lambda expressions and constructors. This approach would ensure the purity of the lambda function and maintain a level of simplicity and straightforwardness in the code, which is in line with Go's philosophy.
This comprehensive package could open up new patterns and capabilities in Go, while effectively managing the risk of side effects. Each component must be carefully considered and implemented to ensure consistency with the existing language philosophy and objectives.
I understand that any change to the language needs to be meticulously planned and executed considering its potential impact on existing code and the learning curve for the community. However, these are my initial thoughts and I'm eager to hear feedback and insights from the community on this proposal.

That operator overloading will never happen in GO was one of the very first design strategies. If you as GO user feel that you are missing something then you can not resist the temptation to produce unreadable code (and should switch to one of the plenty languages in which such is possible and customary). Sorry I don't want to be rude but operator overloading was one of the worst mistakes in computer history. Operator overloading HIDES function calls (these are not visible in the source code) causing code that can only be read by those who created the program. It is like hiding easter-egg functionality in a program but at a large scale. I'm a senior programmer with 40 years of experience in about any programming language and system that exists/existed including multiple self created scripting languages and I'm also the person who ported Python to the VAX/VMS platform. Just take my word for it, operator overloading in GO may never happen and that is one of the foundations of GO. This ongoing conversation ONLY exists to prevent future users from creating duplicate proposals here.

Stephan Veenbeck presents some commonly expressed concerns about operator overloading: it can make the code difficult to read and hide its functions, leading to confusion and errors. These are valid concerns that should be considered in the discussion of potential enhancements for Go.
A potential approach to addressing these concerns might look like this:
Clarity and Readability: Operator overloading needs to be implemented in a way that maintains the readability and comprehensibility of the code. Careful design and clear guidelines could help prevent misuse and restrict the use of overloaded operators to logical and easily understandable ways.

Use Control: Operator overloading should be restricted to specific and appropriate use cases. A possible solution could be to allow it for certain types or in certain contexts to ensure that it does not unnecessarily complicate the code or hide what's actually happening.

Existing Practices in Other Languages: While operator overloading has caused problems in some languages, it is effectively utilized in others. It's worth examining the practices and experiences from these languages to identify possible problems and find solutions.

Community Feedback: It's important to consider the feedback and concerns of the community. A dialogue with users could help address concerns and lead to a solution that can leverage the benefits of operator overloading while also preserving the readability and comprehensibility of the code.

It's crucial to note that introducing such a change needs to be carefully thought out and planned to avoid unwanted side effects. Ultimately, any changes in the language should aim to enhance developer productivity and satisfaction without compromising the principles of simplicity and clarity that have made Go what it is.

there are a simpler solution to the operator implementation.  Just allow more characters in the definition of the name of a function similar to what scala does it and allow for infix notation for single parameter functions.
currently:
type MyValue struct {
value int
}
// Defining a + for the private field
func (r MyValue) add(v *MyValue) MyValue {
return MyValue{r.value+v.value}
}
use currently as:
val1.add(val2)
new:
type MyValue struct {
value int
}
// Defining a + for the private field
func (r MyValue) +(v *MyValue) MyValue {
return MyValue{r.value+v.value}
}
// Defining a ++ for the private field
func (r MyValue) ++() MyValue {
return MyValue{r.value+1}
}
use new as:
val3 := val1 + val2
this way anyone can add "new operators" such as:
~>() >>>()  <--->() etc.
it will get interesting for the * and & operators

There is two cases in my develop experiences.

Add (operate) two same type value.

This case is simplify for developer:
type Point struct {
	X, Y int
}

func (p Point) Add(other Point) Point {
	return Point{p.X + other.X, p.Y + other.Y}
}

func main() {
	p1 := Point{1, 2}
	p2 := Point{3, 4}
	fmt.Println(p1 + p2) // Output: {4 6}
}

Compare two same type value.

type Block struct {
    PrevHash []byte
    Hash     []byte
}

func (b Block) Compare(other Block) bool {
    return bytes.Compare(b.PrevHash, other.PrevHash) == 0 &&
        bytes.Compare(b.Hash, other.Hash) == 0
}

func main() {
    b1 := Block{[]byte("p0"), []byte("h1")}
    b2 := Block{[]byte("p1"), []byte("h2")}

    m := map[Block]struct{}{
        b1: struct{}{},
        b2: struct{}{},
    }
}

At least we could implement a custom optionalChaining operator even though this was dismissed with such an option. Would love to see custom operators They can be limited but having the ability would come a long way.

I'm a little worried about whether this will turn golang into another python. For example, if we customize a symbol like @ for matrix multiplication, this is equivalent to inventing another operation, and its behavior is confusing. What I mean is that only by consulting the documentation can you know the difference between it and *.

I think it is okay if the operator symbol is not overloaded with existing ones.
if you encounter a weird symbol like *. or +., it just means that you need to look at the docs,
it is just the same when you encounter an unknown method name, you look up the docs.
an infix operator is just another form of a method invocation, but it is more readable.
((a +. b) *. c) +. (d *. e)

vs
a.Add(b).Mul(c).Add(d.Mul(e))

you can know that if it is not a standard operator symbol, then it must be a method

I don't personally think this serves any good purpose that solves a specific problem.
It's just syntactic sugar without making something more readable necessarily, neither serving any compilation or type-safety purpose.
From my understanding, which might be wrong,
I think this proposal about operator functions comes from other languages that may have this functionality on top of them.
But, why? What problem does it solve?
Okay, fair enough this example from @win-t is fair

((a +. b) *. c) +. (d *. e)
vs
a.Add(b).Mul(c).Add(d.Mul(e))

Although, I see a fair bit of prons and cons in this one where the cons are more than the pros
Pros

Easier to write and read
Easier to comprehend what this code is doing

Cons

Give me a real life example, where you would actually use that? How frequent would that example be in real life? Is it so frequent that it becomes a struggle in everyday programming? Or is it a once in a year I may need that? And after all, it's just syntactic sugar. Not syntactic sugar like Assembly to C, or for i, n := range objects, but like a self-explanatory code being translated to literal keywords of the language itself. This breaks simplicity by nature. You have to know what those operators on those objects are actually doing. When with a function, its very easy to read the documentation or read the name of the function.
Proposal of a feature that people may misuse for the sake of using it because "it's cool". It happens often. Hate me, but it happens often that people use features just because they exist. That what was the whole debate over generics anyways, wasn't it? For which I advocate for. But I agree that people may misuse generics. Difference is that generics have many real life examples and already the standard library starts using them because they are indeed useful.
Proposal proposes a way to Add(), Mul() etc. an object, when the side-effects may not be apparent what they exactly do, and the user might expect something else from what is actually happening under the hood. People won't hover over +. to see what it does on these objects. But people will hover on what AddMatrix() does to ensure what it does. This offers safety and less bugs.
Abstractions. Abstractions are just purely syntactic sugar for the sake of making an abstraction.
This ((a +. b) *. c) +. (d *. e) makes sense when you have Integers or any numerical types. This a.Add(b).Mul(c).Add(d.Mul(e)) makes sense when you have structs where you don't actually know what an operator actually may actually do and what side-effects it has.
+, - * all these serve a very specific purpose in a language. And by overloading those operators, you're breaking that purpose. Now you're start doubting what an operator actually does.
In a.Add(b).Mul(c).Add(d.Mul(e)) you may just explain on top of what this chained functions are doing. It's not like ((a +. b) *. c) +. (d *. e) is easy to understand either on what exactly it is doing and why. So, you have the same problem here, in neither case, you know why you're doing that operation in the first place. So .... you're gonna have to place comments on top to explain to future programmers what this is doing anyways.
Now I have to distinguish primary type operators with object type operators? This is just breaking simplicity of the language. Now I have to be aware of where there is a primary type operator vs an object type?

For the fairness of all, I agree, ((a +. b) *. c) +. (d *. e) is more readable.
Absolutely right it is.
But for numerical types.
When you're not dealing with numerical types, how are you gonna know what is that overloaded function is doing under the hood, how are you gonna differentiate easily between primary type and object type operators (no a simple +. [dot] is not doing it :P it's even more confusing because the difference is so small). What are the usecases of this and how often are they. What problem does it solve, when do we actually need huge computational operations between objects and why not just do them inside the objects themselves if they're so huge?
tl;dr; I see 100:1 problems/what it solves on this proposal and bringing much confusion.

Hi, just want to clarify

(in this specific example) The +. ... the dot (.) is simply just distracting. Now it makes it kinda even unreadable. For the sake of what? Having operator overloading? It can be fair, if operator overloading indeed serves a very good purpose, but let's go through that.

+, - * all these serve a very specific purpose in a language. And by overloading those operators, you're breaking that purpose

the dot (.), is just an example, it doesn't need to be a dot, we can use any symbol that not distracting, but it's enough to communicate "it is not a normal operator, look up the docs", another alternative might be @+ @*.
I want to make it clear, you cannot overload existing operators, no overload for + - * /, +=, *=, ...
one may argue, that we will have multiple definitions of the @+ operator in the codebase, as everyone can define one for their type, it is not as uniform as the normal + operator that will have the same meaning anywhere in codebase.
But the same situation also arises with normal methods, everyone can define Add() for their type, and for both situations, you are expected to look up the docs to understand its purpose, does it have a side-effect, etc ...

But for numerical types.

I can argue, that the correct usage of the custom operators might be not just "numerical" types, but any types that resemble mathematical sense (group, semigroup, monoid, ...).
In the end, it is just a matter of using the proper "name" for what purpose: Add(), AddMatrix(), AddModularArith() Foo(), Bar(), @+, etc ... one must choose which one is the most make sense for the type they defining.
And sometimes @+ or +. is just the right name, because for some particular types, it behaves just like normal + but with slightly different behavior.
I've done some financial calculations using math/big.Rat, and it is a bit pain to work with.
It's hard to compare the code with the formulas assembled by the business/product team.
The Rat API might be defined with care so that you can reason about performance and memory usage. but most of the time, we don't care about performance, we care about correctness and readability.
Rob also has a comment about how the Int type probably should be done. We should strive for correctness first.
Personally, the operator function is not a feature that I miss the most in golang, I can live without it. I'm neutral about this issue, just want to add some comments.
But if we want to add to the language, I want it to be defined more like magma (in the mathematical sense). the operand and the result must have same type

It seems like most of the pushback towards this feature sounds a lot like the typical arguments for and against operator overloading. However, in general, it seems that operator overloading is most beneficial for numeric data types, things like BigInt, fixed-precision numeric values (ex. currency or other uses), Vectors, Matrices), while other types don't really use overloading, except for comparison and equality.
I think a good middle ground could be only allowing overloading of operators like comparison and equality, then having Go add support for numeric types like vectors, BigInt, fixed-point, etc. that would have first-class support for standard mathematical operators (though we may want some way to differentiate matrix multiplication vs element-wise, perhaps with an @ operator or some alternative), essentially locking those operators down to being available only on types that the language permits. This seems to give the simplicity, usability, and readability benefits that can come from operator overloading to the most common use case, while avoiding pitfalls of bad operator overloading.
Having equality and comparison be overrideable on any struct is valuable since it would allow a single, unambiguous method for equality and comparisons/ordering of all types. The language could even enforce that the operands must be the same type for an equals operator to return true. The fact that there are two different ways to do this (function for structs, operators for primitives) presently makes it less simple than it could be.
Arbitrary operator definition would most certainly complicate the compiler, and lead to possible confusion since it could easily result in operators that do not make much sense on their own. I don't see that happening considering that Go wants to keep the compiler as simple as they can.
I do, however, think operator overloading is a net positive and would like to see support for overloading existing operators. It seems to me that bad operator overloading implementations generally do not get much traction, with libraries doing this poorly generally being avoided. I very rarely find myself needing to overload anything more than an equality operator on most things in languages with the feature, and I think most devs have the common sense to not needlessly throw it around. I find I end up using libraries that do it well often on the flip side, but those are largely when dealing with numeric or vector types in other languages, and they're a huge benefit to code readability. It seems to me that most code authors have learned the lesson to use operator overloading carefully, which seems to have us to the point where comparison operators are the only ones most override unless you are a numeric type, which led me to the suggestion I made earlier.


Fix link to examples documentation

https://docs.docker.com/examples/ just leads to a blank page.
Alternatively this could be an index or some other anchor, but at least this change makes it go to a working page.

Please sign your commits following these rules:
https://github.com/docker/docker/blob/master/CONTRIBUTING.md#sign-your-work
The easiest way to do this is to amend the last commit:
$ git clone -b "patch-1" git@github.com:rtrauntvein/docker.git somewhere
$ cd somewhere
$ git commit --amend -s --no-edit
$ git push -f

Ammending updates the existing PR. You DO NOT need to open a new one.

ping @moxiegirl @thaJeztah @SvenDowideit

LGTM for now, but agreed that it would be good to have an actual introduction / index on that URL.
Thanks!

@rtrauntvein would you be willing to create a file called index.md under examples?
Here is this gist with the content already build:  https://gist.github.com/moxiegirl/0eff3f08453681fd7d09

Please sign your commits following these rules:
https://github.com/docker/docker/blob/master/CONTRIBUTING.md#sign-your-work
The easiest way to do this is to amend the last commit:
$ git clone -b "patch-1" git@github.com:rtrauntvein/docker.git somewhere
$ cd somewhere
$ git commit --amend -s --no-edit
$ git push -f

Ammending updates the existing PR. You DO NOT need to open a new one.

@moxiegirl done - Didn't realize it was that easy to add an index :+1:

@rtrauntvein Well thank you sir. It can be that easy.  I need to remove something off of docs-base to make the transition complete.  LGTM tho all the way.  Thank you.

@moxiegirl should this be cherry-picked in the release, or will you be handling the docs-updates yourself?

@thaJeztah We should start asking Jess for the cherry-picks like we did last release.  She is actually cherry picking into the RC which is a bit cleaner.  Also, well, cherry picking over all the projects myself would mean I end up CP all the time --- cause all the doc changes go in at the last minute on all the projects.  That would leave me little time to actually do the changes... :-P
@jfrazelle can you cherry-pick this...

@moxiegirl @jfrazelle Wondering what works best in general; would it be a problem to add these to the milestone as well? That would help keeping track, and (what I like about that), make it easier in the future which release a PR was in.

@thaJeztah If we did that, would we need to do that for every doc PR? Do we already do it for other PRs?   I really like the idea of having something on the PR (doc or otherwise) to say which release it went out in but is that feasible to maintain/manage?

True, it's a tough one :'( perhaps start with just PR's that should go in after the release branch is created (for the cherry-picks)
(Wondering if we could make something automated to label all PR's that were merged since the last release)


Feature/remove cd4

Removed the CD4 API Controller And Model

This needs to go into develop not master.


Windows: Window::set_resizable

[x] Tested on all platforms changed
[x] Added an entry to CHANGELOG.md if knowledge of this change could be valuable to users
[x] Updated documentation to reflect any user-facing changes, including notes of platform-specific behavior
[x] Created an example program if it would help users understand this functionality

Related to #540.
I did expose the method through the wrapper Window class, so this PR might be blocked on the release of 0.16.  As this will cause Android, iOS, and Emscripten to fail without at least stubs for methods.

Closing to combine with #558