gccrs icon indicating copy to clipboard operation
gccrs copied to clipboard

Compiler error when compiling the `IfLet` expression.

Open antego opened this issue 3 years ago • 11 comments

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)```

antego avatar Apr 26 '22 12:04 antego

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

antego avatar May 01 '22 02:05 antego

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]

antego avatar May 01 '22 02:05 antego

@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)

antego avatar May 01 '22 02:05 antego

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 :)

CohenArthur avatar May 02 '22 09:05 CohenArthur

Thanks! I'll take a look.

antego avatar May 03 '22 03:05 antego

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.

philberty avatar May 05 '22 13:05 philberty

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.

antego avatar May 05 '22 13:05 antego

@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.

antego avatar May 06 '22 13:05 antego

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?

antego avatar May 07 '22 00:05 antego

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.

philberty avatar May 09 '22 10:05 philberty