New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
☣️[Sema] Transform initializers into coercions for conforming numeric literals #15311
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -787,6 +787,10 @@ namespace { | |
/// Simplify a key path expression into a canonical form. | ||
void resolveKeyPathExpr(KeyPathExpr *KPE); | ||
|
||
/// Simplify constructs like `UInt32(1)` into `1 as UInt32` if | ||
/// the type conforms to the expected literal protocol. | ||
Expr *simplifyInitWithLiteral(Expr *E); | ||
|
||
public: | ||
PreCheckExpression(TypeChecker &tc, DeclContext *dc) : TC(tc), DC(dc) { } | ||
|
||
|
@@ -989,6 +993,9 @@ namespace { | |
return KPE; | ||
} | ||
|
||
if (auto *simplified = simplifyInitWithLiteral(expr)) | ||
return simplified; | ||
|
||
return expr; | ||
} | ||
|
||
|
@@ -1547,6 +1554,53 @@ void PreCheckExpression::resolveKeyPathExpr(KeyPathExpr *KPE) { | |
KPE->resolveComponents(TC.Context, components); | ||
} | ||
|
||
Expr *PreCheckExpression::simplifyInitWithLiteral(Expr *E) { | ||
auto *call = dyn_cast<CallExpr>(E); | ||
if (!call || call->getNumArguments() != 1) | ||
return nullptr; | ||
|
||
auto *typeExpr = dyn_cast<TypeExpr>(call->getFn()); | ||
if (!typeExpr) | ||
return nullptr; | ||
|
||
auto *argExpr = call->getArg()->getSemanticsProvidingExpr(); | ||
auto *number = dyn_cast<NumberLiteralExpr>(argExpr); | ||
if (!number) | ||
return nullptr; | ||
|
||
auto *protocol = TC.getLiteralProtocol(number); | ||
if (!protocol) | ||
return nullptr; | ||
|
||
Type type; | ||
if (auto *rep = typeExpr->getTypeRepr()) { | ||
TypeResolutionOptions options; | ||
options |= TypeResolutionFlags::AllowUnboundGenerics; | ||
options |= TypeResolutionFlags::InExpression; | ||
type = TC.resolveType(rep, DC, options); | ||
} else { | ||
type = typeExpr->getTypeLoc().getType(); | ||
} | ||
|
||
if (!type) | ||
return nullptr; | ||
|
||
ConformanceCheckOptions options; | ||
options |= ConformanceCheckFlags::InExpression; | ||
options |= ConformanceCheckFlags::SuppressDependencyTracking; | ||
options |= ConformanceCheckFlags::SkipConditionalRequirements; | ||
|
||
auto result = TC.conformsToProtocol(type, protocol, DC, options); | ||
if (result) { | ||
auto *expr = | ||
new (TC.Context) CoerceExpr(argExpr, {}, typeExpr->getTypeRepr()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We're losing a bunch of the source information in doing this. Should we try to make this a constraint-system change and have CSApply fix up the result, rather than turning it into a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, that's on my agenda to do next. |
||
expr->setImplicit(); | ||
return expr; | ||
} | ||
|
||
return nullptr; | ||
} | ||
|
||
/// \brief Clean up the given ill-formed expression, removing any references | ||
/// to type variables and setting error types on erroneous expression nodes. | ||
void CleanupIllFormedExpressionRAII::doIt(Expr *expr, ASTContext &Context) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this apply to all literal kinds? For example,
Set([1, 2, 3])
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I just tried with
NumberLiteralExpr
because I ran into problem with failable initializer inswiftpm
clashing withExpressibleByStringLiteral
but still wanted to get some performance numbers, andNumberLiteralExpr
since to be the biggest pain point for stdlib folks anyway.