linter icon indicating copy to clipboard operation
linter copied to clipboard

Lint trivial type parameter bound?

Open eernstg opened this issue 3 years ago • 5 comments

Cf. https://github.com/dart-lang/sdk/issues/49521, where a bound of the form X extends FutureOr<X> gives rise to an infinite loop. The infinite loop is handled elsewhere, but perhaps we should lint such bounds in any case, because they will never fail to hold?

This would apply to declarations of the form X extends X?, X extends FutureOr<X>, X extends FutureOr<FutureOr<...FutureOr<X>...>>>, and perhaps others (the list could be expanded over time when additional cases are discovered).

eernstg avatar Jul 28 '22 12:07 eernstg

This sounds to me more like dead code detection, which the analyzer implements as a warning. Would it make sense to have such detection enabled by default (knowing that it's possible to silence any warning)?

bwilkerson avatar Jul 28 '22 14:07 bwilkerson

I think yes: A bound which is always satisfied does not bring any value.

One thing is worth thinking about, though: Does it change inference (or anything else) that a type variable has one of these trivial bounds? It does make a difference whether we have X with no bound or we have X extends dynamic, because the latter makes X work like dynamic the body of the declaration.

eernstg avatar Jul 28 '22 14:07 eernstg

My understanding (which might be wrong) is that a type parameter without a bound effectively has a bound of Object?. If that's the case, then I suspect that removing 'trivial' bounds won't have any impact, but that's a question for someone with a deeper understanding of the type system than I have.

@leafpetersen

bwilkerson avatar Jul 28 '22 15:07 bwilkerson

Per the question around FutureOr, this issue might be relevant.

Per the question around trivial bounds: Currently class Foo<T extends Object?> { T get something => ...} is useful because it means that Foo x = ...; x.something.arglebargle will be a static error on the invocation of arglebargle, rather than a dynamic call with no static error (since the instantiate to bounds result of Foo is Foo<Object?> rather than Foo<dynamic>.

leafpetersen avatar Jul 28 '22 18:07 leafpetersen

[this issue](https://github.com/dart-lang/language/issues/433 might) be relevant.

I forgot about that—but I think that issue (dart-lang/language#433) covers this issue.

That is, if we get dart-lang/language#433 then this issue is not needed (because top types as upper bounds are not useless in general, and the remaining cases targeted by this issue are all associated with union types).

Hence, this issue is kind of anti-blocked on dart-lang/language#433. ;-)

eernstg avatar Jul 29 '22 09:07 eernstg