Skip to content

Commit 28bd093

Browse files
authored
Merge pull request #27433 from hamishknight/a-touch-of-class
[CS] Define a class for every locator path element kind
2 parents 7b4f4e0 + b6b492d commit 28bd093

File tree

7 files changed

+224
-149
lines changed

7 files changed

+224
-149
lines changed

lib/Sema/CSDiagnostics.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -767,8 +767,8 @@ void GenericArgumentsMismatchFailure::emitNoteForMismatch(int position) {
767767
// to parameter conversions, let's use parameter type as a source of
768768
// generic parameter information.
769769
auto paramSourceTy =
770-
locator->isLastElement(ConstraintLocator::ApplyArgToParam) ? getRequired()
771-
: getActual();
770+
locator->isLastElement<LocatorPathElt::ApplyArgToParam>() ? getRequired()
771+
: getActual();
772772

773773
auto genericTypeDecl = paramSourceTy->getAnyGeneric();
774774
auto param = genericTypeDecl->getGenericParams()->getParams()[position];
@@ -1246,7 +1246,7 @@ bool MissingOptionalUnwrapFailure::diagnoseAsError() {
12461246
// r-value adjustment because base could be an l-value type.
12471247
// We want to fix both cases by only diagnose one of them,
12481248
// otherwise this is just going to result in a duplcate diagnostic.
1249-
if (getLocator()->isLastElement(ConstraintLocator::UnresolvedMember))
1249+
if (getLocator()->isLastElement<LocatorPathElt::UnresolvedMember>())
12501250
return false;
12511251

12521252
if (auto assignExpr = dyn_cast<AssignExpr>(anchor))
@@ -2035,7 +2035,7 @@ bool ContextualFailure::diagnoseConversionToNil() const {
20352035

20362036
Optional<ContextualTypePurpose> CTP;
20372037
// Easy case were failure has been identified as contextual already.
2038-
if (locator->isLastElement(ConstraintLocator::ContextualType)) {
2038+
if (locator->isLastElement<LocatorPathElt::ContextualType>()) {
20392039
CTP = getContextualTypePurpose();
20402040
} else {
20412041
// Here we need to figure out where where `nil` is located.
@@ -3596,7 +3596,7 @@ bool MissingArgumentsFailure::diagnoseAsError() {
35963596
//
35973597
// foo(bar) // `() -> Void` vs. `(Int) -> Void`
35983598
// ```
3599-
if (locator->isLastElement(ConstraintLocator::ApplyArgToParam)) {
3599+
if (locator->isLastElement<LocatorPathElt::ApplyArgToParam>()) {
36003600
auto info = *getFunctionArgApplyInfo(locator);
36013601

36023602
auto *argExpr = info.getArgExpr();
@@ -3612,7 +3612,7 @@ bool MissingArgumentsFailure::diagnoseAsError() {
36123612
// func foo() {}
36133613
// let _: (Int) -> Void = foo
36143614
// ```
3615-
if (locator->isLastElement(ConstraintLocator::ContextualType)) {
3615+
if (locator->isLastElement<LocatorPathElt::ContextualType>()) {
36163616
auto &cs = getConstraintSystem();
36173617
emitDiagnostic(anchor->getLoc(), diag::cannot_convert_initializer_value,
36183618
getType(anchor), resolveType(cs.getContextualType()));
@@ -3885,7 +3885,7 @@ bool MissingArgumentsFailure::diagnoseClosure(ClosureExpr *closure) {
38853885

38863886
bool MissingArgumentsFailure::diagnoseInvalidTupleDestructuring() const {
38873887
auto *locator = getLocator();
3888-
if (!locator->isLastElement(ConstraintLocator::ApplyArgument))
3888+
if (!locator->isLastElement<LocatorPathElt::ApplyArgument>())
38893889
return false;
38903890

38913891
if (SynthesizedArgs.size() < 2)

lib/Sema/CSSimplify.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -995,7 +995,7 @@ ConstraintSystem::TypeMatchResult constraints::matchCallArguments(
995995
auto isSynthesizedArgument = [](const AnyFunctionType::Param &arg) -> bool {
996996
if (auto *typeVar = arg.getPlainType()->getAs<TypeVariableType>()) {
997997
auto *locator = typeVar->getImpl().getLocator();
998-
return locator->isLastElement(ConstraintLocator::SynthesizedArgument);
998+
return locator->isLastElement<LocatorPathElt::SynthesizedArgument>();
999999
}
10001000

10011001
return false;
@@ -3233,7 +3233,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
32333233
// TODO(diagnostics): Only binding here for function types, because
32343234
// doing so for KeyPath types leaves the constraint system in an
32353235
// unexpected state for key path diagnostics should we fail.
3236-
if (locator->isLastElement(ConstraintLocator::KeyPathType) &&
3236+
if (locator->isLastElement<LocatorPathElt::KeyPathType>() &&
32373237
type2->is<AnyFunctionType>())
32383238
return matchTypesBindTypeVar(typeVar1, type2, kind, flags, locator,
32393239
formUnsolvedResult);

lib/Sema/ConstraintLocator.cpp

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,11 @@ void ConstraintLocator::Profile(llvm::FoldingSetNodeID &id, Expr *anchor,
3737
id.AddPointer(elt.castTo<LocatorPathElt::GenericParameter>().getType());
3838
break;
3939

40-
case Requirement:
41-
id.AddPointer(elt.castTo<LocatorPathElt::Requirement>().getDecl());
40+
case ProtocolRequirement: {
41+
auto reqElt = elt.castTo<LocatorPathElt::ProtocolRequirement>();
42+
id.AddPointer(reqElt.getDecl());
4243
break;
44+
}
4345

4446
case Witness:
4547
id.AddPointer(elt.castTo<LocatorPathElt::Witness>().getDecl());
@@ -175,22 +177,16 @@ bool ConstraintLocator::isForKeyPathComponent() const {
175177
});
176178
}
177179

178-
bool ConstraintLocator::isLastElement(
179-
ConstraintLocator::PathElementKind expectedKind) const {
180-
auto path = getPath();
181-
return !path.empty() && path.back().getKind() == expectedKind;
182-
}
183-
184180
bool ConstraintLocator::isForGenericParameter() const {
185-
return isLastElement(ConstraintLocator::GenericParameter);
181+
return isLastElement<LocatorPathElt::GenericParameter>();
186182
}
187183

188184
bool ConstraintLocator::isForSequenceElementType() const {
189-
return isLastElement(ConstraintLocator::SequenceElementType);
185+
return isLastElement<LocatorPathElt::SequenceElementType>();
190186
}
191187

192188
bool ConstraintLocator::isForContextualType() const {
193-
return isLastElement(ConstraintLocator::ContextualType);
189+
return isLastElement<LocatorPathElt::ContextualType>();
194190
}
195191

196192
GenericTypeParamType *ConstraintLocator::getGenericParameter() const {
@@ -344,9 +340,9 @@ void ConstraintLocator::dump(SourceManager *sm, raw_ostream &out) {
344340
out << "key path component #" << llvm::utostr(kpElt.getIndex());
345341
break;
346342
}
347-
case Requirement: {
348-
auto reqElt = elt.castTo<LocatorPathElt::Requirement>();
349-
out << "requirement ";
343+
case ProtocolRequirement: {
344+
auto reqElt = elt.castTo<LocatorPathElt::ProtocolRequirement>();
345+
out << "protocol requirement ";
350346
reqElt.getDecl()->dumpRef(out);
351347
break;
352348
}

lib/Sema/ConstraintLocator.h

Lines changed: 31 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -53,90 +53,9 @@ class ConstraintLocator : public llvm::FoldingSetNode {
5353
/// Describes the kind of a particular path element, e.g.,
5454
/// "tuple element", "call result", "base of member lookup", etc.
5555
enum PathElementKind : unsigned char {
56-
/// The argument of function application.
57-
ApplyArgument,
58-
/// The function being applied.
59-
ApplyFunction,
60-
/// Matching an argument to a parameter.
61-
ApplyArgToParam,
62-
/// A generic parameter being opened.
63-
///
64-
/// Also contains the generic parameter type itself.
65-
GenericParameter,
66-
/// The argument type of a function.
67-
FunctionArgument,
68-
/// The result type of a function.
69-
FunctionResult,
70-
/// A tuple element referenced by position.
71-
TupleElement,
72-
/// A tuple element referenced by name.
73-
NamedTupleElement,
74-
/// An optional payload.
75-
OptionalPayload,
76-
/// A generic argument.
77-
/// FIXME: Add support for named generic arguments?
78-
GenericArgument,
79-
/// A member.
80-
/// FIXME: Do we need the actual member name here?
81-
Member,
82-
/// An unresolved member.
83-
UnresolvedMember,
84-
/// The base of a member expression.
85-
MemberRefBase,
86-
/// The lookup for a subscript member.
87-
SubscriptMember,
88-
/// The lookup for a constructor member.
89-
ConstructorMember,
90-
/// An implicit @lvalue-to-inout conversion; only valid for operator
91-
/// arguments.
92-
LValueConversion,
93-
/// RValue adjustment.
94-
RValueAdjustment,
95-
/// The result of a closure.
96-
ClosureResult,
97-
/// The parent of a nested type.
98-
ParentType,
99-
/// The superclass of a protocol existential type.
100-
ExistentialSuperclassType,
101-
/// The instance of a metatype type.
102-
InstanceType,
103-
/// The element type of a sequence in a for ... in ... loop.
104-
SequenceElementType,
105-
/// An argument passed in an autoclosure parameter
106-
/// position, which must match the autoclosure return type.
107-
AutoclosureResult,
108-
/// The requirement that we're matching during protocol conformance
109-
/// checking.
110-
Requirement,
111-
/// The candidate witness during protocol conformance checking.
112-
Witness,
113-
/// This is referring to a type produced by opening a generic type at the
114-
/// base of the locator.
115-
OpenedGeneric,
116-
/// A component of a key path.
117-
KeyPathComponent,
118-
/// The Nth conditional requirement in the parent locator's conformance.
119-
ConditionalRequirement,
120-
/// A single requirement placed on the type parameters.
121-
TypeParameterRequirement,
122-
/// Locator for a binding from an IUO disjunction choice.
123-
ImplicitlyUnwrappedDisjunctionChoice,
124-
/// A result of an expression involving dynamic lookup.
125-
DynamicLookupResult,
126-
/// The desired contextual type passed in to the constraint system.
127-
ContextualType,
128-
/// The missing argument synthesized by the solver.
129-
SynthesizedArgument,
130-
/// The member looked up via keypath based dynamic lookup.
131-
KeyPathDynamicMember,
132-
/// The type of the key path expression
133-
KeyPathType,
134-
/// The root of a key path
135-
KeyPathRoot,
136-
/// The value of a key path
137-
KeyPathValue,
138-
/// The result type of a key path component. Not used for subscripts.
139-
KeyPathComponentResult,
56+
#define LOCATOR_PATH_ELT(Name) Name,
57+
#define ABSTRACT_LOCATOR_PATH_ELT(Name)
58+
#include "ConstraintLocatorPathElts.def"
14059
};
14160

14261
/// Determine the number of numeric values used for the given path
@@ -162,7 +81,7 @@ class ConstraintLocator : public llvm::FoldingSetNode {
16281
case ExistentialSuperclassType:
16382
case SequenceElementType:
16483
case AutoclosureResult:
165-
case Requirement:
84+
case ProtocolRequirement:
16685
case Witness:
16786
case ImplicitlyUnwrappedDisjunctionChoice:
16887
case DynamicLookupResult:
@@ -229,7 +148,7 @@ class ConstraintLocator : public llvm::FoldingSetNode {
229148
case GenericArgument:
230149
case NamedTupleElement:
231150
case TupleElement:
232-
case Requirement:
151+
case ProtocolRequirement:
233152
case Witness:
234153
case KeyPathComponent:
235154
case ConditionalRequirement:
@@ -260,7 +179,7 @@ class ConstraintLocator : public llvm::FoldingSetNode {
260179
/// Describes the kind of data stored here.
261180
enum StoredKind : unsigned char {
262181
StoredGenericParameter,
263-
StoredRequirement,
182+
StoredProtocolRequirement,
264183
StoredWitness,
265184
StoredGenericSignature,
266185
StoredKeyPathDynamicMemberBase,
@@ -356,23 +275,8 @@ class ConstraintLocator : public llvm::FoldingSetNode {
356275
friend class ConstraintLocator;
357276

358277
public:
359-
class ApplyArgToParam;
360-
class SynthesizedArgument;
361-
class AnyTupleElement;
362-
class TupleElement;
363-
class NamedTupleElement;
364-
class KeyPathComponent;
365-
class GenericArgument;
366-
class AnyRequirement;
367-
class ConditionalRequirement;
368-
class TypeParameterRequirement;
369-
class ContextualType;
370-
class Witness;
371-
class Requirement;
372-
class GenericParameter;
373-
class OpenedGeneric;
374-
class KeyPathDynamicMember;
375-
class UnresolvedMember;
278+
#define LOCATOR_PATH_ELT(Name) class Name;
279+
#include "ConstraintLocatorPathElts.def"
376280

377281
PathElement(PathElementKind kind)
378282
: storage(encodeStorage(kind, 0)), storedKind(StoredKindAndValue)
@@ -387,8 +291,8 @@ class ConstraintLocator : public llvm::FoldingSetNode {
387291
case StoredGenericParameter:
388292
return PathElementKind::GenericParameter;
389293

390-
case StoredRequirement:
391-
return PathElementKind::Requirement;
294+
case StoredProtocolRequirement:
295+
return PathElementKind::ProtocolRequirement;
392296

393297
case StoredWitness:
394298
return PathElementKind::Witness;
@@ -537,9 +441,13 @@ class ConstraintLocator : public llvm::FoldingSetNode {
537441
return path[0].castTo<T>();
538442
}
539443

540-
/// Check whether the last element in the path of this locator
541-
/// is of a given kind.
542-
bool isLastElement(ConstraintLocator::PathElementKind kind) const;
444+
/// Check whether the last element in the path of this locator (if any)
445+
/// is a given \c LocatorPathElt subclass.
446+
template <class T>
447+
bool isLastElement() const {
448+
auto path = getPath();
449+
return !path.empty() && path.back().is<T>();
450+
}
543451

544452
/// Attempts to cast the last path element of the locator to a specific
545453
/// \c LocatorPathElt subclass, returning \c None if either unsuccessful or
@@ -701,6 +609,16 @@ template <class X>
701609
inline typename llvm::cast_retty<X, LocatorPathElt>::ret_type
702610
dyn_cast(const LocatorPathElt &) = delete; // Use LocatorPathElt::getAs instead.
703611

612+
#define SIMPLE_LOCATOR_PATH_ELT(Name) \
613+
class LocatorPathElt:: Name final : public LocatorPathElt { \
614+
public: \
615+
Name () : LocatorPathElt(ConstraintLocator:: Name) {} \
616+
\
617+
static bool classof(const LocatorPathElt *elt) { \
618+
return elt->getKind() == ConstraintLocator:: Name; \
619+
} \
620+
};
621+
#include "ConstraintLocatorPathElts.def"
704622

705623
// The following LocatorPathElt subclasses are used to expose accessors for
706624
// specific path element information. They shouldn't introduce additional
@@ -870,15 +788,15 @@ class LocatorPathElt::Witness final : public LocatorPathElt {
870788
}
871789
};
872790

873-
class LocatorPathElt::Requirement final : public LocatorPathElt {
791+
class LocatorPathElt::ProtocolRequirement final : public LocatorPathElt {
874792
public:
875-
Requirement(ValueDecl *decl)
876-
: LocatorPathElt(LocatorPathElt::StoredRequirement, decl) {}
793+
ProtocolRequirement(ValueDecl *decl)
794+
: LocatorPathElt(LocatorPathElt::StoredProtocolRequirement, decl) {}
877795

878796
ValueDecl *getDecl() const { return getStoredPointer<ValueDecl>(); }
879797

880798
static bool classof(const LocatorPathElt *elt) {
881-
return elt->getKind() == ConstraintLocator::Requirement;
799+
return elt->getKind() == ConstraintLocator::ProtocolRequirement;
882800
}
883801
};
884802

@@ -928,15 +846,6 @@ class LocatorPathElt::KeyPathDynamicMember final : public LocatorPathElt {
928846
}
929847
};
930848

931-
class LocatorPathElt::UnresolvedMember final : public LocatorPathElt {
932-
public:
933-
UnresolvedMember() : LocatorPathElt(PathElementKind::UnresolvedMember, 0) {}
934-
935-
static bool classof(const LocatorPathElt *elt) {
936-
return elt->getKind() == ConstraintLocator::UnresolvedMember;
937-
}
938-
};
939-
940849
/// A simple stack-only builder object that constructs a
941850
/// constraint locator without allocating memory.
942851
///

0 commit comments

Comments
 (0)