Skip to content

Commit 20a429b

Browse files
authored
Merge pull request #9348 from bitjammer/rdar-add-Swift-prefix-to-typeof
[Migrator] Add `Swift.` prefix to type(of:) expressions in Swift 3
2 parents a149538 + f697075 commit 20a429b

5 files changed

+94
-2
lines changed

Diff for: lib/Migrator/SyntacticMigratorPass.cpp

+38
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13+
#include "swift/AST/NameLookup.h"
1314
#include "swift/AST/USRGeneration.h"
1415
#include "swift/AST/ASTVisitor.h"
1516
#include "swift/Frontend/Frontend.h"
@@ -536,6 +537,38 @@ struct SyntacticMigratorPass::Implementation : public SourceEntityWalker {
536537
return;
537538
}
538539

540+
/// If the expression is `type(of:)`, in Swift 3 it's a special 'dynamic type
541+
/// expression'. In Swift 4, this is resolved by overload resolution, so
542+
/// if there is a func type(of:) or even var type, it can shadow
543+
/// Swift.type(of:), which is probably not what people want.
544+
///
545+
/// This migration operation adds `Swift.` to disambiguate in Swift 4.
546+
void handleTypeOfFunction(const DynamicTypeExpr *DTE) {
547+
if (!SF->getASTContext().LangOpts.isSwiftVersion3()) {
548+
return;
549+
}
550+
const auto CSR = Lexer::getCharSourceRangeFromSourceRange(SM,
551+
DTE->getSourceRange());
552+
if (SM.extractText(CSR).startswith("Swift.")) {
553+
return;
554+
}
555+
556+
UnqualifiedLookup Lookup {
557+
{ SF->getASTContext().getIdentifier("type") },
558+
SF->getModuleScopeContext(),
559+
/*TypeResolver=*/nullptr,
560+
/*IsKnownPrivate=*/false,
561+
DTE->getLoc()
562+
};
563+
if (Lookup.Results.empty()) {
564+
// There won't be a name shadowing here in Swift 4, so we don't need to
565+
// do anything.
566+
return;
567+
}
568+
569+
Editor.insertBefore(DTE->getLoc(), "Swift.");
570+
}
571+
539572
bool walkToExprPre(Expr *E) override {
540573
if (auto *CE = dyn_cast<CallExpr>(E)) {
541574
handleTupleArgumentMismatches(CE);
@@ -566,6 +599,11 @@ struct SyntacticMigratorPass::Implementation : public SourceEntityWalker {
566599
break;
567600
}
568601
}
602+
603+
if (const auto *DTE = dyn_cast<DynamicTypeExpr>(E)) {
604+
handleTypeOfFunction(DTE);
605+
}
606+
569607
return true;
570608
}
571609

Diff for: test/Migrator/prefix_typeof_expr.swift

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// rdar://problem/32025974
2+
// XFAIL: linux
3+
// RUN: rm -rf %t && mkdir -p %t && %target-swift-frontend -c -update-code -primary-file %s -emit-migrated-file-path %t/prefix_typeof_expr.swift.result -emit-remap-file-path %t/member.swift.remap -o /dev/null
4+
// RUN: diff -u %S/prefix_typeof_expr.swift.expected %t/prefix_typeof_expr.swift.result
5+
6+
class HasTypeVar {
7+
var type: Int {
8+
precondition(true, "\(type(of: self)) should never be asked for its type")
9+
_ = Swift.type(of: 1) // Don't add another prefix to this one
10+
return 1
11+
}
12+
}
13+
14+
class HasTypeMethod {
15+
func type<T>(of: T) -> Int {
16+
_ = type(of: 1)
17+
_ = Swift.type(of: 1) // Don't add another prefix to this one
18+
return 1
19+
}
20+
}
21+
22+
func type<T>(of: T) -> Int {
23+
return 1
24+
}
25+
26+
_ = type(of: 1)
27+
_ = Swift.type(of: 1) // Don't add another prefix to this one

Diff for: test/Migrator/prefix_typeof_expr.swift.expected

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// rdar://problem/32025974
2+
// XFAIL: linux
3+
// RUN: rm -rf %t && mkdir -p %t && %target-swift-frontend -c -update-code -primary-file %s -emit-migrated-file-path %t/prefix_typeof_expr.swift.result -emit-remap-file-path %t/member.swift.remap -o /dev/null
4+
// RUN: diff -u %S/prefix_typeof_expr.swift.expected %t/prefix_typeof_expr.swift.result
5+
6+
class HasTypeVar {
7+
var type: Int {
8+
precondition(true, "\(Swift.type(of: self)) should never be asked for its type")
9+
_ = Swift.type(of: 1) // Don't add another prefix to this one
10+
return 1
11+
}
12+
}
13+
14+
class HasTypeMethod {
15+
func type<T>(of: T) -> Int {
16+
_ = Swift.type(of: 1)
17+
_ = Swift.type(of: 1) // Don't add another prefix to this one
18+
return 1
19+
}
20+
}
21+
22+
func type<T>(of: T) -> Int {
23+
return 1
24+
}
25+
26+
_ = Swift.type(of: 1)
27+
_ = Swift.type(of: 1) // Don't add another prefix to this one

Diff for: test/Migrator/tuple-arguments.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// FIXME: Figure out why this is not working on linux
1+
// rdar://problem/32025974
22
// XFAIL: linux
33

44
// RUN: %target-swift-frontend -typecheck %s -swift-version 3

Diff for: test/Migrator/tuple-arguments.swift.expected

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// FIXME: Figure out why this is not working on linux
1+
// rdar://problem/32025974
22
// XFAIL: linux
33

44
// RUN: %target-swift-frontend -typecheck %s -swift-version 3

0 commit comments

Comments
 (0)