E0270

A cap fn used where a plain fn is expected: a closure that captures a capability-bearing value (a built-in capability, a cap type, a cap fn, or a container of one, including a capability-bearing self), or a cap fn value passed on. The rule is part of type compatibility, so it holds on every route: arguments, returns, assignments, ?, generic instantiation, and inside type arguments such as Option<cap fn()> or List<cap fn()>, which never become Option<fn()> or List<fn()>. A plain fn may always be used as a cap fn. Where values meet, a plain fn and a cap fn join to cap fn rather than conflicting, as trusted and untrusted text join to untrusted: the elements of a list, if and match branches, and the arguments of a generic function for one type parameter, including inside type arguments. So [pure_fn, capturing_closure] is a List<cap fn() -> Int>, and anything that calls its elements must declare cap fn. An annotation fixes the flag, so let fs: List<fn() -> Int> = [pure_fn, capturing_closure] is still E0270. A value already used as a plain fn, by flowing into a plain fn slot or by being called in a contract, rejects a cap fn that arrives later, as with fs = [capturing_closure] after run_all(fs). A closure is a cap fn when anything it captures turns out capability-bearing, even if that is settled only later in the body (let g = || xs before xs.push(out)), so a closure already used as a plain fn is then E0270 at the closure. A mutating method's receiver takes what the method writes into it, so push cannot add a cap fn to a List<fn()>.

Machine-applicable fix: none.

Example

This program fails with E0270.

fn apply(f: fn()) {
    f()
}

fn main(io: Stdout) {
    apply(|| {
        let _ = io.println("hi")
    })
}

Fixed

The same program, fixed.

fn apply(f: cap fn()) {
    f()
}

fn main(io: Stdout) {
    apply(|| {
        let _ = io.println("hi")
    })
}

Listed in the checker notes. oskac explain E0270 prints this entry offline.

All error codes