Merge pull request #18032 from rudkx/restore-order
Return to the old disjunction ordering until some test regressions are addressed.
diff --git a/include/swift/AST/Expr.h b/include/swift/AST/Expr.h
index 5bc4dcf..5126ffa 100644
--- a/include/swift/AST/Expr.h
+++ b/include/swift/AST/Expr.h
@@ -4306,6 +4306,11 @@
///
/// Spelled 'a as T' and produces a value of type 'T'.
class CoerceExpr : public ExplicitCastExpr {
+ /// Since there is already `asLoc` location,
+ /// we use it to store `start` of the initializer
+ /// call source range to save some storage.
+ SourceLoc InitRangeEnd;
+
public:
CoerceExpr(Expr *sub, SourceLoc asLoc, TypeLoc type)
: ExplicitCastExpr(ExprKind::Coerce, sub, asLoc, type, type.getType())
@@ -4315,6 +4320,29 @@
: CoerceExpr(nullptr, asLoc, type)
{ }
+private:
+ CoerceExpr(SourceRange initRange, Expr *literal, TypeLoc type)
+ : ExplicitCastExpr(ExprKind::Coerce, literal, initRange.Start,
+ type, type.getType()), InitRangeEnd(initRange.End)
+ { setImplicit(); }
+
+public:
+ /// Create an implicit coercion expression for literal initialization
+ /// preserving original source information, this way original call
+ /// could be recreated if needed.
+ static CoerceExpr *forLiteralInit(ASTContext &ctx, Expr *literal,
+ SourceRange range, TypeLoc literalType) {
+ return new (ctx) CoerceExpr(range, literal, literalType);
+ }
+
+ bool isLiteralInit() const { return InitRangeEnd.isValid(); }
+
+ SourceRange getSourceRange() const {
+ return isLiteralInit()
+ ? SourceRange(getAsLoc(), InitRangeEnd)
+ : ExplicitCastExpr::getSourceRange();
+ }
+
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::Coerce;
}
diff --git a/include/swift/SILOptimizer/Analysis/Analysis.def b/include/swift/SILOptimizer/Analysis/Analysis.def
index 1e37745..28564a2 100644
--- a/include/swift/SILOptimizer/Analysis/Analysis.def
+++ b/include/swift/SILOptimizer/Analysis/Analysis.def
@@ -44,5 +44,6 @@
ANALYSIS(RCIdentity)
ANALYSIS(SideEffect)
ANALYSIS(TypeExpansion)
+ANALYSIS(PassManagerVerifier)
#undef ANALYSIS
diff --git a/include/swift/SILOptimizer/Analysis/PassManagerVerifierAnalysis.h b/include/swift/SILOptimizer/Analysis/PassManagerVerifierAnalysis.h
new file mode 100644
index 0000000..99a4d0f
--- /dev/null
+++ b/include/swift/SILOptimizer/Analysis/PassManagerVerifierAnalysis.h
@@ -0,0 +1,65 @@
+//===--- PassManagerVerifierAnalysis.h ------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SWIFT_SILOPTIMIZER_ANALYSIS_PASSMANAGERVERIFIERANALYSIS_H
+#define SWIFT_SILOPTIMIZER_ANALYSIS_PASSMANAGERVERIFIERANALYSIS_H
+
+#include "swift/SIL/SILFunction.h"
+#include "swift/SILOptimizer/Analysis/Analysis.h"
+#include "llvm/ADT/DenseSet.h"
+
+namespace swift {
+
+/// An analysis that validates that the pass manager properly sends add/delete
+/// messages as functions are added/deleted from the module.
+///
+/// All methods are no-ops when asserts are disabled.
+class PassManagerVerifierAnalysis : public SILAnalysis {
+ /// The module that we are processing.
+ SILModule &mod;
+
+ /// The set of "live" functions that we are tracking.
+ ///
+ /// All functions in mod must be in liveFunctions and vis-a-versa.
+ llvm::DenseSet<SILFunction *> liveFunctions;
+
+public:
+ PassManagerVerifierAnalysis(SILModule *mod);
+
+ static bool classof(const SILAnalysis *analysis) {
+ return analysis->getKind() == SILAnalysisKind::PassManagerVerifier;
+ }
+
+ /// Validate that the analysis is able to look up all functions and that those
+ /// functions are live.
+ void invalidate() override final;
+
+ /// Validate that the analysis is able to look up the given function.
+ void invalidate(SILFunction *f, InvalidationKind k) override final;
+
+ /// If a function has not yet been seen start tracking it.
+ void notifyAddedOrModifiedFunction(SILFunction *f) override final;
+
+ /// Stop tracking a function.
+ void notifyWillDeleteFunction(SILFunction *f) override final;
+
+ /// Make sure that when we invalidate a function table, make sure we can find
+ /// all functions for all witness tables.
+ void invalidateFunctionTables() override final;
+
+ /// Run the entire verification.
+ void verify() const override final;
+};
+
+} // namespace swift
+
+#endif
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 4999f9f..4bad14c 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -1784,24 +1784,26 @@
/// that instead.
static ProtocolConformance *collapseSpecializedConformance(
Type type,
- ProtocolConformance *conformance) {
+ ProtocolConformance *conformance,
+ SubstitutionMap substitutions) {
while (true) {
- // If the conformance matches, return it.
- if (conformance->getType()->isEqual(type))
- return conformance;
-
switch (conformance->getKind()) {
- case ProtocolConformanceKind::Inherited:
- conformance = cast<InheritedProtocolConformance>(conformance)
- ->getInheritedConformance();
- break;
-
case ProtocolConformanceKind::Specialized:
conformance = cast<SpecializedProtocolConformance>(conformance)
->getGenericConformance();
break;
case ProtocolConformanceKind::Normal:
+ case ProtocolConformanceKind::Inherited:
+ // If the conformance matches, return it.
+ if (conformance->getType()->isEqual(type)) {
+ for (auto subConformance : substitutions.getConformances())
+ if (!subConformance.isAbstract())
+ return nullptr;
+
+ return conformance;
+ }
+
return nullptr;
}
}
@@ -1814,7 +1816,8 @@
// If we are performing a substitution that would get us back to the
// a prior conformance (e.g., mapping into and then out of a conformance),
// return the existing conformance.
- if (auto existing = collapseSpecializedConformance(type, generic)) {
+ if (auto existing = collapseSpecializedConformance(type, generic,
+ substitutions)) {
++NumCollapsedSpecializedProtocolConformances;
return existing;
}
diff --git a/lib/AST/GenericSignatureBuilder.cpp b/lib/AST/GenericSignatureBuilder.cpp
index 1c23f7e..08f1ac6 100644
--- a/lib/AST/GenericSignatureBuilder.cpp
+++ b/lib/AST/GenericSignatureBuilder.cpp
@@ -2167,17 +2167,19 @@
}
}
- // If we haven't found anything yet but have a superclass, look for a type
- // in the superclass.
- // FIXME: Shouldn't we always look in the superclass?
- if (!bestAssocType && concreteDecls.empty() && superclass) {
- if (auto classDecl = superclass->getClassOrBoundGenericClass()) {
- SmallVector<ValueDecl *, 2> superclassMembers;
- classDecl->getParentModule()->lookupQualified(
- superclass, name,
+ // If we haven't found anything yet but have a concrete type or a superclass,
+ // look for a type in that.
+ // FIXME: Shouldn't we always look here?
+ if (!bestAssocType && concreteDecls.empty()) {
+ Type typeToSearch = concreteType ? concreteType : superclass;
+ auto *decl = typeToSearch ? typeToSearch->getAnyNominal() : nullptr;
+ if (decl) {
+ SmallVector<ValueDecl *, 2> foundMembers;
+ decl->getParentModule()->lookupQualified(
+ typeToSearch, name,
NL_QualifiedDefault | NL_OnlyTypes | NL_ProtocolMembers, nullptr,
- superclassMembers);
- for (auto member : superclassMembers) {
+ foundMembers);
+ for (auto member : foundMembers) {
if (auto type = dyn_cast<TypeDecl>(member)) {
// Resolve the signature of this type.
if (!type->hasInterfaceType()) {
@@ -3938,11 +3940,13 @@
type = type.subst(subMap, SubstFlags::UseErrorType);
} else {
// Substitute in the superclass type.
- parentType = basePA->getEquivalenceClassIfPresent()->superclass;
- auto superclassDecl = parentType->getClassOrBoundGenericClass();
+ auto parentPA = basePA->getEquivalenceClassIfPresent();
+ parentType =
+ parentPA->concreteType ? parentPA->concreteType : parentPA->superclass;
+ auto parentDecl = parentType->getAnyNominal();
- subMap = parentType->getMemberSubstitutionMap(
- superclassDecl->getParentModule(), concreteDecl);
+ subMap = parentType->getMemberSubstitutionMap(parentDecl->getParentModule(),
+ concreteDecl);
type = type.subst(subMap, SubstFlags::UseErrorType);
}
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 9f40989..74e3e5f 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -2942,7 +2942,8 @@
MakeAbstractConformanceForGenericType::operator()(CanType dependentType,
Type conformingReplacementType,
ProtocolDecl *conformedProtocol) const {
- assert((conformingReplacementType->is<SubstitutableType>()
+ assert((conformingReplacementType->is<ErrorType>()
+ || conformingReplacementType->is<SubstitutableType>()
|| conformingReplacementType->is<DependentMemberType>())
&& "replacement requires looking up a concrete conformance");
return ProtocolConformanceRef(conformedProtocol);
diff --git a/lib/SILOptimizer/Analysis/CMakeLists.txt b/lib/SILOptimizer/Analysis/CMakeLists.txt
index 7344019..009fea5 100644
--- a/lib/SILOptimizer/Analysis/CMakeLists.txt
+++ b/lib/SILOptimizer/Analysis/CMakeLists.txt
@@ -19,6 +19,7 @@
LoopAnalysis.cpp
LoopRegionAnalysis.cpp
MemoryBehavior.cpp
+ PassManagerVerifierAnalysis.cpp
ProtocolConformanceAnalysis.cpp
RCIdentityAnalysis.cpp
SideEffectAnalysis.cpp
diff --git a/lib/SILOptimizer/Analysis/PassManagerVerifierAnalysis.cpp b/lib/SILOptimizer/Analysis/PassManagerVerifierAnalysis.cpp
new file mode 100644
index 0000000..99ae970
--- /dev/null
+++ b/lib/SILOptimizer/Analysis/PassManagerVerifierAnalysis.cpp
@@ -0,0 +1,100 @@
+//===--- PassManagerVerifierAnalysis.cpp ----------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "sil-passmanager-verifier-analysis"
+#include "swift/SILOptimizer/Analysis/PassManagerVerifierAnalysis.h"
+#include "swift/SIL/SILModule.h"
+#include "llvm/Support/CommandLine.h"
+
+static llvm::cl::opt<bool>
+ EnableVerifier("enable-sil-passmanager-verifier-analysis",
+ llvm::cl::desc("Enable verification of the passmanagers "
+ "function notification infrastructure"),
+ llvm::cl::init(false));
+
+using namespace swift;
+
+PassManagerVerifierAnalysis::PassManagerVerifierAnalysis(SILModule *mod)
+ : SILAnalysis(SILAnalysisKind::PassManagerVerifier), mod(*mod) {
+#ifndef NDEBUG
+ if (!EnableVerifier)
+ return;
+ for (auto &fn : *mod) {
+ DEBUG(llvm::dbgs() << "PMVerifierAnalysis. Add: " << fn.getName() << '\n');
+ liveFunctions.insert(&fn);
+ }
+#endif
+}
+
+/// Validate that the analysis is able to look up all functions and that those
+/// functions are live.
+void PassManagerVerifierAnalysis::invalidate() {}
+
+/// Validate that the analysis is able to look up the given function.
+void PassManagerVerifierAnalysis::invalidate(SILFunction *f,
+ InvalidationKind k) {}
+
+/// If a function has not yet been seen start tracking it.
+void PassManagerVerifierAnalysis::notifyAddedOrModifiedFunction(
+ SILFunction *f) {
+#ifndef NDEBUG
+ if (!EnableVerifier)
+ return;
+ DEBUG(llvm::dbgs() << "PMVerifierAnalysis. Add|Mod: " << f->getName()
+ << '\n');
+ liveFunctions.insert(f);
+#endif
+}
+
+/// Stop tracking a function.
+void PassManagerVerifierAnalysis::notifyWillDeleteFunction(SILFunction *f) {
+#ifndef NDEBUG
+ if (!EnableVerifier)
+ return;
+ DEBUG(llvm::dbgs() << "PMVerifierAnalysis. Delete: " << f->getName() << '\n');
+ assert(liveFunctions.count(f) &&
+ "Tried to delete function that analysis was not aware of?!");
+ liveFunctions.erase(f);
+#endif
+}
+
+/// Make sure that when we invalidate a function table, make sure we can find
+/// all functions for all witness tables.
+void PassManagerVerifierAnalysis::invalidateFunctionTables() {}
+
+/// Run the entire verification.
+void PassManagerVerifierAnalysis::verify() const {
+#ifndef NDEBUG
+ if (!EnableVerifier)
+ return;
+
+ // We check that all functions in the module are in liveFunctions /and/ then
+ // make sure that liveFunctions has the same number of elements. If we have
+ // too many elements, this means we missed a delete event.
+ unsigned funcCount = 0;
+ for (auto &fn : mod) {
+ ++funcCount;
+ assert(liveFunctions.count(&fn) &&
+ "Found function in module that verifier is not aware of?!");
+ }
+ assert(liveFunctions.size() == funcCount &&
+ "Analysis has state for deleted functions?!");
+#endif
+}
+
+//===----------------------------------------------------------------------===//
+// Main Entry Point
+//===----------------------------------------------------------------------===//
+
+SILAnalysis *swift::createPassManagerVerifierAnalysis(SILModule *m) {
+ return new PassManagerVerifierAnalysis(m);
+}
diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp
index 2ba558a..c74645d 100644
--- a/lib/Sema/CSApply.cpp
+++ b/lib/Sema/CSApply.cpp
@@ -3621,6 +3621,36 @@
auto &tc = cs.getTypeChecker();
+ // Since this is literal initialization, we don't
+ // really need to keep wrapping coercion around.
+ if (expr->isLiteralInit()) {
+ auto *literalInit = expr->getSubExpr();
+ // If literal got converted into constructor call
+ // lets put proper source information in place.
+ if (auto *call = dyn_cast<CallExpr>(literalInit)) {
+ call->getFn()->forEachChildExpr([&](Expr *subExpr) -> Expr * {
+ auto *TE = dyn_cast<TypeExpr>(subExpr);
+ if (!TE)
+ return subExpr;
+
+ auto type = TE->getInstanceType(
+ [&](const Expr *expr) { return cs.hasType(expr); },
+ [&](const Expr *expr) { return cs.getType(expr); });
+
+ assert(!type->hasError());
+
+ if (!type->isEqual(toType))
+ return subExpr;
+
+ return cs.cacheType(new (tc.Context)
+ TypeExpr(expr->getCastTypeLoc()));
+ });
+ }
+
+ literalInit->setImplicit(false);
+ return literalInit;
+ }
+
// Turn the subexpression into an rvalue.
auto rvalueSub = cs.coerceToRValue(expr->getSubExpr());
expr->setSubExpr(rvalueSub);
diff --git a/lib/Sema/CSDiag.cpp b/lib/Sema/CSDiag.cpp
index 1e5b9cc..788a5043 100644
--- a/lib/Sema/CSDiag.cpp
+++ b/lib/Sema/CSDiag.cpp
@@ -2814,7 +2814,10 @@
if (!isIntegerType(fromType, CS) || !isIntegerType(toType, CS))
return false;
- auto getInnerCastedExpr = [&]() -> Expr* {
+ auto getInnerCastedExpr = [&]() -> Expr * {
+ if (auto *CE = dyn_cast<CoerceExpr>(expr))
+ return CE->getSubExpr();
+
auto *CE = dyn_cast<CallExpr>(expr);
if (!CE)
return nullptr;
diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp
index 15133a5..9433848 100644
--- a/lib/Sema/CSGen.cpp
+++ b/lib/Sema/CSGen.cpp
@@ -1394,11 +1394,12 @@
Type visitTypeExpr(TypeExpr *E) {
Type type;
// If this is an implicit TypeExpr, don't validate its contents.
- if (auto *rep = E->getTypeRepr()) {
- type = resolveTypeReferenceInExpression(rep);
- } else {
+ if (E->getTypeLoc().wasValidated()) {
type = E->getTypeLoc().getType();
+ } else if (auto *rep = E->getTypeRepr()) {
+ type = resolveTypeReferenceInExpression(rep);
}
+
if (!type || type->hasError()) return Type();
auto locator = CS.getConstraintLocator(E);
diff --git a/lib/Sema/CSSolver.cpp b/lib/Sema/CSSolver.cpp
index 3392da0..5f7d20f 100644
--- a/lib/Sema/CSSolver.cpp
+++ b/lib/Sema/CSSolver.cpp
@@ -1004,7 +1004,7 @@
// Counts the number of overload sets present in the tree so far.
// Note that the traversal is depth-first.
- llvm::SmallVector<std::pair<ApplyExpr *, unsigned>, 4> ApplyExprs;
+ llvm::SmallVector<std::pair<Expr *, unsigned>, 4> ApplyExprs;
// A collection of original domains of all of the expressions,
// so they can be restored in case of failure.
@@ -1031,6 +1031,8 @@
}
if (auto coerceExpr = dyn_cast<CoerceExpr>(expr)) {
+ if (coerceExpr->isLiteralInit())
+ ApplyExprs.push_back({coerceExpr, 1});
visitCoerceExpr(coerceExpr);
return {false, expr};
}
diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp
index 619ea2c..eb593eb 100644
--- a/lib/Sema/TypeCheckConstraints.cpp
+++ b/lib/Sema/TypeCheckConstraints.cpp
@@ -974,6 +974,10 @@
/// Simplify a key path expression into a canonical form.
void resolveKeyPathExpr(KeyPathExpr *KPE);
+ /// Simplify constructs like `UInt32(1)` into `1 as UInt32` if
+ /// the type conforms to the expected literal protocol.
+ Expr *simplifyTypeConstructionWithLiteralArg(Expr *E);
+
public:
PreCheckExpression(TypeChecker &tc, DeclContext *dc, Expr *parent)
: TC(tc), DC(dc), ParentExpr(parent) {}
@@ -1217,6 +1221,9 @@
return KPE;
}
+ if (auto *simplified = simplifyTypeConstructionWithLiteralArg(expr))
+ return simplified;
+
return expr;
}
@@ -1824,6 +1831,66 @@
KPE->resolveComponents(TC.Context, components);
}
+Expr *PreCheckExpression::simplifyTypeConstructionWithLiteralArg(Expr *E) {
+ // If constructor call is expected to produce an optional let's not attempt
+ // this optimization because literal initializers aren't failable.
+ if (!TC.getLangOpts().isSwiftVersionAtLeast(5)) {
+ if (!ExprStack.empty()) {
+ auto *parent = ExprStack.back();
+ if (isa<BindOptionalExpr>(parent) || isa<ForceValueExpr>(parent))
+ return nullptr;
+ }
+ }
+
+ auto *call = dyn_cast<CallExpr>(E);
+ if (!call || call->getNumArguments() != 1)
+ return nullptr;
+
+ auto *typeExpr = dyn_cast<TypeExpr>(call->getFn());
+ if (!typeExpr)
+ return nullptr;
+
+ auto *argExpr = call->getArg()->getSemanticsProvidingExpr();
+ auto *literal = dyn_cast<LiteralExpr>(argExpr);
+ if (!literal)
+ return nullptr;
+
+ auto *protocol = TC.getLiteralProtocol(literal);
+ if (!protocol)
+ return nullptr;
+
+ Type type;
+ if (typeExpr->getTypeLoc().wasValidated()) {
+ type = typeExpr->getTypeLoc().getType();
+ } else if (auto *rep = typeExpr->getTypeRepr()) {
+ TypeResolutionOptions options;
+ options |= TypeResolutionFlags::AllowUnboundGenerics;
+ options |= TypeResolutionFlags::InExpression;
+ type = TC.resolveType(rep, DC, options);
+ typeExpr->getTypeLoc().setType(type);
+ }
+
+ if (!type)
+ return nullptr;
+
+ // Don't bother to convert deprecated selector syntax.
+ if (auto selectorTy = TC.getObjCSelectorType(DC)) {
+ if (type->isEqual(selectorTy))
+ return nullptr;
+ }
+
+ ConformanceCheckOptions options;
+ options |= ConformanceCheckFlags::InExpression;
+ options |= ConformanceCheckFlags::SkipConditionalRequirements;
+
+ auto result = TC.conformsToProtocol(type, protocol, DC, options);
+ if (!result || !result->isConcrete())
+ return nullptr;
+
+ return CoerceExpr::forLiteralInit(TC.Context, argExpr, call->getSourceRange(),
+ typeExpr->getTypeLoc());
+}
+
/// \brief Clean up the given ill-formed expression, removing any references
/// to type variables and setting error types on erroneous expression nodes.
void CleanupIllFormedExpressionRAII::doIt(Expr *expr) {
diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp
index ccf913b..a440a5e 100644
--- a/lib/Sema/TypeCheckDecl.cpp
+++ b/lib/Sema/TypeCheckDecl.cpp
@@ -3664,8 +3664,6 @@
// up to the caller, who must call hasValidSignature() to
// check that validateDecl() returned a fully-formed decl.
if (D->hasValidationStarted()) {
- if (!(D->isBeingValidated() || D->hasValidSignature()))
- D->dump();
// If this isn't reentrant (i.e. D has already been validated), the
// signature better be valid.
assert(D->isBeingValidated() || D->hasValidSignature());
diff --git a/lib/Sema/TypeCheckGeneric.cpp b/lib/Sema/TypeCheckGeneric.cpp
index 445d338..68479e1 100644
--- a/lib/Sema/TypeCheckGeneric.cpp
+++ b/lib/Sema/TypeCheckGeneric.cpp
@@ -220,9 +220,11 @@
return concrete->getDeclaredInterfaceType().subst(subMap);
}
- if (auto superclass = baseEquivClass->superclass) {
- return superclass->getTypeOfMember(
- DC->getParentModule(), concrete,
+ Type baseType = baseEquivClass->concreteType ? baseEquivClass->concreteType
+ : baseEquivClass->superclass;
+
+ if (baseType) {
+ return baseType->getTypeOfMember(DC->getParentModule(), concrete,
concrete->getDeclaredInterfaceType());
}
diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp
index 9bd6133..aa534e3 100644
--- a/lib/Sema/TypeCheckProtocol.cpp
+++ b/lib/Sema/TypeCheckProtocol.cpp
@@ -3318,57 +3318,36 @@
= Conformance->populateSignatureConformances();
class GatherConformancesListener : public GenericRequirementsCheckListener {
- TypeChecker &tc;
NormalProtocolConformance *conformance;
std::function<void(ProtocolConformanceRef)> &writer;
public:
GatherConformancesListener(
- TypeChecker &tc,
- NormalProtocolConformance *conformance,
- std::function<void(ProtocolConformanceRef)> &writer)
- : tc(tc), conformance(conformance), writer(writer) { }
+ NormalProtocolConformance *conformance,
+ std::function<void(ProtocolConformanceRef)> &writer)
+ : conformance(conformance), writer(writer) { }
void satisfiedConformance(Type depTy, Type replacementTy,
ProtocolConformanceRef conformance) override {
// The conformance will use contextual types, but we want the
// interface type equivalent.
-
- // If we have an inherited conformance for an archetype, dig out the
- // superclass conformance to translate.
- Type inheritedInterfaceType;
if (conformance.isConcrete() &&
conformance.getConcrete()->getType()->hasArchetype()) {
auto concreteConformance = conformance.getConcrete();
- if (concreteConformance->getKind()
- == ProtocolConformanceKind::Inherited &&
- conformance.getConcrete()->getType()->is<ArchetypeType>()) {
- inheritedInterfaceType =
- concreteConformance->getType()->mapTypeOutOfContext();
- concreteConformance =
- cast<InheritedProtocolConformance>(concreteConformance)
- ->getInheritedConformance();
- }
// Map the conformance.
- // FIXME: It would be so much easier and efficient if we had
- // ProtocolConformance::mapTypesOutOfContext().
auto interfaceType =
concreteConformance->getType()->mapTypeOutOfContext();
- conformance = *tc.conformsToProtocol(
- interfaceType,
- conformance.getRequirement(),
- this->conformance->getDeclContext(),
- (ConformanceCheckFlags::SuppressDependencyTracking|
- ConformanceCheckFlags::SkipConditionalRequirements));
+ concreteConformance = concreteConformance->subst(
+ interfaceType,
+ [](SubstitutableType *type) -> Type {
+ if (auto *archetypeType = type->getAs<ArchetypeType>())
+ return archetypeType->getInterfaceType();
+ return type;
+ },
+ MakeAbstractConformanceForGenericType());
- // Reinstate inherited conformance.
- if (inheritedInterfaceType) {
- conformance =
- ProtocolConformanceRef(
- tc.Context.getInheritedConformance(inheritedInterfaceType,
- conformance.getConcrete()));
- }
+ conformance = ProtocolConformanceRef(concreteConformance);
}
writer(conformance);
@@ -3384,7 +3363,7 @@
return false;
}
- } listener(TC, Conformance, writer);
+ } listener(Conformance, writer);
auto result = TC.checkGenericArguments(
DC, Loc, Loc,
diff --git a/stdlib/public/core/Flatten.swift b/stdlib/public/core/Flatten.swift
index 09b217d..092cae2 100644
--- a/stdlib/public/core/Flatten.swift
+++ b/stdlib/public/core/Flatten.swift
@@ -85,6 +85,8 @@
}
}
+extension FlattenSequence.Iterator: Sequence { }
+
extension FlattenSequence: Sequence {
/// Returns an iterator over the elements of this sequence.
///
diff --git a/stdlib/public/core/Integers.swift.gyb b/stdlib/public/core/Integers.swift.gyb
index 4ce7b5c..0d02022 100644
--- a/stdlib/public/core/Integers.swift.gyb
+++ b/stdlib/public/core/Integers.swift.gyb
@@ -3592,10 +3592,12 @@
/// to find an absolute value. In addition, because `abs(_:)` always returns
/// a value of the same type, even in a generic context, using the function
/// instead of the `magnitude` property is encouraged.
- @_transparent
public var magnitude: U${Self} {
- let base = U${Self}(_value)
- return self < (0 as ${Self}) ? ~base + 1 : base
+ @inline(__always)
+ get {
+ let base = U${Self}(_value)
+ return self < (0 as ${Self}) ? ~base + 1 : base
+ }
}
% end
diff --git a/test/Constraints/diagnostics.swift b/test/Constraints/diagnostics.swift
index 06d19bf..eb21519 100644
--- a/test/Constraints/diagnostics.swift
+++ b/test/Constraints/diagnostics.swift
@@ -951,7 +951,7 @@
case bar
}
- // expected-error@+2 {{binary operator '*' cannot be applied to operands of type 'Int' and 'Float'}} {{35-41=}} {{42-43=}}
+ // expected-error@+2 {{binary operator '*' cannot be applied to operands of type 'Int' and 'Float'}} {{35-35=Int(}} {{42-42=)}}
// expected-note@+1 {{expected an argument list of type '(Int, Int)'}}
let _: Int = Foo.bar.rawValue * Float(0)
diff --git a/test/Constraints/optional.swift b/test/Constraints/optional.swift
index 2d0b03b..fc16857 100644
--- a/test/Constraints/optional.swift
+++ b/test/Constraints/optional.swift
@@ -272,3 +272,23 @@
func rdar37508855(_ e1: X?, _ e2: X?) -> [X] {
return [e1, e2].filter { $0 == nil }.map { $0! }
}
+
+func se0213() {
+ struct Q: ExpressibleByStringLiteral {
+ typealias StringLiteralType = String
+
+ var foo: String
+
+ init?(_ possibleQ: StringLiteralType) {
+ return nil
+ }
+
+ init(stringLiteral str: StringLiteralType) {
+ self.foo = str
+ }
+ }
+
+ _ = Q("why")?.foo // Ok
+ _ = Q("who")!.foo // Ok
+ _ = Q?("how") // Ok
+}
diff --git a/test/SILOptimizer/diagnostic_constant_propagation-swift4.swift b/test/SILOptimizer/diagnostic_constant_propagation-swift4.swift
index 83390c2..adeac2e 100644
--- a/test/SILOptimizer/diagnostic_constant_propagation-swift4.swift
+++ b/test/SILOptimizer/diagnostic_constant_propagation-swift4.swift
@@ -4,6 +4,5 @@
// These are specific to Swift 4.
func testArithmeticOverflowSwift4() {
- var _ = Int8(126) + (1 + 1) // FIXME: Should expect an integer overflow
- // error but none happens now (see <rdar://problem/39120081>)
+ var _ = Int8(126) + (1 + 1) // expected-error {{arithmetic operation '126 + 2' (on type 'Int8') results in an overflow}}
}
diff --git a/test/SILOptimizer/diagnostic_constant_propagation_floats_x86.swift b/test/SILOptimizer/diagnostic_constant_propagation_floats_x86.swift
index 7081100..7c2f6f8 100644
--- a/test/SILOptimizer/diagnostic_constant_propagation_floats_x86.swift
+++ b/test/SILOptimizer/diagnostic_constant_propagation_floats_x86.swift
@@ -109,8 +109,5 @@
let e2: Float80 = 18_446_744_073_709_551_617 // expected-warning {{'18446744073709551617' is not exactly representable as 'Float80'; it becomes '18446744073709551616'}}
_blackHole(e2)
- // No warnings are emitted for conversion through explicit constructor calls.
- // Note that the error here is because of an implicit conversion of the input
- // literal to 'Int'.
- _blackHole(Float80(18_446_744_073_709_551_617)) // expected-error {{integer literal '18446744073709551617' overflows when stored into 'Int'}}
+ _blackHole(Float80(18_446_744_073_709_551_617)) // Ok
}
diff --git a/test/SILOptimizer/diagnostic_constant_propagation_int_arch32.swift b/test/SILOptimizer/diagnostic_constant_propagation_int_arch32.swift
index 41fd7ed..a4ef070 100644
--- a/test/SILOptimizer/diagnostic_constant_propagation_int_arch32.swift
+++ b/test/SILOptimizer/diagnostic_constant_propagation_int_arch32.swift
@@ -234,8 +234,5 @@
}
func testIntToFloatConversion() {
- // No warnings are emitted for conversion through explicit constructor calls.
- // Note that the error here is because of an implicit conversion of the input
- // literal to 'Int', which is 32 bits in arch32.
- _blackHole(Double(9_007_199_254_740_993)) // expected-error {{integer literal '9007199254740993' overflows when stored into 'Int'}}
+ _blackHole(Double(9_007_199_254_740_993)) // Ok
}
diff --git a/test/expr/expressions.swift b/test/expr/expressions.swift
index b7122d5..9099fc8 100644
--- a/test/expr/expressions.swift
+++ b/test/expr/expressions.swift
@@ -910,3 +910,10 @@
let obj = C();
_ = obj[#column] // Ok.
}
+
+// rdar://problem/23672697 - No way to express literal integers larger than Int without using type ascription
+let _: Int64 = 0xFFF_FFFF_FFFF_FFFF
+let _: Int64 = Int64(0xFFF_FFFF_FFFF_FFFF)
+let _: Int64 = 0xFFF_FFFF_FFFF_FFFF as Int64
+let _ = Int64(0xFFF_FFFF_FFFF_FFFF)
+let _ = 0xFFF_FFFF_FFFF_FFFF as Int64
diff --git a/validation-test/Sema/type_checker_perf/slow/rdar18699199.swift.gyb b/validation-test/Sema/type_checker_perf/fast/rdar18699199.swift.gyb
similarity index 69%
rename from validation-test/Sema/type_checker_perf/slow/rdar18699199.swift.gyb
rename to validation-test/Sema/type_checker_perf/fast/rdar18699199.swift.gyb
index a3108cc..7b950c4 100644
--- a/validation-test/Sema/type_checker_perf/slow/rdar18699199.swift.gyb
+++ b/validation-test/Sema/type_checker_perf/fast/rdar18699199.swift.gyb
@@ -1,4 +1,4 @@
-// RUN: %scale-test --invert-result --begin 1 --end 5 --step 1 --select incrementScopeCounter %s
+// RUN: %scale-test --begin 1 --end 10 --step 1 --select incrementScopeCounter %s
// REQUIRES: OS=macosx
// REQUIRES: asserts
public enum E
diff --git a/validation-test/compiler_crashers_2_fixed/0165-sr8240.swift b/validation-test/compiler_crashers_2_fixed/0165-sr8240.swift
new file mode 100644
index 0000000..5b175c3
--- /dev/null
+++ b/validation-test/compiler_crashers_2_fixed/0165-sr8240.swift
@@ -0,0 +1,14 @@
+// RUN: %target-typecheck-verify-swift
+
+struct Box<Representation> {
+ let value: Representation
+}
+enum Repr {}
+extension Repr {
+ typealias RawEnum = ()
+}
+extension Box where Representation == Repr {
+ init(rawEnumValue: Representation.RawEnum) {
+ fatalError()
+ }
+}
diff --git a/validation-test/compiler_crashers_2_fixed/0166-sr8240-2.swift b/validation-test/compiler_crashers_2_fixed/0166-sr8240-2.swift
new file mode 100644
index 0000000..0723703
--- /dev/null
+++ b/validation-test/compiler_crashers_2_fixed/0166-sr8240-2.swift
@@ -0,0 +1,15 @@
+// RUN: %target-typecheck-verify-swift
+
+struct Box<Representation, T> {
+ let value: Representation
+}
+enum Repr {}
+extension Repr {
+ typealias RawEnum = ()
+}
+extension Box where Representation == Repr, T == Representation.RawEnum {
+ init(rawEnumValue: Representation.RawEnum) {
+ let _: Int.Type = T.self // expected-error {{cannot convert value of type '().Type' to specified type 'Int.Type'}}
+ fatalError()
+ }
+}
diff --git a/validation-test/compiler_crashers_2_fixed/0168-rdar40164371.swift b/validation-test/compiler_crashers_2_fixed/0168-rdar40164371.swift
new file mode 100644
index 0000000..8ab7754
--- /dev/null
+++ b/validation-test/compiler_crashers_2_fixed/0168-rdar40164371.swift
@@ -0,0 +1,44 @@
+// RUN: %target-swift-frontend -emit-sil %s
+
+protocol X1 {
+ associatedtype X3 : X4
+}
+
+protocol X4 {
+ associatedtype X15
+}
+
+protocol X7 { }
+
+protocol X9 : X7 {
+ associatedtype X10 : X7
+}
+
+struct X12 : X9 {
+ typealias X10 = X12
+}
+
+struct X13<I1 : X7> : X9 {
+ typealias X10 = X13<I1>
+}
+
+struct X14<G : X4> : X4 where G.X15 : X9 {
+ typealias X15 = X13<G.X15.X10>
+}
+
+struct X17<A : X4> : X1 where A.X15 == X12 {
+ typealias X3 = X14<A>
+}
+
+struct X18 : X4 {
+ typealias X15 = X12
+}
+
+@_transparent
+func callee<T>(_: T) where T : X1 {
+ let _: T.X3.X15? = nil
+}
+
+func caller(b: X17<X18>) {
+ callee(b)
+}
diff --git a/validation-test/compiler_crashers/28850-unreachable-executed-at-swift-lib-sema-typecheckgeneric-cpp-220.swift b/validation-test/compiler_crashers_fixed/28850-unreachable-executed-at-swift-lib-sema-typecheckgeneric-cpp-220.swift
similarity index 87%
rename from validation-test/compiler_crashers/28850-unreachable-executed-at-swift-lib-sema-typecheckgeneric-cpp-220.swift
rename to validation-test/compiler_crashers_fixed/28850-unreachable-executed-at-swift-lib-sema-typecheckgeneric-cpp-220.swift
index ece7287..dd3f37e 100644
--- a/validation-test/compiler_crashers/28850-unreachable-executed-at-swift-lib-sema-typecheckgeneric-cpp-220.swift
+++ b/validation-test/compiler_crashers_fixed/28850-unreachable-executed-at-swift-lib-sema-typecheckgeneric-cpp-220.swift
@@ -5,5 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// RUN: not --crash %target-swift-frontend %s -emit-ir
+// RUN: not %target-swift-frontend %s -emit-ir
protocol P{class a{protocol a:P{func a:a.a{}typealias a
diff --git a/validation-test/stdlib/Collection/FlattenCollection.swift.gyb b/validation-test/stdlib/Collection/FlattenCollection.swift.gyb
index 26849a5..e4d7833 100644
--- a/validation-test/stdlib/Collection/FlattenCollection.swift.gyb
+++ b/validation-test/stdlib/Collection/FlattenCollection.swift.gyb
@@ -66,10 +66,15 @@
do {
let expected = ["apple", "orange", "banana", "grapefruit", "lychee"]
let base = [["apple", "orange"], ["banana", "grapefruit"], ["lychee"]]
+ let flattened = Minimal${traversal}${kind}(elements: base).joined()
check${traversal}${kind}(
expected,
Minimal${traversal}${kind}(elements: base).joined(),
sameValue: { $0 == $1 })
+ checkSequence(
+ expected,
+ flattened.makeIterator(),
+ sameValue: { $0 == $1 })
}
}
% end