nandi/rustnimpublic Fork
⑂ 7010b5d
Commits
⬇ Clone ▾
git clone https://git.rickub.com/nandi/rustnim.git
git clone ssh://git@rickub.com/nandi/rustnim.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

Download ZIP

Give `?` inside a closure the closure's return type

`?` returns from the closure it is written in, not from the function around
it -- but `self.ret` was left holding the enclosing function's type, so the
early exit would have been built to the wrong shape wherever a closure's type
differed. Scoped to the closure, and cleared when the closure's return type is
not known, which turns a silently wrong lowering into the refusal it should
have been.

The four winnow cases reported against it stay refused: those closures are
arguments to a generic parameter, so nothing says what they return, and `?`
cannot be lowered without that.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
nandithebull committed 2026-09-19T19:42:42-07:00 Browse files
7010b5d parent: 9a32146
modified src/lower.rs +14 -1
@@ -6007,7 +6007,14 @@ impl Lowerer {
60076007 let outer_out = std::mem::take(&mut self.out);
60086008 let outer_indent = std::mem::replace(&mut self.indent, base + 2);
60096009 let outer_target = self.target.take();
6010+ // `?` in a closure returns from the *closure*, so its return type
6011+ // is what the early exit has to build.
6012+ let outer_ret = match &ret_ann {
6013+ Some(t) => self.ret.replace(t.clone()),
6014+ None => self.ret.take(),
6015+ };
60106016 let r = self.block_body_at(&block, ret_ann.as_ref());
6017+ self.ret = outer_ret;
60116018 self.target = outer_target;
60126019 let tail = match r {
60136020 Ok(t) => t,
@@ -6049,7 +6056,13 @@ impl Lowerer {
60496056 .ok_or("a closure body with statements is not implemented yet")?,
60506057 other => other,
60516058 };
6052- let v = self.expr_at(body, ret_ann.as_ref())?;
6059+ let outer_ret = match &ret_ann {
6060+ Some(t) => self.ret.replace(t.clone()),
6061+ None => self.ret.take(),
6062+ };
6063+ let v = self.expr_at(body, ret_ann.as_ref());
6064+ self.ret = outer_ret;
6065+ let v = v?;
60536066 self.pop_scope();
60546067
60556068 let ret = ret_ann
@@ -6007,7 +6007,14 @@ impl Lowerer {
6007 let outer_out = std::mem::take(&mut self.out);6007 let outer_out = std::mem::take(&mut self.out);
6008 let outer_indent = std::mem::replace(&mut self.indent, base + 2);6008 let outer_indent = std::mem::replace(&mut self.indent, base + 2);
6009 let outer_target = self.target.take();6009 let outer_target = self.target.take();
6010+ // `?` in a closure returns from the *closure*, so its return type
6011+ // is what the early exit has to build.
6012+ let outer_ret = match &ret_ann {
6013+ Some(t) => self.ret.replace(t.clone()),
6014+ None => self.ret.take(),
6015+ };
6010 let r = self.block_body_at(&block, ret_ann.as_ref());6016 let r = self.block_body_at(&block, ret_ann.as_ref());
6017+ self.ret = outer_ret;
6011 self.target = outer_target;6018 self.target = outer_target;
6012 let tail = match r {6019 let tail = match r {
6013 Ok(t) => t,6020 Ok(t) => t,
@@ -6049,7 +6056,13 @@ impl Lowerer {
6049 .ok_or("a closure body with statements is not implemented yet")?,6056 .ok_or("a closure body with statements is not implemented yet")?,
6050 other => other,6057 other => other,
6051 };6058 };
6052- let v = self.expr_at(body, ret_ann.as_ref())?;6059+ let outer_ret = match &ret_ann {
6060+ Some(t) => self.ret.replace(t.clone()),
6061+ None => self.ret.take(),
6062+ };
6063+ let v = self.expr_at(body, ret_ann.as_ref());
6064+ self.ret = outer_ret;
6065+ let v = v?;
6053 self.pop_scope();6066 self.pop_scope();
6054 6067
6055 let ret = ret_ann6068 let ret = ret_ann