In Channel§

See primary documentation in context for method fail

method fail(Channel:D: $error)

Closes the Channel (that is, makes subsequent send calls die), and enqueues the error to be thrown as the final element in the channel. Method receive will throw that error as an exception. Does nothing if the channel has already been closed or .fail has already been called on it.

my $c = Channel.new;
$c.fail("Bad error happens!");
$c.receive;
CATCH { default { put .^name''.Str } };
# OUTPUT: «X::AdHoc: Bad error happens!␤»

In Exception§

See primary documentation in context for routine fail

multi sub    fail(Exception $e)
method       fail(Exception:D:)

Exits the calling Routine and returns a Failure object wrapping the exception.

# A custom exception defined 
class ForbiddenWord is Exception {
    has Str $.word;
    method message { "This word is forbidden: «$!word»" }
}
 
sub say-word ( $word ) {
    ForbiddenWord.new(:word($word)).fail if $word eq 'foo';
    $word.say;
}
 
my $result = say-word("foo");
say $result.exception;

The routine form works in the same way, with an alternative syntax: fail ForbiddenWord.new(:word($word)).

In Failure§

See primary documentation in context for sub fail

multi sub    fail(--> Nil)
multi sub    fail(*@text)
multi sub    fail(Exception:U $e  --> Nil )
multi sub    fail($payload --> Nil)
multi sub    fail(|cap (*@msg--> Nil)
multi sub    fail(Failure:U $f --> Nil)
multi sub    fail(Failure:D $fail --> Nil)

Exits the calling Routine and returns a Failure object wrapping the exception $e - or, for the cap or $payload form, an X::AdHoc exception constructed from the concatenation of @text. If the caller activated fatal exceptions via the pragma use fatal;, the exception is thrown instead of being returned as a Failure.

# A custom exception defined 
class ForbiddenDirectory is Exception {
    has Str $.name;
 
    method message { "This directory is forbidden: '$!name'" }
}
 
sub copy-directory-tree ($dir{
    # We don't allow for non-directories to be copied 
    fail "$dir is not a directory" if !$dir.IO.d;
    # We don't allow 'foo' directory to be copied too 
    fail ForbiddenDirectory.new(:name($dir)) if $dir eq 'foo';
    # or above can be written in method form as: 
    # ForbiddenDirectory.new(:name($dir)).fail if $dir eq 'foo'; 
    # Do some actual copying here 
    ...
}
 
# A Failure with X::AdHoc exception object is returned and 
# assigned, so no throwing Would be thrown without an assignment 
my $result = copy-directory-tree("cat.jpg");
say $result.exception# OUTPUT: «cat.jpg is not a directory␤» 
 
# A Failure with a custom Exception object is returned 
$result = copy-directory-tree('foo');
say $result.exception# OUTPUT: «This directory is forbidden: 'foo'␤»

If it's called with a generic Failure, an ad-hoc undefined failure is thrown; if it's a defined Failure, it will be marked as unhandled.

sub re-fail {
    my $x = +"a";
    unless $x.defined {
        $x.handled = True;
        say "Something has failed in \$x "$x.^name;
        # OUTPUT: «Something has failed in $x Failure␤» 
        fail($x);
        return $x;
    }
}
 
my $x = re-fail;
say $x.handled# OUTPUT: «False␤»