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

stage2: orelse at comptime is broken #7662

Closed
g-w1 opened this issue Jan 3, 2021 · 1 comment
Closed

stage2: orelse at comptime is broken #7662

g-w1 opened this issue Jan 3, 2021 · 1 comment
Labels
bug Observed behavior contradicts documented or intended behavior frontend Tokenization, parsing, AstGen, Sema, and Liveness.
Milestone

Comments

@g-w1
Copy link
Contributor

g-w1 commented Jan 3, 2021

This should work, but it does not:

export fn _start() noreturn {
    const b: ?comptime_int = 5;
    const v: comptime_int = b orelse 4;
    unreachable;
}
test.zig:3:31: error: expected pointer, found 'comptime_int'

Here is the untyped zir:

fn_type _start { // unanalyzed
  %0 = const(TypedValue{ .ty = type, .val = type})
  %1 = const(TypedValue{ .ty = type, .val = noreturn})
  %2 = as(%0, %1)
  %3 = fntype([], %2, cc=Unspecified)
} // fn_type _start

fn_body _start { // unanalyzed
  %0 = dbg_stmt()
  %1 = const(TypedValue{ .ty = type, .val = type})
  %2 = const(TypedValue{ .ty = type, .val = type})
  %3 = const(TypedValue{ .ty = type, .val = comptime_int})
  %4 = as(%2, %3)
  %5 = optional_type(%4)
  %6 = as(%1, %5)
  %7 = const(TypedValue{ .ty = comptime_int, .val = 5})
  %8 = as(%6, %7) ; I think this is the problem. An optional comptime int is not a pointer, but if it is null, it never gets referenced.
  %9 = dbg_stmt()
  %10 = const(TypedValue{ .ty = type, .val = type})
  %11 = const(TypedValue{ .ty = type, .val = comptime_int})
  %12 = as(%10, %11)
  %13 = ref(%8)
  %14 = deref(%13)
  %15 = isnull(%14)
  %16 = block({
    %17 = condbr(%15, {
      %18 = const(TypedValue{ .ty = comptime_int, .val = 4})
      %19 = as(%12, %18)
      %20 = break("label_16", %19)
    }, {
      %21 = unwrap_optional_unsafe(%13)
      %22 = break("label_16", %21)
    })
  })
  %23 = deref(%16)
  %24 = as(%12, %23)
  %25 = dbg_stmt()
  %26 = unreachable()
} // fn_body _start

I think the problem is the %23 = deref(%16) line, which is coming from rlWrapPtr at the end of orelseCatchExpr
Adding this does not fix it:

32c32,33
<       %22 = break("label_16", %21)
---
>       %22 = ref(%21)
>       %23 = break("label_16", %22)

Note, this does work:

export fn _start() noreturn {
    const b: ?comptime_int = null;
    const v: comptime_int = b orelse 4;
    unreachable;
}

This seems like a very easy fix, I just cannot think of a fix.

Edit:
Im pretty sure it is because of the resultLoc mechanism:

  %16 = block({
    %17 = condbr(%15, {
      %18 = const(TypedValue{ .ty = comptime_int, .val = 4})
      %19 = as(%12, %18)
      %20 = break("label_16", %19)
    }, {
      %21 = unwrap_optional_unsafe(%13)
      %22 = break("label_16", %21)
    })
  })

Here, %19 = as(%12, %18) is because of the .ty resultloc. We also need to use the resultloc in the else branch

Edit Edit:
it is actually because of the rlWrapPtr at the end of orelseCatchExpr. Changing it to rlWrap fixes it for the case where b != null, but breaks for b == null. It shows this:

fn_type _start { // unanalyzed
  %0 = const(TypedValue{ .ty = type, .val = type})
  %1 = const(TypedValue{ .ty = type, .val = noreturn})
  %2 = as(%0, %1)
  %3 = fntype([], %2, cc=Unspecified)
} // fn_type _start

fn_body _start { // unanalyzed
  %0 = dbg_stmt()
  %1 = const(TypedValue{ .ty = type, .val = type})
  %2 = const(TypedValue{ .ty = type, .val = type})
  %3 = const(TypedValue{ .ty = type, .val = comptime_int})
  %4 = as(%2, %3)
  %5 = optional_type(%4)
  %6 = as(%1, %5)
  %7 = const(TypedValue{ .ty = @Type(.Null), .val = null})
  %8 = as(%6, %7)
  %9 = dbg_stmt()
  %10 = const(TypedValue{ .ty = type, .val = type})
  %11 = const(TypedValue{ .ty = type, .val = comptime_int})
  %12 = as(%10, %11)
  %13 = ref(%8)
  %14 = deref(%13)
  %15 = isnull(%14)
  %16 = block({
    %17 = condbr(%15, {
      %18 = const(TypedValue{ .ty = comptime_int, .val = 4})
      %19 = as(%12, %18)
      %20 = break("label_16", %19)
    }, {
      %21 = unwrap_optional_unsafe(%13)
      %22 = break("label_16", %21)
    })
  })
  %23 = as(%12, %16)
  %24 = dbg_stmt()
  %25 = unreachable()
} // fn_body _start

test.zig:3:31: error: expected comptime_int, found *comptime_int

The reason I am submitting this is because it is a blocker for writing tests for #7628 since this also affects catch, which #7628 allows to be run at comptime.

@g-w1
Copy link
Contributor Author

g-w1 commented Jan 3, 2021

@Vexu pinging you because you seem to have written the code.

@andrewrk andrewrk added enhancement Solving this issue will likely involve adding new logic or components to the codebase. frontend Tokenization, parsing, AstGen, Sema, and Liveness. labels Jan 3, 2021
@andrewrk andrewrk added this to the 0.8.0 milestone Jan 3, 2021
@andrewrk andrewrk added bug Observed behavior contradicts documented or intended behavior and removed enhancement Solving this issue will likely involve adding new logic or components to the codebase. labels Jan 3, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Observed behavior contradicts documented or intended behavior frontend Tokenization, parsing, AstGen, Sema, and Liveness.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants