New Issue: Should operators be treated like methods when defined at the same scope as the type?

16725, “lydia-duncan”, “Should operators be treated like methods when defined at the same scope as the type?”, “2020-11-17T18:11:04Z”

We added support for searching the type definition point first to look for methods last release, enabling us to ensure that types obtained in scopes where the original definition point was not visible could still maintain basic functionality wherever they were used.

This issue is to discuss if operators should be treated the same way.

Here’s a motivating code example:

module One {
  class MyClass {
    var field: int;
  }

  proc +(a: MyClass, b: MyClass) {
    writeln("in One.+ for MyClass");
    var ret = new MyClass(a.field + b.field);
    return ret;
  }
}

module Two {
  // Obtained an instance of MyClass using a locally scoped use, and returned it
  proc blah() {
    use One;
    var fieldVal = 10;
    return new unmanaged MyClass(fieldVal);
  }
}

module User {
  use Two;

  proc main() {
    var x = blah(); // unmanaged
    var y = blah(); // unmanaged
    // use One;      // With this line, this code will compile and run.  Without it, it will fail to find the +
    var z = x + y;  // owned, for kicks
    delete x, y;
  }
}

Pros:

  • operators defined at the same scope as the type are expected to be usable wherever the type is accessible. Failing to use these operators can cause behavior the type author does not expect, which may cause unexpected bugs.

Cons:

  • Operators are not (currently) defined as methods on a type. What distinguishes them from functions that aren’t operators but require that one of their arguments is of the type in question?
    • Counterpoint: the compiler is specifically set up to recognize certain operators and translate the syntactic sugar into calls to those functions. That distinguishes them from ordinary functions.
  • In the case of operators like +, they can take multiple types. Should we arbitrarily choose one of these argument types to jump to? Should we jump to both definition points?