-
Notifications
You must be signed in to change notification settings - Fork 214
Is f<int>.toString()
a method invocation?
#1802
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
For a class, When the receiver does not start with a class name, then it's not a static lookup, and So, all in all, I'm fine with accepting the syntax in general, allowing What worries me is type aliases. typedef D = C<int>;
typedef F = void Function()
...
D.toString(); // static or constructor invocation on `C<int>`.
F.toString(); // instance member invocation on `Type`. Here you have to look up what the alias refers to in order to see whether |
@lrhn wrote:
typedef D = C<int>;
typedef F = void Function();
...
D.toString(); // (1).
F.toString(); // (2). I think there are several reasons why we might want to maintain that " We have already specified that I tend to think that The point is that we have a simple rule: " I'm happy to support the notion that we make a distinction and say that " [Edit: Added backquotes to the pseudo sentential forms such that |
It's not on That's probably a good idea. We can say that if an expression e denotes a type, which basically means it's an identifier T (potentially qualified) denoting a type declaration (class/mixin/type alias) or denoting a type variable, and possibly instantiated with type arguments, then T.name/T<A>.name does not convert T/T<A> to a That means that if If e does not denote a type, like it's (The big questions are then whether |
Yes, that's a good way to say it! And we certainly want to allow For With |
I've always thought For cascades we desugar into evaluating the expression to a value, then calling multiple methods on that value (and finally evaluating to the value). This avoids evaluating the receiver more than once, but also ensures that it is evaluated to a value, and that the invocations are instance member invocations. We haven't, so far, disallows |
This makes sense today. But it was probably not equally obvious when we introduced I'd like to make it an error, too!
Right, but we specify the semantics of an ordinary method invocation in the same way, evaluating the receiver expression to an object first. I think the consistent approach would be to special-case cascades where the receiver is a type literal: It can be used to call one or more static methods, and it is an error to attempt to use it to call one or more instance methods on
Right, but I believe we're in a good position to fix the spec, because the analyzer already flags both invocations as an error in the following example (and the first one is already worded as if we had the same rule as we do for void main() {
String..toString()..runtimeType;
} |
True. Then after we've evaluated the value, we check whether the original expression was a type literal, and then ignore that value (which is safe since evaluating it has no side effects, so the compiler can just not do it anyway). We could do that for cascades too, but I don't think we do. (At least, it doesn't work to call static members on a type).
Wohoo. Let's do it! |
That doesn't match the spec language: It special cases up front how to deal with (including: how to execute) Anyway, let's do it! ;-) |
Conclusions from language meeting:
This is in line with the current specification wording, so we will not make any changes. The treatment of cascades ( |
Uh oh!
There was an error while loading. Please reload this page.
This section indicates that when
C<T>
is a type literal,C<T>.toString
andC<T>.toString()
is a constructor tearoff respectively a constructor invocation, which causes a compile-time error whenC
does not have a constructor namedC.toString
.This is consistent with a very old rule:
C.toString()
is an error whenC
does not have a static member namedtoString
, and if we want to call theObject
instance method we need to use(C).toString()
.However, when
f
denotes a function declaration we have a similar constructsf<T>.toString
andf<T>.toString()
. In this case there is no interpretation of the term which involves a constructor (tearoff or invocation), and hence it seems odd that we would insist that it is an operation that involves a constructor, and then report an error when there is no constructor namedf.toString
.Hence, it seems reasonable that we should
f<T>.toString
andf<T>.toString()
, and consider them to be a tearoff / an invocation of the instance membertoString
. Note that this may be useful, because we might also have some applicable extension methods.(f<T>).toString()
), but report an error which is more meaningful than "there is no such constructor".WDYT, @munificent, @JakeMac, @lrhn, @leafpetersen, @natebosch, @stereotype441?
PS: Unblock dart-lang/sdk#46887 when this issue has been resolved.
The text was updated successfully, but these errors were encountered: