Why this fires¶
The _ placeholder stands in for "the value being piped" or "the argument this short lambda receives". It only has a defined meaning in two positions:
- As a direct argument in the RHS call of a pipe stage (
|>/?>):x |> clamp(0, _, 100)splices the piped value into that slot and the pipe disappears — it becomesclamp(0, x, 100). - As the head of a field/index/method/optional/force chain passed as a call argument, with at least one access after it:
xs.map(_.name)becomesxs.map(|__ph| __ph.name).
Everywhere else a bare _ is not a value — there's nothing for it to stand for — so the compiler rejects it as TE132. Three shapes trigger it:
1. Two or more _ in the same pipe stage¶
Only one _ per stage can be resolved to "the piped value" — a second one has nothing left to bind to.
fn f(a: int, b: int) -> int { return a }
let x = 5
let y = x |> f(_, _)
// ^^^^^^^ error[TE132]: at most one `_` per pipe stage2. A stray _ outside a pipe/short-lambda position¶
let x = 1 + _
// ^ error[TE132]: `_` is only valid in the RHS of `|>`/`?>` or as `_.field` in an argument
fn f(a: int) -> int { return a }
let z = f(_)
// ^ error[TE132]: `_` is only valid in the RHS of `|>`/`?>` or as `_.field` in an argumentA bare _ argument with no trailing access (f(_)) does not become a short lambda — only a chain with at least one access after the head (_.field, _.m(), _[i], _?.x, _!.x) does. f(_) has no access to build a lambda body from, so it falls through to this same validation.
3. _ as the left-hand side of a pipe¶
fn f(a: int) -> int { return a }
let y = _ |> f(_)
// ^ error[TE132]: `_` cannot be the left-hand side of a pipe_ is only ever an RHS-argument placeholder or a short-lambda chain head — it can never be the value flowing into a pipe.
Fix it¶
1. Use at most one _ per stage¶
fn f(a: int, b: int) -> int { return a }
let x = 5
let y = x |> f(_, 2) // ok — one placeholderIf the piped value is needed in more than one argument position, name it first:
let tmp = x
let y = f(tmp, tmp)2. Only use _ where it has a receiver — a pipe stage, or a chain with a trailing access¶
let ys = xs.map(_.name) // ok — `_` is the chain head, `.name` is the access
let y = x |> f(_, 100) // ok — `_` fills the RHS call's placeholder slotA bare _ outside those positions has no defined meaning; bind it to a name instead:
fn f(a: int) -> int { return a }
let x = 5
let z = f(x) // fixed3. Don't pipe from a bare _¶
fn f(a: int) -> int { return a }
let x = 5
let y = x |> f(_) // ok — `_` is the RHS's placeholder, not the LHSSee also¶
- /docs/operators — pipe (
|>), try-pipe (?>), and placeholder syntax. TE131— named-argument call validation, the other TE13x front-end desugar.