Skip to content

Infer generics bounded from above through another generic #285

Open

Description

@Rigidity

Problem

Inference only follows a relation between two generics in one direction, so a generic that's only bounded from above through another generic can't be inferred:

fn feed<A, B>(f: fn(a: A) -> B, g: fn(b: B) -> Int) -> fn(a: A) -> Int {
    fn(a: A) => g(f(a))
}

fn identity<U>(x: U) -> U {
    x
}

fn inc(x: Int) -> Int {
    x + 1
}

fn main() -> Int {
    let h = feed(identity, inc);
    h(1)
}
Error: Cannot infer generic `A` for `feed`; specify it explicitly, e.g. `feed::<...>()` at 14:13
Error: Cannot assign `fn(x: Int) -> Int` to `fn(b: A) -> Int`, since they are incompatible at 14:28

identity gives A ≤ B, and inc gives B ≤ Int, so A = B = Int is a valid instantiation. Reproduces on main (bf81a085) and on #265's branch (675320f4).

Proposal

#265 resolves a generic through the lower candidates of the generics it's bounded below by (A: [B] gives A the lower candidates of B). The reverse, propagating B's upper candidates to a generic that appears in B's lower list, isn't done. Doing it would let A fall back to its upper bound Int when nothing bounds it from below.

A single generic with only an upper bound is already inferred as that bound: fn f<T>(g: fn(x: T) -> Int) -> Int called as f(inc) compiles on main. This would apply the same rule transitively.

Related: #146, #265.

Activity

  1. added
    enhancementA feature request or improvement to the compiler
    on Nov 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementA feature request or improvement to the compiler

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions