Skip to content

Commit e2f8d4d

Browse files
authored
Merge pull request #5687 from DougGregor/drop-witness-markers
Drop witness markers for 'uninteresting' dependent types
2 parents 5d7bfc0 + 320e439 commit e2f8d4d

39 files changed

+217
-105
lines changed

lib/AST/ArchetypeBuilder.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2046,6 +2046,15 @@ Type ArchetypeBuilder::substDependentType(Type type) {
20462046
static void collectRequirements(ArchetypeBuilder &builder,
20472047
ArrayRef<GenericTypeParamType *> params,
20482048
SmallVectorImpl<Requirement> &requirements) {
2049+
// Don't emit WitnessMarker requirements for secondary types with
2050+
// no requirements.
2051+
auto dropRedundantWitnessMarker = [&]() {
2052+
if (!requirements.empty() &&
2053+
requirements.back().getKind() == RequirementKind::WitnessMarker &&
2054+
!requirements.back().getFirstType()->is<GenericTypeParamType>())
2055+
requirements.pop_back();
2056+
};
2057+
20492058
builder.enumerateRequirements([&](RequirementKind kind,
20502059
ArchetypeBuilder::PotentialArchetype *archetype,
20512060
llvm::PointerUnion<Type, ArchetypeBuilder::PotentialArchetype *> type,
@@ -2070,6 +2079,7 @@ static void collectRequirements(ArchetypeBuilder &builder,
20702079
return;
20712080

20722081
if (kind == RequirementKind::WitnessMarker) {
2082+
dropRedundantWitnessMarker();
20732083
requirements.push_back(Requirement(kind, depTy, Type()));
20742084
return;
20752085
}
@@ -2089,6 +2099,8 @@ static void collectRequirements(ArchetypeBuilder &builder,
20892099

20902100
requirements.push_back(Requirement(kind, depTy, repTy));
20912101
});
2102+
2103+
dropRedundantWitnessMarker();
20922104
}
20932105

20942106
GenericSignature *ArchetypeBuilder::getGenericSignature() {

lib/AST/ProtocolConformance.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,8 @@ SpecializedProtocolConformance::getTypeWitnessSubstAndDecl(
393393
// Apply the substitution we computed above
394394
auto specializedType
395395
= genericWitness.getReplacement().subst(substitutionMap, None);
396+
if (!specializedType)
397+
specializedType = ErrorType::get(genericWitness.getReplacement());
396398

397399
// If the type witness was unchanged, just copy it directly.
398400
if (specializedType.getPointer() == genericWitness.getReplacement().getPointer()) {

lib/AST/Type.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2810,12 +2810,12 @@ static Type getMemberForBaseType(ConformanceSource conformances,
28102810
}
28112811

28122812
if (!conformance) return failed();
2813+
if (!conformance->isConcrete()) return failed();
28132814

28142815
// If we have an unsatisfied type witness while we're checking the
28152816
// conformances we're supposed to skip this conformance's unsatisfied type
28162817
// witnesses, and we have an unsatisfied type witness, return
28172818
// "missing".
2818-
assert(conformance->isConcrete());
28192819
if (conformance->getConcrete()->getRootNormalConformance()->getState()
28202820
== ProtocolConformanceState::CheckingTypeWitnesses &&
28212821
!conformance->getConcrete()->hasTypeWitness(assocType, nullptr))

lib/SILOptimizer/Utils/Local.cpp

Lines changed: 3 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1332,28 +1332,6 @@ void ValueLifetimeAnalysis::dump() const {
13321332
// Casts Optimization and Simplification
13331333
//===----------------------------------------------------------------------===//
13341334

1335-
/// \brief Get a substitution corresponding to the type witness.
1336-
/// Inspired by ProtocolConformance::getTypeWitnessByName.
1337-
static const Substitution *
1338-
getTypeWitnessByName(ProtocolConformance *conformance, Identifier name) {
1339-
// Find the named requirement.
1340-
AssociatedTypeDecl *assocType = nullptr;
1341-
assert(conformance && "Missing conformance information");
1342-
auto members = conformance->getProtocol()->lookupDirect(name);
1343-
for (auto member : members) {
1344-
assocType = dyn_cast<AssociatedTypeDecl>(member);
1345-
if (assocType)
1346-
break;
1347-
}
1348-
1349-
if (!assocType)
1350-
return nullptr;
1351-
1352-
if (!conformance->hasTypeWitness(assocType, nullptr)) {
1353-
return nullptr;
1354-
}
1355-
return &conformance->getTypeWitness(assocType, nullptr);
1356-
}
13571335

13581336
/// Check if is a bridging cast, i.e. one of the sides is
13591337
/// a bridged type.
@@ -1513,14 +1491,12 @@ optimizeBridgedObjCToSwiftCast(SILInstruction *Inst,
15131491
SmallVector<SILValue, 1> Args;
15141492

15151493
// Add substitutions
1516-
SmallVector<Substitution, 2> Subs;
15171494
auto Conformances =
15181495
M.getASTContext().AllocateUninitialized<ProtocolConformanceRef>(1);
15191496
Conformances[0] = ProtocolConformanceRef(Conformance);
1520-
Subs.push_back(Substitution(Target, Conformances));
1521-
const Substitution *DepTypeSubst = getTypeWitnessByName(
1522-
Conformance, M.getASTContext().getIdentifier("_ObjectiveCType"));
1523-
Subs.push_back(*DepTypeSubst);
1497+
Substitution Subs[1] = {
1498+
Substitution(Target, Conformances)
1499+
};
15241500
auto SILFnTy = FuncRef->getType();
15251501
SILType SubstFnTy = SILFnTy.substGenericArgs(M, Subs);
15261502
SILType ResultTy = SubstFnTy.castTo<SILFunctionType>()->getSILResult();

lib/Sema/CSApply.cpp

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1573,26 +1573,9 @@ namespace {
15731573
auto fnGenericParams
15741574
= fn->getGenericSignatureOfContext()->getGenericParams();
15751575

1576-
SmallVector<Substitution, 2> Subs;
1577-
Substitution sub(valueType, Conformances);
1578-
Subs.push_back(sub);
1579-
1580-
// Add substitution for the dependent type T._ObjectiveCType.
1581-
if (conformsToBridgedToObjectiveC) {
1582-
auto objcTypeId = tc.Context.Id_ObjectiveCType;
1583-
auto objcAssocType = cast<AssociatedTypeDecl>(
1584-
conformance->getProtocol()->lookupDirect(
1585-
objcTypeId).front());
1586-
const Substitution &objcSubst = conformance->getTypeWitness(
1587-
objcAssocType, &tc);
1588-
1589-
// Create a substitution for the dependent type.
1590-
Substitution newDepTypeSubst(
1591-
objcSubst.getReplacement(),
1592-
objcSubst.getConformances());
1593-
1594-
Subs.push_back(newDepTypeSubst);
1595-
}
1576+
Substitution Subs[1] = {
1577+
Substitution(valueType, Conformances)
1578+
};
15961579

15971580
ConcreteDeclRef fnSpecRef(tc.Context, fn, Subs);
15981581
auto fnRef = new (tc.Context) DeclRefExpr(fnSpecRef,

lib/Sema/CSDiag.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5436,7 +5436,9 @@ bool FailureDiagnosis::visitApplyExpr(ApplyExpr *callExpr) {
54365436
if (calleeInfo.closeness == CC_ExactMatch)
54375437
return true;
54385438

5439-
if (!CS->getContextualType() || calleeInfo.closeness != CC_ArgumentMismatch)
5439+
if (!CS->getContextualType() ||
5440+
(calleeInfo.closeness != CC_ArgumentMismatch &&
5441+
calleeInfo.closeness != CC_OneGenericArgumentMismatch))
54405442
return false;
54415443

54425444
CalleeCandidateInfo candidates(fnExpr, hasTrailingClosure, CS);

lib/Sema/CodeSynthesis.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1438,11 +1438,11 @@ void TypeChecker::completePropertyBehaviorParameter(VarDecl *VD,
14381438

14391439
void TypeChecker::completePropertyBehaviorAccessors(VarDecl *VD,
14401440
VarDecl *ValueImpl,
1441+
Type valueTy,
14411442
ArrayRef<Substitution> SelfInterfaceSubs,
14421443
ArrayRef<Substitution> SelfContextSubs) {
14431444
auto selfTy = SelfContextSubs[0].getReplacement();
1444-
auto valueTy = SelfContextSubs[1].getReplacement();
1445-
1445+
14461446
SmallVector<ASTNode, 3> bodyStmts;
14471447

14481448
auto makeSelfExpr = [&](FuncDecl *fromAccessor,

lib/Sema/ConstraintSystem.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2382,7 +2382,7 @@ class ExprCleaner {
23822382
}
23832383

23842384
std::pair<bool, Pattern*> walkToPatternPre(Pattern *P) override {
2385-
TS->Patterns.insert({ P, P->getType() });
2385+
TS->Patterns.insert({ P, P->hasType() ? P->getType() : Type() });
23862386
return { true, P };
23872387
}
23882388

lib/Sema/TypeCheckDecl.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2958,16 +2958,23 @@ static void checkVarBehavior(VarDecl *decl, TypeChecker &TC) {
29582958
TC.Context.AllocateUninitialized<ProtocolConformanceRef>(1);
29592959
auto selfConformance = new ((void*)conformanceMem.data())
29602960
ProtocolConformanceRef(conformance);
2961-
// FIXME: Additional associated types introduced by other requirements?
2962-
Substitution interfaceSubs[] = {
2961+
Substitution allInterfaceSubs[] = {
29632962
Substitution(behaviorInterfaceSelf, *selfConformance),
29642963
Substitution(decl->getInterfaceType(), valueSub.getConformances()),
29652964
};
2966-
Substitution contextSubs[] = {
2965+
Substitution allContextSubs[] = {
29672966
Substitution(behaviorSelf, *selfConformance),
29682967
Substitution(decl->getType(), valueSub.getConformances()),
29692968
};
2970-
2969+
2970+
ArrayRef<Substitution> interfaceSubs = allInterfaceSubs;
2971+
if (interfaceSubs.back().getConformances().empty())
2972+
interfaceSubs = interfaceSubs.drop_back();
2973+
2974+
ArrayRef<Substitution> contextSubs = allContextSubs;
2975+
if (contextSubs.back().getConformances().empty())
2976+
contextSubs = contextSubs.drop_back();
2977+
29712978
// Now that type witnesses are done, satisfy property and method requirements.
29722979
conformance->setState(ProtocolConformanceState::Checking);
29732980

@@ -3185,6 +3192,7 @@ static void checkVarBehavior(VarDecl *decl, TypeChecker &TC) {
31853192
// Synthesize the bodies of the property's accessors now, forwarding to the
31863193
// 'value' implementation.
31873194
TC.completePropertyBehaviorAccessors(decl, behavior->ValueDecl,
3195+
decl->getType(),
31883196
interfaceSubs, contextSubs);
31893197

31903198
return;

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1591,18 +1591,88 @@ namespace {
15911591
/// requirements.
15921592
SmallVector<std::tuple<AssociatedTypeDecl *, Type, CheckTypeWitnessResult>,
15931593
2> NonViable;
1594+
1595+
void dump(llvm::raw_ostream &out, unsigned indent) const {
1596+
out << "\n";
1597+
out.indent(indent) << "(";
1598+
if (Witness) {
1599+
Witness->dumpRef(out);
1600+
}
1601+
1602+
for (const auto &inferred : Inferred) {
1603+
out << "\n";
1604+
out.indent(indent + 2);
1605+
out << inferred.first->getName() << " := "
1606+
<< inferred.second.getString();
1607+
}
1608+
1609+
for (const auto &inferred : NonViable) {
1610+
out << "\n";
1611+
out.indent(indent + 2);
1612+
out << std::get<0>(inferred)->getName() << " := "
1613+
<< std::get<1>(inferred).getString();
1614+
if (auto nominal = std::get<2>(inferred).getProtocolOrClass())
1615+
out << " [failed constraint " << nominal->getName() << "]";
1616+
}
1617+
1618+
out << ")";
1619+
}
1620+
1621+
LLVM_ATTRIBUTE_DEPRECATED(void dump() const,
1622+
"only for use in the debugger");
15941623
};
15951624

1625+
void InferredAssociatedTypesByWitness::dump() const {
1626+
dump(llvm::errs(), 0);
1627+
}
1628+
15961629
/// The set of witnesses that were considered when attempting to
15971630
/// infer associated types.
15981631
typedef SmallVector<InferredAssociatedTypesByWitness, 2>
15991632
InferredAssociatedTypesByWitnesses;
16001633

1634+
void dumpInferredAssociatedTypesByWitnesses(
1635+
const InferredAssociatedTypesByWitnesses &inferred,
1636+
llvm::raw_ostream &out,
1637+
unsigned indent) {
1638+
for (const auto &value : inferred) {
1639+
value.dump(out, indent);
1640+
}
1641+
}
1642+
1643+
void dumpInferredAssociatedTypesByWitnesses(
1644+
const InferredAssociatedTypesByWitnesses &inferred) LLVM_ATTRIBUTE_USED;
1645+
1646+
void dumpInferredAssociatedTypesByWitnesses(
1647+
const InferredAssociatedTypesByWitnesses &inferred) {
1648+
dumpInferredAssociatedTypesByWitnesses(inferred, llvm::errs(), 0);
1649+
}
1650+
16011651
/// A mapping from requirements to the set of matches with witnesses.
16021652
typedef SmallVector<std::pair<ValueDecl *,
16031653
InferredAssociatedTypesByWitnesses>, 4>
16041654
InferredAssociatedTypes;
16051655

1656+
void dumpInferredAssociatedTypes(const InferredAssociatedTypes &inferred,
1657+
llvm::raw_ostream &out,
1658+
unsigned indent) {
1659+
for (const auto &value : inferred) {
1660+
out << "\n";
1661+
out.indent(indent) << "(";
1662+
value.first->dumpRef(out);
1663+
dumpInferredAssociatedTypesByWitnesses(value.second, out, indent + 2);
1664+
out << ")";
1665+
}
1666+
out << "\n";
1667+
}
1668+
1669+
void dumpInferredAssociatedTypes(
1670+
const InferredAssociatedTypes &inferred) LLVM_ATTRIBUTE_USED;
1671+
1672+
void dumpInferredAssociatedTypes(const InferredAssociatedTypes &inferred) {
1673+
dumpInferredAssociatedTypes(inferred, llvm::errs(), 0);
1674+
}
1675+
16061676
/// The protocol conformance checker.
16071677
///
16081678
/// This helper class handles most of the details of checking whether a

lib/Sema/TypeChecker.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1164,6 +1164,7 @@ class TypeChecker final : public LazyResolver {
11641164
/// property.
11651165
void completePropertyBehaviorAccessors(VarDecl *VD,
11661166
VarDecl *ValueImpl,
1167+
Type valueTy,
11671168
ArrayRef<Substitution> SelfInterfaceSubs,
11681169
ArrayRef<Substitution> SelfContextSubs);
11691170

stdlib/public/core/BidirectionalCollection.swift

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,29 @@ public protocol BidirectionalCollection
134134
///
135135
/// - Complexity: O(1)
136136
var last: Iterator.Element? { get }
137+
138+
/// Accesses a contiguous subrange of the collection's elements.
139+
///
140+
/// The accessed slice uses the same indices for the same elements as the
141+
/// original collection uses. Always use the slice's `startIndex` property
142+
/// instead of assuming that its indices start at a particular value.
143+
///
144+
/// This example demonstrates getting a slice of an array of strings, finding
145+
/// the index of one of the strings in the slice, and then using that index
146+
/// in the original array.
147+
///
148+
/// let streets = ["Adams", "Bryant", "Channing", "Douglas", "Evarts"]
149+
/// let streetsSlice = streets[2 ..< streets.endIndex]
150+
/// print(streetsSlice)
151+
/// // Prints "["Channing", "Douglas", "Evarts"]"
152+
///
153+
/// let index = streetsSlice.index(of: "Evarts") // 4
154+
/// print(streets[index!])
155+
/// // Prints "Evarts"
156+
///
157+
/// - Parameter bounds: A range of the collection's indices. The bounds of
158+
/// the range must be valid indices of the collection.
159+
subscript(bounds: Range<Index>) -> SubSequence { get }
137160
}
138161

139162
/// Default implementation for bidirectional collections.

stdlib/public/core/Indices.swift.gyb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,11 @@ public struct ${Self}<
107107
internal var _endIndex: Elements.Index
108108
}
109109

110-
extension ${collectionForTraversal(Traversal)} where Indices == ${Self}<Self> {
110+
extension ${collectionForTraversal(Traversal)}
111+
% if Traversal != 'RandomAccess':
112+
where Indices == ${Self}<Self>
113+
% end
114+
{
111115
/// The indices that are valid for subscripting the collection, in ascending
112116
/// order.
113117
///

stdlib/public/core/RandomAccessCollection.swift

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,29 @@ public protocol RandomAccessCollection :
8181
/// }
8282
/// // c == MyFancyCollection([2, 4, 6, 8, 10])
8383
var indices: Indices { get }
84+
85+
/// Accesses a contiguous subrange of the collection's elements.
86+
///
87+
/// The accessed slice uses the same indices for the same elements as the
88+
/// original collection uses. Always use the slice's `startIndex` property
89+
/// instead of assuming that its indices start at a particular value.
90+
///
91+
/// This example demonstrates getting a slice of an array of strings, finding
92+
/// the index of one of the strings in the slice, and then using that index
93+
/// in the original array.
94+
///
95+
/// let streets = ["Adams", "Bryant", "Channing", "Douglas", "Evarts"]
96+
/// let streetsSlice = streets[2 ..< streets.endIndex]
97+
/// print(streetsSlice)
98+
/// // Prints "["Channing", "Douglas", "Evarts"]"
99+
///
100+
/// let index = streetsSlice.index(of: "Evarts") // 4
101+
/// print(streets[index!])
102+
/// // Prints "Evarts"
103+
///
104+
/// - Parameter bounds: A range of the collection's indices. The bounds of
105+
/// the range must be valid indices of the collection.
106+
subscript(bounds: Range<Index>) -> SubSequence { get }
84107
}
85108

86109
/// Supply the default "slicing" `subscript` for `RandomAccessCollection`

test/Generics/associated_types.swift

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,17 +160,23 @@ protocol A {
160160
}
161161

162162
protocol B : A {
163-
associatedtype e : A = C<Self> // expected-note {{default type 'C<C<a>>' for associated type 'e' (from protocol 'B') does not conform to 'A'}}
163+
associatedtype e : A = C<Self>
164164
}
165165

166166
extension B {
167167
func c() {
168168
}
169169
}
170170

171-
struct C<a : B> : B { // expected-error {{type 'C<a>' does not conform to protocol 'B'}}
171+
struct C<a : B> : B {
172172
}
173173

174+
struct CC : B {
175+
typealias e = CC
176+
}
177+
178+
C<CC>().c()
179+
174180
// SR-511
175181
protocol sr511 {
176182
typealias Foo // expected-error {{typealias is missing an assigned type; use 'associatedtype' to define an associated type requirement}}

0 commit comments

Comments
 (0)