diff --git a/src/Perl6/Actions.nqp b/src/Perl6/Actions.nqp index 27b25b7fcb0..40b858929e1 100644 --- a/src/Perl6/Actions.nqp +++ b/src/Perl6/Actions.nqp @@ -2480,13 +2480,20 @@ class Perl6::Actions is HLL::Actions does STDActions { unless $block.symbol('$!') { $*W.install_lexical_magical($block, '$!'); } - make QAST::Op.new( + my $qast := QAST::Op.new( :op('callmethod'), :name('start'), :returns($*W.find_symbol(['Promise'])), QAST::WVal.new( :value($*W.find_symbol(['Promise'])) ), $.ast ); + unless $*W.lang-ver-before('d') { + $qast.push(QAST::WVal.new( + :value($*W.find_symbol(['Bool', 'True'])), + :named('report-broken-if-sunk') + )); + } + make $qast; } method statement_prefix:sym($/) { diff --git a/src/core/Promise.pm6 b/src/core/Promise.pm6 index 915b52b1a84..87cc5134c73 100644 --- a/src/core/Promise.pm6 +++ b/src/core/Promise.pm6 @@ -33,19 +33,20 @@ my class Promise does Awaitable { has $!cond; has $!thens; has Mu $!dynamic_context; + has Bool $!report-broken-if-sunk; - submethod new(:$scheduler = $*SCHEDULER) { + submethod new(:$scheduler = $*SCHEDULER, :$report-broken-if-sunk) { my \p = nqp::create(self); - p.BUILD(:$scheduler); + p.BUILD(:$scheduler, :$report-broken-if-sunk); p } - submethod BUILD(:$scheduler = $*SCHEDULER --> Nil) { - $!scheduler := $scheduler; - $!lock := nqp::create(Lock); - $!cond := $!lock.condition(); - $!status := Planned; - $!thens := nqp::list(); + submethod BUILD(:$!scheduler = $*SCHEDULER, :$report-broken-if-sunk --> Nil) { + $!report-broken-if-sunk := so $report-broken-if-sunk; + $!lock := nqp::create(Lock); + $!cond := $!lock.condition(); + $!status := Planned; + $!thens := nqp::list(); } # A Vow is used to enable the right to keep/break a promise @@ -239,8 +240,15 @@ my class Promise does Awaitable { } } - method start(Promise:U: &code, :&catch, :$scheduler = $*SCHEDULER, |c) { - my $p := self.new(:$scheduler); + method sink(--> Nil) { + if $!report-broken-if-sunk && $!lock.protect({ not nqp::elems($!thens) }) { + self.then({ .status == Broken && $!scheduler.handle_uncaught(.cause) }); + } + } + + method start(Promise:U: &code, :&catch, :$scheduler = $*SCHEDULER, + :$report-broken-if-sunk, |c) { + my $p := self.new(:$scheduler, :$report-broken-if-sunk); nqp::bindattr($p, Promise, '$!dynamic_context', nqp::ctx()); my $vow := $p.vow; $scheduler.cue(