Merge pull request #13050 from davezarzycki/nfc_enum_class_TypeResolutionFlags
NFC: Use 'enum class' for TypeResolutionFlags
diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h
index c27a0c1..3fcf20f 100644
--- a/include/swift/AST/Decl.h
+++ b/include/swift/AST/Decl.h
@@ -784,6 +784,9 @@
LLVM_ATTRIBUTE_DEPRECATED(
void dump() const LLVM_ATTRIBUTE_USED,
"only for use within the debugger");
+ LLVM_ATTRIBUTE_DEPRECATED(
+ void dump(const char *filename) const LLVM_ATTRIBUTE_USED,
+ "only for use within the debugger");
void dump(raw_ostream &OS, unsigned Indent = 0) const;
/// \brief Pretty-print the given declaration.
diff --git a/include/swift/AST/DeclNameLoc.h b/include/swift/AST/DeclNameLoc.h
index 067c653..216af88 100644
--- a/include/swift/AST/DeclNameLoc.h
+++ b/include/swift/AST/DeclNameLoc.h
@@ -105,6 +105,14 @@
return getSourceLocs()[FirstArgumentLabelIndex + index];
}
+ SourceLoc getStartLoc() const {
+ return getBaseNameLoc();
+ }
+
+ SourceLoc getEndLoc() const {
+ return NumArgumentLabels == 0 ? getBaseNameLoc() : getRParenLoc();
+ }
+
/// Retrieve the complete source range for this declaration name.
SourceRange getSourceRange() const {
if (NumArgumentLabels == 0) return getBaseNameLoc();
diff --git a/include/swift/AST/Expr.h b/include/swift/AST/Expr.h
index 11529ca..f750f5b 100644
--- a/include/swift/AST/Expr.h
+++ b/include/swift/AST/Expr.h
@@ -2339,7 +2339,10 @@
SourceLoc getLoc() const { return Index->getStartLoc(); }
SourceLoc getStartLoc() const { return Base->getStartLoc(); }
- SourceLoc getEndLoc() const { return Index->getEndLoc(); }
+ SourceLoc getEndLoc() const {
+ auto end = Index->getEndLoc();
+ return end.isValid() ? end : Base->getEndLoc();
+ }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::Subscript;
@@ -2396,7 +2399,7 @@
: SubExpr->getStartLoc());
}
SourceLoc getEndLoc() const {
- return NameLoc.getSourceRange().End ;
+ return NameLoc.getSourceRange().End;
}
SourceLoc getDotLoc() const { return DotLoc; }
diff --git a/include/swift/AST/Types.h b/include/swift/AST/Types.h
index b9420dd..60f9b59 100644
--- a/include/swift/AST/Types.h
+++ b/include/swift/AST/Types.h
@@ -123,7 +123,7 @@
};
private:
- unsigned Bits : BitWidth;
+ unsigned Bits;
public:
RecursiveTypeProperties() : Bits(0) {}
@@ -289,9 +289,9 @@
/// Extra information which affects how the function is called, like
/// regparm and the calling convention.
- unsigned ExtInfo : 16;
+ unsigned ExtInfo : 7;
};
- enum { NumAnyFunctionTypeBits = NumTypeBaseBits + 16 };
+ enum { NumAnyFunctionTypeBits = NumTypeBaseBits + 7 };
static_assert(NumAnyFunctionTypeBits <= 32, "fits in an unsigned");
struct ArchetypeTypeBitfields {
@@ -316,12 +316,12 @@
struct SILFunctionTypeBitfields {
unsigned : NumTypeBaseBits;
- unsigned ExtInfo : 16;
+ unsigned ExtInfo : 6;
unsigned CalleeConvention : 3;
unsigned HasErrorResult : 1;
unsigned CoroutineKind : 2;
};
- enum { NumSILFunctionTypeBits = NumTypeBaseBits + 16 + 6 };
+ enum { NumSILFunctionTypeBits = NumTypeBaseBits + 12 };
static_assert(NumSILFunctionTypeBits <= 32, "fits in an unsigned");
struct AnyMetatypeTypeBitfields {
@@ -376,6 +376,7 @@
void setRecursiveProperties(RecursiveTypeProperties properties) {
TypeBaseBits.Properties = properties.getBits();
+ assert(TypeBaseBits.Properties == properties.getBits() && "Bits dropped!");
}
public:
@@ -2391,21 +2392,22 @@
/// \brief A class which abstracts out some details necessary for
/// making a call.
class ExtInfo {
- // Feel free to rearrange or add bits, but if you go over 15,
- // you'll need to adjust both the Bits field below and
- // BaseType::AnyFunctionTypeBits.
+ // NOTE: If bits are added or removed, then TypeBase::AnyFunctionTypeBits
+ // must be updated to match.
// |representation|isAutoClosure|noEscape|throws|
// | 0 .. 3 | 4 | 5 | 6 |
//
- enum : uint16_t { RepresentationMask = 0x00F };
- enum : uint16_t { AutoClosureMask = 0x010 };
- enum : uint16_t { NoEscapeMask = 0x020 };
- enum : uint16_t { ThrowsMask = 0x040 };
+ enum : unsigned {
+ RepresentationMask = 0x0F,
+ AutoClosureMask = 0x10,
+ NoEscapeMask = 0x20,
+ ThrowsMask = 0x40,
+ };
- uint16_t Bits;
+ unsigned Bits;
- ExtInfo(unsigned Bits) : Bits(static_cast<uint16_t>(Bits)) {}
+ ExtInfo(unsigned Bits) : Bits(Bits) {}
friend class AnyFunctionType;
@@ -2537,6 +2539,7 @@
: TypeBase(Kind, CanTypeContext, properties), Input(Input), Output(Output),
NumParams(NumParams) {
AnyFunctionTypeBits.ExtInfo = Info.Bits;
+ assert(AnyFunctionTypeBits.ExtInfo == Info.Bits && "Bits were dropped!");
}
public:
@@ -3246,20 +3249,21 @@
/// \brief A class which abstracts out some details necessary for
/// making a call.
class ExtInfo {
- // Feel free to rearrange or add bits, but if you go over 15,
- // you'll need to adjust both the Bits field below and
- // TypeBase::AnyFunctionTypeBits.
+ // NOTE: If bits are added or removed, then TypeBase::SILFunctionTypeBits
+ // must be updated to match.
// |representation|pseudogeneric| noescape |
// | 0 .. 3 | 4 | 5 |
//
- enum : uint16_t { RepresentationMask = 0x00F };
- enum : uint16_t { PseudogenericMask = 0x010 };
- enum : uint16_t { NoEscapeMask = 0x020 };
+ enum : unsigned {
+ RepresentationMask = 0x0F,
+ PseudogenericMask = 0x10,
+ NoEscapeMask = 0x20,
+ };
- uint16_t Bits;
+ unsigned Bits;
- ExtInfo(unsigned Bits) : Bits(static_cast<uint16_t>(Bits)) {}
+ ExtInfo(unsigned Bits) : Bits(Bits) {}
friend class SILFunctionType;
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 05362d2..9e0742a 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -3869,6 +3869,7 @@
SILFunctionTypeBits.HasErrorResult = errorResult.hasValue();
SILFunctionTypeBits.ExtInfo = ext.Bits;
+ assert(SILFunctionTypeBits.ExtInfo == ext.Bits && "Bits were dropped!");
SILFunctionTypeBits.CoroutineKind = unsigned(coroutineKind);
NumParameters = params.size();
if (coroutineKind == SILCoroutineKind::None) {
diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp
index 620b828..5c9f0d5 100644
--- a/lib/AST/ASTDumper.cpp
+++ b/lib/AST/ASTDumper.cpp
@@ -14,7 +14,6 @@
//
//===----------------------------------------------------------------------===//
-#include "swift/Basic/QuotedString.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/ASTPrinter.h"
#include "swift/AST/ASTVisitor.h"
@@ -24,12 +23,14 @@
#include "swift/AST/ParameterList.h"
#include "swift/AST/ProtocolConformance.h"
#include "swift/AST/TypeVisitor.h"
+#include "swift/Basic/QuotedString.h"
#include "swift/Basic/STLExtras.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/SaveAndRestore.h"
#include "llvm/Support/raw_ostream.h"
@@ -1177,6 +1178,16 @@
dump(llvm::errs(), 0);
}
+void Decl::dump(const char *filename) const {
+ std::error_code ec;
+ llvm::raw_fd_ostream stream(filename, ec, llvm::sys::fs::F_RW);
+ // In assert builds, we blow up. Otherwise, we just return.
+ assert(!ec && "Failed to open file for dumping?!");
+ if (ec)
+ return;
+ dump(stream, 0);
+}
+
void Decl::dump(raw_ostream &OS, unsigned Indent) const {
// Make sure to print type variables.
llvm::SaveAndRestore<bool> X(getASTContext().LangOpts.DebugConstraintSolver,
diff --git a/lib/AST/SubstitutionMap.cpp b/lib/AST/SubstitutionMap.cpp
index a8f1854..2e4db85 100644
--- a/lib/AST/SubstitutionMap.cpp
+++ b/lib/AST/SubstitutionMap.cpp
@@ -224,7 +224,7 @@
substType->castTo<ArchetypeType>()->getSuperclass()) &&
!substType->isTypeParameter() &&
!substType->isExistentialType()) {
- return *M->lookupConformance(substType, proto);
+ return M->lookupConformance(substType, proto);
}
return ProtocolConformanceRef(proto);
diff --git a/lib/IRGen/IRGenSIL.cpp b/lib/IRGen/IRGenSIL.cpp
index cbada81..bc9229a 100644
--- a/lib/IRGen/IRGenSIL.cpp
+++ b/lib/IRGen/IRGenSIL.cpp
@@ -1473,10 +1473,9 @@
void IRGenModule::emitSILFunction(SILFunction *f) {
if (f->isExternalDeclaration())
return;
+
// Do not emit bodies of public_external functions.
- // The only exception is transparent functions.
- if (hasPublicVisibility(f->getLinkage()) && f->isAvailableExternally() &&
- !f->isTransparent())
+ if (hasPublicVisibility(f->getLinkage()) && f->isAvailableExternally())
return;
PrettyStackTraceSILFunction stackTrace("emitting IR", f);
@@ -5097,7 +5096,6 @@
SILType addrTy = i->getOperand()->getType();
const TypeInfo &addrTI = getTypeInfo(addrTy);
- // Otherwise, do the normal thing.
Address base = getLoweredAddress(i->getOperand());
addrTI.destroy(*this, base, addrTy, false /*isOutlined*/);
}
diff --git a/lib/SIL/SILFunctionType.cpp b/lib/SIL/SILFunctionType.cpp
index e371b0f..7da238d 100644
--- a/lib/SIL/SILFunctionType.cpp
+++ b/lib/SIL/SILFunctionType.cpp
@@ -1130,6 +1130,23 @@
}
};
+/// The convention used for allocating inits. Allocating inits take their normal
+/// parameters at +1 and do not have a self parameter.
+struct DefaultAllocatorConventions : DefaultConventions {
+ DefaultAllocatorConventions()
+ : DefaultConventions(NormalParameterConvention::Owned) {}
+
+ ParameterConvention
+ getDirectSelfParameter(const AbstractionPattern &type) const override {
+ llvm_unreachable("Allocating inits do not have self parameters");
+ }
+
+ ParameterConvention
+ getIndirectSelfParameter(const AbstractionPattern &type) const override {
+ llvm_unreachable("Allocating inits do not have self parameters");
+ }
+};
+
/// The default conventions for Swift setter acccessors.
///
/// These take self at +0, but all other parameters at +1. This is because we
@@ -1220,7 +1237,10 @@
return getSILFunctionType(M, origType, substInterfaceType, extInfo,
DefaultInitializerConventions(), ForeignInfo(),
constant, witnessMethodConformance);
-
+ case SILDeclRef::Kind::Allocator:
+ return getSILFunctionType(M, origType, substInterfaceType, extInfo,
+ DefaultAllocatorConventions(), ForeignInfo(),
+ constant, witnessMethodConformance);
case SILDeclRef::Kind::Func:
// If we have a setter, use the special setter convention. This ensures
// that we take normal parameters at +1.
@@ -1230,7 +1250,6 @@
constant, witnessMethodConformance);
}
LLVM_FALLTHROUGH;
- case SILDeclRef::Kind::Allocator:
case SILDeclRef::Kind::Destroyer:
case SILDeclRef::Kind::GlobalAccessor:
case SILDeclRef::Kind::GlobalGetter:
diff --git a/lib/Sema/CSDiag.cpp b/lib/Sema/CSDiag.cpp
index 8013b18..1bc9bd3 100644
--- a/lib/Sema/CSDiag.cpp
+++ b/lib/Sema/CSDiag.cpp
@@ -1431,7 +1431,7 @@
ValueDecl *member = nullptr;
for (auto cand : result.UnviableCandidates) {
if (member == nullptr)
- member = cand.first;
+ member = cand.first.getDecl();
sameProblem &= cand.second == firstProblem;
}
@@ -1537,12 +1537,12 @@
}
case MemberLookupResult::UR_Inaccessible: {
- auto decl = result.UnviableCandidates[0].first;
+ auto decl = result.UnviableCandidates[0].first.getDecl();
// FIXME: What if the unviable candidates have different levels of access?
diagnose(nameLoc, diag::candidate_inaccessible, decl->getBaseName(),
decl->getFormalAccess());
for (auto cand : result.UnviableCandidates)
- diagnose(cand.first, diag::decl_declared_here, memberName);
+ diagnose(cand.first.getDecl(), diag::decl_declared_here, memberName);
return;
}
@@ -4810,7 +4810,7 @@
SmallVector<OverloadChoice, 2> choices;
for (auto &unviable : results.UnviableCandidates)
- choices.push_back(OverloadChoice(baseType, unviable.first,
+ choices.push_back(OverloadChoice(baseType, unviable.first.getDecl(),
UDE->getFunctionRefKind()));
CalleeCandidateInfo unviableCandidates(baseType, choices, hasTrailingClosure,
diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp
index 4037009..3ae6484 100644
--- a/lib/Sema/CSGen.cpp
+++ b/lib/Sema/CSGen.cpp
@@ -3572,7 +3572,7 @@
// Keep track of all the unviable members.
for (auto Can : LookupResult.UnviableCandidates)
- Result.Impl.AllDecls.push_back(Can.first);
+ Result.Impl.AllDecls.push_back(Can.first.getDecl());
// Keep track of the start of viable choices.
Result.Impl.ViableStartIdx = Result.Impl.AllDecls.size();
diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp
index 3c000d8..3ab4869 100644
--- a/lib/Sema/CSSimplify.cpp
+++ b/lib/Sema/CSSimplify.cpp
@@ -3089,34 +3089,35 @@
// Local function that adds the given declaration if it is a
// reasonable choice.
- auto addChoice = [&](ValueDecl *cand, bool isBridged,
- bool isUnwrappedOptional) {
+ auto addChoice = [&](OverloadChoice candidate) {
+ auto decl = candidate.getDecl();
+
// If the result is invalid, skip it.
- TC.validateDecl(cand);
- if (cand->isInvalid()) {
+ TC.validateDecl(decl);
+ if (decl->isInvalid()) {
result.markErrorAlreadyDiagnosed();
return;
}
// FIXME: Deal with broken recursion
- if (!cand->hasInterfaceType())
+ if (!decl->hasInterfaceType())
return;
// If the argument labels for this result are incompatible with
// the call site, skip it.
- if (!hasCompatibleArgumentLabels(cand)) {
+ if (!hasCompatibleArgumentLabels(decl)) {
labelMismatch = true;
- result.addUnviable(cand, MemberLookupResult::UR_LabelMismatch);
+ result.addUnviable(candidate, MemberLookupResult::UR_LabelMismatch);
return;
}
// If our base is an existential type, we can't make use of any
// member whose signature involves associated types.
if (isExistential) {
- if (auto *proto = cand->getDeclContext()
+ if (auto *proto = decl->getDeclContext()
->getAsProtocolOrProtocolExtensionContext()) {
- if (!proto->isAvailableInExistential(cand)) {
- result.addUnviable(cand,
+ if (!proto->isAvailableInExistential(decl)) {
+ result.addUnviable(candidate,
MemberLookupResult::UR_UnavailableInExistential);
return;
}
@@ -3126,18 +3127,17 @@
// If the invocation's argument expression has a favored type,
// use that information to determine whether a specific overload for
// the candidate should be favored.
- if (isa<ConstructorDecl>(cand) && favoredType &&
+ if (isa<ConstructorDecl>(decl) && favoredType &&
result.FavoredChoice == ~0U) {
// Only try and favor monomorphic initializers.
- if (auto fnTypeWithSelf = cand->getInterfaceType()
- ->getAs<FunctionType>()) {
- if (auto fnType = fnTypeWithSelf->getResult()
- ->getAs<FunctionType>()) {
+ if (auto fnTypeWithSelf = decl->getInterfaceType()
+ ->getAs<FunctionType>()) {
+ if (auto fnType = fnTypeWithSelf->getResult()->getAs<FunctionType>()) {
auto argType = fnType->getInput()->getWithoutParens();
- argType = cand->getInnermostDeclContext()
+ argType = decl->getInnermostDeclContext()
->mapTypeIntoContext(argType);
if (argType->isEqual(favoredType))
- if (!cand->getAttrs().isUnavailable(getASTContext()))
+ if (!decl->getAttrs().isUnavailable(getASTContext()))
result.FavoredChoice = result.ViableCandidates.size();
}
}
@@ -3145,25 +3145,27 @@
// See if we have an instance method, instance member or static method,
// and check if it can be accessed on our base type.
- if (cand->isInstanceMember()) {
- if ((isa<FuncDecl>(cand) && !hasInstanceMethods) ||
- (!isa<FuncDecl>(cand) && !hasInstanceMembers)) {
- result.addUnviable(cand, MemberLookupResult::UR_InstanceMemberOnType);
+ if (decl->isInstanceMember()) {
+ if ((isa<FuncDecl>(decl) && !hasInstanceMethods) ||
+ (!isa<FuncDecl>(decl) && !hasInstanceMembers)) {
+ result.addUnviable(candidate,
+ MemberLookupResult::UR_InstanceMemberOnType);
return;
}
// If the underlying type of a typealias is fully concrete, it is legal
// to access the type with a protocol metatype base.
} else if (isExistential &&
- isa<TypeAliasDecl>(cand) &&
- !cast<TypeAliasDecl>(cand)->getInterfaceType()->getCanonicalType()
+ isa<TypeAliasDecl>(decl) &&
+ !cast<TypeAliasDecl>(decl)->getInterfaceType()->getCanonicalType()
->hasTypeParameter()) {
/* We're OK */
} else {
if (!hasStaticMembers) {
- result.addUnviable(cand, MemberLookupResult::UR_TypeMemberOnInstance);
+ result.addUnviable(candidate,
+ MemberLookupResult::UR_TypeMemberOnInstance);
return;
}
}
@@ -3171,19 +3173,19 @@
// If we have an rvalue base, make sure that the result isn't 'mutating'
// (only valid on lvalues).
if (!isMetatype &&
- !baseTy->is<LValueType>() && cand->isInstanceMember()) {
- if (auto *FD = dyn_cast<FuncDecl>(cand))
+ !baseTy->is<LValueType>() && decl->isInstanceMember()) {
+ if (auto *FD = dyn_cast<FuncDecl>(decl))
if (FD->isMutating()) {
- result.addUnviable(cand,
+ result.addUnviable(candidate,
MemberLookupResult::UR_MutatingMemberOnRValue);
return;
}
// Subscripts and computed properties are ok on rvalues so long
// as the getter is nonmutating.
- if (auto storage = dyn_cast<AbstractStorageDecl>(cand)) {
+ if (auto storage = dyn_cast<AbstractStorageDecl>(decl)) {
if (storage->isGetterMutating()) {
- result.addUnviable(cand,
+ result.addUnviable(candidate,
MemberLookupResult::UR_MutatingGetterOnRValue);
return;
}
@@ -3191,52 +3193,55 @@
}
// If the result's type contains delayed members, we need to force them now.
- if (auto NT = dyn_cast<NominalType>(cand->getInterfaceType().getPointer())) {
+ if (auto NT = dyn_cast<NominalType>(decl->getInterfaceType().getPointer())){
if (auto *NTD = dyn_cast<NominalTypeDecl>(NT->getDecl())) {
TC.forceExternalDeclMembers(NTD);
}
}
+ // Otherwise, we're good, add the candidate to the list.
+ result.addViable(candidate);
+ };
+
+ // Local function that turns a ValueDecl into a properly configured
+ // OverloadChoice.
+ auto getOverloadChoice = [&](ValueDecl *cand, bool isBridged,
+ bool isUnwrappedOptional) -> OverloadChoice {
// If we're looking into an existential type, check whether this
// result was found via dynamic lookup.
if (isDynamicLookup) {
assert(cand->getDeclContext()->isTypeContext() && "Dynamic lookup bug");
-
+
// We found this declaration via dynamic lookup, record it as such.
- result.addViable(OverloadChoice::getDeclViaDynamic(baseTy, cand,
- functionRefKind));
- return;
+ return OverloadChoice::getDeclViaDynamic(baseTy, cand, functionRefKind);
}
-
+
// If we have a bridged type, we found this declaration via bridging.
- if (isBridged) {
- result.addViable(OverloadChoice::getDeclViaBridge(bridgedType, cand,
- functionRefKind));
- return;
- }
-
+ if (isBridged)
+ return OverloadChoice::getDeclViaBridge(bridgedType, cand,
+ functionRefKind);
+
// If we got the choice by unwrapping an optional type, unwrap the base
// type.
Type ovlBaseTy = baseTy;
if (isUnwrappedOptional) {
ovlBaseTy = MetatypeType::get(baseTy->castTo<MetatypeType>()
- ->getInstanceType()
- ->getAnyOptionalObjectType());
- result.addViable(
- OverloadChoice::getDeclViaUnwrappedOptional(ovlBaseTy, cand,
- functionRefKind));
- } else {
- result.addViable(OverloadChoice(ovlBaseTy, cand, functionRefKind));
+ ->getInstanceType()
+ ->getAnyOptionalObjectType());
+ return OverloadChoice::getDeclViaUnwrappedOptional(ovlBaseTy, cand,
+ functionRefKind);
}
+
+ return OverloadChoice(ovlBaseTy, cand, functionRefKind);
};
-
+
// Add all results from this lookup.
retry_after_fail:
labelMismatch = false;
for (auto result : lookup)
- addChoice(result.getValueDecl(),
- /*isBridged=*/false,
- /*isUnwrappedOptional=*/false);
+ addChoice(getOverloadChoice(result.getValueDecl(),
+ /*isBridged=*/false,
+ /*isUnwrappedOptional=*/false));
// If the instance type is a bridged to an Objective-C type, perform
// a lookup into that Objective-C type.
@@ -3259,9 +3264,9 @@
continue;
}
- addChoice(result.getValueDecl(),
- /*isBridged=*/true,
- /*isUnwrappedOptional=*/false);
+ addChoice(getOverloadChoice(result.getValueDecl(),
+ /*isBridged=*/true,
+ /*isUnwrappedOptional=*/false));
}
}
@@ -3275,9 +3280,9 @@
if (objectType->mayHaveMembers()) {
LookupResult &optionalLookup = lookupMember(objectType, memberName);
for (auto result : optionalLookup)
- addChoice(result.getValueDecl(),
- /*bridged*/false,
- /*isUnwrappedOptional=*/true);
+ addChoice(getOverloadChoice(result.getValueDecl(),
+ /*bridged*/false,
+ /*isUnwrappedOptional=*/true));
}
}
}
@@ -3319,7 +3324,9 @@
if (!cand->hasInterfaceType())
continue;
- result.addUnviable(cand, MemberLookupResult::UR_Inaccessible);
+ result.addUnviable(getOverloadChoice(cand, /*isBridged=*/false,
+ /*isUnwrappedOptional=*/false),
+ MemberLookupResult::UR_Inaccessible);
}
}
diff --git a/lib/Sema/ConstraintSystem.h b/lib/Sema/ConstraintSystem.h
index 9be37fe..34721cd 100644
--- a/lib/Sema/ConstraintSystem.h
+++ b/lib/Sema/ConstraintSystem.h
@@ -849,9 +849,9 @@
UR_Inaccessible,
};
- /// This is a list of considered, but rejected, candidates, along with a
+ /// This is a list of considered (but rejected) candidates, along with a
/// reason for their rejection.
- SmallVector<std::pair<ValueDecl*, UnviableReason>, 4> UnviableCandidates;
+ SmallVector<std::pair<OverloadChoice, UnviableReason>, 4> UnviableCandidates;
/// Mark this as being an already-diagnosed error and return itself.
@@ -864,8 +864,8 @@
ViableCandidates.push_back(candidate);
}
- void addUnviable(ValueDecl *VD, UnviableReason reason) {
- UnviableCandidates.push_back({VD, reason});
+ void addUnviable(OverloadChoice candidate, UnviableReason reason) {
+ UnviableCandidates.push_back({candidate, reason});
}
OverloadChoice *getFavoredChoice() {
diff --git a/lib/Sema/OverloadChoice.h b/lib/Sema/OverloadChoice.h
index ee9f0a2..317b6f2 100644
--- a/lib/Sema/OverloadChoice.h
+++ b/lib/Sema/OverloadChoice.h
@@ -22,7 +22,6 @@
#include "llvm/Support/ErrorHandling.h"
#include "swift/AST/Availability.h"
#include "swift/AST/FunctionRefKind.h"
-#include "swift/AST/Type.h"
#include "swift/AST/Types.h"
namespace swift {
@@ -47,10 +46,6 @@
BaseType,
/// \brief The overload choice selects a key path subscripting operation.
KeyPathApplication,
- /// \brief The overload choice indexes into a tuple. Index zero will
- /// have the value of this enumerator, index one will have the value of this
- /// enumerator + 1, and so on. Thus, this enumerator must always be last.
- TupleIndex,
/// \brief The overload choice selects a particular declaration that
/// was found by bridging the base value type to its Objective-C
/// class type.
@@ -58,33 +53,43 @@
/// \brief The overload choice selects a particular declaration that
/// was found by unwrapping an optional context type.
DeclViaUnwrappedOptional,
+ /// \brief The overload choice indexes into a tuple. Index zero will
+ /// have the value of this enumerator, index one will have the value of this
+ /// enumerator + 1, and so on. Thus, this enumerator must always be last.
+ TupleIndex,
};
/// \brief Describes a particular choice within an overload set.
///
-///
class OverloadChoice {
enum : unsigned {
- /// Indicates whether this declaration was bridged, turning a
+ /// Indicates that this is a normal "Decl" kind, or isn't a decl.
+ IsDecl = 0x00,
+ /// Indicates that this declaration was bridged, turning a
/// "Decl" kind into "DeclViaBridge" kind.
- IsBridgedBit = 0x02,
- /// Indicates whether this declaration was resolved by unwrapping an
+ IsDeclViaBridge = 0x01,
+ /// Indicates that this declaration was resolved by unwrapping an
/// optional context type, turning a "Decl" kind into
/// "DeclViaUnwrappedOptional".
- IsUnwrappedOptionalBit = 0x04,
-
- // IsBridged and IsUnwrappedOptional are mutually exclusive, so there is
- // room for another mutually exclusive OverloadChoiceKind to be packed into
- // those two bits.
+ IsDeclViaUnwrappedOptional = 0x02,
+ /// Indicates that this declaration was dynamic, turning a
+ /// "Decl" kind into "DeclViaDynamic" kind.
+ IsDeclViaDynamic = 0x03
};
/// \brief The base type to be used when referencing the declaration
/// along with the two bits above.
- llvm::PointerIntPair<Type, 3, unsigned> BaseAndBits;
+ llvm::PointerIntPair<Type, 3, unsigned> BaseAndDeclKind;
- /// \brief Either the declaration pointer (if the low bit is clear) or the
- /// overload choice kind shifted two bits with the low bit set.
- uintptr_t DeclOrKind;
+ /// We mash together OverloadChoiceKind with tuple indices into a single
+ /// integer representation.
+ typedef llvm::PointerEmbeddedInt<uint32_t, 29>
+ OverloadChoiceKindWithTupleIndex;
+
+ /// \brief Either the declaration pointer or the overload choice kind. The
+ /// second case is represented as an OverloadChoiceKind, but has additional
+ /// values at the top end that represent the tuple index.
+ llvm::PointerUnion<ValueDecl*, OverloadChoiceKindWithTupleIndex> DeclOrKind;
/// The kind of function reference.
/// FIXME: This needs two bits. Can we pack them somewhere?
@@ -92,23 +97,22 @@
public:
OverloadChoice()
- : BaseAndBits(nullptr, 0), DeclOrKind(0),
+ : BaseAndDeclKind(nullptr, 0), DeclOrKind(0),
TheFunctionRefKind(FunctionRefKind::Unapplied) {}
OverloadChoice(Type base, ValueDecl *value,
FunctionRefKind functionRefKind)
- : BaseAndBits(base, 0),
+ : BaseAndDeclKind(base, 0),
TheFunctionRefKind(functionRefKind) {
assert(!base || !base->hasTypeParameter());
assert((reinterpret_cast<uintptr_t>(value) & (uintptr_t)0x03) == 0 &&
"Badly aligned decl");
- DeclOrKind = reinterpret_cast<uintptr_t>(value);
+ DeclOrKind = value;
}
OverloadChoice(Type base, OverloadChoiceKind kind)
- : BaseAndBits(base, 0),
- DeclOrKind((uintptr_t)kind << 2 | (uintptr_t)0x03),
+ : BaseAndDeclKind(base, 0), DeclOrKind(uint32_t(kind)),
TheFunctionRefKind(FunctionRefKind::Unapplied) {
assert(base && "Must have a base type for overload choice");
assert(!base->hasTypeParameter());
@@ -120,19 +124,17 @@
}
OverloadChoice(Type base, unsigned index)
- : BaseAndBits(base, 0),
- DeclOrKind(((uintptr_t)index
- + (uintptr_t)OverloadChoiceKind::TupleIndex) << 2
- | (uintptr_t)0x03),
+ : BaseAndDeclKind(base, 0),
+ DeclOrKind(uint32_t(OverloadChoiceKind::TupleIndex)+index),
TheFunctionRefKind(FunctionRefKind::Unapplied) {
assert(base->getRValueType()->is<TupleType>() && "Must have tuple type");
}
bool isInvalid() const {
- return BaseAndBits.getPointer().isNull()
- && BaseAndBits.getInt() == 0
- && DeclOrKind == 0
- && TheFunctionRefKind == FunctionRefKind::Unapplied;
+ return BaseAndDeclKind.getPointer().isNull() &&
+ BaseAndDeclKind.getInt() == 0 &&
+ DeclOrKind.isNull() &&
+ TheFunctionRefKind == FunctionRefKind::Unapplied;
}
/// Retrieve an overload choice for a declaration that was found via
@@ -140,8 +142,9 @@
static OverloadChoice getDeclViaDynamic(Type base, ValueDecl *value,
FunctionRefKind functionRefKind) {
OverloadChoice result;
- result.BaseAndBits.setPointer(base);
- result.DeclOrKind = reinterpret_cast<uintptr_t>(value) | 0x02;
+ result.BaseAndDeclKind.setPointer(base);
+ result.BaseAndDeclKind.setInt(IsDeclViaDynamic);
+ result.DeclOrKind = value;
result.TheFunctionRefKind = functionRefKind;
return result;
}
@@ -151,76 +154,58 @@
static OverloadChoice getDeclViaBridge(Type base, ValueDecl *value,
FunctionRefKind functionRefKind) {
OverloadChoice result;
- result.BaseAndBits.setPointer(base);
- result.BaseAndBits.setInt(IsBridgedBit);
- result.DeclOrKind = reinterpret_cast<uintptr_t>(value);
+ result.BaseAndDeclKind.setPointer(base);
+ result.BaseAndDeclKind.setInt(IsDeclViaBridge);
+ result.DeclOrKind = value;
result.TheFunctionRefKind = functionRefKind;
return result;
}
/// Retrieve an overload choice for a declaration that was found
/// by unwrapping an optional context type.
- static OverloadChoice getDeclViaUnwrappedOptional(
- Type base,
- ValueDecl *value,
- FunctionRefKind functionRefKind) {
+ static OverloadChoice
+ getDeclViaUnwrappedOptional(Type base, ValueDecl *value,
+ FunctionRefKind functionRefKind) {
OverloadChoice result;
- result.BaseAndBits.setPointer(base);
- result.BaseAndBits.setInt(IsUnwrappedOptionalBit);
- result.DeclOrKind = reinterpret_cast<uintptr_t>(value);
+ result.BaseAndDeclKind.setPointer(base);
+ result.BaseAndDeclKind.setInt(IsDeclViaUnwrappedOptional);
+ result.DeclOrKind = value;
result.TheFunctionRefKind = functionRefKind;
return result;
}
/// \brief Retrieve the base type used to refer to the declaration.
- Type getBaseType() const { return BaseAndBits.getPointer(); }
+ Type getBaseType() const {
+ return BaseAndDeclKind.getPointer();
+ }
/// \brief Determines the kind of overload choice this is.
OverloadChoiceKind getKind() const {
- switch (DeclOrKind & 0x03) {
- case 0x00:
- if (BaseAndBits.getInt() & IsBridgedBit)
- return OverloadChoiceKind::DeclViaBridge;
- if (BaseAndBits.getInt() & IsUnwrappedOptionalBit)
+ if (DeclOrKind.is<ValueDecl*>()) {
+ switch (BaseAndDeclKind.getInt()) {
+ case IsDeclViaBridge: return OverloadChoiceKind::DeclViaBridge;
+ case IsDeclViaDynamic: return OverloadChoiceKind::DeclViaDynamic;
+ case IsDeclViaUnwrappedOptional:
return OverloadChoiceKind::DeclViaUnwrappedOptional;
-
- return OverloadChoiceKind::Decl;
-
- case 0x02: return OverloadChoiceKind::DeclViaDynamic;
- case 0x03: {
- uintptr_t value = DeclOrKind >> 2;
- if (value >= (uintptr_t)OverloadChoiceKind::TupleIndex)
- return OverloadChoiceKind::TupleIndex;
-
- return (OverloadChoiceKind)value;
+ default: return OverloadChoiceKind::Decl;
+ }
}
- default: llvm_unreachable("basic math has escaped me");
- }
+ uint32_t kind = DeclOrKind.get<OverloadChoiceKindWithTupleIndex>();
+ if (kind >= (uint32_t)OverloadChoiceKind::TupleIndex)
+ return OverloadChoiceKind::TupleIndex;
+
+ return (OverloadChoiceKind)kind;
}
/// Determine whether this choice is for a declaration.
bool isDecl() const {
- switch (getKind()) {
- case OverloadChoiceKind::Decl:
- case OverloadChoiceKind::DeclViaDynamic:
- case OverloadChoiceKind::DeclViaBridge:
- case OverloadChoiceKind::DeclViaUnwrappedOptional:
- return true;
-
- case OverloadChoiceKind::BaseType:
- case OverloadChoiceKind::TupleIndex:
- case OverloadChoiceKind::KeyPathApplication:
- return false;
- }
-
- llvm_unreachable("Unhandled OverloadChoiceKind in switch.");
+ return DeclOrKind.is<ValueDecl*>();
}
/// \brief Retrieve the declaration that corresponds to this overload choice.
ValueDecl *getDecl() const {
- assert(isDecl() && "Not a declaration");
- return reinterpret_cast<ValueDecl *>(DeclOrKind & ~(uintptr_t)0x03);
+ return DeclOrKind.get<ValueDecl*>();
}
/// Get the name of the overload choice.
@@ -230,12 +215,13 @@
/// choice.
unsigned getTupleIndex() const {
assert(getKind() == OverloadChoiceKind::TupleIndex);
- return (DeclOrKind >> 2) - (uintptr_t)OverloadChoiceKind::TupleIndex;
+ uint32_t kind = DeclOrKind.get<OverloadChoiceKindWithTupleIndex>();
+ return kind-(uint32_t)OverloadChoiceKind::TupleIndex;
}
/// \brief Retrieves an opaque choice that ignores the base type.
void *getOpaqueChoiceSimple() const {
- return reinterpret_cast<void*>(DeclOrKind);
+ return DeclOrKind.getOpaqueValue();
}
FunctionRefKind getFunctionRefKind() const {
diff --git a/lib/SwiftDemangle/CMakeLists.txt b/lib/SwiftDemangle/CMakeLists.txt
index 8a89845..417aaa2 100644
--- a/lib/SwiftDemangle/CMakeLists.txt
+++ b/lib/SwiftDemangle/CMakeLists.txt
@@ -3,11 +3,6 @@
MangleHack.cpp
LINK_LIBRARIES swiftDemangling)
-# We don't need to link against libbsd on MacOS and FreeBSD.
-if (NOT APPLE AND (NOT SWIFT_HOST_VARIANT STREQUAL "freebsd"))
- target_link_libraries(swiftDemangle PRIVATE bsd)
-endif()
-
swift_install_in_component(compiler
TARGETS swiftDemangle
LIBRARY DESTINATION "lib${LLVM_LIBDIR_SUFFIX}"
diff --git a/lib/SwiftDemangle/SwiftDemangle.cpp b/lib/SwiftDemangle/SwiftDemangle.cpp
index 75029b7..9069aa6 100644
--- a/lib/SwiftDemangle/SwiftDemangle.cpp
+++ b/lib/SwiftDemangle/SwiftDemangle.cpp
@@ -17,9 +17,6 @@
#include "swift/Demangling/Demangle.h"
#include "swift/SwiftDemangle/SwiftDemangle.h"
-#if defined(__linux__) || defined(_WIN32)
-#include <bsd/string.h>
-#endif
static size_t swift_demangle_getDemangledName_Options(const char *MangledName,
char *OutputBuffer, size_t Length,
@@ -36,8 +33,12 @@
if (Result == MangledName)
return 0; // Not a mangled name
- // Copy the result to an output buffer.
- return strlcpy(OutputBuffer, Result.c_str(), Length);
+ // Copy the result to an output buffer and ensure '\0' termination.
+ if (OutputBuffer && Length > 0) {
+ auto Dest = strncpy(OutputBuffer, Result.c_str(), Length);
+ Dest[Length - 1] = '\0';
+ }
+ return Result.length();
}
size_t swift_demangle_getDemangledName(const char *MangledName,
diff --git a/stdlib/public/SDK/os/os_trace_blob.c b/stdlib/public/SDK/os/os_trace_blob.c
index 86c070b..81c86f1 100644
--- a/stdlib/public/SDK/os/os_trace_blob.c
+++ b/stdlib/public/SDK/os/os_trace_blob.c
@@ -14,7 +14,10 @@
#include <dispatch/dispatch.h>
#include <os/base.h>
#include <os/log.h>
+#include <locale.h>
+#if !defined(__linux__)
#include <xlocale.h>
+#endif
#include "os_trace_blob.h"
OS_NOINLINE
diff --git a/stdlib/public/core/ClosedRange.swift b/stdlib/public/core/ClosedRange.swift
index fd6a624..37941c9 100644
--- a/stdlib/public/core/ClosedRange.swift
+++ b/stdlib/public/core/ClosedRange.swift
@@ -85,40 +85,6 @@
}
}
-// FIXME(ABI)#175 (Type checker)
-// WORKAROUND: needed because of rdar://25584401
-/// An iterator over the elements of a `CountableClosedRange` instance.
-@_fixed_layout
-public struct ClosedRangeIterator<Bound> : IteratorProtocol, Sequence
- where
- Bound : Strideable, Bound.Stride : SignedInteger {
-
- @_inlineable
- @_versioned
- internal init(_range r: CountableClosedRange<Bound>) {
- _nextResult = r.lowerBound
- _upperBound = r.upperBound
- }
-
- @_inlineable
- public func makeIterator() -> ClosedRangeIterator {
- return self
- }
-
- @_inlineable
- public mutating func next() -> Bound? {
- let r = _nextResult
- if let x = r {
- _nextResult = x == _upperBound ? nil : x.advanced(by: 1)
- }
- return r
- }
- @_versioned
- internal var _nextResult: Bound?
- @_versioned
- internal let _upperBound: Bound
-}
-
/// A closed range that forms a collection of consecutive values.
///
/// You create a `CountableClosedRange` instance by using the closed range
@@ -187,17 +153,6 @@
public typealias IndexDistance = Bound.Stride
- // FIXME(ABI)#175 (Type checker)
- // WORKAROUND: needed because of rdar://25584401
- public typealias Iterator = ClosedRangeIterator<Bound>
-
- // FIXME(ABI)#175 (Type checker)
- // WORKAROUND: needed because of rdar://25584401
- @_inlineable
- public func makeIterator() -> ClosedRangeIterator<Bound> {
- return ClosedRangeIterator(_range: self)
- }
-
/// The position of the first element in the range.
@_inlineable
public var startIndex: ClosedRangeIndex<Bound> {
@@ -299,16 +254,6 @@
return RandomAccessSlice(base: self, bounds: bounds)
}
- // FIXME(ABI)#175 (Type checker)
- @_inlineable
- public // WORKAROUND: needed because of rdar://25584401
- var indices: DefaultRandomAccessIndices<CountableClosedRange<Bound>> {
- return DefaultRandomAccessIndices(
- _elements: self,
- startIndex: self.startIndex,
- endIndex: self.endIndex)
- }
-
/// Creates an instance with the given bounds.
///
/// Because this initializer does not perform any checks, it should be used
diff --git a/stdlib/public/core/Stride.swift.gyb b/stdlib/public/core/Stride.swift.gyb
index a7f31e5..7a55d05 100644
--- a/stdlib/public/core/Stride.swift.gyb
+++ b/stdlib/public/core/Stride.swift.gyb
@@ -600,17 +600,6 @@
_preconditionFailure("Incrementing past end index")
}
}
-
- // FIXME(ABI)#175 (Type checker)
- @_inlineable
- public // WORKAROUND: needed because of rdar://25584401
- var indices: DefaultRandomAccessIndices<${Self}> {
- return DefaultRandomAccessIndices(
- _elements: self,
- startIndex: self.startIndex,
- endIndex: self.endIndex)
- }
-
}
% end
diff --git a/stdlib/public/stubs/Stubs.cpp b/stdlib/public/stubs/Stubs.cpp
index 0c1fedf..7b6f025 100644
--- a/stdlib/public/stubs/Stubs.cpp
+++ b/stdlib/public/stubs/Stubs.cpp
@@ -64,6 +64,8 @@
#define strtod_l swift_strtod_l
#define strtof_l swift_strtof_l
#define strtold_l swift_strtold_l
+#elif defined(__linux__)
+#include <locale.h>
#else
#include <xlocale.h>
#endif
diff --git a/test/SILGen/guaranteed_normal_args.swift b/test/SILGen/guaranteed_normal_args.swift
new file mode 100644
index 0000000..3a433f2
--- /dev/null
+++ b/test/SILGen/guaranteed_normal_args.swift
@@ -0,0 +1,88 @@
+// RUN: %target-swift-frontend -parse-as-library -module-name Swift -parse-stdlib -emit-silgen -enable-sil-ownership -enable-guaranteed-normal-arguments %s | %FileCheck %s
+
+// This test checks specific codegen related to normal arguments being passed at
+// +0. Eventually, it should be merged into normal SILGen tests.
+
+/////////////////
+// Fake Stdlib //
+/////////////////
+
+precedencegroup AssignmentPrecedence {
+ assignment: true
+}
+
+enum Optional<T> {
+case none
+case some(T)
+}
+
+class Klass {
+ init() {}
+}
+
+struct Buffer {
+ var k: Klass
+ init(inK: Klass) {
+ k = inK
+ }
+}
+
+typealias AnyObject = Builtin.AnyObject
+
+///////////
+// Tests //
+///////////
+
+class KlassWithBuffer {
+ var buffer: Buffer
+
+ // Make sure that the allocating init forwards into the initializing init at +1.
+ // CHECK-LABEL: sil hidden @_T0s15KlassWithBufferCABs0A0C3inK_tcfC : $@convention(method) (@owned Klass, @thick KlassWithBuffer.Type) -> @owned KlassWithBuffer {
+ // CHECK: bb0([[ARG:%.*]] : @owned $Klass,
+ // CHECK: [[INITIALIZING_INIT:%.*]] = function_ref @_T0s15KlassWithBufferCABs0A0C3inK_tcfc : $@convention(method) (@owned Klass, @owned KlassWithBuffer) -> @owned KlassWithBuffer
+ // CHECK: apply [[INITIALIZING_INIT]]([[ARG]],
+ // CHECK: } // end sil function '_T0s15KlassWithBufferCABs0A0C3inK_tcfC'
+ init(inK: Klass = Klass()) {
+ buffer = Buffer(inK: inK)
+ }
+
+ // This test makes sure that we:
+ //
+ // 1. Are able to propagate a +0 value value buffer.k into a +0 value and that
+ // we then copy that +0 value into a +1 value, before we begin the epilog and
+ // then return that value.
+ // CHECK-LABEL: sil hidden @_T0s15KlassWithBufferC03getC14AsNativeObjectBoyF : $@convention(method) (@guaranteed KlassWithBuffer) -> @owned Builtin.NativeObject {
+ // CHECK: bb0([[SELF:%.*]] : @guaranteed $KlassWithBuffer):
+ // CHECK: [[BUF_BOX:%.*]] = alloc_stack $Buffer
+ // CHECK: [[METHOD:%.*]] = class_method [[SELF]] : $KlassWithBuffer, #KlassWithBuffer.buffer!getter.1
+ // CHECK: [[BUF:%.*]] = apply [[METHOD]]([[SELF]])
+ // CHECK: store [[BUF]] to [init] [[BUF_BOX]]
+ // CHECK: [[GEP:%.*]] = struct_element_addr [[BUF_BOX]] : $*Buffer, #Buffer.k
+ // CHECK: [[BUF_KLASS:%.*]] = load [copy] [[GEP]]
+ // CHECK: destroy_addr [[BUF_BOX]]
+ // CHECK: [[BORROWED_BUF_KLASS:%.*]] = begin_borrow [[BUF_KLASS]]
+ // CHECK: [[CASTED_BORROWED_BUF_KLASS:%.*]] = unchecked_ref_cast [[BORROWED_BUF_KLASS]]
+ // CHECK: [[COPY_CASTED_BORROWED_BUF_KLASS:%.*]] = copy_value [[CASTED_BORROWED_BUF_KLASS]]
+ // CHECK: end_borrow [[BORROWED_BUF_KLASS]]
+ // CHECK: destroy_value [[BUF_KLASS]]
+ // CHECK: return [[COPY_CASTED_BORROWED_BUF_KLASS]]
+ // CHECK: } // end sil function '_T0s15KlassWithBufferC03getC14AsNativeObjectBoyF'
+ func getBufferAsNativeObject() -> Builtin.NativeObject {
+ return Builtin.unsafeCastToNativeObject(buffer.k)
+ }
+}
+
+struct StructContainingBridgeObject {
+ var rawValue: Builtin.BridgeObject
+
+ // CHECK-LABEL: sil hidden @_T0s28StructContainingBridgeObjectVAByXl8swiftObj_tcfC : $@convention(method) (@owned AnyObject, @thin StructContainingBridgeObject.Type) -> @owned StructContainingBridgeObject {
+ // CHECK: bb0([[ARG:%.*]] : @owned $AnyObject,
+ // CHECK: [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
+ // CHECK: [[CASTED_ARG:%.*]] = unchecked_ref_cast [[BORROWED_ARG]] : $AnyObject to $Builtin.BridgeObject
+ // CHECK: [[COPY_CASTED_ARG:%.*]] = copy_value [[CASTED_ARG]]
+ // CHECK: assign [[COPY_CASTED_ARG]] to
+ // CHECK: } // end sil function '_T0s28StructContainingBridgeObjectVAByXl8swiftObj_tcfC'
+ init(swiftObj: AnyObject) {
+ rawValue = Builtin.reinterpretCast(swiftObj)
+ }
+}
diff --git a/validation-test/compiler_crashers_2_fixed/0131-sr6466.swift b/validation-test/compiler_crashers_2_fixed/0131-sr6466.swift
new file mode 100644
index 0000000..68d72ec
--- /dev/null
+++ b/validation-test/compiler_crashers_2_fixed/0131-sr6466.swift
@@ -0,0 +1,28 @@
+// RUN: not %target-swift-frontend %s -typecheck
+
+protocol DC {
+ init()
+}
+
+protocol P {
+ associatedtype A: DC
+
+ func f() -> A
+}
+
+protocol Q: P {
+ associatedtype A
+}
+
+extension Q {
+ func f() -> A { return A() }
+}
+
+struct X<T> { }
+
+extension X: P where T: P {
+ typealias A = T.A
+}
+
+extension X: Q where T: Q {
+}
diff --git a/validation-test/stdlib/Range.swift.gyb b/validation-test/stdlib/Range.swift.gyb
index 529aa2d..8361851 100644
--- a/validation-test/stdlib/Range.swift.gyb
+++ b/validation-test/stdlib/Range.swift.gyb
@@ -768,7 +768,7 @@
typealias Collection = CountableClosedRange<MinimalStrideableValue>
expectCollectionAssociatedTypes(
collectionType: Collection.self,
- iteratorType: ClosedRangeIterator<MinimalStrideableValue>.self,
+ iteratorType: IndexingIterator<Collection>.self,
subSequenceType: RandomAccessSlice<Collection>.self,
indexType: ClosedRangeIndex<MinimalStrideableValue>.self,
indexDistanceType: MinimalStrideableValue.Stride.self,