Skip to content

Commit 34cc3e8

Browse files
authored
Merge pull request #79406 from hborla/type-eraser-availability
[ConstraintSystem] Always choose an available type eraser type.
2 parents 1458acb + 8f706b8 commit 34cc3e8

File tree

3 files changed

+90
-7
lines changed

3 files changed

+90
-7
lines changed

include/swift/AST/DeclAttr.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ SIMPLE_DECL_ATTR(_inheritsConvenienceInitializers, InheritsConvenienceInitialize
267267
OnClass | UserInaccessible | NotSerialized | APIStableToAdd | ABIStableToAdd | APIBreakingToRemove | ABIBreakingToRemove,
268268
93)
269269
DECL_ATTR(_typeEraser, TypeEraser,
270-
OnProtocol | UserInaccessible | ABIStableToAdd | ABIBreakingToRemove | APIStableToAdd | APIBreakingToRemove,
270+
OnProtocol | UserInaccessible | ABIStableToAdd | ABIBreakingToRemove | APIStableToAdd | APIBreakingToRemove | AllowMultipleAttributes,
271271
94)
272272
SIMPLE_DECL_ATTR(IBSegueAction, IBSegueAction,
273273
OnFunc | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove,

lib/Sema/ConstraintSystem.cpp

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4553,6 +4553,8 @@ Expr *ConstraintSystem::buildAutoClosureExpr(Expr *expr,
45534553
Expr *ConstraintSystem::buildTypeErasedExpr(Expr *expr, DeclContext *dc,
45544554
Type contextualType,
45554555
ContextualTypePurpose purpose) {
4556+
auto &ctx = dc->getASTContext();
4557+
45564558
if (purpose != CTP_ReturnStmt)
45574559
return expr;
45584560

@@ -4571,13 +4573,33 @@ Expr *ConstraintSystem::buildTypeErasedExpr(Expr *expr, DeclContext *dc,
45714573
return expr;
45724574

45734575
auto *PD = protocols.front();
4574-
auto *attr = PD->getAttrs().getAttribute<TypeEraserAttr>();
4575-
if (!attr)
4576+
4577+
auto contextAvailability =
4578+
TypeChecker::availabilityAtLocation(expr->getLoc(), dc);
4579+
auto refinedAvailability =
4580+
AvailabilityContext::forPlatformRange(
4581+
AvailabilityRange::alwaysAvailable(), ctx);
4582+
4583+
// The least available type eraser for the enclosing context.
4584+
Type typeEraser;
4585+
for (auto *attr : PD->getAttrs().getAttributes<TypeEraserAttr>()) {
4586+
auto eraser = attr->getResolvedType(PD);
4587+
assert(eraser && "Failed to resolve eraser type!");
4588+
4589+
auto *nominal = eraser->getAnyNominal();
4590+
auto nominalAvailability =
4591+
TypeChecker::availabilityForDeclSignature(nominal);
4592+
4593+
if (contextAvailability.isContainedIn(nominalAvailability) &&
4594+
nominalAvailability.isContainedIn(refinedAvailability)) {
4595+
refinedAvailability = nominalAvailability;
4596+
typeEraser = eraser;
4597+
}
4598+
}
4599+
4600+
if (!typeEraser)
45764601
return expr;
45774602

4578-
auto typeEraser = attr->getResolvedType(PD);
4579-
assert(typeEraser && "Failed to resolve eraser type!");
4580-
auto &ctx = dc->getASTContext();
45814603
auto *argList = ArgumentList::forImplicitSingle(ctx, ctx.Id_erasing, expr);
45824604
return CallExpr::createImplicit(
45834605
ctx, TypeExpr::createImplicit(typeEraser, ctx), argList);

test/Sema/type_eraser.swift

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1-
// RUN: %target-swift-frontend -typecheck -disable-availability-checking -dump-ast %s | %FileCheck %s
1+
// RUN: %target-swift-frontend -target %target-cpu-apple-macosx10.15 -typecheck -dump-ast %s | %FileCheck %s
2+
3+
// REQUIRES: OS=macosx
24

35
class AnyP: P {
46
init<T: P>(erasing: T) {}
57
}
68

79
@_typeEraser(AnyP)
10+
@_typeEraser(NewAnyP)
811
protocol P {}
912

1013
struct ConcreteP: P, Hashable {}
@@ -119,3 +122,61 @@ extension DynamicReplacement {
119122
return ConcreteP()
120123
}
121124
}
125+
126+
@available(macOS 100, *)
127+
struct NewAnyP: P {
128+
init(erasing: some P) {}
129+
}
130+
131+
@available(macOS 100, *)
132+
struct NewConcreteP: P {}
133+
134+
// CHECK-LABEL: var_decl{{.*}}x0
135+
dynamic var x0: some P {
136+
// CHECK: return_stmt
137+
// CHECK-NEXT: underlying_to_opaque_expr implicit type="some P"
138+
// CHECK-NEXT: call_expr implicit type="AnyP"
139+
ConcreteP()
140+
}
141+
142+
// CHECK-LABEL: var_decl{{.*}}x1
143+
@available(macOS 99, *)
144+
dynamic var x1: some P {
145+
// CHECK: return_stmt
146+
// CHECK-NEXT: underlying_to_opaque_expr implicit type="some P"
147+
// CHECK-NEXT: call_expr implicit type="AnyP"
148+
ConcreteP()
149+
}
150+
151+
// CHECK-LABEL: var_decl{{.*}}x2
152+
@available(macOS 100, *)
153+
dynamic var x2: some P {
154+
// CHECK: return_stmt
155+
// CHECK-NEXT: underlying_to_opaque_expr implicit type="some P"
156+
// CHECK-NEXT: call_expr implicit type="NewAnyP"
157+
ConcreteP()
158+
}
159+
160+
// CHECK-LABEL: var_decl{{.*}}x3
161+
@available(macOS 101, *)
162+
dynamic var x3: some P {
163+
// CHECK: return_stmt
164+
// CHECK-NEXT: underlying_to_opaque_expr implicit type="some P"
165+
// CHECK-NEXT: call_expr implicit type="NewAnyP"
166+
ConcreteP()
167+
}
168+
169+
// CHECK-LABEL: var_decl{{.*}}x4
170+
dynamic var x4: some P {
171+
if #available(macOS 101, *) {
172+
// CHECK: return_stmt
173+
// CHECK-NEXT: underlying_to_opaque_expr implicit type="some P"
174+
// CHECK-NEXT: call_expr implicit type="NewAnyP"
175+
return NewConcreteP()
176+
} else {
177+
// CHECK: return_stmt
178+
// CHECK-NEXT: underlying_to_opaque_expr implicit type="some P"
179+
// CHECK-NEXT: call_expr implicit type="AnyP"
180+
return ConcreteP()
181+
}
182+
}

0 commit comments

Comments
 (0)