Skip to content

Commit 5190d98

Browse files
authored
Merge pull request swiftlang#77178 from slavapestov/misc-solver-cleanups
Miscellaneous solver cleanups
2 parents c67b0c7 + 8beaa7b commit 5190d98

16 files changed

+332
-425
lines changed

include/swift/AST/ExistentialLayout.h

+13-9
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,11 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212
//
13-
// This file defines the ExistentialLayout struct.
13+
// The ExistentialLayout struct describes the in-memory layout of an existential
14+
// type.
15+
//
16+
// It flattens and canonicalizes protocol compositions, and also expands defaults
17+
// for invertible protocols.
1418
//
1519
//===----------------------------------------------------------------------===//
1620

@@ -33,7 +37,6 @@ struct ExistentialLayout {
3337
hasExplicitAnyObject = false;
3438
containsObjCProtocol = false;
3539
containsSwiftProtocol = false;
36-
containsParameterized = false;
3740
representsAnyObject = false;
3841
}
3942

@@ -53,9 +56,6 @@ struct ExistentialLayout {
5356
/// Whether any protocol members require a witness table.
5457
bool containsSwiftProtocol : 1;
5558

56-
/// Whether any protocol members are parameterized.s
57-
bool containsParameterized : 1;
58-
5959
/// Whether this layout is the canonical layout for plain-old 'AnyObject'.
6060
bool representsAnyObject : 1;
6161

@@ -105,14 +105,18 @@ struct ExistentialLayout {
105105
/// calling this on a temporary is likely to be incorrect.
106106
ArrayRef<ProtocolDecl*> getProtocols() const && = delete;
107107

108+
ArrayRef<ParameterizedProtocolType *> getParameterizedProtocols() const & {
109+
return parameterized;
110+
}
111+
/// The returned ArrayRef points to internal storage, so
112+
/// calling this on a temporary is likely to be incorrect.
113+
ArrayRef<ProtocolDecl*> getParameterizedProtocols() const && = delete;
114+
108115
LayoutConstraint getLayoutConstraint() const;
109116

110117
private:
111118
SmallVector<ProtocolDecl *, 4> protocols;
112-
113-
/// Zero or more primary associated type requirements from a
114-
/// ParameterizedProtocolType
115-
ArrayRef<Type> sameTypeRequirements;
119+
SmallVector<ParameterizedProtocolType *, 4> parameterized;
116120
};
117121

118122
}

include/swift/Sema/Constraint.h

+26-29
Original file line numberDiff line numberDiff line change
@@ -92,14 +92,6 @@ enum class ConstraintKind : char {
9292
LiteralConformsTo,
9393
/// A checked cast from the first type to the second.
9494
CheckedCast,
95-
/// The first type can act as the Self type of the second type (which
96-
/// is a protocol).
97-
///
98-
/// This constraint is slightly looser than a conforms-to constraint, because
99-
/// an existential can be used as the Self of any protocol within the
100-
/// existential, even if it doesn't conform to that protocol (e.g., due to
101-
/// the use of associated types).
102-
SelfObjectOfProtocol,
10395
/// Both types are function types. The first function type's
10496
/// input is the value being passed to the function and its output
10597
/// is a type variable that describes the output. The second
@@ -344,7 +336,10 @@ enum RememberChoice_t : bool {
344336

345337
/// A constraint between two type variables.
346338
class Constraint final : public llvm::ilist_node<Constraint>,
347-
private llvm::TrailingObjects<Constraint, TypeVariableType *> {
339+
private llvm::TrailingObjects<Constraint,
340+
TypeVariableType *,
341+
ConstraintFix *,
342+
OverloadChoice> {
348343
friend TrailingObjects;
349344

350345
/// The kind of constraint.
@@ -353,8 +348,8 @@ class Constraint final : public llvm::ilist_node<Constraint>,
353348
/// The kind of restriction placed on this constraint.
354349
ConversionRestrictionKind Restriction : 8;
355350

356-
/// The fix to be applied to the constraint before visiting it.
357-
ConstraintFix *TheFix = nullptr;
351+
/// Whether we have a fix.
352+
unsigned HasFix : 1;
358353

359354
/// Whether the \c Restriction field is valid.
360355
unsigned HasRestriction : 1;
@@ -438,9 +433,6 @@ class Constraint final : public llvm::ilist_node<Constraint>,
438433
/// The first type
439434
Type First;
440435

441-
/// The overload choice
442-
OverloadChoice Choice;
443-
444436
/// The DC in which the use appears.
445437
DeclContext *UseDC;
446438
} Overload;
@@ -514,6 +506,18 @@ class Constraint final : public llvm::ilist_node<Constraint>,
514506
return { getTrailingObjects<TypeVariableType *>(), NumTypeVariables };
515507
}
516508

509+
size_t numTrailingObjects(OverloadToken<TypeVariableType *>) const {
510+
return NumTypeVariables;
511+
}
512+
513+
size_t numTrailingObjects(OverloadToken<ConstraintFix *>) const {
514+
return HasFix ? 1 : 0;
515+
}
516+
517+
size_t numTrailingObjects(OverloadToken<OverloadChoice>) const {
518+
return Kind == ConstraintKind::BindOverload ? 1 : 0;
519+
}
520+
517521
public:
518522
/// Create a new constraint.
519523
static Constraint *create(ConstraintSystem &cs, ConstraintKind Kind,
@@ -546,10 +550,10 @@ class Constraint final : public llvm::ilist_node<Constraint>,
546550
ValueDecl *requirement, DeclContext *useDC,
547551
FunctionRefKind functionRefKind, ConstraintLocator *locator);
548552

549-
/// Create an overload-binding constraint.
553+
/// Create an overload-binding constraint, possibly with a fix.
550554
static Constraint *createBindOverload(ConstraintSystem &cs, Type type,
551555
OverloadChoice choice,
552-
DeclContext *useDC,
556+
DeclContext *useDC, ConstraintFix *fix,
553557
ConstraintLocator *locator);
554558

555559
/// Create a restricted relational constraint.
@@ -563,13 +567,6 @@ class Constraint final : public llvm::ilist_node<Constraint>,
563567
ConstraintFix *fix, Type first, Type second,
564568
ConstraintLocator *locator);
565569

566-
/// Create a bind overload choice with a fix.
567-
/// Note: This constraint is going to be disabled by default.
568-
static Constraint *createFixedChoice(ConstraintSystem &cs, Type type,
569-
OverloadChoice choice,
570-
DeclContext *useDC, ConstraintFix *fix,
571-
ConstraintLocator *locator);
572-
573570
/// Create a new disjunction constraint.
574571
static Constraint *createDisjunction(ConstraintSystem &cs,
575572
ArrayRef<Constraint *> constraints,
@@ -616,7 +613,11 @@ class Constraint final : public llvm::ilist_node<Constraint>,
616613
}
617614

618615
/// Retrieve the fix associated with this constraint.
619-
ConstraintFix *getFix() const { return TheFix; }
616+
ConstraintFix *getFix() const {
617+
if (HasFix)
618+
return *getTrailingObjects<ConstraintFix *>();
619+
return nullptr;
620+
}
620621

621622
/// Whether this constraint is active, i.e., in the worklist.
622623
bool isActive() const { return IsActive; }
@@ -681,7 +682,6 @@ class Constraint final : public llvm::ilist_node<Constraint>,
681682
case ConstraintKind::LiteralConformsTo:
682683
case ConstraintKind::TransitivelyConformsTo:
683684
case ConstraintKind::CheckedCast:
684-
case ConstraintKind::SelfObjectOfProtocol:
685685
case ConstraintKind::ApplicableFunction:
686686
case ConstraintKind::DynamicCallableApplicableFunction:
687687
case ConstraintKind::BindOverload:
@@ -849,7 +849,7 @@ class Constraint final : public llvm::ilist_node<Constraint>,
849849
/// Retrieve the overload choice for an overload-binding constraint.
850850
OverloadChoice getOverloadChoice() const {
851851
assert(Kind == ConstraintKind::BindOverload);
852-
return Overload.Choice;
852+
return *getTrailingObjects<OverloadChoice>();
853853
}
854854

855855
/// Retrieve the DC in which the overload was used.
@@ -888,9 +888,6 @@ class Constraint final : public llvm::ilist_node<Constraint>,
888888
/// Retrieve the locator for this constraint.
889889
ConstraintLocator *getLocator() const { return Locator; }
890890

891-
/// Clone the given constraint.
892-
Constraint *clone(ConstraintSystem &cs) const;
893-
894891
/// Print constraint placed on type and constraint properties.
895892
///
896893
/// \c skipLocator skips printing of locators.

include/swift/Sema/ConstraintSystem.h

+6-47
Original file line numberDiff line numberDiff line change
@@ -2075,14 +2075,6 @@ struct ClosureIsolatedByPreconcurrency {
20752075
bool operator()(const ClosureExpr *expr) const;
20762076
};
20772077

2078-
/// Determine whether the given expression is part of the left-hand side
2079-
/// of an assignment expression.
2080-
struct IsInLeftHandSideOfAssignment {
2081-
ConstraintSystem &cs;
2082-
2083-
bool operator()(Expr *expr) const;
2084-
};
2085-
20862078
/// Describes the type produced when referencing a declaration.
20872079
struct DeclReferenceType {
20882080
/// The "opened" type, which is the type of the declaration where any
@@ -4374,39 +4366,6 @@ class ConstraintSystem {
43744366
bool wantInterfaceType = false,
43754367
bool adjustForPreconcurrency = true);
43764368

4377-
/// Return the type-of-reference of the given value.
4378-
///
4379-
/// \param baseType if non-null, return the type of a member reference to
4380-
/// this value when the base has the given type
4381-
///
4382-
/// \param UseDC The context of the access. Some variables have different
4383-
/// types depending on where they are used.
4384-
///
4385-
/// \param locator The locator anchored at this value reference, when
4386-
/// it is a member reference.
4387-
///
4388-
/// \param wantInterfaceType Whether we want the interface type, if available.
4389-
///
4390-
/// \param getType Optional callback to extract a type for given declaration.
4391-
static Type
4392-
getUnopenedTypeOfReference(
4393-
VarDecl *value, Type baseType, DeclContext *UseDC,
4394-
llvm::function_ref<Type(VarDecl *)> getType,
4395-
ConstraintLocator *locator,
4396-
bool wantInterfaceType = false,
4397-
bool adjustForPreconcurrency = true,
4398-
llvm::function_ref<Type(const AbstractClosureExpr *)> getClosureType =
4399-
[](const AbstractClosureExpr *) {
4400-
return Type();
4401-
},
4402-
llvm::function_ref<bool(const ClosureExpr *)> isolatedByPreconcurrency =
4403-
[](const ClosureExpr *closure) {
4404-
return closure->isIsolatedByPreconcurrency();
4405-
},
4406-
llvm::function_ref<bool(Expr *)> isAssignTarget = [](Expr *) {
4407-
return false;
4408-
});
4409-
44104369
/// Given the opened type and a pile of information about a member reference,
44114370
/// determine the reference type of the member reference.
44124371
Type getMemberReferenceTypeFromOpenedType(
@@ -4642,7 +4601,7 @@ class ConstraintSystem {
46424601
/// \param getFix Optional callback to determine a fix for a given
46434602
/// choice (first argument is a position of current choice,
46444603
/// second - the choice in question).
4645-
void generateConstraints(
4604+
void generateOverloadConstraints(
46464605
SmallVectorImpl<Constraint *> &constraints, Type type,
46474606
ArrayRef<OverloadChoice> choices, DeclContext *useDC,
46484607
ConstraintLocator *locator,
@@ -4761,10 +4720,10 @@ class ConstraintSystem {
47614720
/// Subroutine of \c matchTypes(), which matches up a value to an
47624721
/// existential type.
47634722
///
4764-
/// \param kind Either ConstraintKind::SelfObjectOfProtocol or
4765-
/// ConstraintKind::ConformsTo. Usually this uses SelfObjectOfProtocol,
4766-
/// but when matching the instance type of a metatype with the instance type
4767-
/// of an existential metatype, since we want an actual conformance check.
4723+
/// \param kind Either ConstraintKind::Subtype or ConstraintKind::ConformsTo.
4724+
/// Usually this uses Subtype, but when matching the instance type of a
4725+
/// metatype with the instance type of an existential metatype, since we
4726+
/// want an actual conformance check.
47684727
TypeMatchResult matchExistentialTypes(Type type1, Type type2,
47694728
ConstraintKind kind,
47704729
TypeMatchOptions flags,
@@ -4971,7 +4930,7 @@ class ConstraintSystem {
49714930
///
49724931
/// \param type The type being tested.
49734932
/// \param protocol The protocol to which the type should conform.
4974-
/// \param kind Either ConstraintKind::SelfObjectOfProtocol or
4933+
/// \param kind Either ConstraintKind::Subtype or
49754934
/// ConstraintKind::ConformsTo.
49764935
/// \param locator Locator describing where this constraint occurred.
49774936
SolutionKind simplifyConformsToConstraint(Type type, ProtocolDecl *protocol,

lib/AST/Type.cpp

+4-7
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,6 @@ ExistentialLayout::ExistentialLayout(CanProtocolType type) {
307307
containsObjCProtocol = protoDecl->isObjC();
308308
containsSwiftProtocol = (!protoDecl->isObjC() &&
309309
!protoDecl->isMarkerProtocol());
310-
containsParameterized = false;
311310
representsAnyObject = false;
312311

313312
protocols.push_back(protoDecl);
@@ -318,7 +317,6 @@ ExistentialLayout::ExistentialLayout(CanProtocolCompositionType type) {
318317
hasExplicitAnyObject = type->hasExplicitAnyObject();
319318
containsObjCProtocol = false;
320319
containsSwiftProtocol = false;
321-
containsParameterized = false;
322320

323321
auto members = type.getMembers();
324322
if (!members.empty() &&
@@ -333,9 +331,9 @@ ExistentialLayout::ExistentialLayout(CanProtocolCompositionType type) {
333331
if (auto protocolType = dyn_cast<ProtocolType>(member)) {
334332
protoDecl = protocolType->getDecl();
335333
} else {
336-
auto parameterized = cast<ParameterizedProtocolType>(member);
337-
protoDecl = parameterized->getProtocol();
338-
containsParameterized = true;
334+
auto *parameterizedType = member->castTo<ParameterizedProtocolType>();
335+
protoDecl = parameterizedType->getProtocol();
336+
parameterized.push_back(parameterizedType);
339337
}
340338
if (protoDecl->isObjC())
341339
containsObjCProtocol = true;
@@ -368,8 +366,7 @@ ExistentialLayout::ExistentialLayout(CanProtocolCompositionType type) {
368366

369367
ExistentialLayout::ExistentialLayout(CanParameterizedProtocolType type)
370368
: ExistentialLayout(type.getBaseType()) {
371-
sameTypeRequirements = type->getArgs();
372-
containsParameterized = true;
369+
parameterized.push_back(type);
373370
}
374371

375372
ExistentialLayout TypeBase::getExistentialLayout() {

lib/IRGen/MetadataRequest.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ static bool usesExtendedExistentialMetadata(CanType type) {
272272
// should turn them into unparameterized protocol types. If the
273273
// structure makes it to IRGen, we have to honor that decision that
274274
// they represent different types.
275-
return layout.containsParameterized;
275+
return !layout.getParameterizedProtocols().empty();
276276
}
277277

278278
static std::optional<std::pair<CanExistentialType, /*depth*/ unsigned>>
@@ -2064,7 +2064,7 @@ namespace {
20642064
llvm::Value *emitExistentialTypeMetadata(CanExistentialType type) {
20652065
auto layout = type.getExistentialLayout();
20662066

2067-
if (layout.containsParameterized) {
2067+
if (!layout.getParameterizedProtocols().empty()) {
20682068
return emitExtendedExistentialTypeMetadata(type);
20692069
}
20702070

lib/Sema/CSBindings.cpp

+1-3
Original file line numberDiff line numberDiff line change
@@ -1873,8 +1873,7 @@ void PotentialBindings::infer(Constraint *constraint) {
18731873
DelayedBy.push_back(constraint);
18741874
break;
18751875

1876-
case ConstraintKind::ConformsTo:
1877-
case ConstraintKind::SelfObjectOfProtocol: {
1876+
case ConstraintKind::ConformsTo: {
18781877
auto protocolTy = constraint->getSecondType();
18791878
if (protocolTy->is<ProtocolType>())
18801879
Protocols.push_back(constraint);
@@ -1985,7 +1984,6 @@ void PotentialBindings::retract(Constraint *constraint) {
19851984

19861985
switch (constraint->getKind()) {
19871986
case ConstraintKind::ConformsTo:
1988-
case ConstraintKind::SelfObjectOfProtocol:
19891987
Protocols.erase(llvm::remove_if(Protocols, isMatchingConstraint),
19901988
Protocols.end());
19911989
break;

0 commit comments

Comments
 (0)