Files
swift-mirror/test/SourceKit/CodeComplete/complete_moduleimportdepth.swift
Doug Gregor 85d488d461 [stdlib] Remove magnitude-based overload of abs(_:).
The standard library has two versions of the `abs(_:)` function:

```
func abs<T : SignedNumeric>(_ x: T) -> T where T.Magnitude == T
func abs<T : SignedNumeric & Comparable>(_ x: T) -> T
```

The first is more specialized than the second because `T.Magnitude` is
known to conform to `Comparable`. Indeed, it’s a more specialized
implementation that returns `magnitude`.

However, this overload behaves oddly: in the expression `abs(-8)`, the type
checker will pick the first overload because it is more specialized. That’s
a general guiding principle for overloading: pick the most specialized
overload that works.

However, to select that overload, it needs to pick a type for the literal
“8” for which that overload works, and it chooses `Double`. The “obvious”
answer, `Int`, doesn’t work because `Int.Magnitude == UInt`.

There is a conflict between the two rules, here: we prefer more-specialized
overloads (but we’ll fall back to less-specialized if those don’t work) and we prefer to use `Int` for integer literals (but we’ll fall back to `Double` if it doesn’t work). We have a few options from a type-checker
perspective:

1. Consider the more-specialized-function rule to be more important
2. Consider the integer-literals-prefer-`Int` rule to be more important
3. Call the result ambiguous and make the user annotate it

The type checker currently does #1, although at some point in the past it
did #2. Moving forward, #1 is a better choice because it prunes the number
of overloads that need to be considered: if the more-specialized overload
succeeds its type-check, the others need not be considered. It’s also
easier to reason about than the literal-scoring approach, because there can
be a direct definition for “more specialized than” that can be reasoned
about.

I think we should dodge the issue by removing the more-specialized version
of `abs(_:)`. Its use of `magnitude` seems unlikely to provide a
significant performance benefit, and the presence of overloading either
forces us to consider both overloads always (which is bad for type checker
performance) or accept the regression that `abs(-8)` is `Double`. Better
to eliminate the overloading and, if needed in the future, find a better
way to introduce the more-specialized implementation without it being a
separate signature.

Fixes rdar://problem/42345366.
2018-12-04 23:10:04 -08:00

110 lines
4.4 KiB
Swift

import ImportsImportsFoo
import FooHelper.FooHelperExplicit
func test() {
let x = 1
#^A^#
}
// XFAIL: broken_std_regex
// REQUIRES: objc_interop
// RUN: %complete-test -hide-none -group=none -tok=A %s -raw -- -I %S/Inputs -F %S/../Inputs/libIDE-mock-sdk > %t
// RUN: %FileCheck %s < %t
// Swift == 1
// CHECK-LABEL: key.name: "abs(:)",
// CHECK-NEXT: key.sourcetext: "abs(<#T##x: Comparable & SignedNumeric##Comparable & SignedNumeric#>)",
// CHECK-NEXT: key.description: "abs(x: Comparable & SignedNumeric)",
// CHECK-NEXT: key.typename: "Comparable & SignedNumeric",
// CHECK-NEXT: key.doc.brief: "Returns the absolute value of the given number.",
// CHECK-NEXT: key.context: source.codecompletion.context.othermodule,
// CHECK-NEXT: key.moduleimportdepth: 1,
// CHECK-NEXT: key.num_bytes_to_erase: 0,
// CHECK-NOT: key.modulename
// CHECK: key.modulename: "Swift"
// CHECK-NEXT: },
// FooHelper.FooHelperExplicit == 1
// CHECK-LABEL: key.name: "fooHelperExplicitFrameworkFunc1(:)",
// CHECK-NEXT: key.sourcetext: "fooHelperExplicitFrameworkFunc1(<#T##a: Int32##Int32#>)",
// CHECK-NEXT: key.description: "fooHelperExplicitFrameworkFunc1(a: Int32)",
// CHECK-NEXT: key.typename: "Int32",
// CHECK-NEXT: key.context: source.codecompletion.context.othermodule,
// CHECK-NEXT: key.moduleimportdepth: 1,
// CHECK-NEXT: key.num_bytes_to_erase: 0,
// CHECK-NOT: key.modulename
// CHECK: key.modulename: "FooHelper.FooHelperExplicit"
// CHECK-NEXT: },
// ImportsImportsFoo == 1
// CHECK-LABEL: key.name: "importsImportsFoo()",
// CHECK-NEXT: key.sourcetext: "importsImportsFoo()",
// CHECK-NEXT: key.description: "importsImportsFoo()",
// CHECK-NEXT: key.typename: "Void",
// CHECK-NEXT: key.context: source.codecompletion.context.othermodule,
// CHECK-NEXT: key.moduleimportdepth: 1,
// CHECK-NEXT: key.num_bytes_to_erase: 0,
// CHECK-NOT: key.modulename
// CHECK: key.modulename: "ImportsImportsFoo"
// CHECK-NEXT: },
// Bar == 2
// CHECK-LABEL: key.name: "BarForwardDeclaredClass",
// CHECK-NEXT: key.sourcetext: "BarForwardDeclaredClass",
// CHECK-NEXT: key.description: "BarForwardDeclaredClass",
// CHECK-NEXT: key.typename: "BarForwardDeclaredClass",
// CHECK-NEXT: key.context: source.codecompletion.context.othermodule,
// CHECK-NEXT: key.moduleimportdepth: 2,
// CHECK-NEXT: key.num_bytes_to_erase: 0,
// CHECK-NOT: key.modulename
// CHECK: key.modulename: "Bar"
// CHECK-NEXT: },
// ImportsFoo == 2
// CHECK-LABEL: key.name: "importsFoo()",
// CHECK-NEXT: key.sourcetext: "importsFoo()",
// CHECK-NEXT: key.description: "importsFoo()",
// CHECK-NEXT: key.typename: "Void",
// CHECK-NEXT: key.context: source.codecompletion.context.othermodule,
// CHECK-NEXT: key.moduleimportdepth: 2,
// CHECK-NEXT: key.num_bytes_to_erase: 0,
// CHECK-NOT: key.modulename
// CHECK: key.modulename: "ImportsFoo"
// CHECK-NEXT: },
// Foo == FooSub == 3
// CHECK-LABEL: key.name: "FooClassBase",
// CHECK-NEXT: key.sourcetext: "FooClassBase",
// CHECK-NEXT: key.description: "FooClassBase",
// CHECK-NEXT: key.typename: "FooClassBase",
// CHECK-NEXT: key.context: source.codecompletion.context.othermodule,
// CHECK-NEXT: key.moduleimportdepth: 3,
// CHECK-NEXT: key.num_bytes_to_erase: 0,
// CHECK-NOT: key.modulename
// CHECK: key.modulename: "Foo"
// CHECK-NEXT: },
// CHECK-LABEL: key.name: "FooSubEnum1",
// CHECK-NEXT: key.sourcetext: "FooSubEnum1",
// CHECK-NEXT: key.description: "FooSubEnum1",
// CHECK-NEXT: key.typename: "FooSubEnum1",
// CHECK-NEXT: key.context: source.codecompletion.context.othermodule,
// CHECK-NEXT: key.moduleimportdepth: 3,
// CHECK-NEXT: key.num_bytes_to_erase: 0,
// CHECK-NOT: key.modulename
// CHECK: key.modulename: "Foo.FooSub"
// CHECK-NEXT: },
// FooHelper == 4
// FIXME: rdar://problem/20230030
// We're picking up the implicit import of FooHelper used to attach FooHelperExplicit to.
// xCHECK-LABEL: key.name: "FooHelperUnnamedEnumeratorA2",
// xCHECK-NEXT: key.sourcetext: "FooHelperUnnamedEnumeratorA2",
// xCHECK-NEXT: key.description: "FooHelperUnnamedEnumeratorA2",
// xCHECK-NEXT: key.typename: "Int",
// xCHECK-NEXT: key.context: source.codecompletion.context.othermodule,
// xCHECK-NEXT: key.moduleimportdepth: 4,
// xCHECK-NEXT: key.num_bytes_to_erase: 0,
// xCHECK-NOT: key.modulename
// xCHECK: key.modulename: "FooHelper"
// xCHECK-NEXT: },