language
language copied to clipboard
Can you tear off `super augment` members?
For example, is something like var m = super augment; allowed? Is it a problem to leak these augmented members?
My sense is that we should allow it, and there isn't an immediate issue.
I suspect that we won't want to allow these to be torn off. It might work in all circumstances, but I would be surprised if we didn't run into corners where it becomes tricky to materialize the augmented member and allow it to be invoked later.
For example, tearing off a reference to an augmented generative constructor means you now have a function that when invoked runs an initializer list that can assign to final fields. What happens if you call that multiple times? (Now that I think about it, I suppose we have that same question even if you don't tear it off and just immediately call it multiple times.)
I'm not aware of a use case for tearing off augmented member references and they are a pretty weird concept, so my inclination is to not support it for now unless we discover a compelling use case for it.
I agree I don't have a particular use case in mind, but I also can't think of a reason to not allow it? It seems like it should probably be allowed just to make things complete, there isn't anything special about those functions that I can think of?
there isn't anything special about those functions that I can think of?
They are definitely kind of special when it comes to generative constructors. Whether other ones are special... probably not? But if it turns out that it makes things easier on the implementation teams to implement augment super calls in a special way that would make tear-offs harder, I wouldn't want to force them to implement a more complex feature that we don't know is useful.
I would prefer to start with this as being allowed but then we could remove it if some issue comes up in implementation?
cc @johnniwinther @scheglov for feedback
They are definitely kind of special when it comes to generative constructors.
You can take a tearoff of those today right?
I would generally say that today there would be almost no reason to augment a generative constructor though, you would just add a new one instead?
I think if we start doing more useful generative constructors then it does become more interesting, but I don't really see any distinction between a generative constructor and a hand written one, at least as far as macros are concerned?
From the analyzer POV I don't see any difference between implementing invocation super augment foo() and tear-off super augment foo.
They are definitely kind of special when it comes to generative constructors.
You can take a tearoff of those today right?
You can tear off a generative constructor, yes. When you invoke the resulting closure, you get a brand new instance that goes through the entire construction process each time, so that makes sense.
It's weirder when you tear-off the augment super call for a generative constructor because the instance has already been created. Though now that I go back and re-read the proposal I actually wrote... maybe it's not so bad? The constructor initializers have already been run for both constructors and can't be re-run. The only thing the augment super call does is run the wrapped constructor's body. So even before you call it, the instance is in a well-defined state.
Yeah, I guess it's OK then.
I believe this also helps to clarify the answer to https://github.com/dart-lang/language/issues/2325
I'm very surprised that we can tear-off super.method, but we can, so we should probably also be able to tear off augment super.method (if it's non-abstract, or the equivalent for augmentations).