Custom warning categories remain global despite lexical use warnings
0 reputation · 26 Feb 2021, 06:43 UTC
0 reputation · 26 Feb 2021, 06:43 UTC
The Perl warnings pragma allows selective enabling of warning categories and an experimental debug flag that prints stack traces. A documented way to add new categories is warnings::register, which registers them globally. When use warnings is invoked inside a lexical block, only the built‑in categories listed there are affected, but custom categories continue to emit warnings regardless of that lexical scope.
Perl’s documentation does not clarify whether custom categories should inherit the lexical scoping of use warnings or remain globally visible. This ambiguity can lead to noisy output in large codebases where a module defines a custom warning that is unintentionally propagated to unrelated parts of the program.
warnings::register be lexically scoped to the block where use warnings is declared?warnings::debug flag remain stable in future Perl releases, or is it likely to be deprecated or altered?35275 reputation · 26 Feb 2021, 15:21 UTC
Custom warning categories registered via warnings::register do participate in Perl's lexical warnings system. A caller can lexically enable or disable a registered category by name using use warnings 'CategoryName' or no warnings 'CategoryName' inside a block. The category name becomes globally known (registered in the package's symbol table), but its enablement follows the caller's lexical scope, not the defining package's scope.
The experimental warnings::debug flag is not guaranteed stable; its output format or existence may change in future Perl releases. Do not rely on it in production code.
When you call warnings::register in package Foo, Perl creates a package variable (e.g., $Foo::WARNING_BITS) that assigns a bit position to that category. The category name "Foo" is now recognized by the warnings pragma. When warnings::warn('Foo', ...) executes, warnings::enabled('Foo') checks the caller's lexical hint hash (%^H) for the bit corresponding to "Foo". If the caller has use warnings 'Foo' (or use warnings which enables all registered categories) in scope, the warning fires; if the caller has no warnings 'Foo', it is suppressed.
The defining package's own use warnings does not automatically enable its custom category for callers. Each caller decides lexically.
# test_warn_scope.pl
package Foo;
warnings::register;
sub bar { warnings::warn('Foo', "custom warning from Foo") }
package main;
print "1. No lexical control - warning fires:\n";
Foo::bar();
print "2. Lexical 'no warnings' - warning suppressed:\n";
{ no warnings 'Foo'; Foo::bar(); }
print "3. Lexical 'use warnings' only - warning fires (enabled by default):\n";
{ use warnings; Foo::bar(); }
print "4. Lexical 'use warnings' with explicit category:\n";
{ use warnings 'Foo'; Foo::bar(); }
Run with perl test_warn_scope.pl. Cases 2 and 3 demonstrate lexical control: case 2 suppresses the warning, case 3 shows it fires because use warnings without arguments enables all categories including registered ones.
{ no warnings 'CategoryName'; ... } to silence it for that dynamic scope.no warnings 'CategoryName' at file scope makes the category disabled by default; callers must explicitly use warnings 'CategoryName' to see it.$SIG{__WARN__}: Install a handler that suppresses or redirects specific custom warnings based on message content or caller context.use warnings 'deprecated' etc., which are universally recognized and lexically scoped.If you are seeing a custom warning fire unexpectedly, check whether the calling scope has a plain use warnings; (which enables all registered categories) rather than an explicit category list. Which Perl version are you targeting, and do you control the calling code or the module defining the category?
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.