Skip to content

Commit 96d7434

Browse files
committed
[Sema] Implement type erasure for dynamic replacement when the
dynamically replaceable function returns an opaque type.
1 parent 9f09add commit 96d7434

File tree

2 files changed

+52
-0
lines changed

2 files changed

+52
-0
lines changed

lib/Sema/CSGen.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3903,6 +3903,38 @@ static bool generateInitPatternConstraints(
39033903
return false;
39043904
}
39053905

3906+
static Expr *eraseTypeForDynamicReplacement(SolutionApplicationTarget target,
3907+
Expr *expr) {
3908+
auto purpose = target.getExprContextualTypePurpose();
3909+
auto *dc = target.getDeclContext();
3910+
auto *decl = dyn_cast_or_null<ValueDecl>(dc->getAsDecl());
3911+
if (!decl)
3912+
return expr;
3913+
3914+
if (!(purpose == CTP_ReturnStmt || purpose == CTP_ReturnSingleExpr) ||
3915+
!(decl->isDynamic() || decl->getDynamicallyReplacedDecl()))
3916+
return expr;
3917+
3918+
auto *opaque =
3919+
target.getExprContextualType()->getAs<OpaqueTypeArchetypeType>();
3920+
if (!opaque)
3921+
return expr;
3922+
3923+
auto protocols = opaque->getConformsTo();
3924+
if (protocols.size() != 1)
3925+
return expr;
3926+
3927+
auto *attr = protocols.front()->getAttrs().getAttribute<TypeEraserAttr>();
3928+
if (!attr)
3929+
return expr;
3930+
3931+
auto typeEraser = attr->getTypeEraserLoc().getType();
3932+
auto &ctx = dc->getASTContext();
3933+
return CallExpr::createImplicit(ctx,
3934+
TypeExpr::createImplicit(typeEraser, ctx),
3935+
{expr}, {ctx.Id_erasing});
3936+
}
3937+
39063938
bool ConstraintSystem::generateConstraints(
39073939
SolutionApplicationTarget &target,
39083940
FreeTypeVariableBinding allowFreeTypeVariables) {
@@ -3919,6 +3951,8 @@ bool ConstraintSystem::generateConstraints(
39193951
target.setExprConversionType(TypeChecker::getOptionalType(expr->getLoc(), var));
39203952
}
39213953

3954+
expr = eraseTypeForDynamicReplacement(target, expr);
3955+
39223956
// Generate constraints for the main system.
39233957
expr = generateConstraints(expr, target.getDeclContext());
39243958
if (!expr)

test/Sema/type_eraser.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// RUN: %target-swift-frontend -typecheck -disable-availability-checking -dump-ast %s | %FileCheck %s
2+
3+
class AnyP: P {
4+
init<T: P>(erasing: T) {}
5+
}
6+
7+
@_typeEraser(AnyP)
8+
protocol P {}
9+
10+
class ConcreteP: P {}
11+
12+
dynamic func opaque() -> some P {
13+
// CHECK: underlying_to_opaque_expr{{.*}}'some P'
14+
// CHECK-NEXT: call_expr implicit type='AnyP'{{.*}}arg_labels=erasing:
15+
// CHECK: call_expr type='ConcreteP'
16+
ConcreteP()
17+
}
18+

0 commit comments

Comments
 (0)