Skip to content

Commit e043e2b

Browse files
committed
[CSFix] Add a fix to remove invalid optional unwrap
If the base type is not optional, trying to unwrap it is incorrect. Introduce a fix to make it look like base was an optional type which leads solver to move forward towards possible solution.
1 parent 2c5ecb4 commit e043e2b

File tree

3 files changed

+50
-3
lines changed

3 files changed

+50
-3
lines changed

lib/Sema/CSFix.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,3 +213,12 @@ AutoClosureForwarding *AutoClosureForwarding::create(ConstraintSystem &cs,
213213
ConstraintLocator *locator) {
214214
return new (cs.getAllocator()) AutoClosureForwarding(cs, locator);
215215
}
216+
217+
bool RemoveUnwrap::diagnose(Expr *root, bool asNote) const {
218+
return false;
219+
}
220+
221+
RemoveUnwrap *RemoveUnwrap::create(ConstraintSystem &cs, Type baseType,
222+
ConstraintLocator *locator) {
223+
return new (cs.getAllocator()) RemoveUnwrap(cs, baseType, locator);
224+
}

lib/Sema/CSFix.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,9 @@ enum class FixKind : uint8_t {
8989
/// @autoclosure conversions are unsupported starting from
9090
/// Swift version 5.
9191
AutoClosureForwarding,
92+
93+
/// Remove `!` or `?` because base is not an optional type.
94+
RemoveUnwrap,
9295
};
9396

9497
class ConstraintFix {
@@ -408,6 +411,23 @@ class AutoClosureForwarding final : public ConstraintFix {
408411
ConstraintLocator *locator);
409412
};
410413

414+
class RemoveUnwrap final : public ConstraintFix {
415+
Type BaseType;
416+
417+
public:
418+
RemoveUnwrap(ConstraintSystem &cs, Type baseType, ConstraintLocator *locator)
419+
: ConstraintFix(cs, FixKind::RemoveUnwrap, locator), BaseType(baseType) {}
420+
421+
std::string getName() const override {
422+
return "remove unwrap operator `!` or `?`";
423+
}
424+
425+
bool diagnose(Expr *root, bool asNote = false) const override;
426+
427+
static RemoveUnwrap *create(ConstraintSystem &cs, Type baseType,
428+
ConstraintLocator *locator);
429+
};
430+
411431
} // end namespace constraints
412432
} // end namespace swift
413433

lib/Sema/CSSimplify.cpp

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2979,10 +2979,27 @@ ConstraintSystem::simplifyOptionalObjectConstraint(
29792979
return SolutionKind::Unsolved;
29802980
}
29812981

2982-
// If the base type is not optional, the constraint fails.
2982+
29832983
Type objectTy = optTy->getOptionalObjectType();
2984-
if (!objectTy)
2985-
return SolutionKind::Error;
2984+
// If the base type is not optional, let's attempt a fix (if possible)
2985+
// and assume that `!` is just not there.
2986+
if (!objectTy) {
2987+
// Let's see if we can apply a specific fix here.
2988+
if (shouldAttemptFixes()) {
2989+
auto *fix =
2990+
RemoveUnwrap::create(*this, optTy, getConstraintLocator(locator));
2991+
2992+
if (recordFix(fix))
2993+
return SolutionKind::Error;
2994+
2995+
// If the fix was successful let's record
2996+
// "fixed" object type and continue.
2997+
objectTy = optTy;
2998+
} else {
2999+
// If fixes are not allowed, no choice but to fail.
3000+
return SolutionKind::Error;
3001+
}
3002+
}
29863003

29873004
// The object type is an lvalue if the optional was.
29883005
if (optLValueTy->is<LValueType>())
@@ -5427,6 +5444,7 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint(
54275444
case FixKind::RelabelArguments:
54285445
case FixKind::AddConformance:
54295446
case FixKind::AutoClosureForwarding:
5447+
case FixKind::RemoveUnwrap:
54305448
llvm_unreachable("handled elsewhere");
54315449
}
54325450

0 commit comments

Comments
 (0)