-
-
Notifications
You must be signed in to change notification settings - Fork 372
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
Introduce $*WARNINGS and ENV<RAKU_WARNINGS> #5206
base: main
Are you sure you want to change the base?
Conversation
Some examples:
|
I don't like the idea of introducing warnings which are not control exceptions. Though not postulated (or I just've never seen it specced in either way), but a warning is anticipated to be a control exception. And it has to remain such, in my view. Especially considering Thus, I'd be for different handling of warning exceptions, not for cardinal change in their behavior. I see the point in the feature and Apparently, some 3rd party code might utilize non-CX behavior in BTW, this may need some prior discussion in |
So why are warnings control exceptions? Historically, it seems so that they can be caught indeed. But the catching of a warning in practice is pretty complicated, needing a |
Looking at the implementation of
So it's completely compile time and not amendable. Which I find to be a disadvantage, as you might want to have warnings (not) enables in production vs development. |
I don't see how is it complicated. Two more lines if
Only from the outside of it, which is totally correct. Consider the following: CONTROL {
when CX::Warn {
note "OUTSIDE: ", .raku;
.rethrow;
}
}
sub foo {
CONTROL {
when CX::Warn {
note "INSIDE: ", .raku;
.rethrow;
}
}
warn "testing warnings";
}
quietly foo; It does what I would expect from the code: reports Basically, speaking of the design side, with proper separation of concerns the code which throws warnings, and the code which handles them must not depend on the kind of warning to be thrown. With the only exception, perhaps, that the throwing part might chose the particular class to be thrown, depending on context. And then we should let the warning class to determine the kind of behavior it implements. This would allow users to have their own approach if necessary without requiring any changes to the core. The optimizer might turn the course of events inside out if it knows that external locus of control would do better in a particular situation. But this is what optimziers do – they break rules intentionally in a controllable way. :) |
Compare:
with:
Also: consider the possibility to switch on / off behaviour of warnings in a production environment. How would you do that with CONTROL blocks? |
Come to think of it, we could also accept a
|
What advantage would it give to us? I'd stick to the point that a warning is a control exception and nothing else. |
Also: consider the possibility to switch on / off behaviour of warnings in a
production environment. How would you do that with CONTROL blocks?
Isn't that as simple as `CONTROL { when CX::Warn { .gist.note unless
%*ENV<PRODUCTION>; .resume } }`?
|
What is good about this PR is the ability to suppress noise when there is an external tool which produces harmless warnings but these warnings disturb me or my tool set in one or other way. |
I will rework this to use the CONTROL mechanism to keep compatibility |
Something went very much wrong about this PR's branch. |
I thought I had just rebased it :-( |
CX::Warn::Quietly - do not show warnings, similar to quietly CX::Warn::Fatal - immediately throw a warning as an exception CX::Warn::Verbose - immediately show warnings with complete backtrace CX::Warn::Collect - collect warnings until END, then show with frequencies CX::Warn::Debug - show warnings with complete backtrace and debugging info The behaviour can be set by setting the new dynamic variable $*WARNINGS to any of these classes (CX::Warn for normal behaviour), with the exception of CX::Warn::Debug which *must* be instantiated. The default behaviour of a process can be set with the RAKU_WARNINGS environment variable, which should have any of "quietly", "fatal", "verbose", or "collect" specified. No specification defaults to the current behaviour. Custom behaviour can also be made by creating one's own CX::Warn::Foo class, which should have a WARN method taking the warning message and a Backtrace object. That method is then expected to do the right thing, and return Nil. Such custom classes can also be activated with RAKU_WARNINGS=foo. I also tried making this a v6.e feature only, but that ran into all sorts of scoping issues. So until these are better understood, this is now implemented as a 6.c feature. The CX::Warn::Debug is special in that it must be instantiated, and as such cannot be activated from an environment variable. The .new method takes any number of *variables* and will show the name of the variable and its value every time a warning is issued. my $foo = 42; my $*WARNINGS = CX::Warn::Debug.new($foo); warn "bar"; will note: $foo = 42 bar in ...
2debd1f
to
a44140c
Compare
I've recreated the branch and added a |
The Callable is given the message, and is supposed to return a string to be used instead of the message. Otherwise works as ::Verbose. my $*WARNINGS = { "foo: $_" } warn "bar"; # foo: bar # in ...
I still disagree with the course taken. To sum up, what worries me are:
I stick to the point that CONTROL {
when CX::Warn::Debug { ... }
when CX::Warn::Fatal { ...; .rethrow }
} class MyApp::CX::Warn::Logging is CX::Warn {
method WARN {
$logger.log: $.message;
nextsame; # Let the default warning do its job
}
} |
} | ||
my class CX::Proceed does X::Control { | ||
method message() { "<proceed control exception>" } | ||
my class CX::Warn::Quietly { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This and the remaining CX::Warn::
must be is CX::Warn
or we may cause problems to code which doesn't care about the kind of warning.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I just realized that they're not to be thrown. That's not what I considered. Need to think more about it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Preliminary, it looks like the right approach would be to have them inherit from CX::Warn
, that's for sure. Then sub EXCEPTION
must chose a wrapper class depending on $*WARNINGS
. Otherwise any use code wanting to react to the kind of warnings being currently used would have to pick into the variable and analyze its content instead of simply multidispatching on CX::Warn::
type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How does &EXCEPTION
even enter into this?
The CX::Warn::xxx
classes are not to be thrown. The reason I chose their name that way, was a. to prevent more global name pollution. I guess they could well be called Warnings::Quietly
, Warnings::Fatal
, etc. Also, there's a bit of prior art with $*UPGRADE-RAT
which currently takes the CX::Warn
class to warn.
To re-iterate: the only time when $*WARNINGS
is checked, is when a warning has already been thrown, and we're about to print the warning on STDERR. Only THEN does it act differently (potentially) from before.
If your main beef is with the name of the CX::Warn::xxx
, I can change them
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To re-iterate: the only time when
$*WARNINGS
is checked, is when a warning has already been thrown, and we're about to print the warning on STDERR. Only THEN does it act differently (potentially) from before.
This is the key point I consider wrong.
Once again, the idea is to let user code decide their behavior depending on the current kind of warning. Best this is done if they can multi-dispatch over warning type object. To have this working correctly, as I stated, all of them must inherit from CX::Warn
and conversion from VM-level control exception into a HLL CX::Warn
instance must take place in EXCEPTION
. In this case all print_control
would have to do is invoke WARN
method on a received CX::Warn
instance. And when done this way the code in my examples would become possible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But, a warn "foo"
doesn't call EXCEPTION
at all???? Only if you have a CONTROL { }
block active, does it run EXCEPTION
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, true. I missed this point. But this changes little because print_control
can use it too if what it received is not a X::Control
instance.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure what you meant there, but that's the reason for me to put the check on $*WARNINGS
in print_control
.
Now, if you find the CX::Warn
class naming confusing, I can change that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, it's not about the naming. It is about handling by user code would that be necessary. It is about being able to multi-dispatch within CONTROL
on a caught warning exception.
Simple, in your implementation print_control
reads $*WARNINGS
and interprets it. EXCEPTION
behavior is unchanged, it creates a CX::Warn
for user when needed.
I propose to teach EXCEPTION
to read and interpret $*WARNINGS
. print_control
might use this ability to get a CX::Warn
to call WARN
upon. This way $*WARNINGS
interpretation is localized in one place, but the result of it can be used by either user's CONTROL
or by print_control
equally well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And, BTW, I don't want them to be renamed. :)
Introduces 5 new classes that provide different behaviours for warnings
The behaviour can be set by setting the new dynamic variable
$*WARNINGS
to any of these classes (CX::Warn for normal behaviour), with the exception ofCX::Warn::Debug
which must be instantiated.The default behaviour of a process can be set with the
RAKU_WARNINGS
environment variable, which should have any of "quietly", "fatal", "verbose", or "collect" specified. No specification defaults to the current behaviour.Custom behaviour can also be made by creating one's own
CX::Warn::Foo
class, which should have a WARN method taking the warning message and aBacktrace
object. That method is then expected to do the right thing, and returnNil
. Such custom classes can also be activated withRAKU_WARNINGS=foo
.I also tried making this a v6.e feature only, but that ran into all sorts of scoping issues. So until these are better understood, this is now implemented as a 6.c feature.
The
CX::Warn::Debug
class is special in that it must be instantiated, and as such cannot be activated from an environment variable. The.new
method takes any number of variables and will show the name of the variable and its value every time a warning is issued.will note: