Skip to content

Commit 0f30887

Browse files
committed
Sema: Simplify decomposeApply() in TypeCheckEffects.cpp
We don't support multiple parameter lists anymore, and partial applications are always desugared into closure applications in valid code, so there was some unnecessary logic here.
1 parent bbbe082 commit 0f30887

File tree

1 file changed

+53
-93
lines changed

1 file changed

+53
-93
lines changed

lib/Sema/TypeCheckEffects.cpp

Lines changed: 53 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -242,69 +242,51 @@ class AbstractFunction {
242242
ParamDecl *TheParameter;
243243
Expr *TheExpr;
244244
};
245-
unsigned TheKind : 2;
246-
unsigned ParamCount : 2;
245+
Kind TheKind;
247246
PolymorphicEffectKind RethrowingKind;
248247
SubstitutionMap Substitutions;
249248

250249
public:
251250
explicit AbstractFunction(Kind kind, Expr *fn)
252251
: TheKind(kind),
253-
ParamCount(1),
254252
RethrowingKind(PolymorphicEffectKind::None) {
255253
TheExpr = fn;
256254
}
257255

258256
explicit AbstractFunction(AbstractFunctionDecl *fn, SubstitutionMap subs)
259257
: TheKind(Kind::Function),
260-
ParamCount(fn->getNumCurryLevels()),
261258
RethrowingKind(fn->getPolymorphicEffectKind(EffectKind::Throws)),
262259
Substitutions(subs) {
263260
TheFunction = fn;
264261
}
265262

266263
explicit AbstractFunction(AbstractClosureExpr *closure)
267264
: TheKind(Kind::Closure),
268-
ParamCount(1),
269265
RethrowingKind(PolymorphicEffectKind::None) {
270266
TheClosure = closure;
271267
}
272268

273269
explicit AbstractFunction(ParamDecl *parameter)
274270
: TheKind(Kind::Parameter),
275-
ParamCount(1),
276271
RethrowingKind(PolymorphicEffectKind::None) {
277272
TheParameter = parameter;
278273
}
279274

280-
Kind getKind() const { return Kind(TheKind); }
281-
282-
/// Whether the function is marked 'rethrows'.
283-
bool isBodyRethrows() const {
284-
switch (RethrowingKind) {
285-
case PolymorphicEffectKind::None:
286-
case PolymorphicEffectKind::Always:
287-
return false;
288-
289-
case PolymorphicEffectKind::ByClosure:
290-
case PolymorphicEffectKind::ByConformance:
291-
case PolymorphicEffectKind::Invalid:
292-
return true;
293-
}
294-
}
275+
Kind getKind() const { return TheKind; }
295276

296277
PolymorphicEffectKind getRethrowingKind() const {
297278
return RethrowingKind;
298279
}
299280

300-
unsigned getNumArgumentsForFullApply() const {
301-
return ParamCount;
302-
}
303-
304281
Type getType() const {
305282
switch (getKind()) {
306283
case Kind::Opaque: return getOpaqueFunction()->getType();
307-
case Kind::Function: return getFunction()->getInterfaceType();
284+
case Kind::Function: {
285+
auto *AFD = getFunction();
286+
if (AFD->hasImplicitSelfDecl())
287+
return AFD->getMethodInterfaceType();
288+
return AFD->getInterfaceType();
289+
}
308290
case Kind::Closure: return getClosure()->getType();
309291
case Kind::Parameter: return getParameter()->getType();
310292
}
@@ -339,23 +321,20 @@ class AbstractFunction {
339321
}
340322

341323
static AbstractFunction decomposeApply(ApplyExpr *apply,
342-
SmallVectorImpl<SmallVector<Expr *, 2>> &argLists) {
343-
Expr *fn;
344-
do {
345-
auto *argExpr = apply->getArg();
346-
if (auto *tupleExpr = dyn_cast<TupleExpr>(argExpr)) {
347-
auto args = tupleExpr->getElements();
348-
argLists.emplace_back(args.begin(), args.end());
349-
} else if (auto *parenExpr = dyn_cast<ParenExpr>(argExpr)) {
350-
argLists.emplace_back();
351-
argLists.back().push_back(parenExpr->getSubExpr());
352-
} else {
353-
argLists.emplace_back();
354-
argLists.back().push_back(argExpr);
355-
}
324+
SmallVectorImpl<Expr *> &args) {
325+
auto *argExpr = apply->getArg();
326+
if (auto *tupleExpr = dyn_cast<TupleExpr>(argExpr)) {
327+
auto elts = tupleExpr->getElements();
328+
args.append(elts.begin(), elts.end());
329+
} else {
330+
auto *parenExpr = cast<ParenExpr>(argExpr);
331+
args.push_back(parenExpr->getSubExpr());
332+
}
333+
334+
Expr *fn = apply->getFn()->getValueProvidingExpr();
356335

357-
fn = apply->getFn()->getValueProvidingExpr();
358-
} while ((apply = dyn_cast<ApplyExpr>(fn)));
336+
if (auto *selfCall = dyn_cast<SelfApplyExpr>(fn))
337+
fn = selfCall->getFn()->getValueProvidingExpr();
359338

360339
return decomposeFunction(fn);
361340
}
@@ -705,6 +684,9 @@ class ApplyClassifier {
705684

706685
/// Check to see if the given function application throws or is async.
707686
Classification classifyApply(ApplyExpr *E) {
687+
if (isa<SelfApplyExpr>(E))
688+
return Classification();
689+
708690
// An apply expression is a potential throw site if the function throws.
709691
// But if the expression didn't type-check, suppress diagnostics.
710692
if (!E->getType() || E->getType()->hasError())
@@ -716,88 +698,66 @@ class ApplyClassifier {
716698
if (!fnType) return Classification::forInvalidCode();
717699

718700
bool isAsync = fnType->isAsync() || E->implicitlyAsync();
701+
719702
// Decompose the application.
720-
SmallVector<SmallVector<Expr *, 2>, 2> argLists;
721-
auto fnRef = AbstractFunction::decomposeApply(E, argLists);
703+
SmallVector<Expr *, 2> args;
704+
auto fnRef = AbstractFunction::decomposeApply(E, args);
722705

723706
// If any of the arguments didn't type check, fail.
724-
for (auto argList : argLists) {
725-
for (auto *arg : argList) {
726-
if (!arg->getType() || arg->getType()->hasError())
727-
return Classification::forInvalidCode();
728-
}
707+
for (auto *arg : args) {
708+
if (!arg->getType() || arg->getType()->hasError())
709+
return Classification::forInvalidCode();
729710
}
730711

731712
// If the function doesn't throw at all, we're done here.
732713
if (!fnType->isThrowing()) {
733714
return isAsync ? Classification::forAsync() : Classification();
734715
}
735716

736-
// If we're applying more arguments than the natural argument
737-
// count, then this is a call to the opaque value returned from
738-
// the function.
739-
if (argLists.size() != fnRef.getNumArgumentsForFullApply()) {
740-
// Special case: a reference to an operator within a type might be
741-
// missing 'self'.
742-
// FIXME: The issue here is that this is an ill-formed expression, but
743-
// we don't know it from the structure of the expression.
744-
if (argLists.size() == 1 && fnRef.getKind() == AbstractFunction::Function &&
745-
isa<FuncDecl>(fnRef.getFunction()) &&
746-
cast<FuncDecl>(fnRef.getFunction())->isOperator() &&
747-
fnRef.getNumArgumentsForFullApply() == 2 &&
748-
fnRef.getFunction()->getDeclContext()->isTypeContext()) {
749-
// Can only happen with invalid code.
750-
assert(fnRef.getFunction()->getASTContext().Diags.hadAnyError());
751-
return Classification::forInvalidCode();
752-
}
753-
754-
assert(argLists.size() > fnRef.getNumArgumentsForFullApply() &&
755-
"partial application was throwing?");
756-
return Classification::forThrow(PotentialThrowReason::forThrowingApply(),
757-
isAsync);
758-
}
759-
760-
if (fnRef.getRethrowingKind() == PolymorphicEffectKind::ByConformance) {
717+
// Handle rethrowing functions.
718+
switch (fnRef.getRethrowingKind()) {
719+
case PolymorphicEffectKind::ByConformance: {
761720
auto substitutions = fnRef.getSubstitutions();
762721
for (auto conformanceRef : substitutions.getConformances()) {
763722
if (conformanceRef.hasEffect(EffectKind::Throws)) {
764723
return Classification::forRethrowingOnly(
765724
PotentialThrowReason::forRethrowsConformance(E), isAsync);
766725
}
767726
}
727+
728+
// 'ByConformance' is a superset of 'ByClosure', so check for
729+
// closure arguments too.
730+
LLVM_FALLTHROUGH;
768731
}
769732

770-
// If the function's body is 'rethrows' for the number of
771-
// arguments we gave it, apply the rethrows logic.
772-
if (fnRef.isBodyRethrows()) {
733+
case PolymorphicEffectKind::ByClosure: {
773734
// We need to walk the original parameter types in parallel
774735
// because it only counts for 'rethrows' purposes if it lines up
775736
// with a throwing function parameter in the original type.
776-
Type type = fnRef.getType();
777-
if (!type) return Classification::forInvalidCode();
737+
auto *origType = fnRef.getType()->getAs<AnyFunctionType>();
738+
if (!origType)
739+
return Classification::forInvalidCode();
778740

779741
// Use the most significant result from the arguments.
780742
Classification result = isAsync ? Classification::forAsync()
781743
: Classification();
782-
for (auto argList : llvm::reverse(argLists)) {
783-
auto fnType = type->getAs<AnyFunctionType>();
784-
if (!fnType)
785-
return Classification::forInvalidCode();
786-
787-
auto params = fnType->getParams();
788-
if (params.size() != argList.size())
789-
return Classification::forInvalidCode();
790-
791-
for (unsigned i = 0, e = params.size(); i < e; ++i) {
792-
result.merge(classifyRethrowsArgument(argList[i],
793-
params[i].getParameterType()));
794-
}
795744

796-
type = fnType->getResult();
745+
auto params = origType->getParams();
746+
if (params.size() != args.size())
747+
return Classification::forInvalidCode();
748+
749+
for (unsigned i = 0, e = params.size(); i < e; ++i) {
750+
result.merge(classifyRethrowsArgument(args[i],
751+
params[i].getParameterType()));
797752
}
753+
798754
return result;
799755
}
800756

757+
default:
758+
break;
759+
}
760+
801761
// Try to classify the implementation of functions that we have
802762
// local knowledge of.
803763
Classification result =

0 commit comments

Comments
 (0)