Do you agree libraries should include warning IDs?

I apologize in advance if this has been suggested by others but here goes.

Just today I was compiling some code and once again I’m presented with scads of warnings generated by libraries. So I thought to myself, “Gosh I wish I had a pragma that I could use to silence warnings from libraries. Or even be able to silence a specific warning.” But then it occurred to me that the warnings I’m seeing don’t seem to have any sort of ID associated with them so I’ve got an all or nothing situation. I mean I could either silence all warnings regardless of source or I can’t silence any of them.

So, assuming there are no warning ids, could we start associating ID’s with warnings to allow for the later use of a pragma mechanism to silence specific warnings?

For example I get the following warning from absinthe (and I realize I may not be up to date on my version):

warning: using map.field notation (without parentheses) to invoke function Absinthe.Type.BuiltIns.DeprecatedDirectiveFields.absinthe_blueprint() is deprecated, you must add parentheses instead: remote.function()

Is there an id associated with this warning? I mean I don’t see any id in the text. Let’s say I wanted to silence this warning because I cannot upgrade Absinthe. There’s no way to silence the warning because I can’t specifically identify it. If it had some id (e. g. W001) then I might be able to do something like:

Code.pragma_silence_warning([“W001”])

or something along those lines.

I’m not sure that I am explaining my thinking very well here but I hope others will understand what I’m getting at. I mean I don’t think we can selectively silence warnings or do much of anything with them until they have ids or some identification mechanism associated with them.

I’d appreciate any thoughts from others if anyone cares to weigh in on this.

3 Likes

Strongly-identified warnings are common in Typescript and Rust, but only at the language compiler level. This is possible to implement via discipline and convention alone. I like them a lot, and Elixir could do similar, but that only gets us part of the way there. You’re asking for library-level warning ids, which requires tooling in the stdlib for registering ids across dependencies, emitting strongly-identified warnings separately from/alongside normal logger configuration mechanisms, then suppressing them. It’d be a big lift!

Worth noting that you can silence warnings today at the dependency, module, and function level already via compile_time_purge_matching. This ability is strictly more flexible than what you propose, but lacks the ability to semantically recognize a warning across changes in dependency versions. I’d argue it’s still better, because a semantically similar warning (with the same “id”) might be omitted from a new codepath in a library in a future version, and you wouldn’t want your existing code to suppress it.

1 Like

I believe logger warnings are different from compiler warnings.

What stops you from doing this?
You can fork and patch absinthe with the fix btw

Huh? The strongly-identified warning is not an ID associated with it, but rather ID+location/code snippet pair. I like the idea of identifying the warnings by ID, but for God’s sake let’s do it properly. The ID as per Rust/TS is nothing but a cludge. There is not much sense in having a short alias for a warning, specifically in the era of machines reading the code. The ID+snippet allows addressing, sharing, and even debugging without a context.

Joe Armstrong has proposed the very same thing for the whole internet once.

1 Like

EEP-74 describes a solution for doing this. If/When implemented, it would be used by all languages running on top of Erlang. Though each compiler would have to implement support for emitting/silencing the warnings.

PR-10032 is a first step in adding this to the Erlang compiler though, as you can see in the comments, it is currently stalled.

9 Likes

I believe you’re trying to be helpful. However, you’ve taken one sentence out of context and you’ve entirely missed the point of what I was asking. Still I feel some obligation to try to explain.

In production code one cannot simply update dependencies. If dependencies are updated tests must be run to ensure that no negative changes are introduced. This is, to my mind anyway, one good way to define production. That is code that cannot be modified in any way without thorough testing to ensure no inadvertent breakage and that includes dependencies.

In this context however, I was offering “I cannot upgrade Absinthe” as a hypotethical reason that I might want to suppress warnings. I reason it this way: I’ve got production code. Because it is production code any changes must proceed carefully. Unless Absinthe (or some other dependency) is actually breaking something I need to keep it where it’s at. But I want to silence the warnings I’m getting from it because they are adding to a list of warnings and I cannot do anything about them (because PRODUCTION code). That hypothetical could have as easily been “I cannot move to the latest version of Elixir because I don’t have a good test suite to ensure nothing breaks in production”.

Again, I appreciate the fact that you’re trying to help but you completely missed the point I was making–likely due to poor communication on my part.

1 Like

Ah–thanks! This is exactly what I am thinking of. Once again, I have a good idea but just a little too late. :slight_smile: Thank you for letting me know about this EEP and the efforts to get this addressed!

I was actually thinking of the pragma mechanism present in C, C++ etc. that allows a developer to silence warnings that he or she is confident can be safely ignored. But the pragma mechanism is predicated on having some simple means of identifying the warning and/or error so that behavior is easy to specify. This is all I want–some simple means of specifying which warning and/or error I’m discussing. A simple handle for a warning; nomenclature. I believe what @garazdawi brought up with EEP-74 is exactly what we need.

Now consider you can silence the warning. You do that. You continue to upgrade. Things break – now without grace period.

I understand this reasoning is thoroughly dwarfed by the fact that elixir has a lot of deprectations, but no plans for the future for any 2.0. It’s still a reasonable problem to have with the ability of silencing what is an issue.

Fair, let me be clearer about what I meant.

I latched onto that map.field-without-parentheses deprecation because I assumed it was a very old warning. That made me read the whole thing as an XY problem. If you can afford to upgrade Elixir (and probably OTP), what stops you from upgrading the libraries? But the warning isn’t old. It only landed about two years ago, so that assumption doesn’t really hold and I’ll drop it.

The narrower point still stands for me though. Upgrading Elixir/OTP isn’t free either. I just went from OTP 28 to 29 and testing surfaced an Absinthe utility lib broken by map key ordering, so I’ve felt exactly that. If you already have the appetite to test an Elixir/OTP bump, bumping the offending dependency tends to be the same class of work. You bump it and re-test.

I am afraid you’ve lost me. I want the ability to selectively silence warnings. Even better would be the ability to silence warnings within some lexical context. That is I could do something akin to:

#pragma warning:silence W1234

use ModuleThatRaisesW1234
#endpragma

Obviously pseudocode but I hope you get my point. That would silence the warning only within a given set of code. But I can’t even silence a warning globally without some way of specifying which warning I want to silence. I’m asking for some consistent nomeclature for warnings as a first step to allowing developers to silence them.

You’re right about the costs/issues associated with upgrading but since I was asking for a mechanism to identify warnings as a first step toward allowing developers to silence warnings, it still feels as if your point–while certainly valid–has almost nothing to do with what I’m talking about. Unless I am still misunderstanding you (which is quite possible).