-
Notifications
You must be signed in to change notification settings - Fork 207
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
Smart casts, type inference and markers #1562
Comments
Promotion of local variables has never been enabled for the case where the tested type The workaround you could use right now is to declare a fresh variable with the type you have tested: void process(Base base) {
final Object executable = base;
if (executable is Executable) {
executable.execute(); // OK.
}
} If you wish to propose that we should be able to promote to an unrelated type then you'd need to come up with a design that does this, considering the entire set of rules about promotion, arguing why the new design would work well, and arguing that it isn't a massively breaking change (or arguing that it is worth doing it anyway). |
@eernstg I am not much acknowledged in the details of Dart's type system. If I understand properly, in the case where If this is the case, wouldn't it be possible to promote |
@mateusfccp I actually thought the same. For example in Kotlin it will treat variable as smart casted and will allow to call methods from both - Base and Executable types. |
As a type, it would be the intersection of However, Dart doesn't support intersection types in general. We have a special kind of intersection type of the form Some proposals related to intersection types in a more general sense have been made, e.g., #1152. However, general support for intersection types inevitably implies general support for union types. We have had |
@eernstg just checked case with different types of https://dart.dev/tools/diagnostic-messages#inconsistent_inheritance abstract class Executable {
int m(int a);
}
class Base {
double m(num a) => 0;
}
class Derivative extends Base implements Executable {
// error: Superinterfaces don't have a valid override for 'm': Base.m (double Function(num)), Executable.m (int Function(int)).
} But I agree that there are some non-trivial cases. |
Maybe it is also a good idea to support method overloading as well in such case? (I've seen requests for that feature as well) |
Thanks, this is exactly what I meant, but I don't know much about the technical terms.
I don't think so. What if, given |
I don't think you can have same method with the same implementation. So there is no possibility to have two exactly the same functions. |
@MatrixDev wrote:
I was referring to the case where the receiver has a union type, and they can certainly create this situation: class C1 {
int Function(int) get m => (x) => x;
}
class C2 {
double m(num n) => 1.1;
}
void main() {
C1 | C2 c1or2 = C1(); // Assume support for union types like `C1 | C2`.
c1or2.m(42); // Error or not?
} The example where an That kind of ambiguity never exists during the static analysis of current Dart code, and that's exactly the reason why it is a non-trivial step to add support for union types. Intersection types are relevant here because it is unlikely to be possible to add support for intersection types without also adding support for union types.
That's the same issue: We don't actually have an object that implements the same method twice, with two identical or different implementations (that doesn't actually matter), because you can never have two instance members with the same name on any given object. But in this case we have a receiver |
I understand where you're coming from but originally described issue doesn't require full type union support. Compiler can check whether it is possible to even have desired types combination during smart casting and throw error if not. IMHO it will even be more safe that way. |
Dart doesn't use smart cast with
is
operator when type in question doesn't extend variable type;The text was updated successfully, but these errors were encountered: