8000 Type inference from default expression doesn’t compile in free function · Issue #72199 · swiftlang/swift · GitHub
[go: up one dir, main page]

Skip to content

Type inference from default expression doesn’t compile in free function #72199

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
ole opened this issue Mar 8, 2024 · 1 comment · Fixed by #79989
Closed

Type inference from default expression doesn’t compile in free function #72199

ole opened this issue Mar 8, 2024 · 1 comment · Fixed by #79989
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. expressions Feature: expressions type checker Area → compiler: Semantic analysis

Comments

@ole
Copy link
Contributor
ole commented Mar 8, 2024

Description

A function definition that relies on Type inference from default expression (SE-0347) compiles when it's defined inside a type (a method), but does't compile when it's defined as a free function.

Reproduction

As a method, this compiles:

struct MyTask {
    func sleep<C: Clock>(
        until deadline: C.Instant,
        clock: C = ContinuousClock()
    ) async throws {}
}

But: the same function signature as a free function doesn't compile:

func sleep<C: Clock>(
    until deadline: C.Instant,
    // ❌: Cannot use default expression for inference of 'C' 
    // because it is inferrable from parameters #0, #1
    clock: C = ContinuousClock()
) async throws {}

Expected behavior

The free function should compile.

Environment

macOS 14.3, Xcode 15.3 (Swift 5.10)

$ swift --version
swift-driver version: 1.90.11.1 Apple Swift version 5.10 (swiftlang-5.10.0.13 clang-1500.3.9.4)
Target: arm64-apple-macosx14.0

Additional information

Forum thread where this is being discussed: https://forums.swift.org/t/type-inference-from-default-expression-doesnt-compile-in-free-function/70521/3

@ole ole added bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. triage needed This issue needs more specific labels labels Mar 8, 2024
@hborla hborla added type checker Area → compiler: Semantic analysis expressions Feature: expressions and removed triage needed This issue needs more specific labels labels Jul 14, 2024
@ph1ps
Copy link
Contributor
ph1ps commented Jan 28, 2025

I did some digging because I've had this issue in a couple of libraries now. However, I do not have enough knowledge to fix it myself, so I hope someone could help me get up a PR, or someone more knowledgable gets inspired to fix this themselves.

I think there are two problems here, one masking the other one. Both of them are related to the affected parameter counting here: https://github.com/swiftlang/swift/blob/248c0260f064066aa595ffa7b6fffaf407a70ca1/lib/Sema/TypeCheckConstraints.cpp#L635C5-L641C6

Issue 1

The following function has affectedParams.size() == 0. This is because it tries to count the arguments of the function of this shape: Foo.bar(_:)(_:duration:instant) and the parameters are not the clock but rather the instance of Foo. I don't know how you'd call that shape, I guess it is curried?

struct Foo {
    func bar<C: Clock>(_ c: C = ContinuousClock(), duration: C.Duration, instant: C.Instant) {
        fatalError()
    }
}

You can also confirm this, by copying the test case from type_inference_from_default_exprs.swift for this specific error:

func testInferFromOtherPos1<T>(_: T = 42, _: [T]) {}

into a struct, where it does not emit an error anymore.

Issue 2

I think this might be the actual issue. A parameter is counted if it is a GenericTypeParamType. However, DependentMemberTypes are also counted because it de-sugars to GenericTypeParamType. So either, someone would have to exclude DependentMemberType from this counting, or just not count the same parameter multiple times. (and I don't think they should be counted, because eg. the type of clock cannot actually be inferred by the duration or instant, right?)

hamishknight pushed a commit that referenced this issue May 29, 2025
… function (#79989)

This is an attempt to solving
#72199.
As I've already lined out in the issue, this seems to be a two-fold
problem.

The first one was a rather easy fix, as I've seen similar approaches in
different parts of the codebase. It is pretty much just un-currying the
generic function.

The second problem was, that `DependentMemberType`s were counted towards
the generic-parameter-should-only-be-mentioned-once-limit even though
you cannot infer the generic type from the dependent member type.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. expressions Feature: expressions type checker Area → compiler: Semantic analysis
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants
0