Sema: Don't crash if a property with an opaque result type has both an initial value and a getter

This commit is contained in:
Slava Pestov
2025-09-22 11:03:26 -04:00
parent a4625ba2cb
commit 5cc9b9b237
2 changed files with 20 additions and 17 deletions

View File

@@ -9446,23 +9446,26 @@ applySolutionToInitialization(SyntacticElementTarget target, Expr *initializer,
// If this property has an opaque result type, set the underlying type
// substitutions based on the initializer.
if (auto var = resultTarget.getInitializationPattern()->getSingleVar()) {
SubstitutionMap substitutions;
if (auto opaque = var->getOpaqueResultTypeDecl()) {
resultTarget.getAsExpr()->forEachChildExpr([&](Expr *expr) -> Expr * {
if (auto coercionExpr = dyn_cast<UnderlyingToOpaqueExpr>(expr)) {
auto newSubstitutions =
coercionExpr->substitutions.mapReplacementTypesOutOfContext();
if (substitutions.empty()) {
substitutions = newSubstitutions;
} else {
assert(substitutions.getCanonical() ==
newSubstitutions.getCanonical());
}
}
return expr;
});
if (!var->getParsedAccessor(AccessorKind::Get)) {
if (auto opaque = var->getOpaqueResultTypeDecl()) {
SubstitutionMap substitutions;
opaque->setUniqueUnderlyingTypeSubstitutions(substitutions);
resultTarget.getAsExpr()->forEachChildExpr([&](Expr *expr) -> Expr * {
if (auto coercionExpr = dyn_cast<UnderlyingToOpaqueExpr>(expr)) {
auto newSubstitutions =
coercionExpr->substitutions.mapReplacementTypesOutOfContext();
if (substitutions.empty()) {
substitutions = newSubstitutions;
} else {
assert(substitutions.getCanonical() ==
newSubstitutions.getCanonical());
}
}
return expr;
});
opaque->setUniqueUnderlyingTypeSubstitutions(substitutions);
}
}
}