Merge pull request #17280 from xedin/rdar-41141944-4.2
[4.2][TypeChecker] When formatting witness type for diagnostics don't assu…
diff --git a/include/swift/IDE/DigesterEnums.def b/include/swift/IDE/DigesterEnums.def
index 26fb0cb..bb0cfc9 100644
--- a/include/swift/IDE/DigesterEnums.def
+++ b/include/swift/IDE/DigesterEnums.def
@@ -80,6 +80,7 @@
NODE_ANNOTATION_CHANGE_KIND(SimpleStringRepresentableUpdate)
NODE_ANNOTATION_CHANGE_KIND(SimpleOptionalStringRepresentableUpdate)
NODE_ANNOTATION_CHANGE_KIND(TypeAliasDeclToRawRepresentable)
+NODE_ANNOTATION_CHANGE_KIND(RevertTypeAliasDeclToRawRepresentable)
NODE_ANNOTATION_CHANGE_KIND(RevertDictionaryKeyUpdate)
NODE_ANNOTATION_CHANGE_KIND(RevertOptionalDictionaryKeyUpdate)
diff --git a/lib/ClangImporter/ImportType.cpp b/lib/ClangImporter/ImportType.cpp
index fc58c94..315e401 100644
--- a/lib/ClangImporter/ImportType.cpp
+++ b/lib/ClangImporter/ImportType.cpp
@@ -974,8 +974,8 @@
// Convert the type arguments.
for (auto typeArg : typeArgs) {
Type importedTypeArg = Impl.importTypeIgnoreIUO(
- typeArg, ImportTypeKind::BridgedValue, AllowNSUIntegerAsInt,
- Bridging, OTK_None);
+ typeArg, ImportTypeKind::ObjCCollectionElement,
+ AllowNSUIntegerAsInt, Bridging, OTK_None);
if (!importedTypeArg) {
importedTypeArgs.clear();
break;
@@ -1102,7 +1102,7 @@
case ImportTypeKind::CFUnretainedOutParameter:
case ImportTypeKind::Property:
case ImportTypeKind::PropertyWithReferenceSemantics:
- case ImportTypeKind::BridgedValue:
+ case ImportTypeKind::ObjCCollectionElement:
case ImportTypeKind::Typedef:
return true;
}
@@ -1116,7 +1116,7 @@
case ImportTypeKind::Abstract:
case ImportTypeKind::Typedef:
case ImportTypeKind::Value:
- case ImportTypeKind::BridgedValue:
+ case ImportTypeKind::ObjCCollectionElement:
case ImportTypeKind::Variable:
case ImportTypeKind::Result:
case ImportTypeKind::Pointee:
@@ -1283,14 +1283,29 @@
}
// SwiftTypeConverter turns block pointers into @convention(block) types.
- // In a bridgeable context, or in the direct structure of a typedef,
- // we would prefer to instead use the default Swift convention.
+ // In some contexts, we bridge them to use the Swift function type
+ // representation. This includes typedefs of block types, which use the
+ // Swift function type representation.
if (hint == ImportHint::Block) {
if (canBridgeTypes(importKind)) {
+ // Determine the function type representation we need.
+ //
+ // For Objective-C collection arguments, we cannot bridge from a block
+ // to a Swift function type, so force the block representation. Normally
+ // the mapped type will have a block representation (making this a no-op),
+ // but in cases where the Clang type was written as a typedef of a
+ // block type, that typedef will have a Swift function type
+ // representation. This code will then break down the imported type
+ // alias and produce a function type with block representation.
+ auto requiredFunctionTypeRepr = FunctionTypeRepresentation::Swift;
+ if (importKind == ImportTypeKind::ObjCCollectionElement) {
+ requiredFunctionTypeRepr = FunctionTypeRepresentation::Block;
+ }
+
auto fTy = importedType->castTo<FunctionType>();
FunctionType::ExtInfo einfo = fTy->getExtInfo();
- if (einfo.getRepresentation() != FunctionTypeRepresentation::Swift) {
- einfo = einfo.withRepresentation(FunctionTypeRepresentation::Swift);
+ if (einfo.getRepresentation() != requiredFunctionTypeRepr) {
+ einfo = einfo.withRepresentation(requiredFunctionTypeRepr);
importedType = fTy->withExtInfo(einfo);
}
}
diff --git a/lib/ClangImporter/ImporterImpl.h b/lib/ClangImporter/ImporterImpl.h
index 6855643..324fb81 100644
--- a/lib/ClangImporter/ImporterImpl.h
+++ b/lib/ClangImporter/ImporterImpl.h
@@ -108,8 +108,8 @@
/// \brief Import the type of a literal value.
Value,
- /// \brief Import the type of a literal value that can be bridged.
- BridgedValue,
+ /// \brief Import the type of an Objective-C generic argument.
+ ObjCCollectionElement,
/// \brief Import the declared type of a variable.
Variable,
diff --git a/lib/Migrator/APIDiffMigratorPass.cpp b/lib/Migrator/APIDiffMigratorPass.cpp
index 4189e66..18c1fe7 100644
--- a/lib/Migrator/APIDiffMigratorPass.cpp
+++ b/lib/Migrator/APIDiffMigratorPass.cpp
@@ -275,6 +275,8 @@
std::vector<APIDiffItem*> getRelatedDiffItems(ValueDecl *VD) {
std::vector<APIDiffItem*> results;
+ if (!VD)
+ return results;
auto addDiffItems = [&](ValueDecl *VD) {
llvm::SmallString<64> Buffer;
llvm::raw_svector_ostream OS(Buffer);
@@ -921,9 +923,66 @@
insertHelperFunction(Kind, RawType, NewAttributeType, FromString, WrapTarget);
}
+ bool hasRevertRawRepresentableChange(ValueDecl *VD) {
+ for (auto Item: getRelatedDiffItems(VD)) {
+ if (auto *CI = dyn_cast<CommonDiffItem>(Item)) {
+ if (CI->DiffKind ==
+ NodeAnnotation::RevertTypeAliasDeclToRawRepresentable)
+ return true;
+ }
+ }
+ return false;
+ }
+
+ bool handleRevertRawRepresentable(Expr *E) {
+ // Change attribute.rawValue to attribute
+ if (auto *MRE = dyn_cast<MemberRefExpr>(E)) {
+ auto Found = false;
+ if (auto *Base = MRE->getBase()) {
+ if (hasRevertRawRepresentableChange(Base->getType()->getAnyNominal())) {
+ Found = true;
+ }
+ }
+ if (!Found)
+ return false;
+ auto NL = MRE->getNameLoc().getStartLoc();
+ auto DL = MRE->getDotLoc();
+ if (NL.isInvalid() || DL.isInvalid())
+ return false;
+ CharSourceRange Range = Lexer::getCharSourceRangeFromSourceRange(SM, {DL, NL});
+ if (Range.str() == ".rawValue") {
+ Editor.remove(Range);
+ return true;
+ }
+ }
+
+ // Change attribute(rawValue: "value") to "value"
+ if (auto *CE = dyn_cast<CallExpr>(E)) {
+ auto Found = false;
+ if (auto *CRC = dyn_cast<ConstructorRefCallExpr>(CE->getFn())) {
+ if (auto *TE = dyn_cast<TypeExpr>(CRC->getBase())) {
+ if (hasRevertRawRepresentableChange(TE->getInstanceType()->getAnyNominal()))
+ Found = true;
+ }
+ }
+ if (!Found)
+ return false;
+ std::vector<CallArgInfo> AllArgs =
+ getCallArgInfo(SM, CE->getArg(), LabelRangeEndAt::LabelNameOnly);
+ if (AllArgs.size() == 1 && AllArgs.front().LabelRange.str() == "rawValue") {
+ Editor.replace(CE->getSourceRange(), Lexer::getCharSourceRangeFromSourceRange(SM,
+ AllArgs.front().ArgExp->getSourceRange()).str());
+ return true;
+ }
+ }
+ return false;
+ }
+
bool walkToExprPre(Expr *E) override {
if (E->getSourceRange().isInvalid())
return false;
+ if (handleRevertRawRepresentable(E))
+ return false;
if (handleQualifiedReplacement(E))
return false;
if (handleAssignDestMigration(E))
diff --git a/stdlib/public/core/Bool.swift b/stdlib/public/core/Bool.swift
index 9b7719e..155cba3 100644
--- a/stdlib/public/core/Bool.swift
+++ b/stdlib/public/core/Bool.swift
@@ -43,6 +43,7 @@
/// print(i)
/// i -= 1
/// }
+/// // error: 'Int' is not convertible to 'Bool'
///
/// The correct approach in Swift is to compare the `i` value with zero in the
/// `while` statement.
diff --git a/stdlib/public/core/Dictionary.swift b/stdlib/public/core/Dictionary.swift
index 197dd8e..d9d9428 100644
--- a/stdlib/public/core/Dictionary.swift
+++ b/stdlib/public/core/Dictionary.swift
@@ -294,7 +294,7 @@
/// dictionary called `interestingNumbers` with string keys and values that
/// are integer arrays, then sorts each array in-place in descending order.
///
-/// var interestingNumbers = ["primes": [2, 3, 5, 7, 11, 13, 15],
+/// var interestingNumbers = ["primes": [2, 3, 5, 7, 11, 13, 17],
/// "triangular": [1, 3, 6, 10, 15, 21, 28],
/// "hexagonal": [1, 6, 15, 28, 45, 66, 91]]
/// for key in interestingNumbers.keys {
@@ -302,7 +302,7 @@
/// }
///
/// print(interestingNumbers["primes"]!)
-/// // Prints "[15, 13, 11, 7, 5, 3, 2]"
+/// // Prints "[17, 13, 11, 7, 5, 3, 2]"
///
/// Iterating Over the Contents of a Dictionary
/// ===========================================
@@ -408,7 +408,7 @@
///
/// - Parameter minimumCapacity: The minimum number of key-value pairs that
/// the newly created dictionary should be able to store without
- // reallocating its storage buffer.
+ /// reallocating its storage buffer.
@inlinable // FIXME(sil-serialize-all)
public init(minimumCapacity: Int) {
_variantBuffer = .native(_NativeBuffer(minimumCapacity: minimumCapacity))
@@ -805,8 +805,56 @@
}
extension Dictionary {
- /// Accesses the element with the given key, or the specified default value,
- /// if the dictionary doesn't contain the given key.
+ /// Accesses the value with the given key. If the dictionary doesn't contain
+ /// the given key, accesses the provided default value as if the key and
+ /// default value existed in the dictionary.
+ ///
+ /// Use this subscript when you want either the value for a particular key
+ /// or, when that key is not present in the dictionary, a default value. This
+ /// example uses the subscript with a message to use in case an HTTP response
+ /// code isn't recognized:
+ ///
+ /// var responseMessages = [200: "OK",
+ /// 403: "Access forbidden",
+ /// 404: "File not found",
+ /// 500: "Internal server error"]
+ ///
+ /// let httpResponseCodes = [200, 403, 301]
+ /// for code in httpResponseCodes {
+ /// let message = responseMessages[code, default: "Unknown response"]
+ /// print("Response \(code): \(message)")
+ /// }
+ /// // Prints "Response 200: OK"
+ /// // Prints "Response 403: Access Forbidden"
+ /// // Prints "Response 301: Unknown response"
+ ///
+ /// When a dictionary's `Value` type has value semantics, you can use this
+ /// subscript to perform in-place operations on values in the dictionary.
+ /// The following example uses this subscript while counting the occurences
+ /// of each letter in a string:
+ ///
+ /// let message = "Hello, Elle!"
+ /// var letterCounts: [Character: Int] = [:]
+ /// for letter in message {
+ /// letterCounts[letter, defaultValue: 0] += 1
+ /// }
+ /// // letterCounts == ["H": 1, "e": 2, "l": 4, "o": 1, ...]
+ ///
+ /// When `letterCounts[letter, defaultValue: 0] += 1` is executed with a
+ /// value of `letter` that isn't already a key in `letterCounts`, the
+ /// specified default value (`0`) is returned from the subscript,
+ /// incremented, and then added to the dictionary under that key.
+ ///
+ /// - Note: Do not use this subscript to modify dictionary values if the
+ /// dictionary's `Value` type is a class. In that case, the default value
+ /// and key are not written back to the dictionary after an operation.
+ ///
+ /// - Parameters:
+ /// - key: The key the look up in the dictionary.
+ /// - defaultValue: The default value to use if `key` doesn't exist in the
+ /// dictionary.
+ /// - Returns: The value associated with `key` in the dictionary`; otherwise,
+ /// `defaultValue`.
@inlinable // FIXME(sil-serialize-all)
public subscript(
key: Key, default defaultValue: @autoclosure () -> Value
diff --git a/stdlib/public/core/Equatable.swift b/stdlib/public/core/Equatable.swift
index f9751ba..75c49f2 100644
--- a/stdlib/public/core/Equatable.swift
+++ b/stdlib/public/core/Equatable.swift
@@ -29,15 +29,15 @@
/// example shows how the `contains(_:)` method can be used with an array of
/// strings.
///
-/// let students = ["Nora", "Fern", "Ryan", "Rainer"]
+/// let students = ["Kofi", "Abena", "Efua", "Kweku", "Akosua"]
///
-/// let nameToCheck = "Ryan"
+/// let nameToCheck = "Kofi"
/// if students.contains(nameToCheck) {
/// print("\(nameToCheck) is signed up!")
/// } else {
/// print("No record of \(nameToCheck).")
/// }
-/// // Prints "Ryan is signed up!"
+/// // Prints "Kofi is signed up!"
///
/// Conforming to the Equatable Protocol
/// ====================================
diff --git a/stdlib/public/core/InputStream.swift b/stdlib/public/core/InputStream.swift
index 6c145c8..2eecdd7 100644
--- a/stdlib/public/core/InputStream.swift
+++ b/stdlib/public/core/InputStream.swift
@@ -19,7 +19,7 @@
/// Unicode [replacement characters][rc].
///
/// [rc]:
-/// http://en.wikipedia.org/wiki/Specials_(Unicode_block)#Replacement_character
+/// https://unicode.org/glossary/#replacement_character
///
/// - Parameter strippingNewline: If `true`, newline characters and character
/// combinations are stripped from the result; otherwise, newline characters
diff --git a/stdlib/public/core/Integers.swift.gyb b/stdlib/public/core/Integers.swift.gyb
index 38e6d57..0627f64 100644
--- a/stdlib/public/core/Integers.swift.gyb
+++ b/stdlib/public/core/Integers.swift.gyb
@@ -977,6 +977,10 @@
/// In debug builds (`-Onone`) a runtime error is still triggered if the
/// operation overflows.
///
+ /// This method is not a synonym for the masking addition operator (`&+`).
+ /// Use that operator instead of this method when you want to discard any
+ /// overflow that results from an addition operation.
+ ///
/// - Parameter rhs: The value to add to this value.
/// - Returns: The sum of this value and `rhs`.
""",
@@ -993,6 +997,10 @@
/// In debug builds (`-Onone`) a runtime error is still triggered if the
/// operation overflows.
///
+ /// This method is not a synonym for the masking subtraction operator (`&-`).
+ /// Use that operator instead of this method when you want to discard any
+ /// overflow that results from a subtraction operation.
+ ///
/// - Parameter rhs: The value to subtract from this value.
/// - Returns: The result of subtracting `rhs` from this value.
""",
@@ -1009,6 +1017,10 @@
/// In debug builds (`-Onone`) a runtime error is still triggered if the
/// operation overflows.
///
+ /// This method is not a synonym for the masking multiplication operator
+ /// (`&*`). Use that operator instead of this method when you want to discard
+ /// any overflow that results from an addition operation.
+ ///
/// - Parameter rhs: The value to multiply by this value.
/// - Returns: The product of this value and `rhs`.
""",
@@ -2417,22 +2429,6 @@
extension FixedWidthInteger {
/// The empty bitset.
- ///
- /// The `allZeros` static property is the [identity element][] for bitwise OR
- /// and XOR operations and the [fixed point][] for bitwise AND operations.
- /// For example:
- ///
- /// let x: UInt8 = 5 // 0b00000101
- ///
- /// // Identity
- /// x | .allZeros // 0b00000101
- /// x ^ .allZeros // 0b00000101
- ///
- /// // Fixed point
- /// x & .allZeros // 0b00000000
- ///
- /// [identity element]:http://en.wikipedia.org/wiki/Identity_element
- /// [fixed point]:http://en.wikipedia.org/wiki/Fixed_point_(mathematics)
@inlinable // FIXME(sil-serialize-all)
@available(swift, deprecated: 3.1, obsoleted: 4.0, message: "Use 0")
public static var allZeros: Self { return 0 }
diff --git a/stdlib/public/core/OptionSet.swift b/stdlib/public/core/OptionSet.swift
index d6a24df..c551fce 100644
--- a/stdlib/public/core/OptionSet.swift
+++ b/stdlib/public/core/OptionSet.swift
@@ -20,10 +20,11 @@
/// requires no extra work on your part.
///
/// When creating an option set, include a `rawValue` property in your type
-/// declaration. The `rawValue` property must be of a type that conforms to
-/// the `FixedWidthInteger` protocol, such as `Int` or `UInt8`. Next, create
-/// unique options as static properties of your custom type using unique
-/// powers of two (1, 2, 4, 8, 16, and so forth) for each individual
+/// declaration. For your type to automatically receive default implementations
+/// for set-related operations, the `rawValue` property must be of a type that
+/// conforms to the `FixedWidthInteger` protocol, such as `Int` or `UInt8`.
+/// Next, create unique options as static properties of your custom type using
+/// unique powers of two (1, 2, 4, 8, 16, and so forth) for each individual
/// property's raw value so that each property can be represented by a single
/// bit of the type's raw value.
///
diff --git a/stdlib/public/core/Policy.swift b/stdlib/public/core/Policy.swift
index 10e7c26..327cdde 100644
--- a/stdlib/public/core/Policy.swift
+++ b/stdlib/public/core/Policy.swift
@@ -454,22 +454,6 @@
static prefix func ~ (x: Self) -> Self
/// The empty bitset.
- ///
- /// The `allZeros` static property is the [identity element][] for bitwise OR
- /// and XOR operations and the [fixed point][] for bitwise AND operations.
- /// For example:
- ///
- /// let x: UInt8 = 5 // 0b00000101
- ///
- /// // Identity
- /// x | .allZeros // 0b00000101
- /// x ^ .allZeros // 0b00000101
- ///
- /// // Fixed point
- /// x & .allZeros // 0b00000000
- ///
- /// [identity element]:http://en.wikipedia.org/wiki/Identity_element
- /// [fixed point]:http://en.wikipedia.org/wiki/Fixed_point_(mathematics)
@available(swift, deprecated: 3.1, obsoleted: 4.0, message: "Use 0 or init() of a type conforming to FixedWidthInteger")
static var allZeros: Self { get }
}
diff --git a/test/ClangImporter/objc_bridging_generics.swift b/test/ClangImporter/objc_bridging_generics.swift
index 8ac6c6c..4ff8cb2 100644
--- a/test/ClangImporter/objc_bridging_generics.swift
+++ b/test/ClangImporter/objc_bridging_generics.swift
@@ -414,3 +414,7 @@
let _: Int = insufficient.foo // expected-error{{cannot convert value of type 'Set<AnyHashable>' to specified type 'Int'}}
let _: Int = extra.foo // expected-error{{cannot convert value of type 'Set<ElementConcrete>' to specified type 'Int'}}
}
+
+func testGenericsWithTypedefBlocks(hba: HasBlockArray) {
+ let _: Int = hba.blockArray() // expected-error{{type '[@convention(block) () -> Void]'}}
+}
diff --git a/test/ClangImporter/objc_ir.swift b/test/ClangImporter/objc_ir.swift
index ab8f375..ca3a76e 100644
--- a/test/ClangImporter/objc_ir.swift
+++ b/test/ClangImporter/objc_ir.swift
@@ -13,6 +13,7 @@
import objc_ext
import TestProtocols
import ObjCIRExtras
+import objc_generics
// CHECK: @"\01L_selector_data(method:withFloat:)" = private global [18 x i8] c"method:withFloat:\00"
// CHECK: @"\01L_selector_data(method:withDouble:)" = private global [19 x i8] c"method:withDouble:\00"
@@ -344,6 +345,13 @@
// CHECK: call void @llvm.dbg.declare(metadata %TSo26SwiftConstrGenericNameTestCySo8NSNumberCG** {{%.+}}, metadata ![[SWIFT_CONSTR_GENERIC_NAME_ALIAS_VAR:[0-9]+]], metadata !DIExpression())
}
+// CHECK-LABEL: S7objc_ir22testBlocksWithGenerics3hbaypSo13HasBlockArrayC_tF
+func testBlocksWithGenerics(hba: HasBlockArray) -> Any {
+ // CHECK: {{call swiftcc.*SSo13HasBlockArrayC05blockC0SayyyXBGyFTcTO}}
+ let _ = hba.blockPointerType()
+ return hba.blockArray
+}
+
// CHECK: linkonce_odr hidden {{.*}} @"$SSo1BC3intABSgs5Int32V_tcfcTO"
// CHECK: load i8*, i8** @"\01L_selector(initWithInt:)"
// CHECK: call [[OPAQUE:%.*]]* bitcast (void ()* @objc_msgSend
diff --git a/test/Inputs/clang-importer-sdk/usr/include/objc_generics.h b/test/Inputs/clang-importer-sdk/usr/include/objc_generics.h
index b08c045..f9e1a15 100644
--- a/test/Inputs/clang-importer-sdk/usr/include/objc_generics.h
+++ b/test/Inputs/clang-importer-sdk/usr/include/objc_generics.h
@@ -112,3 +112,10 @@
@interface Third : Second<Third *>
@end
+
+typedef void (^ _Nonnull BlockPointerType)(void);
+
+@interface HasBlockArray : NSObject
+- (NSArray<BlockPointerType> * _Nonnull)blockArray;
+- (BlockPointerType)blockPointerType;
+@end
diff --git a/test/Migrator/Inputs/Cities.swift b/test/Migrator/Inputs/Cities.swift
index 3f324ed..22d1694 100644
--- a/test/Migrator/Inputs/Cities.swift
+++ b/test/Migrator/Inputs/Cities.swift
@@ -74,3 +74,17 @@
case Regular
case Bold
}
+
+public struct AwesomeCityAttribute: RawRepresentable {
+ public init?(rawValue: String) { self.rawValue = rawValue }
+ public var rawValue: String
+ public typealias RawValue = String
+}
+
+public class Wrapper {
+ public struct Attribute: RawRepresentable {
+ public init?(rawValue: String) { self.rawValue = rawValue }
+ public var rawValue: String
+ public typealias RawValue = String
+ }
+}
\ No newline at end of file
diff --git a/test/Migrator/Inputs/string-representable.json b/test/Migrator/Inputs/string-representable.json
index e35ed0f..b23f4d7 100644
--- a/test/Migrator/Inputs/string-representable.json
+++ b/test/Migrator/Inputs/string-representable.json
@@ -227,4 +227,26 @@
"RightComment": "AwesomeIntWrapper",
"ModuleName": "bar"
},
+ {
+ "DiffItemKind": "CommonDiffItem",
+ "NodeKind": "TypeDecl",
+ "NodeAnnotation": "RevertTypeAliasDeclToRawRepresentable",
+ "ChildIndex": "0",
+ "LeftUsr": "s:6Cities20AwesomeCityAttributeV",
+ "LeftComment": "String",
+ "RightUsr": "",
+ "RightComment": "String",
+ "ModuleName": "Cities"
+ },
+ {
+ "DiffItemKind": "CommonDiffItem",
+ "NodeKind": "TypeDecl",
+ "NodeAnnotation": "RevertTypeAliasDeclToRawRepresentable",
+ "ChildIndex": "0",
+ "LeftUsr": "s:6Cities7WrapperC9AttributeV",
+ "LeftComment": "String",
+ "RightUsr": "",
+ "RightComment": "String",
+ "ModuleName": "Cities"
+ },
]
diff --git a/test/Migrator/string-representable.swift b/test/Migrator/string-representable.swift
index 33394ee..e1eafb1 100644
--- a/test/Migrator/string-representable.swift
+++ b/test/Migrator/string-representable.swift
@@ -45,3 +45,12 @@
}
class C: BarForwardDeclaredClass {}
+
+func revert(_ a: AwesomeCityAttribute, b: Wrapper.Attribute) {
+ _ = AwesomeCityAttribute(rawValue: "somevalue")
+ _ = AwesomeCityAttribute.init(rawValue: "somevalue")
+ _ = a.rawValue
+ _ = Wrapper.Attribute(rawValue: "somevalue")
+ _ = Wrapper.Attribute.init(rawValue: "somevalue")
+ _ = b.rawValue
+}
diff --git a/test/Migrator/string-representable.swift.expected b/test/Migrator/string-representable.swift.expected
index 1a60198..e1e78cc 100644
--- a/test/Migrator/string-representable.swift.expected
+++ b/test/Migrator/string-representable.swift.expected
@@ -46,6 +46,15 @@
class C: BarForwardDeclaredClass {}
+func revert(_ a: AwesomeCityAttribute, b: Wrapper.Attribute) {
+ _ = "somevalue"
+ _ = "somevalue"
+ _ = a
+ _ = "somevalue"
+ _ = "somevalue"
+ _ = b
+}
+
// Helper function inserted by Swift 4.2 migrator.
fileprivate func convertToNewAttribute(_ input: String) -> NewAttribute {
return NewAttribute(rawValue: input)
diff --git a/test/api-digester/Outputs/apinotes-migrator-gen-revert.json b/test/api-digester/Outputs/apinotes-migrator-gen-revert.json
index 6025fa4..97e354e 100644
--- a/test/api-digester/Outputs/apinotes-migrator-gen-revert.json
+++ b/test/api-digester/Outputs/apinotes-migrator-gen-revert.json
@@ -1,6 +1,17 @@
[
{
"DiffItemKind": "CommonDiffItem",
+ "NodeKind": "TypeDecl",
+ "NodeAnnotation": "RevertTypeAliasDeclToRawRepresentable",
+ "ChildIndex": "0",
+ "LeftUsr": "c:APINotesTest.h@T@CatAttributeName",
+ "LeftComment": "String",
+ "RightUsr": "",
+ "RightComment": "NSString",
+ "ModuleName": "APINotesTest"
+ },
+ {
+ "DiffItemKind": "CommonDiffItem",
"NodeKind": "Function",
"NodeAnnotation": "RevertSimpleStringRepresentableUpdate",
"ChildIndex": "1",
diff --git a/tools/swift-api-digester/swift-api-digester.cpp b/tools/swift-api-digester/swift-api-digester.cpp
index 30d95a5..ab8ffcd 100644
--- a/tools/swift-api-digester/swift-api-digester.cpp
+++ b/tools/swift-api-digester/swift-api-digester.cpp
@@ -252,6 +252,7 @@
llvm::BumpPtrAllocator Allocator;
UpdatedNodesMap UpdateMap;
NodeMap TypeAliasUpdateMap;
+ NodeMap RevertTypeAliasUpdateMap;
TypeMemberDiffVector TypeMemberDiffs;
public:
llvm::BumpPtrAllocator &allocator() {
@@ -266,6 +267,9 @@
NodeMap &getTypeAliasUpdateMap() {
return TypeAliasUpdateMap;
}
+ NodeMap &getRevertTypeAliasUpdateMap() {
+ return RevertTypeAliasUpdateMap;
+ }
TypeMemberDiffVector &getTypeMemberDiffs() {
return TypeMemberDiffs;
}
@@ -3793,6 +3797,27 @@
return 0;
}
+static void populateAliasChanges(NodeMap &AliasMap, DiffVector &AllItems,
+ const bool isRevert) {
+ for (auto Pair: AliasMap) {
+ auto UnderlyingType = Pair.first->getAs<SDKNodeDeclTypeAlias>()->
+ getUnderlyingType()->getPrintedName();
+ auto RawType = AliasMap[(SDKNode*)Pair.first]->getAs<SDKNodeDeclType>()->
+ getRawValueType()->getPrintedName();
+ if (isRevert) {
+ auto *D = Pair.second->getAs<SDKNodeDecl>();
+ AllItems.emplace_back(SDKNodeKind::DeclType,
+ NodeAnnotation::RevertTypeAliasDeclToRawRepresentable, "0",
+ D->getUsr(), "", RawType, UnderlyingType, D->getModuleName());
+ } else {
+ auto *D = Pair.first->getAs<SDKNodeDecl>();
+ AllItems.emplace_back(SDKNodeKind::DeclTypeAlias,
+ NodeAnnotation::TypeAliasDeclToRawRepresentable, "0",
+ D->getUsr(), "", UnderlyingType, RawType, D->getModuleName());
+ }
+ }
+}
+
static int compareSDKs(StringRef LeftPath, StringRef RightPath,
StringRef DiffPath,
llvm::StringSet<> &IgnoredRemoveUsrs) {
@@ -3827,20 +3852,15 @@
DiffVector AllItems;
DiffItemEmitter::collectDiffItems(LeftModule, AllItems);
- auto &AliasMap = Ctx.getTypeAliasUpdateMap();
// Find type alias change first.
+ auto &AliasMap = Ctx.getTypeAliasUpdateMap();
TypeAliasDiffFinder(LeftModule, RightModule, AliasMap).search();
+ populateAliasChanges(AliasMap, AllItems, /*IsRevert*/false);
- for (auto Pair: AliasMap) {
- auto Left = Pair.first->getAs<SDKNodeDeclTypeAlias>()->getUnderlyingType()->
- getPrintedName();
- auto Right = AliasMap[(SDKNode*)Pair.first]->getAs<SDKNodeDeclType>()->
- getRawValueType()->getPrintedName();
- auto *D = Pair.first->getAs<SDKNodeDecl>();
- AllItems.emplace_back(SDKNodeKind::DeclTypeAlias,
- NodeAnnotation::TypeAliasDeclToRawRepresentable, "0",
- D->getUsr(), "", Left, Right, D->getModuleName());
- }
+ // Find type alias revert change.
+ auto &RevertAliasMap = Ctx.getRevertTypeAliasUpdateMap();
+ TypeAliasDiffFinder(RightModule, LeftModule, RevertAliasMap).search();
+ populateAliasChanges(RevertAliasMap, AllItems, /*IsRevert*/true);
AllItems.erase(std::remove_if(AllItems.begin(), AllItems.end(),
[&](CommonDiffItem &Item) {