Compiler error when compiling the `IfLet` expression.
related to #1170
Compilation fails for the IfLet expression.
Code
fn main() -> i32 {
let mut res = 0;
enum E {
X(u8),
}
let v = E::X(4);
if let E::X(n) = v {
res = n;
}
0
}
Meta
- gccrs git sha: https://github.com/Rust-GCC/gccrs/commit/b74044fb6278e373da607a8f1f5df2193ce27d65
Error output
FAIL: rust/compile/macro43.rs (internal compiler error: in append_reference_for_def, at rust/resolve/rust-name-resolver.h:227)```
AST dump
Crate:
inner attributes: none
items:
i32 main()
BlockExpr:
outer attributes: none
inner attributes: none
statements:
outer attributes: none
let mut res = 0
E
Generic params: none
Where clause: none
Items:
X(
outer attributes: none
u8)
outer attributes: none
let v = CallExpr:
outer attributes: none
Function expr: E::X
Call params:
4
ExprStmtWithBlock:
IfLetExpr:
outer attributes: none
Condition match arm patterns:
TupleStructPattern:
Path: E::X
Tuple struct items:
n
Scrutinee expr: v
If let block expr: BlockExpr:
outer attributes: none
inner attributes: none
statements:
ExprStmtWithoutBlock:
AssignmentExpr:
left: res
right: n
final expression: none
final expression:
0
HIR dump
HIR::Crate:
inner attributes: none
items:
private
i32 main()
BlockExpr:
{
outer attributes: none
inner attributes: none
statements:
Outer attributes: none
let mut res = ( 0 ([C: 0 Nid: 6 Hid: 23]))
private E
Generic params: none
Where clause: none
Items:
X [Tuple variant](outer attributes: none
private u8)
Outer attributes: none
let v = E::X::[C: 0 Nid: 24 Hid: 33](( 4 ([C: 0 Nid: 25 Hid: 34])),)::[C: 0 Hid: 35]
ExprStmtWithBlock:
none (this should not happen and is an error)
final expression:
( 0 ([C: 0 Nid: 55 Hid: 38]))
}::[C: 0 Nid: 57 Hid: 40 Lid: 6]
::[C: 0 Hid: 41]
@CohenArthur would love to fix this issue but not sure how to proceed.
Looks like the AST lowering didn't correctly lower the if let expression? This part of the HIR is suspicious:
ExprStmtWithBlock:
none (this should not happen and is an error)
Yes, that looks like a good assumption. You can look into the AST lowering pass, which is located in gcc/rust/hir/rust-ast-lower*. The code responsible for lowering AST::If* nodes is in rust-ast-lower-expr.h, and it is missing a lowerer for AST::IfLetExpr so that might be a track to follow.
I can assign you this issue and you see how you feel about solving it? We can always fix it together or have someone else fix it if it doesn't interest you anymore at some point :)
Thanks! I'll take a look.
Hi @antego would you like me to setup a guide for you on this? You have already found one of the main missing pieces which is HIR lowering.
Though there are several parts that are need resolved when fixing this issue:
- [ ] name resolution
- [ ] hir-lowering
- [ ] type resolution
- [ ] code-generation
Name resolution will ensure we setup the proper conventions for resolveing the new bindings created in the if-let expr but we also need to ensure that the correct scoping is applied here.
HIR lowering you already have a PR out for
Type resolution is about setting up all the relevant type information for this bloc.
Code generation is all about generating the GENERIC for this.
Yeah, I've created a draft PR with a commit that I can reference here and ask for the further help 😂
Hi @antego would you like me to setup a guide for you on this?
Yes please!
but we also need to ensure that the correct scoping is applied here.
Yeah I've seen that the error happens around the place that iterates through Ribs so I started reading this. But I still feel lost about what is actually happening here.
@philberty could you please give some pointers for where the code for the name resolution, type resolution and code generation is located? So that I could check how it works for the IfExpr for example.
Is that right that the name resolution should be implemented in rust-ast-resolve-expr.cc? And type resolution in rust-hir-type-check-expr.h?
Hi, @antego Yep name resolution should be fairly simple here, You should be able to copy how we do name resolution for the if blocks from that file. Though if let statements add a new binding and scope level so you need to declare the pattern so you should be able to see how that is done from rust-ast-resolve-stmt.
It's possible to do each of these things in separate PR's so the HIR lowering piece is definitely something that can be merged now independently.