Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Confusion about the LLBC produced for a closure #205

Open
msprotz opened this issue May 29, 2024 · 5 comments
Open

Confusion about the LLBC produced for a closure #205

msprotz opened this issue May 29, 2024 · 5 comments
Assignees

Comments

@msprotz
Copy link
Contributor

msprotz commented May 29, 2024

jonathan@verveine:~/Code/eurydice (protz_trait_clauses) $ \cat test/closure/src/main.rs
fn f() -> [u8; 1] {
    let s = [0; 1];
    let a: [u8; 1] = core::array::from_fn(|_| s[0]);
    a
}

fn main() {
    let actual = f()[0];
    let expected = 0;
    assert_eq!(actual, expected);
}

if I run eurydice on this, and I pass --log '*', I get a dump of the LLBC:

  fn closure::f::closure<0, 1>(state^1 : &0 mut ((&1 (@Array<u8, 1: usize>))), v@2 : (usize)) -> u8
{
    v@0 : u8;
    state^1 : &0 mut ((&1 (@Array<u8, 1: usize>)));
    v@2 : usize;
    v@3 : usize;
    v@4 : &'_ (@Array<u8, 1: usize>);
    v@5 : &'_ (u8);

    v@3 := (0: usize : usize);
    v@4 := &*((*(state^1)).0);
    v@5 := move @ArrayIndexShared<'_, u8, 1: usize>(move v@4, copy v@3);
    v@0 := copy *(v@5);
    drop v@3;
    return
  }

Now here's the snippet of Eurydice that we care for:

        match decl with
        | None -> None
        | Some decl ->
            let { C.def_id; name; signature; body; is_global_decl_body; item_meta; _ } = decl in
            let env = { env with generic_params = signature.generics } in
            L.log "AstOfLlbc" "Visiting %sfunction: %s\n%s"
              (if body = None then "opaque " else "")
              (string_of_name env name)
              (Charon.PrintLlbcAst.Ast.fun_decl_to_string env.format_env "  " "  " decl);

            assert (def_id = id);
            let name = lid_of_name env name in
            match body with
            | None ->
                ... (* irrelevant *)

            | Some { arg_count; locals; body; _ } ->
                if is_global_decl_body then
                  None
                else
                  let env = push_cg_binders env signature.C.generics.const_generics in
                  let env = push_type_binders env signature.C.generics.types in

                  L.log "AstOfLlbc" "ty of locals: %s"
                    (String.concat " ++ " (List.map (fun (local: C.var) ->
                      Charon.PrintTypes.ty_to_string env.format_env local.var_ty) locals));
                  L.log "AstOfLlbc" "ty of inputs: %s"
                    (String.concat " ++ " (List.map (fun t ->
                      Charon.PrintTypes.ty_to_string env.format_env t) signature.C.inputs));

Here's the fun bit: the types in the signature don't agree with the types of the locals.

ty of locals: u8 ++ &'0_0 mut ((&'0_1 (@Array<u8, 1: usize>))) ++ usize ++ usize ++ &'_ (@Array<u8, 1: usize>) ++ &'_ (u8)
ty of inputs: &'0_0 mut ((&'0_1 (@Array<u8, 1: usize>))) ++ (usize)

notably, one has a tuple of size one for the usize, while the other doesn't!

Please help me understand if I'm missing something or if this is a bug somewhere. Thanks!

@Nadrieril
Copy link
Member

That really seems like a bug. See also #194 for our plans for closures

@msprotz
Copy link
Contributor Author

msprotz commented May 29, 2024

Ok I worked around it by normalizing (t) to t everywhere.

@sonmarcho
Copy link
Member

sonmarcho commented May 30, 2024

This is strange. I wonder where the tuple is introduced: is it Rustc's fault or our fault?
I think this is the culprit (we should check if the length is 1):


(and if not the problem is probably in this file)

@Nadrieril
Copy link
Member

I would guess the tuple comes from the Fn trait: a closure like |x, y, z| ... implements Fn<(X, Y, Z)>. Do we special-case the case of single arguments anywhere?

@sonmarcho
Copy link
Member

I do some transformations above to, among other things, make the closure state more explicit (this is the update_closure_signatures file I refer to above). The error likely comes from there, and especially this line where I do not special case on single arguments (I didn't have much time to recheck the code, but it is possible Rust does it on its side).

@Nadrieril Nadrieril self-assigned this Jul 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants