Repository navigation
Inconsistent and misleading error messages for non-assignable operands of [] and []= #64561
Description
When an index, or a value assigned through operator []=, isn't assignable to the corresponding parameter type, the CFE and analyzer report it with one of two messages:
- A: "The argument type 'num' can't be assigned to the parameter type 'int'." (CFE
ArgumentTypeNotAssignable, analyzerargument_type_not_assignable) - B: "A value of type 'num' can't be assigned to a variable of type 'int'." (CFE
InvalidAssignmentError, analyzerinvalid_assignment)
Which message is used depends on the form of the expression, and differs between the front ends. Message B is also misleading here: there's no variable of type int, only a parameter of operator [] or operator []=.
Repro
class C {
int operator [](int i) => 0;
void operator []=(int i, int v) {}
}
extension E on String {
int operator [](int i) => 0;
void operator []=(int i, int v) {}
}
class D extends C {
void m(num n, C c, C? nc, String s) {
super[n];
c[n];
s[n];
E(s)[n];
super[n] = 0;
super[0] = n;
c[n] = 0;
c[0] = n;
E(s)[0] = n;
nc?[0] = n;
c..[0] = n;
var x1 = super[0] = n;
var x2 = c[0] = n;
super[n] += 0;
c[n] += 0;
c[0] ??= n;
}
}Results (SDK built from main on 2026-10-09):
| Expression | Non-assignable operand | CFE | Analyzer |
|---|---|---|---|
super[n] |
index | A | A |
c[n], s[n] (extension), E(s)[n] |
index | B | A |
super[n] = 0; |
index | A | A |
c[n] = 0; |
index | B | A |
super[n] += 0, c[n] += 0 |
index | B | A |
super[0] = n; (statement) |
value | A | B |
var x1 = super[0] = n; (value context) |
value | B | B |
c[0] = n, E(s)[0] = n, nc?[0] = n, c..[0] = n, var x2 = c[0] = n |
value | B | B |
c[0] ??= n |
value | B | B |
- Analyzer: consistent. Indices get A, assigned values get B.
- CFE: indices get A only for
super[i]and statement-contextsuper[i] = v; every other index gets B. Assigned values get B, except statement-contextsuper[i] = v, which gets A. That exception arises because the CFE lowers statement-contextsuper[i] = vto an invocation ofoperator []=, which is type-checked like an ordinary method call. CFE and analyzer disagree on flow analysis ofsuper[() {...}] = v#64510 is about the same lowering; the pending fix for it keeps the current messages, leaving them to this issue.
Suggested fix
Report all of these with a single, accurate message in both front ends. Since the index and the assigned value are both arguments to operator [] / operator []=, message A is already accurate for all of them. Alternatively, a new message could name the operator, e.g. "The argument type 'num' can't be assigned to the parameter type 'int' of 'operator []='."
Activity
johnniwinther commentedon Oct 12, 2026
cc @bwilkerson @scheglov
stereotype441 commentedon Oct 12, 2026
I'm prototyping a fix now. @bwilkerson or @scheglov, if either of you would rather work on this, let me know and I'll stop my work on it.
bwilkerson commentedon Oct 12, 2026
I agree that the two front-ends should produce the same message and that A is better than B. But while A is technically correct, I wonder whether it's the most helpful message for users. I suspect that most users don't think of operators as being method invocations in disguise, so a better message might be something like
or
That said, we probably already do the same for messages related to other operators, so it might be better to be consistent.