gleam-lang/gleam

Variant narrowing for constants

Open

#5,310 创建于 2026年1月21日

在 GitHub 查看
 (5 评论) (2 反应) (0 负责人)Rust (21,417 star) (960 fork)batch import
help wanted

描述

Type refinement currently works for constants inside case expressions, but only when the pattern explicitly matches the record constructor (not in all patterns). Matching on a constant and explicitly using the record constructor in the pattern allows accessing fields specific to that variant within that specific branch.

Since the value of a module constant is known at compile time, the compiler can guarantee which variant it holds. Therefore, accessing fields that exist on that specific variant should be type-safe globally, without requiring a case unwrapping or a specific pattern match.

Code examples

Current working behavior (Refinement in specific case): Gleam playground

pub type Wibble {
  Wibble
  Wobble(int: Int)
}

const wobble = Wobble(42)

pub fn main() {
  // This works today
  case wobble {
    Wibble -> 24
    Wobble(_) -> wobble.int // Accessing field on the constant after matching
  }
}

(Note: this generates invalid Erlang as reported in #5261, but works for the JavaScript target.)

Proposed behavior (Global refinement): Gleam playground

pub type Wibble {
  Wibble
  Wobble(int: Int)
}

const wobble = Wobble(42)

pub fn main() {
  // Proposed: This should compile because 'wobble' is known to be 'Wobble' at compile time.
  wobble.int
}

Currently, this produces the following error:

error: Unknown record field
   ┌─ /src/main.gleam:10:10
   │
10 │   wobble.int
   │          ^^^ This field does not exist

The value being accessed has this type:

    Wibble

It does not have fields that are common across all variants.

Note: The field you are trying to access is not defined consistently across
all variants of this custom type. To fix this, ensure that all variants
include the field with the same name, position, and type.

贡献者指南

Variant narrowing for constants · gleam-lang/gleam#5310 | Good First Issue