Skip to content

Commit 9a838bb

Browse files
committed
Differentiate between Swift 5 and “Swift 6” #file
In -swift-version 5 and earlier, #file will continue to be a synonym for #filePath; in a future -swift-version (“Swift 6 mode”), it will become a synonym for #fileID. #file in libraries will be interpreted according to the language mode the library was compiled in, not the language mode its client uses. Implement this behavior, tied to a frontend flag instead of a language version. We do so by splitting the old `MagicIdentifierLiteralExprKind::File` into two separate cases, `FileIDSpelledAsFile` and `FilePathSpelledAsFile`, and propagating this distinction throughout the AST. This seems cleaner than looking up the setting for the module the declaration belongs to every time we see `File`. This doesn’t handle module interfaces yet; we’ll take care of those in a separate commit.
1 parent 745dbef commit 9a838bb

File tree

9 files changed

+74
-18
lines changed

9 files changed

+74
-18
lines changed

include/swift/AST/MagicIdentifierKinds.def

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,19 +52,27 @@
5252
// Magic string literals
5353
//
5454

55-
/// The \c #file magic identifier literal.
56-
MAGIC_STRING_IDENTIFIER(File, "#file", PoundFileExpr)
57-
MAGIC_IDENTIFIER_TOKEN(File, pound_file)
58-
MAGIC_IDENTIFIER_DEPRECATED_TOKEN(File, kw___FILE__)
59-
6055
/// The \c #fileID magic identifier literal.
6156
MAGIC_STRING_IDENTIFIER(FileID, "#fileID", PoundFileIDExpr)
6257
MAGIC_IDENTIFIER_TOKEN(FileID, pound_fileID)
6358

59+
/// The \c #file magic identifier literal, written in code where it is
60+
/// a synonym for \c #fileID (i.e. "Swift 6 mode" code).
61+
MAGIC_STRING_IDENTIFIER(FileIDSpelledAsFile, "#file", PoundFileExpr)
62+
// tok::pound_file is shared with FilePathSpelledAsFile; please write custom
63+
// code paths for it.
64+
6465
/// The \c #filePath magic identifier literal.
6566
MAGIC_STRING_IDENTIFIER(FilePath, "#filePath", PoundFilePathExpr)
6667
MAGIC_IDENTIFIER_TOKEN(FilePath, pound_filePath)
6768

69+
/// The \c #file magic identifier literal, written in code where it is
70+
/// a synonym for \c #filePath (i.e. Swift 5 mode code).
71+
MAGIC_STRING_IDENTIFIER(FilePathSpelledAsFile, "#file", PoundFileExpr)
72+
// tok::pound_file is shared with FileIDSpelledAsFile; please write custom
73+
// code paths for it.
74+
MAGIC_IDENTIFIER_DEPRECATED_TOKEN(FilePathSpelledAsFile, kw___FILE__)
75+
6876
/// The \c #function magic identifier literal.
6977
MAGIC_STRING_IDENTIFIER(Function, "#function", PoundFunctionExpr)
7078
MAGIC_IDENTIFIER_TOKEN(Function, pound_function)

lib/IDE/CodeCompletion.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4033,6 +4033,12 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
40334033
Optional<CodeCompletionLiteralKind> literalKind) {
40344034
CodeCompletionKeywordKind kwKind;
40354035
switch (magicKind) {
4036+
case MagicIdentifierLiteralExpr::FileIDSpelledAsFile:
4037+
kwKind = CodeCompletionKeywordKind::pound_file;
4038+
break;
4039+
case MagicIdentifierLiteralExpr::FilePathSpelledAsFile:
4040+
// Already handled by above case.
4041+
return;
40364042
#define MAGIC_IDENTIFIER_TOKEN(NAME, TOKEN) \
40374043
case MagicIdentifierLiteralExpr::NAME: \
40384044
kwKind = CodeCompletionKeywordKind::TOKEN; \

lib/Parse/ParseExpr.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1019,8 +1019,13 @@ static bool isValidTrailingClosure(bool isExprBasic, Parser &P){
10191019
/// Map magic literal tokens such as #file to their
10201020
/// MagicIdentifierLiteralExpr kind.
10211021
static MagicIdentifierLiteralExpr::Kind
1022-
getMagicIdentifierLiteralKind(tok Kind) {
1022+
getMagicIdentifierLiteralKind(tok Kind, const LangOptions &Opts) {
10231023
switch (Kind) {
1024+
case tok::pound_file:
1025+
// TODO: Enable by default at the next source break.
1026+
return Opts.EnableConcisePoundFile
1027+
? MagicIdentifierLiteralExpr::FileIDSpelledAsFile
1028+
: MagicIdentifierLiteralExpr::FilePathSpelledAsFile;
10241029
#define MAGIC_IDENTIFIER_TOKEN(NAME, TOKEN) \
10251030
case tok::TOKEN: \
10261031
return MagicIdentifierLiteralExpr::Kind::NAME;
@@ -1450,7 +1455,7 @@ ParserResult<Expr> Parser::parseExprPrimary(Diag<> ID, bool isExprBasic) {
14501455
#define MAGIC_IDENTIFIER_DEPRECATED_TOKEN(NAME, TOKEN) case tok::TOKEN:
14511456
#include "swift/AST/MagicIdentifierKinds.def"
14521457
{
1453-
auto Kind = getMagicIdentifierLiteralKind(Tok.getKind());
1458+
auto Kind = getMagicIdentifierLiteralKind(Tok.getKind(), Context.LangOpts);
14541459
auto replacement = MagicIdentifierLiteralExpr::getKindString(Kind);
14551460

14561461
diagnose(Tok.getLoc(), diag::snake_case_deprecated,
@@ -1460,11 +1465,12 @@ ParserResult<Expr> Parser::parseExprPrimary(Diag<> ID, bool isExprBasic) {
14601465
}
14611466

14621467
// Cases for non-deprecated magic identifier tokens
1468+
case tok::pound_file:
14631469
#define MAGIC_IDENTIFIER_DEPRECATED_TOKEN(NAME, TOKEN)
14641470
#define MAGIC_IDENTIFIER_TOKEN(NAME, TOKEN) case tok::TOKEN:
14651471
#include "swift/AST/MagicIdentifierKinds.def"
14661472
{
1467-
auto Kind = getMagicIdentifierLiteralKind(Tok.getKind());
1473+
auto Kind = getMagicIdentifierLiteralKind(Tok.getKind(), Context.LangOpts);
14681474
SyntaxKind SKind = getMagicIdentifierSyntaxKind(Kind);
14691475

14701476
ExprContext.setCreateSyntax(SKind);

lib/SILGen/SILGenApply.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4848,6 +4848,7 @@ RValue SILGenFunction::emitLiteral(LiteralExpr *literal, SGFContext C) {
48484848

48494849
auto magicLiteral = cast<MagicIdentifierLiteralExpr>(literal);
48504850
switch (magicLiteral->getKind()) {
4851+
case MagicIdentifierLiteralExpr::FileIDSpelledAsFile:
48514852
case MagicIdentifierLiteralExpr::FileID: {
48524853
std::string value = loc.isValid() ? getMagicFileIDString(loc) : "";
48534854
builtinLiteralArgs = emitStringLiteral(*this, literal, value, C,
@@ -4857,7 +4858,7 @@ RValue SILGenFunction::emitLiteral(LiteralExpr *literal, SGFContext C) {
48574858
break;
48584859
}
48594860

4860-
case MagicIdentifierLiteralExpr::File:
4861+
case MagicIdentifierLiteralExpr::FilePathSpelledAsFile:
48614862
case MagicIdentifierLiteralExpr::FilePath: {
48624863
StringRef value = loc.isValid() ? getMagicFilePathString(loc) : "";
48634864
builtinLiteralArgs = emitStringLiteral(*this, literal, value, C,

lib/Serialization/Deserialization.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,9 +215,10 @@ getActualDefaultArgKind(uint8_t raw) {
215215
CASE(Normal)
216216
CASE(Inherited)
217217
CASE(Column)
218-
CASE(File)
219218
CASE(FileID)
219+
CASE(FileIDSpelledAsFile)
220220
CASE(FilePath)
221+
CASE(FilePathSpelledAsFile)
221222
CASE(Line)
222223
CASE(Function)
223224
CASE(DSOHandle)

lib/Serialization/ModuleFormat.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0;
5555
/// describe what change you made. The content of this comment isn't important;
5656
/// it just ensures a conflict if two people change the module format.
5757
/// Don't worry about adhering to the 80-column limit for this line.
58-
const uint16_t SWIFTMODULE_VERSION_MINOR = 564; // `@derivative` attribute accessor kind
58+
const uint16_t SWIFTMODULE_VERSION_MINOR = 565; // #fileID
5959

6060
/// A standard hash seed used for all string hashes in a serialized module.
6161
///
@@ -481,9 +481,10 @@ using ValueOwnershipField = BCFixed<2>;
481481
enum class DefaultArgumentKind : uint8_t {
482482
None = 0,
483483
Normal,
484-
File,
485484
FileID,
485+
FileIDSpelledAsFile,
486486
FilePath,
487+
FilePathSpelledAsFile,
487488
Line,
488489
Column,
489490
Function,

lib/Serialization/Serialization.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1121,9 +1121,10 @@ static uint8_t getRawStableDefaultArgumentKind(swift::DefaultArgumentKind kind)
11211121
CASE(Normal)
11221122
CASE(Inherited)
11231123
CASE(Column)
1124-
CASE(File)
11251124
CASE(FileID)
11261125
CASE(FilePath)
1126+
CASE(FileIDSpelledAsFile)
1127+
CASE(FilePathSpelledAsFile)
11271128
CASE(Line)
11281129
CASE(Function)
11291130
CASE(DSOHandle)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
public func useLibrary(file: String = #file) {}

test/SILGen/magic_identifier_file.swift

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,19 @@
1-
// RUN: %target-swift-emit-silgen -module-name Foo %/s | %FileCheck --check-prefixes=BOTH,ABSOLUTE %s
2-
// RUN: %target-swift-emit-silgen -enable-experimental-concise-pound-file -DNEEDS_CONCISE -module-name Foo %/s | %FileCheck --check-prefixes=BOTH,CONCISE %s
1+
// RUN: %empty-directory(%t)
32

4-
// FIXME: Once this feature becomes non-experimental, we should update existing
5-
// tests and delete this file.
3+
// Build library in Swift 5 mode:
4+
// RUN: %target-build-swift-dylib(%t/%target-library-name(MagicIdentifierFileSwift5)) -module-name MagicIdentifierFileSwift5 -emit-module-path %t/MagicIdentifierFileSwift5.swiftmodule -emit-module-interface-path %t/MagicIdentifierFileSwift5.swiftinterface -swift-version 5 -enable-library-evolution %S/Inputs/MagicIdentifierFileSwift.swift
5+
6+
// Build library in "Swift 6" mode:
7+
// RUN: %target-build-swift-dylib(%t/%target-library-name(MagicIdentifierFileSwift6)) -module-name MagicIdentifierFileSwift6 -emit-module-path %t/MagicIdentifierFileSwift6.swiftmodule -emit-module-interface-path %t/MagicIdentifierFileSwift6.swiftinterface -swift-version 5 -enable-experimental-concise-pound-file -enable-library-evolution %S/Inputs/MagicIdentifierFileSwift.swift
8+
9+
// Test in Swift 5 mode:
10+
// RUN: %target-swift-emit-silgen -I %t -module-name Foo %/s | %FileCheck --check-prefixes=BOTH,ABSOLUTE %s
11+
12+
// Test in "Swift 6" mode:
13+
// RUN: %target-swift-emit-silgen -I %t -enable-experimental-concise-pound-file -module-name Foo %/s | %FileCheck --check-prefixes=BOTH,CONCISE %s
14+
15+
import MagicIdentifierFileSwift5
16+
import MagicIdentifierFileSwift6
617

718
func directUse() {
819
// BOTH-LABEL: sil {{.*}} @$s3Foo9directUseyyF
@@ -13,11 +24,29 @@ func directUse() {
1324

1425
func indirectUse() {
1526
// BOTH-LABEL: sil {{.*}} @$s3Foo11indirectUseyyF
16-
fatalError()
27+
useIndirectly()
1728
// ABSOLUTE: string_literal utf8 "SOURCE_DIR/test/SILGen/magic_identifier_file.swift"
1829
// CONCISE: string_literal utf8 "Foo/magic_identifier_file.swift"
1930
}
2031

32+
func swift5LibraryUse() {
33+
// BOTH-LABEL: sil {{.*}} @$s3Foo16swift5LibraryUseyyF
34+
MagicIdentifierFileSwift5.useLibrary()
35+
// BOTH: string_literal utf8 "SOURCE_DIR/test/SILGen/magic_identifier_file.swift"
36+
}
37+
38+
func swift6LibraryUse() {
39+
// BOTH-LABEL: sil {{.*}} @$s3Foo16swift6LibraryUseyyF
40+
MagicIdentifierFileSwift6.useLibrary()
41+
// BOTH: string_literal utf8 "Foo/magic_identifier_file.swift"
42+
}
43+
44+
func stdlibUse() {
45+
// BOTH-LABEL: sil {{.*}} @$s3Foo9stdlibUseyyF
46+
fatalError()
47+
// BOTH: string_literal utf8 "SOURCE_DIR/test/SILGen/magic_identifier_file.swift"
48+
}
49+
2150
func forceUnwrap(_ x: ()?) {
2251
// BOTH-LABEL: sil {{.*}} @$s3Foo11forceUnwrapyyytSgF
2352
_ = x!
@@ -30,6 +59,8 @@ func forceTry(_ fn: () throws -> ()) {
3059
// BOTH: string_literal utf8 "Foo/magic_identifier_file.swift"
3160
}
3261

62+
func useIndirectly(file: String = #file) {}
63+
3364
// CONCISE-LABEL: // Mappings from '#fileID' to '#filePath':
3465
// CONCISE: // 'Foo/magic_identifier_file.swift' => 'SOURCE_DIR/test/SILGen/magic_identifier_file.swift'
3566

0 commit comments

Comments
 (0)