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

Dead Code/Declarations Due to Never #60338

Open
RohitSaily opened this issue Mar 17, 2025 · 0 comments
Open

Dead Code/Declarations Due to Never #60338

RohitSaily opened this issue Mar 17, 2025 · 0 comments
Labels
area-devexp For issues related to the analysis server, IDE support, linter, `dart fix`, and diagnostic messages. devexp-warning Issues with the analyzer's Warning codes P2 A bug or feature request we're likely to work on type-enhancement A request for a change that isn't a bug

Comments

@RohitSaily
Copy link
Contributor

RohitSaily commented Mar 17, 2025

Dart SDK version: 3.8.0-149.0.dev (dev) (Thu Feb 27 04:01:43 2025 -0800) on "macos_x64"

There are several ways to use Never to create dead code or declarations that are impossible to use, without getting any static warnings.

Examples

All the dead code or declarations discussed here are not currently recognized by static analysis.

The following type cast is dead code. The exit is performed but the casting of the result is dead code.

int i()=>
	exit(1) as int;

The following function can never run because it needs a Never instance as input.

void f<T extends Never>(T never)
{}

The following function can be run without issue because its type parameter is satisfied by Never.

void f<T extends Never>()
{}
void main()
{	f();
}

Static analysis can even be satisfied at the call site by using an expression which evaluates to Never as input. Since that expression evaluates to Never the subsequent evaluation of f is impossible, and that call is dead code.

import 'dart:io';
void f<T extends Never>(T never)
{}
void main()
{	f(exit(1));
}

Similarly I can define a class with an assignable Never field.

final class No
{	Never field;
	No(this.field);
}

This can never be instantiated, the entire declaration's instance members and constructors become dead declarations. Its static members would still be usable, as long as they don't require Never objects to be inputted. The Never object doesn't necessarily need to be declared as a stored field, the result is the same if the class can only be constructed via constructors which require Never input.

final class No
{	No(Never field);
}

It is possible for only constructors to be dead declarations and still have instance API be usable if there exists a way to construct without Never input.

final class Yes
{	Yes.no(Never field);//This is a dead declaration.
	Yes();//This is not, so the class can still be instantiated and any instance members can be used.
}

Similarly from #60251, impossible to use instance API can be declared.

extension on Never
{	int get impossible=>
		0;
}

In that issue, @FMorschel also pointed this out for extension types.

extension type No(Never no)
{}

Expectation

Any function which requires a Never object to be specified as input should be marked as a dead declaration/code. Any type declaring a Never object as a stored field or requiring Never as input in order to be instantiated should have all its instance methods and constructors marked as dead declarations. Furthermore, any type that extends or mixes in such code would have to do the same. In the case of implements it is possible to override the field as a getter and therefore does not necessarily render the type nonusable.

final class No
{	final Never field;
	No(this.field);//Can't instantiate!
}
final class Yes implements No
{	@override Never get field=>
		throw Error();
	Yes();//Can instantiate!
}

It can also be indicated that if the type is intended to only be implemented, it should be declared as an abstract interface class instead.

Related Issues and Discussions

Related to the currently open issues

Related to the recently closed issue

There's also the discussion which Never analysis issues spawned from dart-lang/language#4279

@RohitSaily RohitSaily added the area-analyzer Use area-analyzer for Dart analyzer issues, including the analysis server and code completion. label Mar 17, 2025
@johnniwinther johnniwinther added area-devexp For issues related to the analysis server, IDE support, linter, `dart fix`, and diagnostic messages. and removed area-analyzer Use area-analyzer for Dart analyzer issues, including the analysis server and code completion. labels Mar 18, 2025
@pq pq added devexp-warning Issues with the analyzer's Warning codes 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 Mar 18, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-devexp For issues related to the analysis server, IDE support, linter, `dart fix`, and diagnostic messages. devexp-warning Issues with the analyzer's Warning codes P2 A bug or feature request we're likely to work on type-enhancement A request for a change that isn't a bug
Projects
None yet
Development

No branches or pull requests

3 participants