Comments (5)
Indeed, the graph is more like (restricting to only the types Never
< int
< Object?
):
graph TD
subgraph "Type hierarchy of int Function(int)"
O("Object") --> F
F("Function") --> ON
ON("Object? Function(Never)") --> IN
ON --> OI
IN("int Function(Never)") --> NN
IN --> II
OI("Object Function(int)") --> II
OI --> OO
NN("Never Function(Never)") --> NI
II("int Function(int)") --> NI
II --> IO
OO("Object? Function(Object?)") --> IO
NI("Never Function(int)") --> NO
IO("int Function(Object?)") --> NO
NO("Never Function(Object?)") --> N
N("Never")
end
In (covariant) return position, going from Object?
to int
to Never
(or generally to a subtype) creates a subtype.
In contravariant parameter position, going from Never
to int
to Object?
, or a any supertype, creates a subtype.
And it's all about what subtyping means: Substitutability. A value of the subtype must be usable where a value of the supertype is expected. A value of the subtype is-a value of the supertype, and satisfies all requirements that the supertype has.
For a function, that means it must return at most the same values as the supertype, and must accept at least the same arguments that the code might pass to the supertype.
Accepting more arguments is OK, someone expecting a supertype value won't be calling it with more than what the supertype accepts. Accepting fewer is not OK.
Returning fewer results (only int
s and not fx num
) is also OK, the supertype could return int
s, so a caller will not be surprised.
from sdk.
When figuring out the element type of a list literal by looking at the type of the element expressions, the compiler attempts to find the least upper bound of the element expression types.
And it succeeds. Here, for 2a, it finds Object Function(Never)
, which is an upper bound of int Function (int)
and String Function(String)
. (Not sure it's the last upper bound, since Comparable<Object> Function(Never)
is lower, but it's good enough.)
And it is below Function
, so it's a better approximation of the least upper bound than Function
, so that's what the inference chooses.
For 2b, the type found by inference is again a supertype of both element expression types. You can test that both objects satisfy is Object Function(String)
.
So this is working as intended.
from sdk.
For 2b, the type found by inference is again a supertype of both element expression types. You can test that both objects satisfy
is Object Function(String)
.
I think what confused me, and where I seem to have a misunderstanding, is how the function argument type is being resolved as a lower bound instead of an upper bound of the specified types.
For example, in the following cases, with my prior understanding, I would've expected the opposite for all of them:
print(((int x) => x) is Object Function(Object)); // prints false
print(((int x) => x) is Object Function(Never)); // prints true
print(((int x) => x) is Object Function(num)); // prints false
print(((num x) => x) is Object Function(int)); // prints true
In other words, this is the type lattice I had in mind when I was looking at it, and I assumed Object Function(Object)
, or Function
, would be resolved:
graph TD
subgraph "My Incorrect understanding"
A(Object) --> B(Function)
B --> C("Object Function(Object)")
C --> D("int Function(int)")
C --> E("String Function(String)")
D --> F(Never)
E --> F
end
I would appreciate it if you would help me understand: why the type of the function argument seem to be resolved in different direction than that of the return type?
from sdk.
I think after reading about Covariance and contravariance (wikipedia), I understood that argument type in the Function constructor is contravariant which answers my previous question.
They also kindly mentioned in the article:
... programmers often find contravariance unintuitive
... and I had to agree with them 😅
Thanks a lot.
from sdk.
It's pretty clear to me know -- thanks a lot for the detailed explanation, @lrhn 🙏🏽
from sdk.
Related Issues (20)
- Convert all formal parameters to named doesn't handle super parameters well HOT 3
- Convert all formal parameters to named offered when there are no positional parameters to convert HOT 3
- Convert all formal parameters to named changes optional named parameters to required HOT 2
- [macOS] OS::GetCurrentMonotonicTicks should probably use `CLOCK_UPTIME_RAW`. HOT 6
- Unable to create NativeCallback from function HOT 2
- DevTools server is not robust when it has multiple devtools clients connected to different apps
- Add a concept of trusted clients to the DevTools server HOT 1
- `dart analyze` should use LSP to communicate with analysis server HOT 1
- Analyzer hang related to `string.dart` HOT 2
- generated_plugin_registrant is adding _ to import file HOT 1
- [analyzer] Incorrect recursive instance creation in the constant context leads to analyzer not showing any new errors HOT 5
- extension type not compiling for flutter web HOT 1
- [bug-arm32] The variable of type int returns an incorrect value HOT 5
- Latest Chrome Browser no longer works with Twilio Video/Programmable Video, issue seems to originate in the DART:JS package HOT 5
- Type inference discrepancy HOT 6
- [dart2wasm] Implement structs backed by TypedData HOT 2
- Semantics highlighting gets shifted HOT 4
- IPV6 uri resolving creates invalid host HOT 1
- [analyzer] Incorrect completion for redirecting constructors HOT 4
- quick-fix for `use_named_constants` HOT 10
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from sdk.