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

Make UP ignore inaccessible types. #2994

Open
lrhn opened this issue Apr 11, 2023 · 0 comments
Open

Make UP ignore inaccessible types. #2994

lrhn opened this issue Apr 11, 2023 · 0 comments
Labels
feature Proposed language feature that solves one or more problems inference least-upper-bound Proposals about improvements of the LUB algorithm

Comments

@lrhn
Copy link
Member

lrhn commented Apr 11, 2023

The current least-upper-bound/UP semantic function on types is fickle and often confusing. (See fx. dart-lang/sdk#51730).

The operation is defined based on the intersection of the set of superinterfaces of the operand types, and then choosing one which is maximal and unique by a particular measure (length of shortest superinterface chain to Object) to avoid having to make an arbitrary choice between equally viable upper bounds.

It's still hard to predict the result of UP on two types, because the entire set of superinterfaces can contain (library-)private implementation details that are not exposed outside of the implementing library.

One thing which might make the result a little more predictable and less confusing could be to ignore types whose declaration is library private and not accessible at the point where the UP occurs.
That includes both which supertypes to include, and how their distance to Object is calculated.

That requires defining what the point of an UP operation is. If it's part of the semantics of a syntactic construct, the UP happens in the library where that syntactic construct occurs. I believe that's well-defined.

It also requires deciding what happens if one (or both) of the initial operands of UP is itself private to another library. That can happen through libraries exposing private types in public API, but is likely going to be very rare, so the precise behavior won't be very important.
If we just ignore that type itself from the superinterface set, we might end up with UP(T, T) != T for some types. But the result will be an accessible type.
If we allow the initial operands to be library private, ignore their library private super-interfaces, the result will likely be exactly the same for everything except UP(T, T).
Either one of those will work.

And it might give a surprising result if a private type is exported by a public type alias. It might make sense to determine whether a superinterface is available in a particular type hierarchy based on whether the super-type declaration (extends, with, implements, on) uses an accessible name, not whether the type declaration itself is public.
(Or maybe it's included if either is public. Some design space to explore here.)

The UP will still be deterministic, based on the type hierarchies, but will not depend on any invisible types.
The result of UP(T1, T2) can differ between two libraries, if the current libraries can see more superinterfaces. But it's only seeing types defined in the same library, and being subclassed inside the same library, so it shouldn't be too much of a surprise that they exist, or where they are in the type hierarchy.

@lrhn lrhn added the feature Proposed language feature that solves one or more problems label Apr 11, 2023
@leafpetersen leafpetersen added least-upper-bound Proposals about improvements of the LUB algorithm inference labels Apr 11, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature Proposed language feature that solves one or more problems inference least-upper-bound Proposals about improvements of the LUB algorithm
Projects
None yet
Development

No branches or pull requests

2 participants