-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Compiler should not print warnings #46264
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
Comments
This warning is a language specification mandated warning, which is why all source tools implement it. We may want to make warnings ignorable in other tools too, or make other tools not print even spec mandated warnings (let the analyzer be the only tool which does warnings). |
Yeah, IMHO we should change the spec here. From a developer experience perspective, the analyzer is where the warnings are useful and the compiler should just always be silent unless it really can't build the code, IMHO. It just makes sense from a developer's point of view to have one source of places for messages about how the code is wrong. If for some reason we really need the compiler to show warnings, having it implement |
From a user perspective, we should consider that there are three, rather than two, cases where language warnings are relevant. The first is when a user analyzes code statically via the analyzer. It is fine IMO to emit warnings in the first and second cases, but the third case should not emit non-fatal warnings, ever. This is because the user or other programs intended to interpret the stdout/stderr of the code, may not expect there to be warnings in the output because after all, the program didn't print them itself and ran just fine.
|
I'm triaging this to
cc @bkonyi |
I don't really see why #2 should print warnings either. It doesn't print lints, and some of the "warnings" we print (e.g. that When you're running That said, if there is a way to mute the compiler in general then I would be satisfied with just having the |
the flutter tool talks to the compiler over stdin/stdout, and what we get over stderr is completely unstructured. Its not possible today for the tool to tell the difference between a warning and an error, so we'd either need to show all of it or none of it. This came up in the past during the FFI stabilization, the warnings were ultimately removed IIRC. |
Any chance we can prioritize this? It's currently blocking one of the PRs I'm trying to merge over in Flutter land. |
Some prior discussion about case 3 (compiling code in order to immediately run it) in #34137 |
I am seeing this warning as well in a very unexpected place. I have a package,
This is very weird because I am using Dart 2.15.1 and the
What could be the issue? EDIT: created a new issue as I think this one is not really very related. |
+1 on changing the spec so that compilers only emit errors leaving all warnings to the analyzer. An alternate solution would be to teach the compilers about the user's workspace (current package for the simple case, multiple packages for the monorepo case) but that seems like a lot of extra plumbing for minimal benefit given users already see the correct list of warnings in the analyzer. |
As a counterpoint to this, just about every other language I've looked into does provide errors and warnings via the compiler (the notion of a separate analyzer is somewhat idiosyncratic to Dart), so I do wonder whether leaning into the way that Dart does this is the right solution. This is especially true if we want to move towards a world where more of the code is shared between the two. This proposal seems to me to be the most consistent and forward compatible. |
Dart is IMHO superior to other languages precisely because of this difference. Execution time is a much worse time to give warnings and errors than during development. |
Agreed, but Dart is now also an AOT language, in which compilation time and execution time are not always the same. This is why I liked the specific proposal I linked to above: it separates the notion of what tool provides the errors and warnings from when the errors and warnings are provided. If you are developing with the compiler, you should (at least have the option to) get errors and warnings. If you are executing with the compiler/JIT, you should only get errors. In general, I'm resistant to us building in deep assumptions about how people use our tooling stack without good reason. I see no reason not to support the ability to run a single command to get errors/warnings/compiled output, the way that just about every other tooling stack I've every used supports. |
I wouldn't object to having a way to get the compiler to also output all the things the analyzer tells us, sure. What I object to is having a different concept of "non-fatal message" from the compiler than what the analyzer outputs. For example, having different lints trigger warnings in the compiler than in the analyzer, having |
Yes, I very much support unifying the experience. That said, there are (at least now) some ways in which the compiler is the only way to get some errors and warnings, since the analyzer does not (I believe) support analyzing with different settings for conditional imports. |
To be clear, I fully support the compilers emitting errors. My concern is with the compiler emitting non-errors, particularly non-errors that are outside of the scope of the user's workspace like it does now. I agree that the analyzer does not handle analyzing conditional imports correctly today. That is something that should be fixed or the conditional import feature should be improved rather than relying on compilers to warn about conditional import bugs. That said, I do not recall ever catching a conditional import issue with a compiler. When I did bad things that the analyzer couldn't catch, the issues always seemed to show up at runtime. One other datapoint is that for Bazel workspaces, we are already relying on the analyzer to emit lints and warnings as part of compiles (although we probably end up with mostly redundant warnings from the compilers as well). |
No, what we are doing now is similar to gcc emitting warnings if run Rust surfaces all errors, warnings, and lints through the compiler.
I would say that this is something we should fix. |
@leafpetersen and I discussed this a bit more. Long term we are in agreement that the ideal workflow is an integrated Dart Analyzer + CFE that would enable compilers to can optionally show warnings and lints with compiler output with 100% consistency with what IDEs and |
The analyzer supports conditional imports. import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/file_system/memory_file_system.dart';
import 'package:analyzer/src/dart/analysis/analysis_context_collection.dart';
import 'package:analyzer/src/test_utilities/mock_sdk.dart';
void main() async {
final resourceProvider = MemoryResourceProvider();
final sdkRoot = resourceProvider.getFolder('/sdk');
createMockSdk(
resourceProvider: resourceProvider,
root: sdkRoot,
);
resourceProvider.newFile('/home/test/lib/a.dart', r'''
void f(int a) {
a as int;
}
''');
resourceProvider.newFile('/home/test/lib/b.dart', r'''
void f(int a) {}
''');
var file = resourceProvider.newFile('/home/test/lib/test.dart', r'''
import 'a.dart'
if (my.flag) 'b.dart';
''');
final collection = AnalysisContextCollectionImpl(
includedPaths: ['/home'],
resourceProvider: resourceProvider,
sdkPath: sdkRoot.path,
declaredVariables: {
'my.flag': 'true',
},
);
final analysisContext = collection.contextFor(file.path);
final analysisSession = analysisContext.currentSession;
final unitResult = await analysisSession.getResolvedUnit(file.path);
unitResult as ResolvedUnitResult;
print(
unitResult.libraryElement.importedLibraries
.map((e) => e.source.fullName)
.toList(),
);
} |
I stand corrected. How do we surface this to users? |
I would phrase this as "more effort than we can afford right now", but otherwise LGTM. |
Well, this is a right question. Because currently we don't. IIRC we had something like For IDEs, we can either devise a way to declare variables in Anyway, I just wanted to make it more specific - the analyzer does support conditional imports, but user facing tools don't. Which might be a slightly simpler problem to fix implementation wise, although might cause additional arguments about UX :-) |
Gotcha, thanks. |
Ideally we would be better than the other compiler toolchains, not as bad as them. :-) |
But certainly not worse. In other words, I strongly believe that what the other toolchains do here is the correct thing to do, and that what we do is not, and I would like to see evidence (or at least an argument) to convince me otherwise. |
I don't object to warnings in general, if they can be silenced (using the same mechanisms as the analyzer, currently Personally I don't ever want these warnings; when I say |
@mit-mit If we hide warnings from packages that the developer depends on and respect |
Supporting |
Given that supporting |
Can you point to any analysis of how common using |
There's 614 |
There are about 150 In g3 there is at least one code generator that generates code with |
This is not a valid ignore. |
I'm aware that ignoring lints is pretty common. But given the the topic here is hiding of CFE (common front end) warnings, I think the relevant data point is about hiding those (or analyzer warnings similar to those)? |
Fwiw, I think you could make a pretty solid argument that the The same probably goes for most if not all warnings defined in the spec. Yes, the language tries to pretend version constraints and pub itself do not exist. But, the fact of the matter is they do exist, and this warning is actually actively encouraging you to make potentially unsafe changes, because it doesn't understand those things. |
I agree that the compiler shouldn't look at package version constraints. But it's less clear to me that we shouldn't do that in the analyzer. The analyzer is intentionally not just a compiler, so if it would be more helpful to our users for it to consider package version constraints, I'm not sure we should take that option off the table without first doing a cost/benefit analysis. (Analyzer already does a fair bit of analysis of the |
Right, conceptually I think it would be nice if the analyzer could take your package version constraints into account. In practice I think it might not be feasible, but that is a different question. I could imagine a lot of benefits though. |
FWIW in a bunch of Flutter code to avoid the unignorable compiler warning log spam when writing code that deals with APIs that are nullable in old versions and non-nullable in new ones we've explicitly used hacky functions that happen to not cause any warnings today, like this: /// This allows a value of type T or T? to be treated as a value of type T?.
///
/// We use this so that APIs that have become non-nullable can still be used
/// with `!` and `?` on the stable branch.
T? _ambiguate<T>(T? value) => value; Interestingly, this pattern is starting to seep into the ecosystem: https://www.google.com/search?q=flutter+%22ambiguate%22+site%3Apub.dev |
It's the new |
Without wading into this again, I would strongly caution against driving long term strategic choices in our tooling off of short term issues like this. Mixed mode code won't be a thing within a year or so. There may (or may not) be good reasons for doing this long term, but short term pain around the migration is not a good motivation for driving the long term UX of our product. I would strongly suggest staying focused on the long term UX of the language that we want to see for our users. |
This is not a mixed mode issue, it's an issue of an API that changed from nullable to non-nullable, which is not going away. I agree that we should focus on long term issues; the above is an example of the kind of thing people are doing because of (unignorable bogus) warnings today, and I see no reason to believe that's a short-term issue. |
That is actually a very interesting situation. Changing a function from returning It's non-breaking because everything you can do on a Some of the things you can do on That's where the warnings come in. Warnings are not errors, so the change is still non-breaking, even if it makes existing code get warnings for doing unnecessary things, and out tools are able to recognize those This is code that wants to be compatible with multiple distinct versions of the same API, and it does so by doing things that are unnecessary for some of the versions. And therefore it makes sense to be able to silence the warning. There is no workaround, no way to rewrite and not get the warning while still satisfying the original goal. That's why all warnings must be silenceable. There can be reasons for keeping the warning-triggering code in the program, reasons why the analysis leading to the warning is wrong, because it just doesn't have all the facts. So, either make compilers respect (If we want a general helper instead of extension MakeNullable<T extends Object> on T? {
T? get nullable => this;
} ) |
Here's my two cents on this. I'm working on transpiling another language to Dart to use in a package for flutter. If I could just ignore the error when I build that would be one thing, but because the end user is the one compiling all the packages, I really need to prevent them from seeing a warning if I have asserted that it is ok. |
I can think of a couple of solutions for you situation. The first is to generate an The second, and in my mind better, is to run |
I don't think the compilers respect ignore comments (at least not yet). The |
yes, I have been unable to find a way to ignore the warning with ignore_for_file. I'm of the mind that no warning should ever be unignoreable unless its really an error. And if an automated "fixer" can find a warning and absolutely reliably auto correct it, then it should definitely be a warning, and, I believe, handled by the analyzer rather than the compiler. The dart fix suggestion is interesting to me. However, I'd have a few questions about that approach:
If a human is supposed to confirm validity of the mutations then this probably isn't a valid approach to work around the issue. Isn't an unnecessary shift to a nullable context going to generate its own unignorable warning maybe? All in all, this should simply be an ignorable warning. Generated/Transpiled code is a valid use case that should be considered in the tooling. |
as an addendum, a language that seems to be trying to eschew reflection in a lot of cases should make special affordances to not interfere with the ease of generating logic without compulsory warnings. |
I believe this is the case.
This will generate an analyzer hint (which can be ignored, but which will probably not be visible to end users anyway since it is presumably in a different package). It will generate no compiler diagnostic.
Acknowledged. |
The argument against up-casting is that the compiler can then not (or not as easily) choose to just ignore the null-assert/null-aware check. An |
The issue linked above (VeryGoodOpenSource/dart_frog#460) is an interesting example of how this is causing more confusion than help in the wider community, IMHO. |
We have changed the language specification so that tools are no longer required to report all specified warnings. More context is here. This shouldn't be interpreted to mean that the language team prefers that any particular tool does not report warnings. We are just removing a constraint on the discussion. If, say, CFE decides they think it's best to stop reporting warnings, now they can do that without being in violation of the spec. But if CFE wants to continue reporting some or all of the warnings, they are free to do that as well. It's a product/UX decision now and not a specification/correctness issue. |
When I compile this:
...I get:
I'm happy for the analyzer to give the warning, but why is the compiler also doing so? And how do I silence it?
The context is that I have code (a Flutter plugin) that needs to compile against two versions of an API. In one version (Flutter stable) a particular field is nullable, in the more recent version (Flutter master), it's non-nullable. I don't mind having lots of
// ignore
s in the code during the transition, but I don't want users to be faced with lots of warnings they can't do anything about when compiling their apps.The text was updated successfully, but these errors were encountered: