Skip to content

[CS] Define a class for every locator path element kind #27433

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Sep 30, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions lib/Sema/CSDiagnostics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -767,8 +767,8 @@ void GenericArgumentsMismatchFailure::emitNoteForMismatch(int position) {
// to parameter conversions, let's use parameter type as a source of
// generic parameter information.
auto paramSourceTy =
locator->isLastElement(ConstraintLocator::ApplyArgToParam) ? getRequired()
: getActual();
locator->isLastElement<LocatorPathElt::ApplyArgToParam>() ? getRequired()
: getActual();

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

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

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

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

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

if (SynthesizedArgs.size() < 2)
Expand Down
4 changes: 2 additions & 2 deletions lib/Sema/CSSimplify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -995,7 +995,7 @@ ConstraintSystem::TypeMatchResult constraints::matchCallArguments(
auto isSynthesizedArgument = [](const AnyFunctionType::Param &arg) -> bool {
if (auto *typeVar = arg.getPlainType()->getAs<TypeVariableType>()) {
auto *locator = typeVar->getImpl().getLocator();
return locator->isLastElement(ConstraintLocator::SynthesizedArgument);
return locator->isLastElement<LocatorPathElt::SynthesizedArgument>();
}

return false;
Expand Down Expand Up @@ -3233,7 +3233,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
// TODO(diagnostics): Only binding here for function types, because
// doing so for KeyPath types leaves the constraint system in an
// unexpected state for key path diagnostics should we fail.
if (locator->isLastElement(ConstraintLocator::KeyPathType) &&
if (locator->isLastElement<LocatorPathElt::KeyPathType>() &&
type2->is<AnyFunctionType>())
return matchTypesBindTypeVar(typeVar1, type2, kind, flags, locator,
formUnsolvedResult);
Expand Down
24 changes: 10 additions & 14 deletions lib/Sema/ConstraintLocator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,11 @@ void ConstraintLocator::Profile(llvm::FoldingSetNodeID &id, Expr *anchor,
id.AddPointer(elt.castTo<LocatorPathElt::GenericParameter>().getType());
break;

case Requirement:
id.AddPointer(elt.castTo<LocatorPathElt::Requirement>().getDecl());
case ProtocolRequirement: {
auto reqElt = elt.castTo<LocatorPathElt::ProtocolRequirement>();
id.AddPointer(reqElt.getDecl());
break;
}

case Witness:
id.AddPointer(elt.castTo<LocatorPathElt::Witness>().getDecl());
Expand Down Expand Up @@ -175,22 +177,16 @@ bool ConstraintLocator::isForKeyPathComponent() const {
});
}

bool ConstraintLocator::isLastElement(
ConstraintLocator::PathElementKind expectedKind) const {
auto path = getPath();
return !path.empty() && path.back().getKind() == expectedKind;
}

bool ConstraintLocator::isForGenericParameter() const {
return isLastElement(ConstraintLocator::GenericParameter);
return isLastElement<LocatorPathElt::GenericParameter>();
}

bool ConstraintLocator::isForSequenceElementType() const {
return isLastElement(ConstraintLocator::SequenceElementType);
return isLastElement<LocatorPathElt::SequenceElementType>();
}

bool ConstraintLocator::isForContextualType() const {
return isLastElement(ConstraintLocator::ContextualType);
return isLastElement<LocatorPathElt::ContextualType>();
}

GenericTypeParamType *ConstraintLocator::getGenericParameter() const {
Expand Down Expand Up @@ -344,9 +340,9 @@ void ConstraintLocator::dump(SourceManager *sm, raw_ostream &out) {
out << "key path component #" << llvm::utostr(kpElt.getIndex());
break;
}
case Requirement: {
auto reqElt = elt.castTo<LocatorPathElt::Requirement>();
out << "requirement ";
case ProtocolRequirement: {
auto reqElt = elt.castTo<LocatorPathElt::ProtocolRequirement>();
out << "protocol requirement ";
reqElt.getDecl()->dumpRef(out);
break;
}
Expand Down
153 changes: 31 additions & 122 deletions lib/Sema/ConstraintLocator.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,90 +53,9 @@ class ConstraintLocator : public llvm::FoldingSetNode {
/// Describes the kind of a particular path element, e.g.,
/// "tuple element", "call result", "base of member lookup", etc.
enum PathElementKind : unsigned char {
/// The argument of function application.
ApplyArgument,
/// The function being applied.
ApplyFunction,
/// Matching an argument to a parameter.
ApplyArgToParam,
/// A generic parameter being opened.
///
/// Also contains the generic parameter type itself.
GenericParameter,
/// The argument type of a function.
FunctionArgument,
/// The result type of a function.
FunctionResult,
/// A tuple element referenced by position.
TupleElement,
/// A tuple element referenced by name.
NamedTupleElement,
/// An optional payload.
OptionalPayload,
/// A generic argument.
/// FIXME: Add support for named generic arguments?
GenericArgument,
/// A member.
/// FIXME: Do we need the actual member name here?
Member,
/// An unresolved member.
UnresolvedMember,
/// The base of a member expression.
MemberRefBase,
/// The lookup for a subscript member.
SubscriptMember,
/// The lookup for a constructor member.
ConstructorMember,
/// An implicit @lvalue-to-inout conversion; only valid for operator
/// arguments.
LValueConversion,
/// RValue adjustment.
RValueAdjustment,
/// The result of a closure.
ClosureResult,
/// The parent of a nested type.
ParentType,
/// The superclass of a protocol existential type.
ExistentialSuperclassType,
/// The instance of a metatype type.
InstanceType,
/// The element type of a sequence in a for ... in ... loop.
SequenceElementType,
/// An argument passed in an autoclosure parameter
/// position, which must match the autoclosure return type.
AutoclosureResult,
/// The requirement that we're matching during protocol conformance
/// checking.
Requirement,
/// The candidate witness during protocol conformance checking.
Witness,
/// This is referring to a type produced by opening a generic type at the
/// base of the locator.
OpenedGeneric,
/// A component of a key path.
KeyPathComponent,
/// The Nth conditional requirement in the parent locator's conformance.
ConditionalRequirement,
/// A single requirement placed on the type parameters.
TypeParameterRequirement,
/// Locator for a binding from an IUO disjunction choice.
ImplicitlyUnwrappedDisjunctionChoice,
/// A result of an expression involving dynamic lookup.
DynamicLookupResult,
/// The desired contextual type passed in to the constraint system.
ContextualType,
/// The missing argument synthesized by the solver.
SynthesizedArgument,
/// The member looked up via keypath based dynamic lookup.
KeyPathDynamicMember,
/// The type of the key path expression
KeyPathType,
/// The root of a key path
KeyPathRoot,
/// The value of a key path
KeyPathValue,
/// The result type of a key path component. Not used for subscripts.
KeyPathComponentResult,
#define LOCATOR_PATH_ELT(Name) Name,
#define ABSTRACT_LOCATOR_PATH_ELT(Name)
#include "ConstraintLocatorPathElts.def"
};

/// Determine the number of numeric values used for the given path
Expand All @@ -162,7 +81,7 @@ class ConstraintLocator : public llvm::FoldingSetNode {
case ExistentialSuperclassType:
case SequenceElementType:
case AutoclosureResult:
case Requirement:
case ProtocolRequirement:
case Witness:
case ImplicitlyUnwrappedDisjunctionChoice:
case DynamicLookupResult:
Expand Down Expand Up @@ -229,7 +148,7 @@ class ConstraintLocator : public llvm::FoldingSetNode {
case GenericArgument:
case NamedTupleElement:
case TupleElement:
case Requirement:
case ProtocolRequirement:
case Witness:
case KeyPathComponent:
case ConditionalRequirement:
Expand Down Expand Up @@ -260,7 +179,7 @@ class ConstraintLocator : public llvm::FoldingSetNode {
/// Describes the kind of data stored here.
enum StoredKind : unsigned char {
StoredGenericParameter,
StoredRequirement,
StoredProtocolRequirement,
StoredWitness,
StoredGenericSignature,
StoredKeyPathDynamicMemberBase,
Expand Down Expand Up @@ -356,23 +275,8 @@ class ConstraintLocator : public llvm::FoldingSetNode {
friend class ConstraintLocator;

public:
class ApplyArgToParam;
class SynthesizedArgument;
class AnyTupleElement;
class TupleElement;
class NamedTupleElement;
class KeyPathComponent;
class GenericArgument;
class AnyRequirement;
class ConditionalRequirement;
class TypeParameterRequirement;
class ContextualType;
class Witness;
class Requirement;
class GenericParameter;
class OpenedGeneric;
class KeyPathDynamicMember;
class UnresolvedMember;
#define LOCATOR_PATH_ELT(Name) class Name;
#include "ConstraintLocatorPathElts.def"

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

case StoredRequirement:
return PathElementKind::Requirement;
case StoredProtocolRequirement:
return PathElementKind::ProtocolRequirement;

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

/// Check whether the last element in the path of this locator
/// is of a given kind.
bool isLastElement(ConstraintLocator::PathElementKind kind) const;
/// Check whether the last element in the path of this locator (if any)
/// is a given \c LocatorPathElt subclass.
template <class T>
bool isLastElement() const {
auto path = getPath();
return !path.empty() && path.back().is<T>();
}

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

#define SIMPLE_LOCATOR_PATH_ELT(Name) \
class LocatorPathElt:: Name final : public LocatorPathElt { \
public: \
Name () : LocatorPathElt(ConstraintLocator:: Name) {} \
\
static bool classof(const LocatorPathElt *elt) { \
return elt->getKind() == ConstraintLocator:: Name; \
} \
};
#include "ConstraintLocatorPathElts.def"

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

class LocatorPathElt::Requirement final : public LocatorPathElt {
class LocatorPathElt::ProtocolRequirement final : public LocatorPathElt {
public:
Requirement(ValueDecl *decl)
: LocatorPathElt(LocatorPathElt::StoredRequirement, decl) {}
ProtocolRequirement(ValueDecl *decl)
: LocatorPathElt(LocatorPathElt::StoredProtocolRequirement, decl) {}

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

static bool classof(const LocatorPathElt *elt) {
return elt->getKind() == ConstraintLocator::Requirement;
return elt->getKind() == ConstraintLocator::ProtocolRequirement;
}
};

Expand Down Expand Up @@ -928,15 +846,6 @@ class LocatorPathElt::KeyPathDynamicMember final : public LocatorPathElt {
}
};

class LocatorPathElt::UnresolvedMember final : public LocatorPathElt {
public:
UnresolvedMember() : LocatorPathElt(PathElementKind::UnresolvedMember, 0) {}

static bool classof(const LocatorPathElt *elt) {
return elt->getKind() == ConstraintLocator::UnresolvedMember;
}
};

/// A simple stack-only builder object that constructs a
/// constraint locator without allocating memory.
///
Expand Down
Loading