Skip to content
This repository was archived by the owner on Feb 22, 2018. It is now read-only.

Should we differentiate between implicit and explicit casts? #293

Closed
vsmenon opened this issue Aug 18, 2015 · 8 comments
Closed

Should we differentiate between implicit and explicit casts? #293

vsmenon opened this issue Aug 18, 2015 · 8 comments

Comments

@vsmenon
Copy link
Contributor

vsmenon commented Aug 18, 2015

We generate a dart.as for both implicit and explicit (user as) cases. Do we need to differentiate?

// StrongModeError or CastError?
dynamic l1 = [];
List<int> l2 = l1;

// Ditto?
dynamic l1 = [];
var l2 = l1 as List<int>;

@leafpetersen ?

@jmesserly
Copy link
Contributor

easy enough to differentiate these, if we want to

@jmesserly
Copy link
Contributor

fwiw, I vote: differentiate

@vsmenon
Copy link
Contributor Author

vsmenon commented Aug 18, 2015

Yeah, it's probably worth differentiating just for something like an --elide-checks mode - which should (I think) drop the as in the first example but keep it in the second.

But, other than that, should they have different behavior?

@jmesserly
Copy link
Contributor

yeah, that's a good question. On the one hand, they're all runtime checks ensuring soundness, so they're all the same. In the short term, it might be helpful to have a different error message (and maybe error type) to help folks understand where they error came from.

As an aside, I think this particular one:

List<int> l2 = l1;

... is sort of an explicit cast. At one point, that was the only syntax for explicit casts in Dart, and I think that style has stuck around, to some extent. Contrast with:

// some point further down in the method
l2 = l1; // implicit

@jmesserly
Copy link
Contributor

In particular, VariableDeclaration is more explicit than arguments of a MethodInvocation, an AssignmentExpression, or other Expressions that can cause an implicit cast. IMHO.

@leafpetersen
Copy link
Contributor

From a correctness standpoint (wanting to preserve semantics between regular dart and strong dart), we need to be sure that any casts that we insert are either casts that are already implied by checked mode, or else are casts that will throw StrongModeError on failure. I think that inference might introduce implicit casts that are not implied by checked mode in the original program. For example:

    class A {};
    class B extends A {};
    class C extends A {};
    var x = new B();
    A y = new C();
   // There is no checked mode cast implied here 
   // (or at least the cast is trivial and will always succeed),
   // but in strong mode there is an implied downcast, and it will fail.
    x = y;

This suggests that we should throw a StrongModeError here if the implied cast fails, unlike an explicit user inserted error. We could choose to only do this for casts that aren't already implied by checked mode, but I'm not sure that I see a benefit. I think that catching checked mode cast errors is a really bad idea anyway. I think I'd be happiest if our inserted casts always threw a StrongModeError on failure. I could maybe see an argument for a special case for VariableDeclaration nodes as @jmesserly describes above, but I still think the benefit is small, and the potential for insanity due to checked-mode/non-checked-mode incoherence is high.

This feels related to #296 .

@jmesserly
Copy link
Contributor

We have the same issue on dcalls, I think we throw a nSM instead of a StrongModeError or TypeError if the arg types fail to match

@jmesserly
Copy link
Contributor

was fixed in dart-lang/sdk#26583

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Development

No branches or pull requests

3 participants