// #target: macos-x64
module test;
interface Foo { fn int test(); }

fn int int.test(&self) @dynamic => *self + 1;

fn int main()
{
	Foo? v = (Foo)&&2;
	int x = v.test()!!;
	return x;
}

/* #expect: test.ll

define i32 @main() #0 {
entry:
  %v = alloca %any, align 8
  %v.f = alloca i64, align 8
  %taddr = alloca i32, align 4
  %x = alloca i32, align 4
  %error_var = alloca i64, align 8
  %.inlinecache = alloca ptr, align 8
  %.cachedtype = alloca ptr, align 8
  %varargslots = alloca [1 x %any], align 16
  %indirectarg = alloca %"any[]", align 8
  store ptr null, ptr %.cachedtype, align 8
  store i32 2, ptr %taddr, align 4
  %0 = insertvalue %any undef, ptr %taddr, 0
  %1 = insertvalue %any %0, i64 ptrtoint (ptr @"$ct.int" to i64), 1
  store %any %1, ptr %v, align 8
  store i64 0, ptr %v.f, align 8
  %optval = load i64, ptr %v.f, align 8
  %not_err = icmp eq i64 %optval, 0
  %2 = call i1 @llvm.expect.i1(i1 %not_err, i1 true)
  br i1 %2, label %after_check, label %assign_optional

assign_optional:                                  ; preds = %entry
  store i64 %optval, ptr %error_var, align 8
  br label %panic_block

after_check:                                      ; preds = %entry
  %ptradd = getelementptr inbounds i8, ptr %v, i64 8
  %3 = load i64, ptr %ptradd, align 8
  %4 = inttoptr i64 %3 to ptr
  %5 = load ptr, ptr %.cachedtype, align 8
  %6 = icmp eq ptr %4, %5
  br i1 %6, label %cache_hit, label %cache_miss

cache_miss:                                       ; preds = %after_check
  %7 = call ptr @.dyn_search(ptr %4, ptr @"$sel.test")
  store ptr %7, ptr %.inlinecache, align 8
  store ptr %4, ptr %.cachedtype, align 8
  br label %9

cache_hit:                                        ; preds = %after_check
  %8 = load ptr, ptr %.inlinecache, align 8
  br label %9

9:                                                ; preds = %cache_hit, %cache_miss
  %fn_phi = phi ptr [ %8, %cache_hit ], [ %7, %cache_miss ]
  %10 = icmp eq ptr %fn_phi, null
  br i1 %10, label %missing_function, label %match

missing_function:                                 ; preds = %9
  %11 = load ptr, ptr @std.core.builtin.panic, align 8
  call void %11(ptr @.panic_msg, i64 41, ptr @.file, i64 26, ptr @.func, i64 4, i32 9) #2
  unreachable

match:                                            ; preds = %9
  %12 = load ptr, ptr %v, align 8
  %13 = call i32 %fn_phi(ptr %12)
  br label %noerr_block

panic_block:                                      ; preds = %assign_optional
  %14 = insertvalue %any undef, ptr %error_var, 0
  %15 = insertvalue %any %14, i64 ptrtoint (ptr @"$ct.fault" to i64), 1
  store %any %15, ptr %varargslots, align 16
  %16 = insertvalue %"any[]" undef, ptr %varargslots, 0
  %"$$temp" = insertvalue %"any[]" %16, i64 1, 1
  store %"any[]" %"$$temp", ptr %indirectarg, align 8
  call void @std.core.builtin.panicf
  unreachable

noerr_block:                                      ; preds = %match
  store i32 %13, ptr %x, align 4
  %17 = load i32, ptr %x, align 4
  ret i32 %17
}
