Skip to content

Commit 3d2fd56

Browse files
authored
Merge pull request #36523 from ahoppen/pr/revert-remove-unreachable-code
Revert "Sema: Remove some unreachable code from CSApply"
2 parents 25fdf7e + 180dd2b commit 3d2fd56

File tree

9 files changed

+140
-26
lines changed

9 files changed

+140
-26
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,13 @@ ERROR(cannot_apply_lvalue_binop_to_subelement,none,
225225
ERROR(cannot_apply_lvalue_binop_to_rvalue,none,
226226
"left side of mutating operator has immutable type %0", (Type))
227227

228+
ERROR(cannot_subscript_base,none,
229+
"cannot subscript a value of type %0",
230+
(Type))
231+
232+
ERROR(cannot_subscript_ambiguous_base,none,
233+
"cannot subscript a value of incorrect or ambiguous type", ())
234+
228235
ERROR(cannot_subscript_nil_literal,none,
229236
"cannot subscript a nil literal value", ())
230237
ERROR(conditional_cast_from_nil,none,

include/swift/AST/Expr.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3148,9 +3148,24 @@ class LoadExpr : public ImplicitConversionExpr {
31483148
static bool classof(const Expr *E) { return E->getKind() == ExprKind::Load; }
31493149
};
31503150

3151+
/// This is a conversion from an expression of UnresolvedType to an arbitrary
3152+
/// other type, and from an arbitrary type to UnresolvedType. This node does
3153+
/// not appear in valid code, only in code involving diagnostics.
3154+
class UnresolvedTypeConversionExpr : public ImplicitConversionExpr {
3155+
public:
3156+
UnresolvedTypeConversionExpr(Expr *subExpr, Type type)
3157+
: ImplicitConversionExpr(ExprKind::UnresolvedTypeConversion, subExpr, type) {}
3158+
3159+
static bool classof(const Expr *E) {
3160+
return E->getKind() == ExprKind::UnresolvedTypeConversion;
3161+
}
3162+
};
3163+
31513164
/// FunctionConversionExpr - Convert a function to another function type,
31523165
/// which might involve renaming the parameters or handling substitutions
31533166
/// of subtypes (in the return) or supertypes (in the input).
3167+
///
3168+
/// FIXME: This should be a CapturingExpr.
31543169
class FunctionConversionExpr : public ImplicitConversionExpr {
31553170
public:
31563171
FunctionConversionExpr(Expr *subExpr, Type type)

include/swift/AST/ExprNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ ABSTRACT_EXPR(Apply, Expr)
151151
ABSTRACT_EXPR(ImplicitConversion, Expr)
152152
EXPR(Load, ImplicitConversionExpr)
153153
EXPR(DestructureTuple, ImplicitConversionExpr)
154+
EXPR(UnresolvedTypeConversion, ImplicitConversionExpr)
154155
EXPR(FunctionConversion, ImplicitConversionExpr)
155156
EXPR(CovariantFunctionConversion, ImplicitConversionExpr)
156157
EXPR(CovariantReturnConversion, ImplicitConversionExpr)

lib/AST/ASTDumper.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2270,6 +2270,11 @@ class PrintExpr : public ExprVisitor<PrintExpr> {
22702270
printRec(E->getResultExpr());
22712271
PrintWithColorRAII(OS, ParenthesisColor) << ')';
22722272
}
2273+
void visitUnresolvedTypeConversionExpr(UnresolvedTypeConversionExpr *E) {
2274+
printCommon(E, "unresolvedtype_conversion_expr") << '\n';
2275+
printRec(E->getSubExpr());
2276+
PrintWithColorRAII(OS, ParenthesisColor) << ')';
2277+
}
22732278
void visitFunctionConversionExpr(FunctionConversionExpr *E) {
22742279
printCommon(E, "function_conversion_expr") << '\n';
22752280
printRec(E->getSubExpr());

lib/AST/Expr.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,7 @@ ConcreteDeclRef Expr::getReferencedDecl(bool stopAtParenExpr) const {
338338

339339
PASS_THROUGH_REFERENCE(Load, getSubExpr);
340340
NO_REFERENCE(DestructureTuple);
341+
NO_REFERENCE(UnresolvedTypeConversion);
341342
PASS_THROUGH_REFERENCE(FunctionConversion, getSubExpr);
342343
PASS_THROUGH_REFERENCE(CovariantFunctionConversion, getSubExpr);
343344
PASS_THROUGH_REFERENCE(CovariantReturnConversion, getSubExpr);
@@ -662,6 +663,7 @@ bool Expr::canAppendPostfixExpression(bool appendingPostfixOperator) const {
662663

663664
case ExprKind::Load:
664665
case ExprKind::DestructureTuple:
666+
case ExprKind::UnresolvedTypeConversion:
665667
case ExprKind::FunctionConversion:
666668
case ExprKind::CovariantFunctionConversion:
667669
case ExprKind::CovariantReturnConversion:

lib/SILGen/SILGenExpr.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,8 @@ namespace {
446446
RValue visitConditionalBridgeFromObjCExpr(ConditionalBridgeFromObjCExpr *E,
447447
SGFContext C);
448448
RValue visitArchetypeToSuperExpr(ArchetypeToSuperExpr *E, SGFContext C);
449+
RValue visitUnresolvedTypeConversionExpr(UnresolvedTypeConversionExpr *E,
450+
SGFContext C);
449451
RValue visitFunctionConversionExpr(FunctionConversionExpr *E,
450452
SGFContext C);
451453
RValue visitCovariantFunctionConversionExpr(
@@ -956,6 +958,12 @@ RValue RValueEmitter::visitSuperRefExpr(SuperRefExpr *E, SGFContext C) {
956958
return RValue(SGF, E, result);
957959
}
958960

961+
RValue RValueEmitter::
962+
visitUnresolvedTypeConversionExpr(UnresolvedTypeConversionExpr *E,
963+
SGFContext C) {
964+
llvm_unreachable("invalid code made its way into SILGen");
965+
}
966+
959967
RValue RValueEmitter::visitOtherConstructorDeclRefExpr(
960968
OtherConstructorDeclRefExpr *E, SGFContext C) {
961969
// This should always be a child of an ApplyExpr and so will be emitted by

lib/Sema/CSApply.cpp

Lines changed: 96 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2894,7 +2894,8 @@ namespace {
28942894
auto type = simplifyType(openedType);
28952895
cs.setType(expr, type);
28962896

2897-
assert(!type->is<UnresolvedType>());
2897+
if (type->is<UnresolvedType>())
2898+
return expr;
28982899

28992900
auto &ctx = cs.getASTContext();
29002901

@@ -2917,11 +2918,14 @@ namespace {
29172918
ConcreteDeclRef witness = conformance.getWitnessByName(
29182919
conformingType->getRValueType(), constrName);
29192920

2920-
auto selectedOverload = solution.getOverloadChoice(
2921+
auto selectedOverload = solution.getOverloadChoiceIfAvailable(
29212922
cs.getConstraintLocator(expr, ConstraintLocator::ConstructorMember));
29222923

2924+
if (!selectedOverload)
2925+
return nullptr;
2926+
29232927
auto fnType =
2924-
simplifyType(selectedOverload.openedType)->castTo<FunctionType>();
2928+
simplifyType(selectedOverload->openedType)->castTo<FunctionType>();
29252929

29262930
auto newArg = coerceCallArguments(
29272931
expr->getArg(), fnType, witness,
@@ -3221,8 +3225,18 @@ namespace {
32213225
// Determine the declaration selected for this overloaded reference.
32223226
auto memberLocator = cs.getConstraintLocator(expr,
32233227
ConstraintLocator::Member);
3224-
auto selected = solution.getOverloadChoice(memberLocator);
3228+
auto selectedElt = solution.getOverloadChoiceIfAvailable(memberLocator);
3229+
3230+
if (!selectedElt) {
3231+
// If constraint solving resolved this to an UnresolvedType, then we're
3232+
// in an ambiguity tolerant mode used for diagnostic generation. Just
3233+
// leave this as whatever type of member reference it already is.
3234+
Type resultTy = simplifyType(cs.getType(expr));
3235+
cs.setType(expr, resultTy);
3236+
return expr;
3237+
}
32253238

3239+
auto selected = *selectedElt;
32263240
if (!selected.choice.getBaseType()) {
32273241
// This is one of the "outer alternatives", meaning the innermost
32283242
// methods didn't work out.
@@ -3454,19 +3468,40 @@ namespace {
34543468
Expr *visitSubscriptExpr(SubscriptExpr *expr) {
34553469
auto *memberLocator =
34563470
cs.getConstraintLocator(expr, ConstraintLocator::SubscriptMember);
3457-
auto overload = solution.getOverloadChoice(memberLocator);
3471+
auto overload = solution.getOverloadChoiceIfAvailable(memberLocator);
3472+
3473+
// Handles situation where there was a solution available but it didn't
3474+
// have a proper overload selected from subscript call, might be because
3475+
// solver was allowed to return free or unresolved types, which can
3476+
// happen while running diagnostics on one of the expressions.
3477+
if (!overload) {
3478+
auto *base = expr->getBase();
3479+
auto &de = cs.getASTContext().Diags;
3480+
auto baseType = cs.getType(base);
34583481

3459-
if (overload.choice.getKind() ==
3482+
if (auto errorType = baseType->getAs<ErrorType>()) {
3483+
de.diagnose(base->getLoc(), diag::cannot_subscript_base,
3484+
errorType->getOriginalType())
3485+
.highlight(base->getSourceRange());
3486+
} else {
3487+
de.diagnose(base->getLoc(), diag::cannot_subscript_ambiguous_base)
3488+
.highlight(base->getSourceRange());
3489+
}
3490+
3491+
return nullptr;
3492+
}
3493+
3494+
if (overload->choice.getKind() ==
34603495
OverloadChoiceKind::KeyPathDynamicMemberLookup) {
34613496
return buildDynamicMemberLookupRef(
34623497
expr, expr->getBase(), expr->getIndex()->getStartLoc(), SourceLoc(),
3463-
overload, memberLocator);
3498+
*overload, memberLocator);
34643499
}
34653500

34663501
return buildSubscript(
34673502
expr->getBase(), expr->getIndex(), expr->getArgumentLabels(),
34683503
expr->hasTrailingClosure(), cs.getConstraintLocator(expr),
3469-
expr->isImplicit(), expr->getAccessSemantics(), overload);
3504+
expr->isImplicit(), expr->getAccessSemantics(), *overload);
34703505
}
34713506

34723507
/// "Finish" an array expression by filling in the semantic expression.
@@ -4337,7 +4372,8 @@ namespace {
43374372
expr->getSubPattern()->forEachVariable([](VarDecl *VD) {
43384373
VD->setInvalid();
43394374
});
4340-
if (!SuppressDiagnostics) {
4375+
if (!SuppressDiagnostics
4376+
&& !cs.getType(simplified)->is<UnresolvedType>()) {
43414377
auto &de = cs.getASTContext().Diags;
43424378
de.diagnose(simplified->getLoc(), diag::pattern_in_expr,
43434379
expr->getSubPattern()->getKind());
@@ -4816,12 +4852,18 @@ namespace {
48164852
// If this is an unresolved link, make sure we resolved it.
48174853
if (kind == KeyPathExpr::Component::Kind::UnresolvedProperty ||
48184854
kind == KeyPathExpr::Component::Kind::UnresolvedSubscript) {
4819-
auto foundDecl = solution.getOverloadChoice(locator);
4855+
auto foundDecl = solution.getOverloadChoiceIfAvailable(locator);
4856+
if (!foundDecl) {
4857+
// If we couldn't resolve the component, leave it alone.
4858+
resolvedComponents.push_back(origComponent);
4859+
componentTy = origComponent.getComponentType();
4860+
continue;
4861+
}
48204862

48214863
isDynamicMember =
4822-
foundDecl.choice.getKind() ==
4864+
foundDecl->choice.getKind() ==
48234865
OverloadChoiceKind::DynamicMemberLookup ||
4824-
foundDecl.choice.getKind() ==
4866+
foundDecl->choice.getKind() ==
48254867
OverloadChoiceKind::KeyPathDynamicMemberLookup;
48264868

48274869
// If this was a @dynamicMemberLookup property, then we actually
@@ -4852,9 +4894,11 @@ namespace {
48524894
case KeyPathExpr::Component::Kind::OptionalChain: {
48534895
didOptionalChain = true;
48544896
// Chaining always forces the element to be an rvalue.
4855-
assert(!componentTy->hasUnresolvedType());
48564897
auto objectTy =
48574898
componentTy->getWithoutSpecifierType()->getOptionalObjectType();
4899+
if (componentTy->hasUnresolvedType() && !objectTy) {
4900+
objectTy = componentTy;
4901+
}
48584902
assert(objectTy);
48594903

48604904
auto loc = origComponent.getLoc();
@@ -4906,8 +4950,8 @@ namespace {
49064950
}
49074951

49084952
// Wrap a non-optional result if there was chaining involved.
4909-
assert(!componentTy->hasUnresolvedType());
49104953
if (didOptionalChain && componentTy &&
4954+
!componentTy->hasUnresolvedType() &&
49114955
!componentTy->getWithoutSpecifierType()->isEqual(leafTy)) {
49124956
assert(leafTy->getOptionalObjectType()->isEqual(
49134957
componentTy->getWithoutSpecifierType()));
@@ -4926,8 +4970,8 @@ namespace {
49264970

49274971
// The final component type ought to line up with the leaf type of the
49284972
// key path.
4929-
assert(!componentTy->hasUnresolvedType());
4930-
assert(componentTy->getWithoutSpecifierType()->isEqual(leafTy));
4973+
assert(!componentTy || componentTy->hasUnresolvedType()
4974+
|| componentTy->getWithoutSpecifierType()->isEqual(leafTy));
49314975

49324976
if (!isFunctionType)
49334977
return E;
@@ -5038,13 +5082,18 @@ namespace {
50385082

50395083
// Unwrap the last component type, preserving @lvalue-ness.
50405084
auto optionalTy = components.back().getComponentType();
5041-
assert(!optionalTy->hasUnresolvedType());
50425085
Type objectTy;
50435086
if (auto lvalue = optionalTy->getAs<LValueType>()) {
50445087
objectTy = lvalue->getObjectType()->getOptionalObjectType();
5088+
if (optionalTy->hasUnresolvedType() && !objectTy) {
5089+
objectTy = optionalTy;
5090+
}
50455091
objectTy = LValueType::get(objectTy);
50465092
} else {
50475093
objectTy = optionalTy->getOptionalObjectType();
5094+
if (optionalTy->hasUnresolvedType() && !objectTy) {
5095+
objectTy = optionalTy;
5096+
}
50485097
}
50495098
assert(objectTy);
50505099

@@ -5473,9 +5522,11 @@ Expr *ExprRewriter::coerceExistential(Expr *expr, Type toType) {
54735522
Type toInstanceType = toType;
54745523

54755524
// Look through metatypes
5476-
while (fromInstanceType->is<AnyMetatypeType>() &&
5525+
while ((fromInstanceType->is<UnresolvedType>() ||
5526+
fromInstanceType->is<AnyMetatypeType>()) &&
54775527
toInstanceType->is<ExistentialMetatypeType>()) {
5478-
fromInstanceType = fromInstanceType->castTo<AnyMetatypeType>()->getInstanceType();
5528+
if (!fromInstanceType->is<UnresolvedType>())
5529+
fromInstanceType = fromInstanceType->castTo<AnyMetatypeType>()->getInstanceType();
54795530
toInstanceType = toInstanceType->castTo<ExistentialMetatypeType>()->getInstanceType();
54805531
}
54815532

@@ -5675,6 +5726,11 @@ Expr *ExprRewriter::coerceCallArguments(
56755726
LocatorPathElt::ApplyArgToParam(argIdx, paramIdx, flags));
56765727
};
56775728

5729+
bool matchCanFail =
5730+
llvm::any_of(params, [](const AnyFunctionType::Param &param) {
5731+
return param.getPlainType()->hasUnresolvedType();
5732+
});
5733+
56785734
// Determine whether this application has curried self.
56795735
bool skipCurriedSelf = apply ? hasCurriedSelf(cs, callee, apply) : true;
56805736
// Determine the parameter bindings.
@@ -5732,7 +5788,9 @@ Expr *ExprRewriter::coerceCallArguments(
57325788
args, params, paramInfo, unlabeledTrailingClosureIndex,
57335789
/*allowFixes=*/false, listener, trailingClosureMatching);
57345790

5735-
assert(callArgumentMatch && "Call arguments did not match up?");
5791+
assert((matchCanFail || callArgumentMatch) &&
5792+
"Call arguments did not match up?");
5793+
(void)matchCanFail;
57365794

57375795
auto parameterBindings = std::move(callArgumentMatch->parameterBindings);
57385796

@@ -6469,7 +6527,8 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
64696527
if (knownRestriction != solution.ConstraintRestrictions.end()) {
64706528
switch (knownRestriction->second) {
64716529
case ConversionRestrictionKind::DeepEquality: {
6472-
assert(!toType->hasUnresolvedType());
6530+
if (toType->hasUnresolvedType())
6531+
break;
64736532

64746533
// HACK: Fix problem related to Swift 4 mode (with assertions),
64756534
// since Swift 4 mode allows passing arguments with extra parens
@@ -7030,8 +7089,9 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
70307089
break;
70317090
}
70327091

7033-
assert(!fromType->hasUnresolvedType());
7034-
assert(!toType->hasUnresolvedType());
7092+
// Unresolved types come up in diagnostics for lvalue and inout types.
7093+
if (fromType->hasUnresolvedType() || toType->hasUnresolvedType())
7094+
return cs.cacheType(new (ctx) UnresolvedTypeConversionExpr(expr, toType));
70357095

70367096
// Use an opaque type to abstract a value of the underlying concrete type.
70377097
if (toType->getAs<OpaqueTypeArchetypeType>()) {
@@ -7608,14 +7668,19 @@ Expr *ExprRewriter::finishApply(ApplyExpr *apply, Type openedType,
76087668
// FIXME: handle unwrapping everywhere else
76097669
assert(!unwrapResult);
76107670

7611-
assert(!cs.getType(fn)->is<UnresolvedType>());
7671+
// If this is an UnresolvedType in the system, preserve it.
7672+
if (cs.getType(fn)->is<UnresolvedType>()) {
7673+
cs.setType(apply, cs.getType(fn));
7674+
return apply;
7675+
}
76127676

76137677
// We have a type constructor.
76147678
auto metaTy = cs.getType(fn)->castTo<AnyMetatypeType>();
76157679
auto ty = metaTy->getInstanceType();
76167680

76177681
// If we're "constructing" a tuple type, it's simply a conversion.
76187682
if (auto tupleTy = ty->getAs<TupleType>()) {
7683+
// FIXME: Need an AST to represent this properly.
76197684
return coerceToType(apply->getArg(), tupleTy, locator);
76207685
}
76217686

@@ -7624,14 +7689,19 @@ Expr *ExprRewriter::finishApply(ApplyExpr *apply, Type openedType,
76247689
auto *ctorLocator =
76257690
cs.getConstraintLocator(locator, {ConstraintLocator::ApplyFunction,
76267691
ConstraintLocator::ConstructorMember});
7627-
auto selected = solution.getOverloadChoice(ctorLocator);
7692+
auto selected = solution.getOverloadChoiceIfAvailable(ctorLocator);
7693+
if (!selected) {
7694+
assert(ty->hasError() || ty->hasUnresolvedType());
7695+
cs.setType(apply, ty);
7696+
return apply;
7697+
}
76287698

76297699
assert(ty->getNominalOrBoundGenericNominal() || ty->is<DynamicSelfType>() ||
76307700
ty->isExistentialType() || ty->is<ArchetypeType>());
76317701

76327702
// Consider the constructor decl reference expr 'implicit', but the
76337703
// constructor call expr itself has the apply's 'implicitness'.
7634-
Expr *declRef = buildMemberRef(fn, /*dotLoc=*/SourceLoc(), selected,
7704+
Expr *declRef = buildMemberRef(fn, /*dotLoc=*/SourceLoc(), *selected,
76357705
DeclNameLoc(fn->getEndLoc()), locator,
76367706
ctorLocator, /*implicit=*/true,
76377707
AccessSemantics::Ordinary);
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=COMPLETE
2+
3+
.undefined() #^COMPLETE^#
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=COMPLETE
2+
3+
0odd.foo.bar #^COMPLETE^#

0 commit comments

Comments
 (0)