Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

Named mutabilities on literals, like 'm Box { .. }

Open
#208 1 comment 0 reactions 1 assignee View on GitHub

Maintainers usually reply within 1 day

@samvv is already working on this.

Since Oct 27, 2026.

Assessment

This issue has not been assessed yet.

Description

discussion scope:syntax scope:types

Not decided yet. This is a proposal to discuss.

A function can name a mutability in its signature, like 'm in fn next(n: 'm Node) -> 'm Node (#206), but its body can't make a value with that mutability. A literal is imm, or mut with mut, and never 'm. So a signature that returns 'm T can only return something it was given.

Where this matters

The class method fmap of Functor, if it keeps the mutability of what it's given:

class Functor[F] { fn fmap[A, B](f: fn(A) -> B, x: 'm F[A]) -> 'm F[B]; }

impl Functor[Box] {
  fn fmap(f, b) = Box { item: f(b.item) };       // `imm Box[B]`, not `'m Box[B]`
  fn fmap(f, b) = mut Box { item: f(b.item) };   // `mut Box[B]`, not `'m Box[B]`
}

The caller chooses 'm, so neither body type-checks.

Proposal

Let a literal take a named mutability from its function, wherever mut is allowed now:

impl Functor[Box] { fn fmap(f, b) = 'm Box { item: f(b.item) }; }

fn wrap(x: i32) -> 'm Box[i32] = 'm Box { item: x };
fn single(x: i32) -> 'm [i32] = 'm [x];
fn meters(x: f64) -> 'm Meters = 'm Meters(x);

Why it's sound

A value that was just made has no other names, so it can be either kind. If the caller picks Mut, it gets a fresh value it may change. If the caller picks Imm, the value never changes, since nobody else has it.

  • The body can't change it, since 'm might be Imm: the same rule as for parameters with a named or hidden mutability.
  • Deep imm still holds. Inside the body 'm is a parameter. At each call, the instantiated type is checked as usual, so an imm Box[mut [i32]] that comes out is reported there.
  • Enums aren't affected: with impl Functor[Option], 'm Option[B] is Option[B].

What it doesn't solve

A value built step by step is mut while it's being built, and can't become 'm:

impl Functor[Vec] {
  fn fmap(f, xs) {
    let ys = mut [];
    for x in xs { ys.push(f(x)); }
    ys          // `mut [B]`, not `'m [B]`
  }
}

That would need a conversion that copies when the kinds differ, like fn into[T](xs: mut [T]) -> 'm [T], or knowing that nothing else refers to ys (uniqueness). The conversion needs run-time support, so it would wait for #195.

That's why imm F[B] stays the meaning of an unwritten return type in a class method, which any impl can satisfy. 'm F[B] would be the class author's choice.

Syntax

'm [1] and 'm Box { .. } start with what the lexer reads as a label ('m). A label is always followed by :, as in 'outer: loop { }, so 'm without a colon is unambiguous.

Related

  • "Impls for struct type constructors" in the open questions of site/docs/internals/type-checking/mutability.mdx.
  • The plan to let each application F[A] carry its own mutability, so that a type constructor like Box has none. That's needed first for impl Functor[Box] to make sense at all.
Dominant language
Rust
Stars
54
Forks
3
Avg merge
7m
Merged PRs (30d)
28

Getting set up

This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from boltlang/Bolt

All issues in boltlang/Bolt

Similar issues

More Rust issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.