GALA-E0070 — Read-only pointer where an interface is expected

When it fires. The address of an immutable binding — a val, a parameter not declared var, a receiver — is a read-only ConstPtr[T], not a *T (ConstPtr). ConstPtr has only its own methods, Deref and IsNil, so it does not implement an interface whose methods are declared on T or *T. The error fires when such a value fills a slot of that interface type: a function or method argument (GALA or Go), a typed val / var, an assignment, or a return value.

Minimal repro.

package main

struct Counter(var N int)

func (c *Counter) Notify(s string) {
    c.N = c.N + 1
}

type Notifier interface {
    Notify(s string)
}

func send(n Notifier) {
    n.Notify("x")
}

func main() {
    val c = Counter(0)
    send(&c)
    Println(c.N)
}

Error output.

error[GALA-E0070]: cannot use &c (ConstPtr[Counter]) as Notifier: a read-only ConstPtr does not implement Notifier (missing Notify)
  --> main.gala:19:10
   |
19 |     send(&c)
   |          ^^ &c is read-only because c is immutable
   |
   = hint: &c is read-only because c is immutable; declare it `var c` to pass a *Counter

Fix. A method with a pointer receiver may change the value, so it needs a mutable one. Declare it var, and &c is a *Counter:

package main

struct Counter(var N int)

func (c *Counter) Notify(s string) {
    c.N = c.N + 1
}

type Notifier interface {
    Notify(s string)
}

func send(n Notifier) {
    n.Notify("x")
}

func main() {
    var c = Counter(0)
    send(&c)
    Println(c.N) // 1
}

When the type implements the interface with value receivers, the value itself implements it too, and the hint says to pass c rather than &c.

Rationale. Before this code the call reached go build, which reported

cannot use std.NewConstPtr(c.Ptr()) (value of struct type std.ConstPtr[Counter]) as Notifier value in argument to send: std.ConstPtr[Counter] does not implement Notifier (missing method Notify)

naming a wrapper and a Ptr() call that are not in the source. Making ConstPtr implement the interface is not an option: the methods in question take a *T that may write through it, which is exactly what a read-only pointer exists to prevent.

Scope. An empty interface (any) holds a ConstPtr like any other value, and a ConstPtr passed where a *T is expected is left to Go’s type check as before.