dart-lang / language

Design of the Dart language
Other
2.67k stars 205 forks source link

Report an error for incompatible signatures of operator `[]` / `[]=`? #1347

Open eernstg opened 3 years ago

eernstg commented 3 years ago

The null safety specification requires the following:

It is an error if a class has a setter and a getter with the same basename where the return type of the getter is not a subtype of the argument type of the setter.

The language specification indicates that operator [] and operator []= is a getter/setter pair, and this seems to imply that the return type of operator [] is a subtype of the type of the second parameter of operator []=.

(Aside: This was introduced into the language specification in https://github.com/dart-lang/language/commit/8fa22ea447303d5a544b1762c4bb5366b8634db9 together with other changes aiming at treating getter/setter pairs consistently. It is a little bit delicate because these operators have a different parameter list shape than other getter/setter pairs and a statement like 'getters never have a formal parameter part' is not true for operator [], so we should probably adjust the wording to say that these operators are treated as a getter/setter pair with respect to lexical lookups, and with respect to the signature subtyping constraint.)

However, the analyzer and the common front end do not currently emit a compile-time error for a violation of this rule. For instace, the following program is accepted:

class A {
  bool operator [](int i) => true;
  operator []=(int index, String value) {}
}

void main() {}

It would be a breaking change to emit this error, but it would also be a consistency improvement, and the motivation for the corresponding rule about other getter/setter pairs would apply equally here.

@natebosch, @leafpetersen, @jakemac53, @lrhn, @stereotype441, @munificent, WDYT?

lrhn commented 3 years ago

so we should probably adjust the wording to say that these operators are treated as a getter/setter pair with respect to lexical lookups, and with respect to the signature subtyping constraint.)

We should say how they are treated as those (as if the second parameter of []= is the setter parameter and the return type of [] is the getter return type, or as if it's a getter/setter pair for each individual value of the first parameter).

Do we want any rules for the relation between the first parameters of [] and []=? Must it be the same type, or can it be completely different? It matters for x[e]++ where the type of e must be assignable to both, but otherwise there doesn't have to be any relation.

I personally think we should move towards requiring the same type for the index parameters and for getter/setter types, not just subtypes in one semi-arbitrary direction. (I don't find x = x; a compelling example of anything useful.)