Implement checking observe declarations (#6709)

This adds SemIR structs and implements building `observe` lists, as well
as naming, formatting, and importing `observe` declarations.

---------

Co-authored-by: Dana Jansens <danakj@orodu.net>
This commit is contained in:
Özgür T. Önsoy
2026-07-08 17:07:10 +00:00
committed by GitHub
co-authored by Dana Jansens
parent 918bb9364f
commit 08385adeb5
713 changed files with 13013 additions and 13 deletions
@@ -135,6 +135,8 @@ fn F() -> i32 {
// CHECK:STDOUT: %Destroy.Op.bound: <bound method> = bound_method %n.var, constants.%Destroy.Op.1a2547.2
// CHECK:STDOUT: %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%n.var)
// CHECK:STDOUT: return %Int.as.Copy.impl.Op.call
// CHECK:STDOUT:
// CHECK:STDOUT: !observes:
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Destroy.Op.loc16_3.1(%self.param: ref %i32.builtin) = "no_op";
@@ -142,5 +144,7 @@ fn F() -> i32 {
// CHECK:STDOUT: fn @Destroy.Op.loc16_3.2(%self.param: ref %i32) {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: return
// CHECK:STDOUT:
// CHECK:STDOUT: !observes:
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -326,6 +326,8 @@ fn F() {
// CHECK:STDOUT: %Destroy.Op.bound.loc16: <bound method> = bound_method %s.var, constants.%Destroy.Op.1a2547.6
// CHECK:STDOUT: %Destroy.Op.call.loc16: init %empty_tuple.type = call %Destroy.Op.bound.loc16(%s.var)
// CHECK:STDOUT: return
// CHECK:STDOUT:
// CHECK:STDOUT: !observes:
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Destroy.Op.loc24(%self.param: ref %ptr.d08) = "no_op";
@@ -335,11 +337,15 @@ fn F() {
// CHECK:STDOUT: fn @Destroy.Op.loc22_3.2(%self.param: ref %i32) {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: return
// CHECK:STDOUT:
// CHECK:STDOUT: !observes:
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Destroy.Op.loc22_3.3(%self.param: ref %tuple.type.e55) {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: return
// CHECK:STDOUT:
// CHECK:STDOUT: !observes:
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Destroy.Op.loc18(%self.param: ref %ptr.939) = "no_op";
@@ -347,5 +353,7 @@ fn F() {
// CHECK:STDOUT: fn @Destroy.Op.loc16(%self.param: ref %struct_type.a.b.b4c) {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: return
// CHECK:STDOUT:
// CHECK:STDOUT: !observes:
// CHECK:STDOUT: }
// CHECK:STDOUT:
+2
View File
@@ -129,5 +129,7 @@ fn Foo(ptr: C*) {
// CHECK:STDOUT: %field.ref.loc27_13: %C.elem = name_ref field, @C.%.loc17 [concrete = @C.%.loc17]
// CHECK:STDOUT: %.loc27_13.2: ref %ptr.6b6 = class_element_access %.loc27_13.1, element0
// CHECK:STDOUT: return
// CHECK:STDOUT:
// CHECK:STDOUT: !observes:
// CHECK:STDOUT: }
// CHECK:STDOUT:
+4
View File
@@ -172,6 +172,8 @@ fn F() -> i32 {
// CHECK:STDOUT: %Destroy.Op.bound.loc16: <bound method> = bound_method %n.var, constants.%Destroy.Op.1a2547.3
// CHECK:STDOUT: %Destroy.Op.call.loc16: init %empty_tuple.type = call %Destroy.Op.bound.loc16(%n.var)
// CHECK:STDOUT: return %Int.as.Copy.impl.Op.call
// CHECK:STDOUT:
// CHECK:STDOUT: !observes:
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Destroy.Op.loc17(%self.param: ref %ptr.d08) = "no_op";
@@ -181,5 +183,7 @@ fn F() -> i32 {
// CHECK:STDOUT: fn @Destroy.Op.loc16_3.2(%self.param: ref %i32) {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: return
// CHECK:STDOUT:
// CHECK:STDOUT: !observes:
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -151,6 +151,8 @@ fn NonConstNonConst(p: X**) { TakeNonConstConst(p); }
// CHECK:STDOUT: %.loc12_13.2: %ptr.faf = converted %p.ref.loc12, %.loc12_13.1
// CHECK:STDOUT: %TakeConst.call: init %empty_tuple.type = call %TakeConst.ref(%.loc12_13.2)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT:
// CHECK:STDOUT: !observes:
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Const(%p.param: %ptr.faf) {
@@ -159,6 +161,8 @@ fn NonConstNonConst(p: X**) { TakeNonConstConst(p); }
// CHECK:STDOUT: %p.ref: %ptr.faf = name_ref p, %p
// CHECK:STDOUT: %TakeConst.call: init %empty_tuple.type = call %TakeConst.ref(%p.ref)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT:
// CHECK:STDOUT: !observes:
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @NonConstConst(%p.param: %ptr.845) {
@@ -169,6 +173,8 @@ fn NonConstNonConst(p: X**) { TakeNonConstConst(p); }
// CHECK:STDOUT: %.loc25_18.2: %ptr.b53 = converted %p.ref, %.loc25_18.1
// CHECK:STDOUT: %TakeConstConst.call: init %empty_tuple.type = call %TakeConstConst.ref(%.loc25_18.2)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT:
// CHECK:STDOUT: !observes:
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_todo_nested_qualifiers.carbon
@@ -195,6 +201,8 @@ fn NonConstNonConst(p: X**) { TakeNonConstConst(p); }
// CHECK:STDOUT: %.loc22: %ptr.b53 = converted %p.ref, <error> [concrete = <error>]
// CHECK:STDOUT: %TakeConstConst.call: init %empty_tuple.type = call %TakeConstConst.ref(<error>)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT:
// CHECK:STDOUT: !observes:
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @ConstNonConst(%p.param: %ptr.060) {
@@ -204,5 +212,7 @@ fn NonConstNonConst(p: X**) { TakeNonConstConst(p); }
// CHECK:STDOUT: %.loc38: %ptr.b53 = converted %p.ref, <error> [concrete = <error>]
// CHECK:STDOUT: %TakeConstConst.call: init %empty_tuple.type = call %TakeConstConst.ref(<error>)
// CHECK:STDOUT: <elided>
// CHECK:STDOUT:
// CHECK:STDOUT: !observes:
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -61,5 +61,7 @@ fn Test() {
// CHECK:STDOUT: %addr.loc29_5: <error> = addr_of %undeclared.ref.loc29 [concrete = <error>]
// CHECK:STDOUT: %addr.loc29_3: <error> = addr_of <error> [concrete = <error>]
// CHECK:STDOUT: return
// CHECK:STDOUT:
// CHECK:STDOUT: !observes:
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -72,5 +72,7 @@ let n2: i32 = undeclared->foo;
// CHECK:STDOUT: %.loc24: ref <error> = deref <error> [concrete = <error>]
// CHECK:STDOUT: %foo.ref: <error> = name_ref foo, <error> [concrete = <error>]
// CHECK:STDOUT: return
// CHECK:STDOUT:
// CHECK:STDOUT: !observes:
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -56,5 +56,7 @@ fn A() {
// CHECK:STDOUT: %.loc25: ref <error> = deref <error> [concrete = <error>]
// CHECK:STDOUT: %foo.ref: <error> = name_ref foo, <error> [concrete = <error>]
// CHECK:STDOUT: return
// CHECK:STDOUT:
// CHECK:STDOUT: !observes:
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -60,5 +60,7 @@ fn F() {
// CHECK:STDOUT: %.loc27: ref <error> = deref <error> [concrete = <error>]
// CHECK:STDOUT: %foo.ref: <error> = name_ref foo, <error> [concrete = <error>]
// CHECK:STDOUT: return
// CHECK:STDOUT:
// CHECK:STDOUT: !observes:
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -114,5 +114,7 @@ fn Deref(n: i32) {
// CHECK:STDOUT: %.loc45_5: ref <error> = deref %.loc45_4.2 [concrete = <error>]
// CHECK:STDOUT: %foo.ref.loc45: <error> = name_ref foo, <error> [concrete = <error>]
// CHECK:STDOUT: return
// CHECK:STDOUT:
// CHECK:STDOUT: !observes:
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -79,5 +79,7 @@ var p2: i32->foo;
// CHECK:STDOUT: assign file.%p.var, <error>
// CHECK:STDOUT: assign file.%p2.var, <error>
// CHECK:STDOUT: return
// CHECK:STDOUT:
// CHECK:STDOUT: !observes:
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -89,5 +89,7 @@ fn ConstMismatch(p: const {}*) -> const ({}*) {
// CHECK:STDOUT: %p.ref: %ptr.bf9 = name_ref p, %p
// CHECK:STDOUT: %.loc23: %const.987 = converted %p.ref, <error> [concrete = <error>]
// CHECK:STDOUT: return <error>
// CHECK:STDOUT:
// CHECK:STDOUT: !observes:
// CHECK:STDOUT: }
// CHECK:STDOUT:
+4
View File
@@ -134,6 +134,8 @@ var a: i32* = a_ref;
// CHECK:STDOUT: %ptr.as.Copy.impl.Op.call: init %ptr.d08 = call %bound_method.loc5_19.2(%addr) [concrete = constants.%addr]
// CHECK:STDOUT: assign file.%a_ref.var, %ptr.as.Copy.impl.Op.call
// CHECK:STDOUT: return
// CHECK:STDOUT:
// CHECK:STDOUT: !observes:
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- implicit.impl.carbon
@@ -211,5 +213,7 @@ var a: i32* = a_ref;
// CHECK:STDOUT: %ptr.as.Copy.impl.Op.call: init %ptr.d08 = call %bound_method.loc4_15.2(%.loc4)
// CHECK:STDOUT: assign file.%a.var, %ptr.as.Copy.impl.Op.call
// CHECK:STDOUT: return
// CHECK:STDOUT:
// CHECK:STDOUT: !observes:
// CHECK:STDOUT: }
// CHECK:STDOUT:
+2
View File
@@ -119,5 +119,7 @@ fn F(p: const (const (const i32*)*)) -> const i32 {
// CHECK:STDOUT: %bound_method.loc17_10.2: <bound method> = bound_method %.loc17_10.2, %specific_fn
// CHECK:STDOUT: %const.as.Copy.impl.Op.call: init %const.6a8 = call %bound_method.loc17_10.2(%.loc17_10.2)
// CHECK:STDOUT: return %const.as.Copy.impl.Op.call
// CHECK:STDOUT:
// CHECK:STDOUT: !observes:
// CHECK:STDOUT: }
// CHECK:STDOUT:
+4
View File
@@ -135,6 +135,8 @@ fn ConstPtr(p: const i32*) -> (const i32)* {
// CHECK:STDOUT: %bound_method.loc16_10.2: <bound method> = bound_method %p.ref, %specific_fn
// CHECK:STDOUT: %ptr.as.Copy.impl.Op.call: init %ptr.d08 = call %bound_method.loc16_10.2(%p.ref)
// CHECK:STDOUT: return %ptr.as.Copy.impl.Op.call
// CHECK:STDOUT:
// CHECK:STDOUT: !observes:
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @ConstPtr(%p.param: %ptr.774) -> out %return.param: %ptr.774 {
@@ -146,5 +148,7 @@ fn ConstPtr(p: const i32*) -> (const i32)* {
// CHECK:STDOUT: %bound_method.loc20_10.2: <bound method> = bound_method %p.ref, %specific_fn
// CHECK:STDOUT: %ptr.as.Copy.impl.Op.call: init %ptr.774 = call %bound_method.loc20_10.2(%p.ref)
// CHECK:STDOUT: return %ptr.as.Copy.impl.Op.call
// CHECK:STDOUT:
// CHECK:STDOUT: !observes:
// CHECK:STDOUT: }
// CHECK:STDOUT: