Skip to content
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

refine no-implicit-dynamic to allow inference from explicit dynamic #26781

Closed
jmesserly opened this issue Jun 28, 2016 · 11 comments
Closed

refine no-implicit-dynamic to allow inference from explicit dynamic #26781

jmesserly opened this issue Jun 28, 2016 · 11 comments
Labels
area-analyzer Use area-analyzer for Dart analyzer issues, including the analysis server and code completion. P2 A bug or feature request we're likely to work on strict-analysis-needed Mark issues where strict-raw-types, strict-inference and similar analysis options were helpful type-enhancement A request for a change that isn't a bug

Comments

@jmesserly
Copy link

jmesserly commented Jun 28, 2016

no-implicit-dynamic feels too restrictive. Is there some way we can make dynamic code concise while still preventing it in places where it was not intended?

The text below was the original proposal -- some of this may be obsolete. Needs review.


In any position where a type could be inferred, report if inference fails. Inference here includes downward inference and variable initialization, TBD other cases like [42 as dynamic].

Some examples where an error would be reported:

class C<T> {}
T f<T>(Object x) { return x as T; }
main() {
  var x;           // type of variable not known
  var c = new C(); // type of generic class not known
  var l = [];      // type of List not known
  (a, b) => null;  // type of lambda expression not known
  f(42);           // generic function type arg not known
  dynamic d;
  var x = d; // var is a request for inference
}

These would not be errors:

class C<T> { C.withArg(T t); C(); }
void f<T>(T x) {}
takesADynamicFn(f(x)) {}
main() {
  dynamic d;
  takesADynamicFn((a) => null);
  C<dynamic> c = new C(); // infers `new C<dynamic>()`
  C c = new C(); // equivalent to previous line

  var l = [d]; // inferred to mean `<dynamic>[d]`
  f(d); // inferred `f<dynamic>(d)`
  var c = new C.withArg(d); // once upwards inference is supported here
}

There is a bit of a debate around upwards inference cases, in particular the [d], f(d), and new withArg(d) examples above. My inclination is to accept them, as we already have some stricter flags (no-implicit-dynamic) that would reject.

Original context: #25573 (comment)

@jmesserly jmesserly added area-analyzer Use area-analyzer for Dart analyzer issues, including the analysis server and code completion. analyzer-strong-mode P2 A bug or feature request we're likely to work on type-enhancement A request for a change that isn't a bug labels Jun 28, 2016
@jmesserly
Copy link
Author

CC @leafpetersen @munificent -- let me know if those examples look right (you'll get another chance to review it in CL form :) )

@jmesserly jmesserly self-assigned this Jun 28, 2016
@leafpetersen
Copy link
Member

I thought we had come down the other way on

 dynamic d;
 var x = d;

but I could be misremembering.

I'm fine with the categorization above, but I'm not sure whether I like calling this categorization --no-inferred-dynamic, since it does, in fact, infer dynamic in lots of cases. Maybe something like --no-failed-inference? @kevmoo any thoughts about this?

@jmesserly
Copy link
Author

I thought we had come down the other way on [...] var x = d

Sounds good to me. Moved that one back. How do you feel about the upwards inference examples?

@jmesserly
Copy link
Author

Status update: need to step back and work out a design for this starting from the use cases.

For the moment I think it makes sense to expose the other two flags: no-implicit-casts is very simple and cleans up the type system (assignability relation is just subtype), and no-implicit-dynamic, while a bit blunt, operates in a simple way and doesn't depend on strong mode. It might be too noisy, but we can see what the feedback is like.

I view this bug as a request to blend a static typing+inference and dynamic typing+inference in a way that makes both feel natural to use. I think that can be done (e.g. C# dynamic does it pretty well IMO), but it needs a bit more thought.

@jmesserly
Copy link
Author

jmesserly commented Oct 19, 2016

@nex3 reported being unhappy with no-implicit-dynamic here: #27624
@munificent reported the same thing in the original CL that added no-implicit-dynamic.

The gist is that we should be able to infer from an explicit dynamic. However, as illustrated by examples above it's not clear where to draw this line.

My personal advice would be to not use dynamic, unless you want dynamic dispatch. Prefer Object if you mean to accept any value. That should allow Object to be inferred and be statically safer.

@jmesserly jmesserly changed the title implement no-inferred-dynamic refine no-implicit-dynamic to allow inference from explicit dynamic Oct 19, 2016
@nex3
Copy link
Member

nex3 commented Oct 19, 2016

The gist is that we should be able to infer from an explicit dynamic. However, as illustrated by examples above it's not clear where to draw this line.

I'd consider all the examples listed as "not errors" above not errors. I would also prefer that Leaf's example not be an error.

My personal advice would be to not use dynamic, unless you want dynamic dispatch. Prefer Object if you mean to accept any value. That should allow Object to be inferred and be statically safer.

This seems contrary to the spirit of this style guide entry, which indicates that Object should be used to mean "any object". In my experience, dynamic is usually used as a substitute for union types, where only a few specific types are acceptable.

Another option would be to update the style guide.

@jmesserly
Copy link
Author

yeah that style entry is pretty old. There's a note somewhere that we need to refresh the style guide in the context of Strong Mode/Dart 2. I think that particular entry made sense in Dart 1 where error checking was almost non-existent anyway. Nowadays dynamic means loss of error checking, loss of refactoring reliability, and on some implementations slower operations.

@nex3
Copy link
Member

nex3 commented Oct 19, 2016

It looks like converting to Object doesn't really work, though: #27625

@munificent
Copy link
Member

I do think it's useful for API designers to be able to signal "This accepts any and all objects and will handle them all fine" distinctly from "This accepts certain objects, but I can't express which ones in the type system". But if end up losing that, it's not the end of the world, I suppose.

Nowadays dynamic means loss of error checking, loss of refactoring reliability, and on some implementations slower operations.

My assumption is that most APIs that accept dynamic because there isn't a better type to specify (like a union) generally cast that object to one of a few more precise types in their body to get back to a more statically-typed realm when possible.

But now that you mention it, my assumption may be wrong. Maybe we should use dynamic to mean "I want actual runtime dynamism" and use "Object" to mean "No better specific type."

@nex3
Copy link
Member

nex3 commented Oct 20, 2016

I personally have never wanted, or really even seen a compelling use-case for, runtime dynamism in Dart. Keeping it as the default behavior for cases where a type is unspecified and can't be inferred seems less than optimal.

@jmesserly
Copy link
Author

There are other bugs now tracking improved strictness flags, we do plan to refactor bits of --no-implicit-dynamic into more useful pieces.

@eernstg eernstg added the strict-analysis-needed Mark issues where strict-raw-types, strict-inference and similar analysis options were helpful label Apr 18, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-analyzer Use area-analyzer for Dart analyzer issues, including the analysis server and code completion. P2 A bug or feature request we're likely to work on strict-analysis-needed Mark issues where strict-raw-types, strict-inference and similar analysis options were helpful type-enhancement A request for a change that isn't a bug
Projects
None yet
Development

No branches or pull requests

5 participants