Skip to content

Type argument inference crash: lambda passed as Supplier<? extends List<? extends T>> to a ? extends target #2159

Closed

Description

@aosen-xiong
import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;

class WildcardSupplier {
    static <T> List<T> defer(Supplier<? extends List<? extends T>> s) {
        throw new Error();
    }

    void m() {
        List<? extends Number> x = defer(() -> new ArrayList<Integer>());
    }
}

javac -processor nullness WildcardSupplier.java (plain javac accepts it):

WildcardSupplier.java:11: error: [type.argument.inference.crashed] Type argument inference crashed for WildcardSupplier.defer
        List<? extends Number> x = defer(() -> new ArrayList<Integer>());
                                        ^
  error: An exception occurred:  False bound for: Constraint: inference type: capture#864 of ? extends T <: Number Result: FALSE

With -AconvertTypeArgInferenceCrashToWarning=false, the exception is thrown from:

FalseBoundException: False bound for: Constraint: inference type: capture#557 of ? extends T <: Number Result: FALSE
  at ...typeinference8.constraint.ConstraintSet.reduceOneStep(ConstraintSet.java:458)
  at ...typeinference8.bound.BoundSet.incorporateToFixedPoint(BoundSet.java:365)
  at ...typeinference8.InvocationTypeInference.createB3(InvocationTypeInference.java:444)
  at ...typeinference8.InvocationTypeInference.infer(InvocationTypeInference.java:170)
  at ...typeinference8.DefaultTypeArgumentInference.inferTypeArgs(DefaultTypeArgumentInference.java:108)

No crash with a method reference, a Supplier variable, or null as the argument; with Supplier<List<? extends T>> or Supplier<? extends List<T>> as the parameter type; or with List<Number>, List<?>, or List<? super Integer> as the target. Also reproduces with the Interning and Tainting Checkers.

Found in micrometer: StatsdMeterRegistry.java:276/285 (retry(Mono.defer(() -> { … return Mono.empty(); })) with a Mono<? extends …> parameter). Possibly related: #2032 (fixed; same capture of ? extends T <: … shape), but this still crashes on master.

Activity

  1. aosen-xiong commented on Sep 26, 2026

    @aosen-xiong
    CollaboratorAuthor

    Two smaller programs fail on the same kind of constraint (capture of ? extends T <: …) with no lambda. They crash at different places in InvocationTypeInference.createB3, so they may not share a root cause with the original.

    Double wildcard in a return type:

    class NoLambda {
        static class Box<T> {}
    
        static <T> Box<? extends Box<? extends T>> make() {
            throw new Error();
        }
    
        void m() {
            Box<? extends Box<? extends String>> b = make();
        }
    }
    NoLambda.java:9: error: [type.argument.inference.crashed] Type argument inference crashed for NoLambda.make
            Box<? extends Box<? extends String>> b = make();
                                                         ^
      error: An exception occurred:  False bound for: Constraint: inference type: capture#485 of ? extends T <: String Result: FALSE
    
    FalseBoundException: False bound for: Constraint: inference type: capture#154 of ? extends T <: String Result: FALSE
      at ...typeinference8.constraint.ConstraintSet.reduceOneStep(ConstraintSet.java:458)
      at ...typeinference8.constraint.ConstraintSet.reduce(ConstraintSet.java:391)
      at ...typeinference8.bound.CaptureBound.incorporate(CaptureBound.java:156)
      at ...typeinference8.bound.CaptureBound.createAndIncorporateCaptureConstraint(CaptureBound.java:111)
      at ...typeinference8.InvocationTypeInference.createB3(InvocationTypeInference.java:381)
    

    Single wildcard inside java.util.function.Function:

    import java.util.function.Function;
    
    class FunctionReturn {
        static class Box<T> {}
    
        static <T> Function<Throwable, Box<? extends T>> make() {
            throw new Error();
        }
    
        void m() {
            Function<Throwable, Box<? extends String>> f = make();
        }
    }
    FunctionReturn.java:11: error: [type.argument.inference.crashed] Type argument inference crashed for FunctionReturn.make
      error: An exception occurred:  False bound for: Constraint: inference type: capture#4 of ? extends T <: String Result: FALSE
    
    FalseBoundException: False bound for: Constraint: inference type: capture#360 of ? extends T <: String Result: FALSE
      at ...typeinference8.constraint.ConstraintSet.reduceOneStep(ConstraintSet.java:458)
      at ...typeinference8.constraint.ConstraintSet.reduce(ConstraintSet.java:391)
      at ...typeinference8.InvocationTypeInference.createB3(InvocationTypeInference.java:443)
    

    The second one also crashes with java.util.function.Supplier. It does not crash with a user-defined functional interface interface Fn<A, B> { B apply(A a); }, or with a single Box<Box<? extends T>>.

    Spring-framework sites with this failure:

    • Mono.defer(() -> …) passed to switchIfEmpty(Mono<? extends T>) or concatWith(Publisher<? extends T>): TransactionAspectSupport.java:981, LiteWebJarsResourceResolver.java:74/90, VersionResourceResolver.java:165 and AbstractCharSequenceDecoder.java:107.
    • onErrorResume(predicate, exceptionWrappingFunction(response)), where the method returns Function<Throwable, Mono<? extends T>>: DefaultWebClient.java:672. This is the FunctionReturn shape.
    • Nested then(Mono.defer(() -> x.then(Mono.defer(() -> Mono.empty())))): AbstractReactiveTransactionManager.java:506.
  2. added this to the next-release milestone on Sep 26, 2026
  3. aosen-xiong commented on Sep 28, 2026

    @aosen-xiong
    CollaboratorAuthor

    On master aea76ae, this still causes type-argument inference crashes in micrometer (2 sites) and spring-framework (7 sites).

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

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions