Skip to content

Commit 1509acc

Browse files
authored
[ConstraintSystem] Open only directly declared opaque types related to return statements (swiftlang#38762)
* [ConstraintSystem] NFC: Rename `openOpaqueTypeRec` and make `openOpaqueType` private for individual types * [ConstraintSystem] Require a contextual purpose for `openOpaqueType(Type, ...)` Some of the contexts require special handling e.g. return type of a function can only open directly declared opaque result type(s), this would be implemented in a follow-up commit. * [ConstraintSystem] Open only directly declared opaque types related to return statements Re-establish a check which would only open opaque types directly declared in the return type of a function/accessor declaration, otherwise constraint system would end up with type variables it has no context for if the type had generic parameters. Resolves: rdar://81531010
1 parent b12ab96 commit 1509acc

File tree

6 files changed

+83
-15
lines changed

6 files changed

+83
-15
lines changed

include/swift/Sema/ConstraintSystem.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3855,11 +3855,15 @@ class ConstraintSystem {
38553855
/// \returns The opened type, or \c type if there are no archetypes in it.
38563856
Type openType(Type type, OpenedTypeMap &replacements);
38573857

3858-
/// "Open" an opaque archetype type.
3859-
Type openOpaqueType(Type type, ConstraintLocatorBuilder locator);
3858+
private:
3859+
/// "Open" an opaque archetype type, similar to \c openType.
3860+
Type openOpaqueType(OpaqueTypeArchetypeType *type,
3861+
ConstraintLocatorBuilder locator);
38603862

3863+
public:
38613864
/// Recurse over the given type and open any opaque archetype types.
3862-
Type openOpaqueTypeRec(Type type, ConstraintLocatorBuilder locator);
3865+
Type openOpaqueType(Type type, ContextualTypePurpose context,
3866+
ConstraintLocatorBuilder locator);
38633867

38643868
/// "Open" the given function type.
38653869
///

lib/Sema/BuilderTransform.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1845,7 +1845,8 @@ ConstraintSystem::matchResultBuilder(AnyFunctionRef fn, Type builderType,
18451845

18461846
// Bind the body result type to the type of the transformed expression.
18471847
addConstraint(bodyResultConstraintKind, transformedType,
1848-
openOpaqueTypeRec(bodyResultType, locator), locator);
1848+
openOpaqueType(bodyResultType, CTP_ReturnStmt, locator),
1849+
locator);
18491850
return getTypeMatchSuccess();
18501851
}
18511852

lib/Sema/CSGen.cpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1706,10 +1706,12 @@ namespace {
17061706

17071707
auto locator = CS.getConstraintLocator(expr);
17081708
auto contextualType = CS.getContextualType(expr);
1709+
auto contextualPurpose = CS.getContextualTypePurpose(expr);
17091710

17101711
auto joinElementTypes = [&](Optional<Type> elementType) {
1711-
auto openedElementType = elementType.map(
1712-
[&](Type type) { return CS.openOpaqueTypeRec(type, locator); });
1712+
auto openedElementType = elementType.map([&](Type type) {
1713+
return CS.openOpaqueType(type, contextualPurpose, locator);
1714+
});
17131715

17141716
const auto elements = expr->getElements();
17151717
unsigned index = 0;
@@ -1829,7 +1831,9 @@ namespace {
18291831

18301832
auto locator = CS.getConstraintLocator(expr);
18311833
auto contextualType = CS.getContextualType(expr);
1832-
auto openedType = CS.openOpaqueTypeRec(contextualType, locator);
1834+
auto contextualPurpose = CS.getContextualTypePurpose(expr);
1835+
auto openedType =
1836+
CS.openOpaqueType(contextualType, contextualPurpose, locator);
18331837

18341838
// If a contextual type exists for this expression and is a dictionary
18351839
// type, apply it directly.
@@ -2241,7 +2245,8 @@ namespace {
22412245
type = type->getReferenceStorageReferent();
22422246

22432247
Type replacedType = CS.replaceInferableTypesWithTypeVars(type, locator);
2244-
Type openedType = CS.openOpaqueTypeRec(replacedType, locator);
2248+
Type openedType =
2249+
CS.openOpaqueType(replacedType, CTP_Initialization, locator);
22452250
assert(openedType);
22462251

22472252
auto *subPattern = cast<TypedPattern>(pattern)->getSubPattern();

lib/Sema/CSSimplify.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12006,7 +12006,7 @@ void ConstraintSystem::addContextualConversionConstraint(
1200612006
// Add the constraint.
1200712007
auto *convertTypeLocator =
1200812008
getConstraintLocator(expr, LocatorPathElt::ContextualType(purpose));
12009-
auto openedType = openOpaqueTypeRec(conversionType, convertTypeLocator);
12009+
auto openedType = openOpaqueType(conversionType, purpose, convertTypeLocator);
1201012010
addConstraint(constraintKind, getType(expr), openedType, convertTypeLocator,
1201112011
/*isFavored*/ true);
1201212012
}

lib/Sema/ConstraintSystem.cpp

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -844,9 +844,8 @@ Type ConstraintSystem::openType(Type type, OpenedTypeMap &replacements) {
844844
});
845845
}
846846

847-
Type ConstraintSystem::openOpaqueType(Type type,
847+
Type ConstraintSystem::openOpaqueType(OpaqueTypeArchetypeType *opaque,
848848
ConstraintLocatorBuilder locator) {
849-
auto opaque = type->castTo<OpaqueTypeArchetypeType>();
850849
auto opaqueLocator = locator.withPathElement(
851850
LocatorPathElt::OpenedOpaqueArchetype(opaque->getDecl()));
852851

@@ -868,16 +867,36 @@ Type ConstraintSystem::openOpaqueType(Type type,
868867
return underlyingTyVar;
869868
}
870869

871-
Type ConstraintSystem::openOpaqueTypeRec(Type type,
872-
ConstraintLocatorBuilder locator) {
870+
Type ConstraintSystem::openOpaqueType(Type type, ContextualTypePurpose context,
871+
ConstraintLocatorBuilder locator) {
873872
// Early return if `type` is `NULL` or if there are no opaque archetypes (in
874873
// which case there is certainly nothing for us to do).
875874
if (!type || !type->hasOpaqueArchetype())
876875
return type;
877876

877+
auto inReturnContext = [](ContextualTypePurpose context) {
878+
return context == CTP_ReturnStmt || context == CTP_ReturnSingleExpr;
879+
};
880+
881+
if (!(context == CTP_Initialization || inReturnContext(context)))
882+
return type;
883+
884+
auto shouldOpen = [&](OpaqueTypeArchetypeType *opaqueType) {
885+
if (!inReturnContext(context))
886+
return true;
887+
888+
if (auto *func = dyn_cast<AbstractFunctionDecl>(DC))
889+
return opaqueType->getDecl()->isOpaqueReturnTypeOfFunction(func);
890+
891+
return true;
892+
};
893+
878894
return type.transform([&](Type type) -> Type {
879-
if (type->is<OpaqueTypeArchetypeType>())
880-
return openOpaqueType(type, locator);
895+
auto *opaqueType = type->getAs<OpaqueTypeArchetypeType>();
896+
897+
if (opaqueType && shouldOpen(opaqueType))
898+
return openOpaqueType(opaqueType, locator);
899+
881900
return type;
882901
});
883902
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// RUN: %target-swift-frontend -disable-availability-checking -typecheck -verify %s
2+
3+
// rdar://81531010 - Failure to infer `Context` from contextual return type
4+
5+
protocol View {}
6+
struct EmptyView: View {}
7+
8+
@resultBuilder struct ViewBuilder {
9+
static func buildBlock() -> EmptyView { EmptyView() }
10+
}
11+
12+
struct Data: View {
13+
}
14+
15+
protocol Modifier {
16+
associatedtype Body
17+
associatedtype Content
18+
19+
@ViewBuilder func body(content: Content) -> Body
20+
}
21+
22+
extension View {
23+
func config<S: Modifier>(_: S) -> S.Body where S.Content == Self, S.Body: View {
24+
fatalError()
25+
}
26+
}
27+
28+
struct DataModifier<Content: View> : Modifier {
29+
init(_: Data) {}
30+
func body(content: Content) -> some View {}
31+
}
32+
33+
struct Test {
34+
typealias Value = DataModifier<Data>.Body
35+
36+
func test(data: Data) -> Value {
37+
return data.config(DataModifier(data)) // Ok (Value is not considered an opaque type)
38+
}
39+
}

0 commit comments

Comments
 (0)