-
Notifications
You must be signed in to change notification settings - Fork 1.7k
"is" doesn't work in classes #43167
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
I believe that this is correct - @leafpetersen @lrhn to confirm - |
Why then this works fine? void main() {
A a = AB();
if (a is AB) {
print(a.test);
}
} |
The reason promotion doesn't work is that we don't promote instance variables, only local variables. So yes, promotion is broken when you declare the variable in a class. |
I don't understand.. so you don't plan on fixing this? Is there any issue to track this? |
Promotion on instance variables can't be done soundly. This is definitely a pain point, but we haven't found a good solution yet. There are (at least) two open issue tracking requests to try to find sound patterns to allow promotion, with some discussion of the issues. |
@bernaferrari the problem is that you can't tell if "a" will always return the same type -- consider for example: class C extends TestClass {
bool _flag = false;
@override
A get a {
_flag = !_flag;
if (flag)
return AB();
return A();
}
} ...if you call |
What I was thinking @Hixie was something like Kotlin smart cast, where it allows some impressive and advanced stuff while keeping it relatively simple. |
@bernaferrari even final isn't enough for soundness unfortunately. See the first issue I linked above for further explanation of why not. I just filed an issue for discussion of a runtime checked version of promoting instance checks here. |
@bernaferrari as far as I can tell, everything listed under "smart casts" on that page is stuff Dart already does. |
I just tried to reproduce a similar code sample and it works fine on Kotlin with both interface and open class: open class A {
open fun getMessage(): String = "A"
}
interface B {
fun getMessage(): String = "B"
}
interface C {
fun test(): String = "C"
}
class AB : A(), B, C {
override fun getMessage(): String = "AB"
}
class Main {
private val a: A = AB()
fun main(): String {
if (a is AB) {
return a.test()
}
return ""
}
}
Main().main() Dart can detect final A a = AB();
test() {
if (a is AB) {
print(a.test()); // Fails because it thinks a is A, and not AB.
final AB ab = a;
print(ab.test()); // Works
}
} |
@bernaferrari That example is not the same code, because properties in Kotlin are sealed by default. If you change your code to add
Adding non-virtual members to Dart is one of the directions that we could go in to help address this. Note though that this would prevent you from using the class as an interface, which is one of the features of Dart that many people speak positively of. |
ohhhh D: now I can see the hole 😭. I don't know how to contribute to the discussion. So, I guess.. Thanks! haha |
No problem, and good to hear feedback. Note that there's some active discussion in the language repository (links I shared above, and others recently filed) on this general topic if you're still interested in it. |
I'm having a very weird error. I couldn't find any other bug report, but it seems big. Basically, cast is broken when you declare the variable in a class.
Reproducible issue:
Tested on DartPad and locally. Possible fix: declare as dynamic. But it is a bad fix.
The text was updated successfully, but these errors were encountered: