Repository: edgedb/edgedb

Issue:
Missing source position on a 'cannot reference correlated set' error
I'm trying to do nested UPDATE  and get the error 'InvalidReferenceError: cannot reference correlated set ... here'

Schema:

```esdl
module default {
    type Foo {
        required link bar -> Bar {
            constraint exclusive;
        };
    }

    type Bar {
	property baz -> int32;
    }
}
```

Query:

```EdgeQL
UPDATE Foo 
SET {
  bar := (UPDATE .bar SET {baz := <int32>42})
}
```

**Error InvalidReferenceError: cannot reference correlated set 'Foo' here**

I'm not sure if I'm doing nested updated correctly. Found this approach here: https://github.com/edgedb/edgedb/discussions/2392

I'd love to understand what that error means and how to properly do the recursive update with current version.


- EdgeDB Version: 2.9+4fbadd2
- EdgeDB CLI Version: 2.2.6+7eabbf9
- OS Version: MacOS 13.1 (22C65)


Discussion:
Argh, it doesn't have a source position in it, which is definitely a bug.

EdgeDB won't let you refer to something in an outer scope like `Foo` from inside an inner mutation statement.
You could do something like
```
UPDATE Foo                                                                      
SET {                                                                           
  bar := (with b := Foo.bar, UPDATE b SET {baz := <int32>42})                   
};
```
There are also various ways you could rewrite it to not use an `update` on Foo, since nothing is actually changing.

You could do `UPDATE Foo.bar SET {baz := <int32>42};` (though that will return something different)
Obviously in real life probably you have a filter on Foo, so you'd make it a subquery or something WITH-bound.
Keeping this bug open to track the missing source context.

Also `cannot reference correlated set` here is a terrible error message and we need to make it better.
Thanks @msullivan! `UPDATE Foo.bar ...` works and in a way even more expressive!

Resolving patch:
diff --git a/edb/ir/scopetree.py b/edb/ir/scopetree.py
--- a/edb/ir/scopetree.py
+++ b/edb/ir/scopetree.py
@@ -511,7 +511,10 @@ def attach_subtree(self, node: ScopeTreeNode,
                 descendant.optional = desc_optional
                 descendant.strip_path_namespace(dns | vns)
                 visible.fuse_subtree(
-                    descendant, self_fenced=False, node_fenced=desc_fenced)
+                    descendant,
+                    self_fenced=False,
+                    node_fenced=desc_fenced,
+                    context=context)
 
             elif descendant.parent_fence is node:
                 # Unfenced path.
@@ -563,7 +566,8 @@ def attach_subtree(self, node: ScopeTreeNode,
                     existing.fuse_subtree(
                         current,
                         self_fenced=existing_fenced,
-                        node_fenced=node_fenced)
+                        node_fenced=node_fenced,
+                        context=context)
 
                     current = existing
 
@@ -668,6 +672,7 @@ def fuse_subtree(
         node: ScopeTreeNode,
         self_fenced: bool=False,
         node_fenced: bool=False,
+        context: Optional[pctx.ParserContext]=None,
     ) -> None:
         node.remove()
 
@@ -684,7 +689,7 @@ def fuse_subtree(
         else:
             subtree = node
 
-        self.attach_subtree(subtree, was_fenced=self_fenced)
+        self.attach_subtree(subtree, was_fenced=self_fenced, context=context)
 
     def remove_subtree(self, node: ScopeTreeNode) -> None:
         """Remove the given subtree from this node."""


Test patch:
diff --git a/tests/test_edgeql_ir_scopetree.py b/tests/test_edgeql_ir_scopetree.py
--- a/tests/test_edgeql_ir_scopetree.py
+++ b/tests/test_edgeql_ir_scopetree.py
@@ -96,3 +96,11 @@ def test_edgeql_ir_scope_tree_bad_05(self):
             )
         """
         # This one is fine now, since it is a property
+
+    @tb.must_fail(errors.InvalidReferenceError,
+                  "cannot reference correlated set 'User' here",
+                  line=2, col=45)
+    def test_edgeql_ir_scope_tree_bad_06(self):
+        """
+        UPDATE User SET { avatar := (UPDATE .avatar SET { text := "foo" }) }
+        """