Skip to content

Commit f89b981

Browse files
authored
Merge pull request #69950 from slavapestov/clean-up-open-existentials
Cleanups and fixes for opened existentials
2 parents 8167476 + 6fb5b94 commit f89b981

15 files changed

+272
-671
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7364,16 +7364,6 @@ WARNING(backdeployed_opaque_result_not_supported,none,
73647364
// MARK: Implicit opening of existential types
73657365
//------------------------------------------------------------------------------
73667366

7367-
ERROR(result_requires_explicit_coercion,none,
7368-
"inferred result type %0 requires explicit coercion due to "
7369-
"loss of generic requirements",
7370-
(Type))
7371-
7372-
NOTE(candidate_result_requires_explicit_coercion,none,
7373-
"inferred result type %0 requires explicit coercion due to "
7374-
"loss of generic requirements",
7375-
(Type))
7376-
73777367
ERROR(concurrency_task_to_thread_model_custom_executor,none,
73787368
"custom executors are not permitted within %0", (StringRef))
73797369
ERROR(concurrency_task_to_thread_model_async_main,none,

include/swift/AST/GenericSignature.h

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -362,8 +362,6 @@ class alignas(1 << TypeAlignInBits) GenericSignatureImpl final
362362
/// Determine whether the given dependent type is required to be a class.
363363
bool requiresClass(Type type) const;
364364

365-
Type getUpperBound(Type type, bool wantDependentUpperBound = false) const;
366-
367365
/// Determine the superclass bound on the given dependent type.
368366
Type getSuperclassBound(Type type) const;
369367

@@ -457,19 +455,12 @@ class alignas(1 << TypeAlignInBits) GenericSignatureImpl final
457455
/// generic parameter types by their sugared form.
458456
Type getSugaredType(Type type) const;
459457

460-
/// Given a type parameter, compute the most specific supertype (upper bound)
461-
/// that is not dependent on other type parameters.
462-
///
463-
/// \note If the upper bound is a protocol or protocol composition,
464-
/// will return an instance of \c ExistentialType.
465-
Type getNonDependentUpperBounds(Type type) const;
466-
467-
/// Given a type parameter, compute the most specific supertype (upper bound)
468-
/// that is possibly dependent on other type parameters.
458+
/// Given a type parameter, compute the most specific supertype (upper bound),
459+
/// possibly dependent on other type parameters.
469460
///
470461
/// \note If the upper bound is a protocol or protocol composition,
471462
/// will return an instance of \c ExistentialType.
472-
Type getDependentUpperBounds(Type type) const;
463+
Type getUpperBound(Type type) const;
473464

474465
static void Profile(llvm::FoldingSetNodeID &ID,
475466
ArrayRef<GenericTypeParamType *> genericParams,

include/swift/AST/Types.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -757,11 +757,6 @@ class alignas(1 << TypeAlignInBits) TypeBase
757757
/// Retrieve the set of type parameter packs that occur within this type.
758758
void walkPackReferences(llvm::function_ref<bool (Type)> fn);
759759

760-
/// Replace opened archetypes with the given root with their most
761-
/// specific non-dependent upper bounds throughout this type.
762-
Type typeEraseOpenedArchetypesWithRoot(const OpenedArchetypeType *root,
763-
const DeclContext *useDC) const;
764-
765760
/// Given a declaration context, returns a function type with the 'self'
766761
/// type curried as the input if the declaration context describes a type.
767762
/// Otherwise, returns the type itself.

include/swift/Sema/CSFix.h

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -3410,40 +3410,6 @@ class IgnoreDefaultExprTypeMismatch : public AllowArgumentMismatch {
34103410
}
34113411
};
34123412

3413-
class AddExplicitExistentialCoercion final : public ConstraintFix {
3414-
Type ErasedResultType;
3415-
3416-
AddExplicitExistentialCoercion(ConstraintSystem &cs, Type erasedResultTy,
3417-
ConstraintLocator *locator,
3418-
FixBehavior fixBehavior)
3419-
: ConstraintFix(cs, FixKind::AddExplicitExistentialCoercion, locator,
3420-
fixBehavior),
3421-
ErasedResultType(erasedResultTy) {}
3422-
3423-
public:
3424-
std::string getName() const override {
3425-
return "add explicit existential type coercion";
3426-
}
3427-
3428-
bool diagnose(const Solution &solution, bool asNote = false) const override;
3429-
3430-
static bool
3431-
isRequired(ConstraintSystem &cs, Type resultTy,
3432-
ArrayRef<std::pair<TypeVariableType *, OpenedArchetypeType *>>
3433-
openedExistentials,
3434-
ConstraintLocatorBuilder locator);
3435-
3436-
static bool
3437-
isRequired(ConstraintSystem &cs, Type resultTy,
3438-
llvm::function_ref<llvm::Optional<Type>(TypeVariableType *)>
3439-
findExistentialType,
3440-
ConstraintLocatorBuilder locator);
3441-
3442-
static AddExplicitExistentialCoercion *create(ConstraintSystem &cs,
3443-
Type resultTy,
3444-
ConstraintLocator *locator);
3445-
};
3446-
34473413
class RenameConflictingPatternVariables final
34483414
: public ConstraintFix,
34493415
private llvm::TrailingObjects<RenameConflictingPatternVariables,

include/swift/Sema/ConstraintSystem.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5770,12 +5770,19 @@ llvm::Optional<MatchCallArgumentResult> matchCallArguments(
57705770
Expr *getArgumentLabelTargetExpr(Expr *fn);
57715771

57725772
/// Given a type that includes an existential type that has been opened to
5773-
/// the given type variable, type-erase occurrences of that opened type
5774-
/// variable and anything that depends on it to their non-dependent bounds.
5773+
/// the given type variable, replace the opened type variable and its member
5774+
/// types with their upper bounds.
57755775
Type typeEraseOpenedExistentialReference(Type type, Type existentialBaseType,
57765776
TypeVariableType *openedTypeVar,
57775777
TypePosition outermostPosition);
57785778

5779+
5780+
/// Given a type that includes opened existential archetypes derived from
5781+
/// the given generic environment, replace the archetypes with their upper
5782+
/// bounds.
5783+
Type typeEraseOpenedArchetypesWithRoot(Type type,
5784+
const OpenedArchetypeType *root);
5785+
57795786
/// Returns true if a reference to a member on a given base type will apply
57805787
/// its curried self parameter, assuming it has one.
57815788
///

lib/AST/GenericSignature.cpp

Lines changed: 18 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -635,26 +635,23 @@ unsigned GenericSignatureImpl::getGenericParamOrdinal(
635635
return GenericParamKey(param).findIndexIn(getGenericParams());
636636
}
637637

638-
Type GenericSignatureImpl::getNonDependentUpperBounds(Type type) const {
639-
return getUpperBound(type);
640-
}
641-
642-
Type GenericSignatureImpl::getDependentUpperBounds(Type type) const {
643-
return getUpperBound(type, /*wantDependentBound=*/true);
644-
}
645-
646-
Type GenericSignatureImpl::getUpperBound(Type type,
647-
bool wantDependentBound) const {
638+
Type GenericSignatureImpl::getUpperBound(Type type) const {
648639
assert(type->isTypeParameter());
649640

650-
bool hasExplicitAnyObject = requiresClass(type);
651-
652641
llvm::SmallVector<Type, 2> types;
642+
unsigned rootDepth = type->getRootGenericParam()->getDepth();
643+
644+
bool hasExplicitAnyObject = requiresClass(type);
653645

654646
if (Type superclass = getSuperclassBound(type)) {
655647
do {
656648
superclass = getReducedType(superclass);
657-
if (wantDependentBound || !superclass->hasTypeParameter()) {
649+
650+
if (!superclass.findIf([&](Type t) {
651+
if (auto *paramTy = t->getAs<GenericTypeParamType>())
652+
return (paramTy->getDepth() == rootDepth);
653+
return false;
654+
})) {
658655
break;
659656
}
660657
} while ((superclass = superclass->getSuperclass()));
@@ -684,31 +681,13 @@ Type GenericSignatureImpl::getUpperBound(Type type,
684681

685682
// If the reduced type is at a lower depth than the root generic
686683
// parameter of T, then it's constrained.
687-
bool hasOuterGenericParam = false;
688-
bool hasInnerGenericParam = false;
689-
reducedType.visit([&](Type t) {
690-
if (auto *paramTy = t->getAs<GenericTypeParamType>()) {
691-
unsigned rootDepth = type->getRootGenericParam()->getDepth();
692-
if (paramTy->getDepth() == rootDepth)
693-
hasInnerGenericParam = true;
694-
else {
695-
assert(paramTy->getDepth() < rootDepth);
696-
hasOuterGenericParam = true;
697-
}
698-
}
699-
});
700-
701-
if (hasInnerGenericParam && hasOuterGenericParam) {
702-
llvm::errs() << "Weird same-type requirements?\n";
703-
llvm::errs() << "Interface type: " << type << "\n";
704-
llvm::errs() << "Member type: " << memberType << "\n";
705-
llvm::errs() << "Reduced member type: " << reducedType << "\n";
706-
llvm::errs() << GenericSignature(this) << "\n";
707-
abort();
708-
}
709-
710-
if (!hasInnerGenericParam && (wantDependentBound || !hasOuterGenericParam))
684+
if (!reducedType.findIf([&](Type t) {
685+
if (auto *paramTy = t->getAs<GenericTypeParamType>())
686+
return (paramTy->getDepth() == rootDepth);
687+
return false;
688+
})) {
711689
argTypes.push_back(reducedType);
690+
}
712691
}
713692

714693
// If we have constrained all primary associated types, create a
@@ -721,7 +700,8 @@ Type GenericSignatureImpl::getUpperBound(Type type,
721700
//
722701
// In that case just add the base type in the default branch below.
723702
if (argTypes.size() == primaryAssocTypes.size()) {
724-
types.push_back(ParameterizedProtocolType::get(getASTContext(), baseType, argTypes));
703+
types.push_back(ParameterizedProtocolType::get(
704+
getASTContext(), baseType, argTypes));
725705
continue;
726706
}
727707
}

lib/AST/Type.cpp

Lines changed: 1 addition & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -606,83 +606,6 @@ void TypeBase::getRootOpenedExistentials(
606606
});
607607
}
608608

609-
Type TypeBase::typeEraseOpenedArchetypesWithRoot(
610-
const OpenedArchetypeType *root, const DeclContext *useDC) const {
611-
assert(root->isRoot() && "Expected a root archetype");
612-
613-
Type type = Type(const_cast<TypeBase *>(this));
614-
if (!hasOpenedExistential())
615-
return type;
616-
617-
const auto sig = root->getASTContext().getOpenedExistentialSignature(
618-
root->getExistentialType(), useDC->getGenericSignatureOfContext());
619-
620-
unsigned metatypeDepth = 0;
621-
622-
std::function<Type(Type)> transformFn;
623-
transformFn = [&](Type type) -> Type {
624-
return type.transformRec([&](TypeBase *ty) -> llvm::Optional<Type> {
625-
// Don't recurse into children unless we have to.
626-
if (!ty->hasOpenedExistential())
627-
return Type(ty);
628-
629-
if (isa<MetatypeType>(ty)) {
630-
const auto instanceTy = ty->getMetatypeInstanceType();
631-
++metatypeDepth;
632-
const auto erasedTy = transformFn(instanceTy);
633-
--metatypeDepth;
634-
635-
if (instanceTy.getPointer() == erasedTy.getPointer()) {
636-
return Type(ty);
637-
}
638-
639-
return Type(ExistentialMetatypeType::get(erasedTy));
640-
}
641-
642-
// Opaque types whose substitutions involve this type parameter are
643-
// erased to their upper bound.
644-
if (auto opaque = dyn_cast<OpaqueTypeArchetypeType>(ty)) {
645-
for (auto replacementType :
646-
opaque->getSubstitutions().getReplacementTypes()) {
647-
if (replacementType->hasOpenedExistentialWithRoot(root)) {
648-
Type interfaceType = opaque->getInterfaceType();
649-
auto genericSig =
650-
opaque->getDecl()->getOpaqueInterfaceGenericSignature();
651-
return genericSig->getNonDependentUpperBounds(interfaceType);
652-
}
653-
}
654-
}
655-
656-
auto *const archetype = dyn_cast<OpenedArchetypeType>(ty);
657-
if (!archetype) {
658-
// Recurse.
659-
return llvm::None;
660-
}
661-
662-
if (!root->isEqual(archetype->getRoot())) {
663-
return Type(ty);
664-
}
665-
666-
Type erasedTy;
667-
if (root->isEqual(archetype)) {
668-
erasedTy = root->getExistentialType();
669-
} else {
670-
erasedTy =
671-
sig->getNonDependentUpperBounds(archetype->getInterfaceType());
672-
}
673-
674-
if (metatypeDepth) {
675-
if (const auto existential = erasedTy->getAs<ExistentialType>())
676-
return existential->getConstraintType();
677-
}
678-
679-
return erasedTy;
680-
});
681-
};
682-
683-
return transformFn(type);
684-
}
685-
686609
Type TypeBase::addCurriedSelfType(const DeclContext *dc) {
687610
if (!dc->isTypeContext())
688611
return this;
@@ -3681,7 +3604,7 @@ Type ArchetypeType::getExistentialType() const {
36813604
auto interfaceType = getInterfaceType();
36823605
auto genericSig = genericEnv->getGenericSignature();
36833606

3684-
auto upperBound = genericSig->getDependentUpperBounds(interfaceType);
3607+
auto upperBound = genericSig->getUpperBound(interfaceType);
36853608

36863609
return genericEnv->mapTypeIntoContext(upperBound);
36873610
}

lib/Sema/CSApply.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -880,8 +880,8 @@ namespace {
880880
Type resultTy;
881881
resultTy = cs.getType(result);
882882
if (resultTy->hasOpenedExistentialWithRoot(record.Archetype)) {
883-
Type erasedTy = resultTy->typeEraseOpenedArchetypesWithRoot(
884-
record.Archetype, dc);
883+
Type erasedTy = constraints::typeEraseOpenedArchetypesWithRoot(
884+
resultTy, record.Archetype);
885885
auto range = result->getSourceRange();
886886
result = coerceToType(result, erasedTy, locator);
887887
// FIXME: Implement missing tuple-to-tuple conversion
@@ -1590,8 +1590,8 @@ namespace {
15901590
} else {
15911591
// Erase opened existentials from the type of the thunk; we're
15921592
// going to open the existential inside the thunk's body.
1593-
containerTy = containerTy->typeEraseOpenedArchetypesWithRoot(
1594-
knownOpened->second, dc);
1593+
containerTy = constraints::typeEraseOpenedArchetypesWithRoot(
1594+
containerTy, knownOpened->second);
15951595
selfTy = containerTy;
15961596
}
15971597
}
@@ -1673,8 +1673,8 @@ namespace {
16731673
// If the base was an opened existential, erase the opened
16741674
// existential.
16751675
if (openedExistential) {
1676-
refType = refType->typeEraseOpenedArchetypesWithRoot(
1677-
baseTy->castTo<OpenedArchetypeType>(), dc);
1676+
refType = constraints::typeEraseOpenedArchetypesWithRoot(
1677+
refType, baseTy->castTo<OpenedArchetypeType>());
16781678
}
16791679

16801680
return refType;
@@ -1884,8 +1884,8 @@ namespace {
18841884
getConstraintSystem().getConstraintLocator(memberLocator));
18851885
if (knownOpened != solution.OpenedExistentialTypes.end()) {
18861886
curryThunkTy =
1887-
curryThunkTy
1888-
->typeEraseOpenedArchetypesWithRoot(knownOpened->second, dc)
1887+
constraints::typeEraseOpenedArchetypesWithRoot(
1888+
curryThunkTy, knownOpened->second)
18891889
->castTo<FunctionType>();
18901890
}
18911891
}

0 commit comments

Comments
 (0)