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

The mechanism that turns [] from List<X> xs = const []; into <Never>[] doesn't handle invariance #4223

Open
eernstg opened this issue Jan 6, 2025 · 2 comments
Labels
question Further information is requested type-inference Type inference, issues or improvements

Comments

@eernstg
Copy link
Member

eernstg commented Jan 6, 2025

Thanks to @sgrekhov for bringing this up. Consider the following program:

class C<X> {
  const C();
}

void foo<T>() {
  C<void Function<Y extends T>()> c1 = const C.new(); // Error
}

main() {
  foo<int>();
}

The current implementations (in particular, DartPad based on Dart SDK 3.7.0-243.0.dev) report an error both during analysis and during compilation:

A value of type 'C<void Function<Y extends Never>()>' can't be assigned to a variable of type 'C<void Function<Y extends T>()>'.
compileDDC
main.dart:9:46: Error: A value of type 'C<void Function<Y extends Object?>()>' can't be assigned to a variable of type 'C<void Function<Y extends T>()>'.
 - 'C' is from 'package:dartpad_sample/main.dart' ('/tmp/dartpadUZQXLM/lib/main.dart').
 - 'Object' is from 'dart:core'.
  C<void Function<Y extends T>()> c1 = const C.new();
                                             ^

Note that the analyzer replaces T by Never and DDC replaces it by Object?. None of them will work, because function types are invariant in their type parameter bounds.

However, I couldn't find any specification document where the specified behavior is given.

One useful approach could be to report an error when a constant inference makes an attempt to replace a type variable in the context type, and that type variable is in an invariant position. Another approach could be to replace the entire function type by Never when it occurs in a covariant position and by Object? when it occurs in a contravariant position.

@dart-lang/language-team, WDYT?

@eernstg eernstg added question Further information is requested type-inference Type inference, issues or improvements labels Jan 6, 2025
@lrhn
Copy link
Member

lrhn commented Jan 6, 2025

I guess any choice will be correct, in that it causes an unavoidable compile time error.

There is no valid constant type argument that makes the result assignable to a context type that has a type variable in an invariant position.
Whether that causes an error in inference, or if inference makes some arbitrary choice and causes a compile time error afterwards is a usability issue.
(Early error is better than introducing something the author didn't write, and the reporting that as an error.)

You do suggest moving the replacement up a level, replacing the entire function type with Never, which is a valid choice for now (and not entirely meaningless), but will eventually fail if we get invariant type variables:

class C<inout T> {const C();} 
void foo<inout T>([C<T> v = const C()]) ...

There is no type argument to C() that satisfies the context type, and nothing around it that can be replaced with Never. It's just not solvable.
Might as well accept that now.

@eernstg
Copy link
Member Author

eernstg commented Jan 7, 2025

Good point!

I'd suggest that the constant expression inference engine should simply report an error when it encounters a non-constant type in an invariant position in the context type. This would handle function type bounds as well as type parameters which are declared to be invariant.

If the developer wishes to replace a composite type by some other type (e.g., replacing a function type by Never) then (1) they can do it manually for now, and it won't break, and (2) we can cover additional cases later on, if we wish to do so.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested type-inference Type inference, issues or improvements
Projects
None yet
Development

No branches or pull requests

2 participants