-
Notifications
You must be signed in to change notification settings - Fork 10.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement (Sugared) Bound Generic Extensions
A scoped-down version of #39307. Implement extension of bound generic types. The important bit here is in TypeCheckGeneric where we now use the underlying type of a typealias and its associated nominal type decl when we're generating substitutions for the extended type. Put this behind a new experimental flag -enable-experimental-bound-generic-extensions Resolves SR-4875 Resolves rdar://17434633
- Loading branch information
Showing
9 changed files
with
182 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
// RUN: %target-swift-frontend -module-name Test -typecheck -emit-module-interface-path - -enable-experimental-bound-generic-extensions %s | %FileCheck %s | ||
|
||
public struct Tree<T> { | ||
public struct Branch<B> { | ||
public struct Nest<N> { | ||
public struct Egg {} | ||
} | ||
} | ||
} | ||
|
||
// CHECK: extension Test.Tree.Branch.Nest.Egg { | ||
// CHECK: public static func tweet() | ||
// CHECK: } | ||
extension Tree.Branch.Nest.Egg { public static func tweet() {} } | ||
|
||
// CHECK: extension Test.Tree.Branch.Nest.Egg where T == Swift.Int { | ||
// CHECK: public static func twoot() | ||
// CHECK: } | ||
extension Tree<Int>.Branch.Nest.Egg { public static func twoot() {} } | ||
|
||
// CHECK: extension Test.Tree.Branch.Nest.Egg where T == Swift.Int, B == Swift.String { | ||
// CHECK: public static func twote() | ||
// CHECK: } | ||
extension Tree<Int>.Branch<String>.Nest.Egg { public static func twote() {} } | ||
|
||
// CHECK: extension Test.Tree.Branch.Nest.Egg where T == Swift.Int, B == Swift.String, N == Swift.Void { | ||
// CHECK: public static func twite() | ||
// CHECK: } | ||
extension Tree<Int>.Branch<String>.Nest<Void>.Egg { public static func twite() {} } | ||
|
||
// CHECK: extension Swift.Array where Element == Swift.String { | ||
// CHECK: public func rejoinder() -> Swift.String | ||
// CHECK: } | ||
extension [String] { public func rejoinder() -> String { return self.joined() } } | ||
|
||
// CHECK: public typealias StringDict<T> = [Swift.String : T] | ||
public typealias StringDict<T> = [String: T] | ||
|
||
// CHECK: extension Swift.Dictionary where Key == Swift.String, Value == Swift.Int | ||
extension StringDict<Int> { public static func mark() {} } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
// RUN: %target-swift-emit-silgen -enable-experimental-bound-generic-extensions %s | %FileCheck %s | ||
|
||
struct Tree<T> { | ||
struct Branch<B> { | ||
struct Nest<N> { | ||
struct Egg {} | ||
} | ||
} | ||
} | ||
|
||
// CHECK: extension Tree.Branch.Nest.Egg { | ||
// CHECK: static func tweet() | ||
// CHECK: } | ||
|
||
// CHECK: extension Tree.Branch.Nest.Egg where T == Int { | ||
// CHECK: static func twoot() | ||
// CHECK: } | ||
|
||
// CHECK: extension Tree.Branch.Nest.Egg where T == Int, B == String { | ||
// CHECK: static func twote() | ||
// CHECK: } | ||
|
||
// CHECK: extension Tree.Branch.Nest.Egg where T == Int, B == String, N == () { | ||
// CHECK: static func twite() | ||
// CHECK: } | ||
|
||
// CHECK: @$s31mangling_specialized_extensions4TreeV6BranchV4NestV3EggV5tweetyyFZ : $@convention(method) <T><B><N> (@thin Tree<T>.Branch<B>.Nest<N>.Egg.Type) -> () | ||
extension Tree.Branch.Nest.Egg { static func tweet() {} } | ||
|
||
// CHECK: @$s31mangling_specialized_extensions4TreeV6BranchV4NestV3EggVAASiRszrlE5twootyyFZ : $@convention(method) <T where T == Int><B><N> (@thin Tree<Int>.Branch<B>.Nest<N>.Egg.Type) -> () | ||
extension Tree<Int>.Branch.Nest.Egg { static func twoot() {} } | ||
|
||
// CHECK: @$s31mangling_specialized_extensions4TreeV6BranchV4NestV3EggVAASiRszSSRsd__rlE5twoteyyFZ : $@convention(method) <T where T == Int><B where B == String><N> (@thin Tree<Int>.Branch<String>.Nest<N>.Egg.Type) -> () | ||
extension Tree<Int>.Branch<String>.Nest.Egg { static func twote() {} } | ||
|
||
// CHECK: @$s31mangling_specialized_extensions4TreeV6BranchV4NestV3EggVAASiRszSSRsd__ytRsd0__rlE5twiteyyFZ : $@convention(method) (@thin Tree<Int>.Branch<String>.Nest<()>.Egg.Type) -> () | ||
extension Tree<Int>.Branch<String>.Nest<Void>.Egg { static func twite() {} } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
// RUN: %target-typecheck-verify-swift -enable-experimental-bound-generic-extensions | ||
|
||
extension Array<Int> { | ||
func someIntFuncOnArray() {} | ||
} | ||
|
||
let _ = [0, 1, 2].someIntFuncOnArray() | ||
|
||
extension [Character] { | ||
func makeString() -> String { fatalError() } | ||
} | ||
|
||
let _ = ["a", "b", "c"].makeString() | ||
let _ = [1, 2, 3].makeString() // expected-error 3 {{cannot convert value of type 'Int' to expected element type 'Character'}} | ||
|
||
extension Set<_> {} // expected-error {{cannot extend a type that contains placeholders}} | ||
|
||
// https://bugs.swift.org/browse/SR-4875 | ||
|
||
struct Foo<T, U> { | ||
var x: T | ||
var y: U | ||
} | ||
|
||
typealias IntFoo<U> = Foo<Int, U> | ||
|
||
extension IntFoo where U == Int { | ||
func hello() { | ||
print("hello") | ||
} | ||
} | ||
|
||
Foo(x: "test", y: 1).hello() | ||
|
||
struct MyType<TyA, TyB> { | ||
var a : TyA, b : TyB | ||
} | ||
|
||
typealias A<T1, T2> = MyType<T2, T1> | ||
|
||
extension A {} | ||
|
||
extension A<Float, Int> {} | ||
extension A<Void, Void> {} | ||
|
||
struct Tree<T> { | ||
struct Branch<B> { | ||
struct Nest<N> { | ||
struct Egg {} | ||
} | ||
} | ||
} | ||
|
||
extension Tree.Branch.Nest.Egg { static func tweet() {} } | ||
extension Tree<Int>.Branch.Nest.Egg { static func twoot() {} } | ||
extension Tree<Int>.Branch<String>.Nest.Egg { static func twote() {} } | ||
extension Tree<Int>.Branch<String>.Nest<Void>.Egg { static func twite() {} } | ||
|
||
func testNestedExtensions() { | ||
do { | ||
Tree<Void>.Branch<Void>.Nest<Void>.Egg.tweet() | ||
} | ||
|
||
do { | ||
Tree<Int>.Branch<Void>.Nest<Void>.Egg.twoot() | ||
Tree<Int>.Branch<Int>.Nest<Void>.Egg.twoot() | ||
Tree<Int>.Branch<Int>.Nest<Int>.Egg.twoot() | ||
} | ||
|
||
do { | ||
Tree<Int>.Branch<String>.Nest<Void>.Egg.twote() | ||
Tree<Int>.Branch<String>.Nest<Float>.Egg.twote() | ||
} | ||
|
||
Tree<Int>.Branch<String>.Nest<Void>.Egg.twite() | ||
} |