slint-ui/slint · error

one token

Error message

one token

What it means

`point_span` expects the token stream from parsing `p<id>` to yield at least one token; `"p{id}"` always lexes to exactly one identifier token, so an empty stream means the token-source machinery is broken.

Solutions

  1. Check that the proc-macro2 runtime is functional in your build (e.g. wasm builds need the correct feature set)
  2. File a compiler bug: the token stream for `p<id>` must be non-empty for all usize ids
  3. Pin/upgrade proc-macro2 to a version where `parse` on a simple identifier works
Defensive patterns

Strategy: validation

Validate before calling

debug_assert!(tokens.into_iter().count() >= 1, "p<id> must lex to one token");

Prevention

When it happens

Trigger: `format!("p{id}").parse::<TokenStream>()` returning an empty stream — only possible if the lexer dropped the token or the parse silently produced nothing due to a proc-macro2 runtime issue.

Common situations: Seen only when the compiler is embedded in an environment where string-to-TokenStream parsing misbehaves, or after a lexer regression.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of slint-ui/slint@bb937076de (2026-09-16). Data as JSON: /api/errors/2a4fd524004158f6. Report an issue: GitHub.

Appendix: source

Thrown at internal/compiler/generator/slint_sc.rs:192

    match written {
        Some(name) => name.text().to_string().trim().to_string(),
        None => elem.base_type.to_string(),
    }
}

/// The name of a property as the source writes it: `move_declarations` hoists
/// a declaration onto the root element under a name of its own making.
fn source_name(elem: &Element, name: &SmolStr) -> SmolStr {
    let moved_from = elem.property_declarations.get(name).and_then(|d| d.moved_from.clone());
    moved_from.unwrap_or_else(|| name.clone())
}

/// A span naming point `id`: the span of a token parsed from the text
/// `p<id>`, which `source_text` gives back. Fallback spans can be made in no
/// other way, and the printer is the only reader.
fn point_span(id: usize) -> Span {
    let tokens: TokenStream = format!("p{id}").parse().expect("an identifier");
    tokens.into_iter().next().expect("one token").span()
}

/// The point a span names, if any.
fn point_id(span: Span) -> Option<usize> {
    span.source_text()?.strip_prefix('p')?.parse().ok()
}

/// The tokens as the range of the point, when they are one. See `stamped`.
fn stamped_at(point: Option<Span>, tokens: TokenStream) -> TokenStream {
    match point {
        Some(span) => stamped(span, tokens),
        None => tokens,
    }
}

/// The tokens as a point's range: a group without delimiters, which prints
/// as the tokens alone, stamped with the point's span.
fn stamped(span: Span, tokens: TokenStream) -> TokenStream {

View on GitHub (pinned to bb937076de)