Skip to content

Commit f8f6d61

Browse files
slavapestovtkremenek
authored andcommitted
Fixes for typealiases involving generics (#3811)
* Serialization: Another fix for generic typealiases Fixes <https://bugs.swift.org/browse/SR-1889>. * Sema: Fix FindCapturedVars to look through typealiases Fixes <https://bugs.swift.org/browse/SR-1781>.
1 parent 17a5510 commit f8f6d61

File tree

6 files changed

+51
-35
lines changed

6 files changed

+51
-35
lines changed

lib/Sema/TypeCheckCaptures.cpp

Lines changed: 18 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ class FindCapturedVars : public ASTWalker {
7373
if (!type)
7474
return;
7575

76+
// We want to look through type aliases here.
77+
type = type->getCanonicalType();
78+
7679
// If the type contains dynamic 'Self', conservatively assume we will
7780
// need 'Self' metadata at runtime. We could generalize the analysis
7881
// used below for usages of generic parameters in Objective-C
@@ -95,42 +98,22 @@ class FindCapturedVars : public ASTWalker {
9598
});
9699
}
97100

98-
// Nothing to do if the type is concrete.
99-
if (!type->hasArchetype())
100-
return;
101-
102-
// Walk the type to see if we have any archetypes that are *not* open
103-
// existentials and that aren't type-erased.
104-
class CapturesTypeWalker final : public TypeWalker {
105-
SourceLoc &GenericParamCaptureLoc;
106-
SourceLoc CurLoc;
107-
108-
public:
109-
CapturesTypeWalker(SourceLoc &GenericParamCaptureLoc,
110-
SourceLoc curLoc)
111-
: GenericParamCaptureLoc(GenericParamCaptureLoc),
112-
CurLoc(curLoc) {}
113-
114-
Action walkToTypePre(Type t) override {
115-
// Similar to dynamic 'Self', IRGen doesn't really need type metadata
116-
// for class-bound archetypes in nearly as many cases as with opaque
117-
// archetypes.
118-
//
119-
// Perhaps this entire analysis should happen at the SILGen level,
120-
// instead, but even there we don't really have enough information to
121-
// perform it accurately.
122-
if (t->is<ArchetypeType>() && !t->isOpenedExistential()) {
123-
if (GenericParamCaptureLoc.isInvalid())
124-
GenericParamCaptureLoc = CurLoc;
125-
return Action::Continue;
101+
// Similar to dynamic 'Self', IRGen doesn't really need type metadata
102+
// for class-bound archetypes in nearly as many cases as with opaque
103+
// archetypes.
104+
//
105+
// Perhaps this entire analysis should happen at the SILGen level,
106+
// instead, but even there we don't really have enough information to
107+
// perform it accurately.
108+
if (type->hasArchetype()) {
109+
type.visit([&](Type t) {
110+
if (t->is<ArchetypeType>() &&
111+
!t->isOpenedExistential() &&
112+
GenericParamCaptureLoc.isInvalid()) {
113+
GenericParamCaptureLoc = loc;
126114
}
127-
128-
return Action::Continue;
129-
}
130-
};
131-
132-
type.walk(CapturesTypeWalker(GenericParamCaptureLoc,
133-
loc));
115+
});
116+
}
134117
}
135118

136119
/// Add the specified capture to the closure's capture list, diagnosing it

lib/Serialization/Deserialization.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1359,6 +1359,8 @@ Decl *ModuleFile::resolveCrossReference(Module *M, uint32_t pathLen) {
13591359
// Simple case: use the nominal type's generic parameters.
13601360
paramList = nominal->getGenericParams();
13611361
}
1362+
} else if (auto alias = dyn_cast<TypeAliasDecl>(base)) {
1363+
paramList = alias->getGenericParams();
13621364
} else if (auto fn = dyn_cast<AbstractFunctionDecl>(base))
13631365
paramList = fn->getGenericParams();
13641366

test/expr/capture/generic_params.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,13 @@ func outerGeneric<T>(t: T, x: AnyObject) {
2222
// they're not mentioned in the function body
2323
// CHECK: func_decl "innerGeneric(u:)"<U> type='<U> (u: U) -> ()' {{.*}} captures=(<generic> )
2424
func innerGeneric<U>(u: U) {}
25+
26+
// Make sure we look through typealiases
27+
typealias TT = (a: T, b: T)
28+
29+
// CHECK: func_decl "localFunction(tt:)" type='<T> (tt: TT) -> ()' {{.*}} captures=(<generic> )
30+
func localFunction(tt: TT) {}
31+
32+
// CHECK: closure_expr type='(TT) -> ()' {{.*}} captures=(<generic> )
33+
let _: (TT) -> () = { _ in }
2534
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// RUN: true
2+
3+
public enum Result<T, U>
4+
{
5+
case success(T)
6+
case failure(U)
7+
}
8+
9+
public typealias GenericResult<T> = Result<T, Error>
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// RUN: rm -rf %t && mkdir %t
2+
3+
// RUN: %target-build-swift %S/main.swift %S/library.swift
4+
// RUN: %target-build-swift -g %S/main.swift %S/library.swift
5+
6+
// REQUIRES: executable_test
7+
8+
func testFunction<T>(withCompletion completion: (Result<T, Error>) -> Void) { }
9+
testFunction { (result: GenericResult<Int>) in }

test/multifile/typealias/two-modules/main.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55
// RUN: %target-build-swift -emit-library -c %S/library.swift -o %t/linker/library.o
66
// RUN: %target-build-swift %S/main.swift %t/linker/library.o -I %t/linker/ -L %t/linker/ -o %t/linker/main
77

8+
// RUN: %target-build-swift -g -emit-module -c %S/library.swift -o %t/linker/library.o
9+
// RUN: %target-build-swift -g -emit-library -c %S/library.swift -o %t/linker/library.o
10+
// RUN: %target-build-swift -g %S/main.swift %t/linker/library.o -I %t/linker/ -L %t/linker/ -o %t/linker/main
11+
812
// REQUIRES: executable_test
913

1014
import library

0 commit comments

Comments
 (0)