Skip to content

Commit 850745a

Browse files
Merge pull request #33680 from AnthonyLatsis/unbound-placeholder
CSGen: Infer generic arguments in typed placeholders
2 parents 43574f7 + 6b1b837 commit 850745a

File tree

2 files changed

+37
-51
lines changed

2 files changed

+37
-51
lines changed

lib/Sema/CSGen.cpp

Lines changed: 33 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1328,17 +1328,11 @@ namespace {
13281328

13291329
Type
13301330
resolveTypeReferenceInExpression(TypeRepr *repr, TypeResolverContext resCtx,
1331-
OpenUnboundGenericTypeFn unboundTyOpener) {
1332-
if (!unboundTyOpener) {
1333-
unboundTyOpener = [](auto unboundTy) {
1334-
// FIXME: Don't let unbound generic types escape type resolution.
1335-
// For now, just return the unbound generic type.
1336-
return unboundTy;
1337-
};
1338-
}
1339-
const auto result =
1340-
TypeResolution::forContextual(CS.DC, resCtx, unboundTyOpener)
1341-
.resolveType(repr);
1331+
const ConstraintLocatorBuilder &locator) {
1332+
// Introduce type variables for unbound generics.
1333+
const auto opener = OpenUnboundGenericType(CS, locator);
1334+
const auto result = TypeResolution::forContextual(CS.DC, resCtx, opener)
1335+
.resolveType(repr);
13421336
if (result->hasError()) {
13431337
return Type();
13441338
}
@@ -1364,8 +1358,7 @@ namespace {
13641358
auto *repr = E->getTypeRepr();
13651359
assert(repr && "Explicit node has no type repr!");
13661360
type = resolveTypeReferenceInExpression(
1367-
repr, TypeResolverContext::InExpression,
1368-
OpenUnboundGenericType(CS, locator));
1361+
repr, TypeResolverContext::InExpression, locator);
13691362
}
13701363

13711364
if (!type || type->hasError()) return Type();
@@ -2067,10 +2060,8 @@ namespace {
20672060
const auto resolvedTy = resolveTypeReferenceInExpression(
20682061
closure->getExplicitResultTypeRepr(),
20692062
TypeResolverContext::InExpression,
2070-
// Introduce type variables for unbound generics.
2071-
OpenUnboundGenericType(
2072-
CS, CS.getConstraintLocator(
2073-
closure, ConstraintLocator::ClosureResult)));
2063+
CS.getConstraintLocator(closure,
2064+
ConstraintLocator::ClosureResult));
20742065
if (resolvedTy)
20752066
return resolvedTy;
20762067
}
@@ -2354,9 +2345,7 @@ namespace {
23542345

23552346
const Type castType = resolveTypeReferenceInExpression(
23562347
isPattern->getCastTypeRepr(), TypeResolverContext::InExpression,
2357-
OpenUnboundGenericType(CS,
2358-
locator.withPathElement(
2359-
LocatorPathElt::PatternMatch(pattern))));
2348+
locator.withPathElement(LocatorPathElt::PatternMatch(pattern)));
23602349
if (!castType) return Type();
23612350

23622351
auto *subPattern = isPattern->getSubPattern();
@@ -2407,32 +2396,31 @@ namespace {
24072396
FunctionRefKind functionRefKind = FunctionRefKind::Compound;
24082397
if (enumPattern->getParentType() || enumPattern->getParentTypeRepr()) {
24092398
// Resolve the parent type.
2410-
Type parentType = [&]() -> Type {
2411-
if (auto preTy = enumPattern->getParentType()) {
2412-
return preTy;
2399+
const auto parentType = [&] {
2400+
auto *const patternMatchLoc = CS.getConstraintLocator(
2401+
locator, {LocatorPathElt::PatternMatch(pattern),
2402+
ConstraintLocator::ParentType});
2403+
2404+
// FIXME: Sometimes the parent type is realized eagerly in
2405+
// ResolvePattern::visitUnresolvedDotExpr, so we have to open it
2406+
// ex post facto. Remove this once we learn how to resolve patterns
2407+
// while generating constraints to keep the opening of generic types
2408+
// contained within the type resolver.
2409+
if (const auto preresolvedTy = enumPattern->getParentType()) {
2410+
const auto openedTy =
2411+
CS.openUnboundGenericTypes(preresolvedTy, patternMatchLoc);
2412+
assert(openedTy);
2413+
return openedTy;
24132414
}
2415+
24142416
return resolveTypeReferenceInExpression(
24152417
enumPattern->getParentTypeRepr(),
2416-
TypeResolverContext::InExpression, [](auto unboundTy) {
2417-
// FIXME: We ought to pass an OpenUnboundGenericType object
2418-
// rather than calling CS.openUnboundGenericType below, but
2419-
// sometimes the parent type is resolved eagerly in
2420-
// ResolvePattern::visitUnresolvedDotExpr, letting unbound
2421-
// generics escape.
2422-
return unboundTy;
2423-
});
2418+
TypeResolverContext::InExpression, patternMatchLoc);
24242419
}();
24252420

24262421
if (!parentType)
24272422
return Type();
24282423

2429-
parentType = CS.openUnboundGenericTypes(
2430-
parentType, CS.getConstraintLocator(
2431-
locator, {LocatorPathElt::PatternMatch(pattern),
2432-
ConstraintLocator::ParentType}));
2433-
2434-
assert(parentType);
2435-
24362424
// Perform member lookup into the parent's metatype.
24372425
Type parentMetaType = MetatypeType::get(parentType);
24382426
CS.addValueMemberConstraint(
@@ -2976,8 +2964,7 @@ namespace {
29762964
// Validate the resulting type.
29772965
const auto toType = resolveTypeReferenceInExpression(
29782966
repr, TypeResolverContext::ExplicitCastExpr,
2979-
// Introduce type variables for unbound generics.
2980-
OpenUnboundGenericType(CS, CS.getConstraintLocator(expr)));
2967+
CS.getConstraintLocator(expr));
29812968
if (!toType)
29822969
return nullptr;
29832970

@@ -3003,8 +2990,7 @@ namespace {
30032990
auto *const repr = expr->getCastTypeRepr();
30042991
const auto toType = resolveTypeReferenceInExpression(
30052992
repr, TypeResolverContext::ExplicitCastExpr,
3006-
// Introduce type variables for unbound generics.
3007-
OpenUnboundGenericType(CS, CS.getConstraintLocator(expr)));
2993+
CS.getConstraintLocator(expr));
30082994
if (!toType)
30092995
return nullptr;
30102996

@@ -3036,8 +3022,7 @@ namespace {
30363022
auto *const repr = expr->getCastTypeRepr();
30373023
const auto toType = resolveTypeReferenceInExpression(
30383024
repr, TypeResolverContext::ExplicitCastExpr,
3039-
// Introduce type variables for unbound generics.
3040-
OpenUnboundGenericType(CS, CS.getConstraintLocator(expr)));
3025+
CS.getConstraintLocator(expr));
30413026
if (!toType)
30423027
return nullptr;
30433028

@@ -3064,8 +3049,7 @@ namespace {
30643049
auto &ctx = CS.getASTContext();
30653050
const auto toType = resolveTypeReferenceInExpression(
30663051
expr->getCastTypeRepr(), TypeResolverContext::ExplicitCastExpr,
3067-
// Introduce type variables for unbound generics.
3068-
OpenUnboundGenericType(CS, CS.getConstraintLocator(expr)));
3052+
CS.getConstraintLocator(expr));
30693053
if (!toType)
30703054
return nullptr;
30713055

@@ -3273,9 +3257,9 @@ namespace {
32733257
Type visitEditorPlaceholderExpr(EditorPlaceholderExpr *E) {
32743258
if (auto *placeholderRepr = E->getPlaceholderTypeRepr()) {
32753259
// Just resolve the referenced type.
3276-
// FIXME: The type reference needs to be opened into context.
32773260
return resolveTypeReferenceInExpression(
3278-
placeholderRepr, TypeResolverContext::InExpression, nullptr);
3261+
placeholderRepr, TypeResolverContext::InExpression,
3262+
CS.getConstraintLocator(E));
32793263
}
32803264

32813265
auto locator = CS.getConstraintLocator(E);
@@ -3346,9 +3330,7 @@ namespace {
33463330
// If a root type was explicitly given, then resolve it now.
33473331
if (auto rootRepr = E->getRootType()) {
33483332
const auto rootObjectTy = resolveTypeReferenceInExpression(
3349-
rootRepr, TypeResolverContext::InExpression,
3350-
// Introduce type variables for unbound generics.
3351-
OpenUnboundGenericType(CS, locator));
3333+
rootRepr, TypeResolverContext::InExpression, locator);
33523334
if (!rootObjectTy || rootObjectTy->hasError())
33533335
return Type();
33543336

test/Sema/editor_placeholders.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
func foo(_ x: Int) -> Int {}
44
func foo(_ x: Float) -> Float {}
5+
func foo<T>(_ t: T) -> T {}
56

67
var v = foo(<#T##x: Float##Float#>) // expected-error {{editor placeholder}}
78
v = "" // expected-error {{cannot assign value of type 'String' to type 'Float'}}
@@ -36,3 +37,6 @@ func test_ambiguity_with_placeholders(pairs: [(rank: Int, count: Int)]) -> Bool
3637
// expected-error@-1 {{editor placeholder in source file}}
3738
// expected-error@-2 {{ambiguous use of 'subscript(_:)'}}
3839
}
40+
41+
let unboundInPlaceholder1: Array<Never> = <#T##Array#> // expected-error{{editor placeholder in source file}}
42+
let unboundInPlaceholder2: Array<Never> = foo(<#T##t: Array##Array<Never>#>) // expected-error{{editor placeholder in source file}}

0 commit comments

Comments
 (0)