diff --git a/lib/Sema/CSFix.cpp b/lib/Sema/CSFix.cpp index 9cc21f32a4f..0249be20efa 100644 --- a/lib/Sema/CSFix.cpp +++ b/lib/Sema/CSFix.cpp @@ -213,3 +213,12 @@ AutoClosureForwarding *AutoClosureForwarding::create(ConstraintSystem &cs, ConstraintLocator *locator) { return new (cs.getAllocator()) AutoClosureForwarding(cs, locator); } + +bool RemoveUnwrap::diagnose(Expr *root, bool asNote) const { + return false; +} + +RemoveUnwrap *RemoveUnwrap::create(ConstraintSystem &cs, Type baseType, + ConstraintLocator *locator) { + return new (cs.getAllocator()) RemoveUnwrap(cs, baseType, locator); +} diff --git a/lib/Sema/CSFix.h b/lib/Sema/CSFix.h index 3491ccbe19a..c400f134ca6 100644 --- a/lib/Sema/CSFix.h +++ b/lib/Sema/CSFix.h @@ -89,6 +89,9 @@ enum class FixKind : uint8_t { /// @autoclosure conversions are unsupported starting from /// Swift version 5. AutoClosureForwarding, + + /// Remove `!` or `?` because base is not an optional type. + RemoveUnwrap, }; class ConstraintFix { @@ -408,6 +411,23 @@ public: ConstraintLocator *locator); }; +class RemoveUnwrap final : public ConstraintFix { + Type BaseType; + +public: + RemoveUnwrap(ConstraintSystem &cs, Type baseType, ConstraintLocator *locator) + : ConstraintFix(cs, FixKind::RemoveUnwrap, locator), BaseType(baseType) {} + + std::string getName() const override { + return "remove unwrap operator `!` or `?`"; + } + + bool diagnose(Expr *root, bool asNote = false) const override; + + static RemoveUnwrap *create(ConstraintSystem &cs, Type baseType, + ConstraintLocator *locator); +}; + } // end namespace constraints } // end namespace swift diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 4b7c3145b65..61b6fe1b8e7 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -2979,10 +2979,27 @@ ConstraintSystem::simplifyOptionalObjectConstraint( return SolutionKind::Unsolved; } - // If the base type is not optional, the constraint fails. + Type objectTy = optTy->getOptionalObjectType(); - if (!objectTy) - return SolutionKind::Error; + // If the base type is not optional, let's attempt a fix (if possible) + // and assume that `!` is just not there. + if (!objectTy) { + // Let's see if we can apply a specific fix here. + if (shouldAttemptFixes()) { + auto *fix = + RemoveUnwrap::create(*this, optTy, getConstraintLocator(locator)); + + if (recordFix(fix)) + return SolutionKind::Error; + + // If the fix was successful let's record + // "fixed" object type and continue. + objectTy = optTy; + } else { + // If fixes are not allowed, no choice but to fail. + return SolutionKind::Error; + } + } // The object type is an lvalue if the optional was. if (optLValueTy->is()) @@ -5427,6 +5444,7 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint( case FixKind::RelabelArguments: case FixKind::AddConformance: case FixKind::AutoClosureForwarding: + case FixKind::RemoveUnwrap: llvm_unreachable("handled elsewhere"); }