Merge pull request #17576 from DougGregor/disable-generic-typealias-mangling-4.2
[4.2] Don't mangle generic type aliases at all
diff --git a/lib/IDE/CodeCompletion.cpp b/lib/IDE/CodeCompletion.cpp
index 9d9d7fa..efc4208 100644
--- a/lib/IDE/CodeCompletion.cpp
+++ b/lib/IDE/CodeCompletion.cpp
@@ -3368,8 +3368,17 @@
}
void tryPostfixOperator(Expr *expr, PostfixOperatorDecl *op) {
- if (!expr->getType())
+ auto Ty = expr->getType();
+ if (!Ty)
return;
+
+ SWIFT_DEFER {
+ // Restore type.
+ // FIXME: This is workaround for getTypeOfExpressionWithoutApplying()
+ // modifies type of 'expr'.
+ expr->setType(Ty);
+ };
+
// We allocate these expressions on the stack because we know they can't
// escape and there isn't a better way to allocate scratch Expr nodes.
UnresolvedDeclRefExpr UDRE(op->getName(), DeclRefKind::PostfixOperator,
@@ -3444,6 +3453,9 @@
LHS->getType()->is<AnyFunctionType>()))
return;
+ // Preserve LHS type for restoring it.
+ Type LHSTy = LHS->getType();
+
// We allocate these expressions on the stack because we know they can't
// escape and there isn't a better way to allocate scratch Expr nodes.
UnresolvedDeclRefExpr UDRE(op->getName(), DeclRefKind::BinaryOperator,
@@ -3456,13 +3468,20 @@
// Reset sequence.
SE->setElement(SE->getNumElements() - 1, nullptr);
SE->setElement(SE->getNumElements() - 2, nullptr);
+ LHS->setType(LHSTy);
prepareForRetypechecking(SE);
- // Reset any references to operators in types, so they are properly
- // handled as operators by sequence folding.
- //
- // FIXME: Would be better to have some kind of 'OperatorRefExpr'?
for (auto &element : sequence.drop_back(2)) {
+ // Unfold AssignExpr for re-typechecking sequence.
+ if (auto *AE = dyn_cast_or_null<AssignExpr>(element)) {
+ AE->setSrc(nullptr);
+ AE->setDest(nullptr);
+ }
+
+ // Reset any references to operators in types, so they are properly
+ // handled as operators by sequence folding.
+ //
+ // FIXME: Would be better to have some kind of 'OperatorRefExpr'?
if (auto operatorRef = element->getMemberOperatorRef()) {
operatorRef->setType(nullptr);
element = operatorRef;
@@ -3496,20 +3515,20 @@
}
}
- void flattenBinaryExpr(BinaryExpr *expr, SmallVectorImpl<Expr *> &sequence) {
- auto LHS = expr->getArg()->getElement(0);
- if (auto binexpr = dyn_cast<BinaryExpr>(LHS))
- flattenBinaryExpr(binexpr, sequence);
- else
- sequence.push_back(LHS);
-
- sequence.push_back(expr->getFn());
-
- auto RHS = expr->getArg()->getElement(1);
- if (auto binexpr = dyn_cast<BinaryExpr>(RHS))
- flattenBinaryExpr(binexpr, sequence);
- else
- sequence.push_back(RHS);
+ void flattenBinaryExpr(Expr *expr, SmallVectorImpl<Expr *> &sequence) {
+ if (auto binExpr = dyn_cast<BinaryExpr>(expr)) {
+ flattenBinaryExpr(binExpr->getArg()->getElement(0), sequence);
+ sequence.push_back(binExpr->getFn());
+ flattenBinaryExpr(binExpr->getArg()->getElement(1), sequence);
+ } else if (auto assignExpr = dyn_cast<AssignExpr>(expr)) {
+ flattenBinaryExpr(assignExpr->getDest(), sequence);
+ sequence.push_back(assignExpr);
+ flattenBinaryExpr(assignExpr->getSrc(), sequence);
+ assignExpr->setDest(nullptr);
+ assignExpr->setSrc(nullptr);
+ } else {
+ sequence.push_back(expr);
+ }
}
void typeCheckLeadingSequence(SmallVectorImpl<Expr *> &sequence) {
@@ -3519,10 +3538,10 @@
// Take advantage of the fact the type-checker leaves the types on the AST.
if (!typeCheckExpression(const_cast<DeclContext *>(CurrDeclContext),
expr)) {
- if (auto binexpr = dyn_cast<BinaryExpr>(expr)) {
+ if (isa<BinaryExpr>(expr) || isa<AssignExpr>(expr)) {
// Rebuild the sequence from the type-checked version.
sequence.clear();
- flattenBinaryExpr(binexpr, sequence);
+ flattenBinaryExpr(expr, sequence);
return;
}
}
@@ -3548,6 +3567,9 @@
if (sequence.size() > 1)
typeCheckLeadingSequence(sequence);
+ // Retrieve typechecked LHS.
+ LHS = sequence.back();
+
// Create a single sequence expression, which we will modify for each
// operator, filling in the operator and dummy right-hand side.
sequence.push_back(nullptr); // operator
diff --git a/lib/Sema/CSRanking.cpp b/lib/Sema/CSRanking.cpp
index 56eb1a4..32192f6 100644
--- a/lib/Sema/CSRanking.cpp
+++ b/lib/Sema/CSRanking.cpp
@@ -372,6 +372,10 @@
auto *param = paramList->get(paramNum);
return param->getAttrs().hasAttribute<ImplicitlyUnwrappedOptionalAttr>();
}
+ if (auto *ee = dyn_cast<EnumElementDecl>(decl)) {
+ auto *param = ee->getParameterList()->get(paramNum);
+ return param->getAttrs().hasAttribute<ImplicitlyUnwrappedOptionalAttr>();
+ }
auto *subscript = cast<SubscriptDecl>(decl);
auto *index = subscript->getIndices()->get(paramNum);
diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp
index b40ac85..decc345 100644
--- a/lib/Serialization/Deserialization.cpp
+++ b/lib/Serialization/Deserialization.cpp
@@ -678,6 +678,8 @@
numConformances);
auto replacementTy = getType(replacementID);
+ if (!replacementTy)
+ replacementTy = ErrorType::get(getContext());
if (genericEnv) {
replacementTy = genericEnv->mapTypeIntoContext(replacementTy);
}
diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp
index 38f070b..af7f0c6 100644
--- a/lib/Serialization/Serialization.cpp
+++ b/lib/Serialization/Serialization.cpp
@@ -1646,7 +1646,8 @@
abbrCode,
addTypeRef(type),
substitutions.size());
- writeSubstitutions(substitutions, abbrCodes, genericEnv);
+ writeSubstitutions(substitutions, abbrCodes, genericEnv,
+ /*ignoreReplacementErrors*/true);
writeConformance(conf->getGenericConformance(), abbrCodes, genericEnv);
break;
@@ -1691,7 +1692,8 @@
void
Serializer::writeSubstitutions(SubstitutionList substitutions,
const std::array<unsigned, 256> &abbrCodes,
- GenericEnvironment *genericEnv) {
+ GenericEnvironment *genericEnv,
+ bool ignoreReplacementErrors) {
using namespace decls_block;
auto abbrCode = abbrCodes[BoundGenericSubstitutionLayout::Code];
@@ -1700,6 +1702,8 @@
if (genericEnv && replacementType->hasArchetype()) {
replacementType = replacementType->mapTypeOutOfContext();
}
+ if (replacementType->hasError() && ignoreReplacementErrors)
+ replacementType = Type();
BoundGenericSubstitutionLayout::emitRecord(
Out, ScratchRecord, abbrCode,
diff --git a/lib/Serialization/Serialization.h b/lib/Serialization/Serialization.h
index c571c3b..f91cd3f 100644
--- a/lib/Serialization/Serialization.h
+++ b/lib/Serialization/Serialization.h
@@ -495,7 +495,8 @@
/// being written.
void writeSubstitutions(SubstitutionList substitutions,
const std::array<unsigned, 256> &abbrCodes,
- GenericEnvironment *genericEnv = nullptr);
+ GenericEnvironment *genericEnv = nullptr,
+ bool ignoreReplacementErrors = false);
/// Write a normal protocol conformance.
void writeNormalConformance(const NormalProtocolConformance *conformance);
diff --git a/test/IDE/complete_crashes.swift b/test/IDE/complete_crashes.swift
index 8549d0e..4e07d68 100644
--- a/test/IDE/complete_crashes.swift
+++ b/test/IDE/complete_crashes.swift
@@ -220,10 +220,9 @@
func foo_38149042(bar: Bar_38149042) {
_ = bar.foo? #^RDAR_38149042^# .x
}
-// RDAR_38149042: Begin completions, 3 items
+
+// RDAR_38149042: Begin completions
// RDAR_38149042-DAG: Decl[InstanceVar]/CurrNominal: .x[#Int#]; name=x
-// RDAR_38149042-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]: [' ']=== {#AnyObject?#}[#Bool#]; name==== AnyObject?
-// RDAR_38149042-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]: [' ']!== {#AnyObject?#}[#Bool#]; name=!== AnyObject?
// RDAR_38149042: End completions
// rdar://problem/38272904
@@ -246,3 +245,53 @@
bar_38272904(a: .foo() #^RDAR_38272904^#)
}
// RDAR_38272904: Begin completions
+
+// rdar://problem/41159258
+// RUN: %target-swift-ide-test -code-completion -source-filename=%s -code-completion-token=RDAR41159258_1
+// RUN: %target-swift-ide-test -code-completion -source-filename=%s -code-completion-token=RDAR41159258_2 | %FileCheck %s -check-prefix=RDAR_41159258
+public func ==(lhs: RDAR41159258_MyResult1, rhs: RDAR41159258_MyResult1) -> Bool {
+ fatalError()
+}
+public func ==(lhs: RDAR41159258_MyResult2, rhs: RDAR41159258_MyResult2) -> Bool {
+ fatalError()
+}
+public enum RDAR41159258_MyResult1 {
+ case failure(Error)
+}
+public enum RDAR41159258_MyResult2 {
+ case failure(Error)
+}
+
+public struct RDAR41159258_MyError: Error {}
+
+func foo(x: RDAR41159258_MyResult1) {
+ let x: RDAR41159258_MyResult1
+ x = .failure(RDAR41159258_MyError()) #^RDAR41159258_1^#
+ let y: Bool
+ y = .failure(RDAR41159258_MyError()) #^RDAR41159258_2^#
+}
+// RDAR_41159258: Begin completions
+
+
+// rdar://problem/41232519
+// RUN: %target-swift-ide-test -code-completion -source-filename=%s -code-completion-token=RDAR41232519 | %FileCheck %s -check-prefix=RDAR_41232519
+public protocol IntProvider {
+ func nextInt() -> Int
+}
+
+public final class IntStore {
+ public var myInt: Int = 0
+ func readNextInt(from provider: IntProvider) {
+ myInt = provider.nextInt() #^RDAR41232519^#
+ }
+}
+// RDAR_41232519: Begin completions
+
+// rdar://problem/28188259
+// RUN: %target-swift-ide-test -code-completion -code-completion-token=RDAR_28188259 -source-filename=%s | %FileCheck %s -check-prefix=RDAR_28188259
+func test_28188259(x: ((Int) -> Void) -> Void) {
+ x({_ in }#^RDAR_28188259^#)
+}
+// RDAR_28188259: Begin completions
+// RDAR_28188259-DAG: Pattern/CurrModule: ({#_#})[#Void#]; name=(_)
+// RDAR_28188259: End completions
diff --git a/validation-test/Serialization/SR7337.swift b/validation-test/Serialization/SR7337.swift
new file mode 100644
index 0000000..b3f9c81
--- /dev/null
+++ b/validation-test/Serialization/SR7337.swift
@@ -0,0 +1,20 @@
+// RUN: %empty-directory(%t)
+// RUN: %target-build-swift -emit-module -o %t/Lib.swiftmodule %s -DLIB
+// RUN: %target-build-swift -emit-module -o %t/main.swiftmodule -I %t %s
+
+#if LIB
+
+protocol Proto {}
+
+open class Base<T> {}
+public struct ArbitraryStruct {}
+
+extension Base: Proto where T: Proto {}
+
+#else // LIB
+
+import Lib
+
+final class ConcreteSub: Base<ArbitraryStruct> {}
+
+#endif // LIB
\ No newline at end of file