Skip to content

Commit 5f2dde4

Browse files
authored
Merge pull request #28370 from xedin/rethink-force-optional-fix
[ConstraintSystem] Make `ForceOptional` fix a part of `repairFailures`
2 parents c70f924 + 1459974 commit 5f2dde4

File tree

10 files changed

+249
-149
lines changed

10 files changed

+249
-149
lines changed

lib/Sema/CSDiagnostics.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1216,6 +1216,11 @@ bool MissingOptionalUnwrapFailure::diagnoseAsError() {
12161216
if (hasComplexLocator())
12171217
return false;
12181218

1219+
if (!getUnwrappedType()->isBool()) {
1220+
if (diagnoseConversionToBool())
1221+
return true;
1222+
}
1223+
12191224
auto *anchor = getAnchor();
12201225

12211226
// If this is an unresolved member expr e.g. `.foo` its

lib/Sema/CSDiagnostics.h

Lines changed: 26 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -631,35 +631,6 @@ class MemberAccessOnOptionalBaseFailure final : public FailureDiagnostic {
631631
bool diagnoseAsError() override;
632632
};
633633

634-
/// Diagnose failures related to use of the unwrapped optional types,
635-
/// which require some type of force-unwrap e.g. "!" or "try!".
636-
class MissingOptionalUnwrapFailure final : public FailureDiagnostic {
637-
Type BaseType;
638-
Type UnwrappedType;
639-
640-
public:
641-
MissingOptionalUnwrapFailure(ConstraintSystem &cs, Type baseType,
642-
Type unwrappedType, ConstraintLocator *locator)
643-
: FailureDiagnostic(cs, locator), BaseType(baseType),
644-
UnwrappedType(unwrappedType) {}
645-
646-
bool diagnoseAsError() override;
647-
648-
private:
649-
Type getBaseType() const {
650-
return resolveType(BaseType, /*reconstituteSugar=*/true);
651-
}
652-
653-
Type getUnwrappedType() const {
654-
return resolveType(UnwrappedType, /*reconstituteSugar=*/true);
655-
}
656-
657-
/// Suggest a default value via `?? <default value>`
658-
void offerDefaultValueUnwrapFixIt(DeclContext *DC, Expr *expr) const;
659-
/// Suggest a force optional unwrap via `!`
660-
void offerForceUnwrapFixIt(Expr *expr) const;
661-
};
662-
663634
/// Diagnose errors associated with rvalues in positions
664635
/// where an lvalue is required, such as inout arguments.
665636
class RValueTreatedAsLValueFailure final : public FailureDiagnostic {
@@ -852,6 +823,32 @@ class ContextualFailure : public FailureDiagnostic {
852823
getDiagnosticFor(ContextualTypePurpose context, bool forProtocol);
853824
};
854825

826+
/// Diagnose failures related to use of the unwrapped optional types,
827+
/// which require some type of force-unwrap e.g. "!" or "try!".
828+
class MissingOptionalUnwrapFailure final : public ContextualFailure {
829+
public:
830+
MissingOptionalUnwrapFailure(ConstraintSystem &cs, Type fromType, Type toType,
831+
ConstraintLocator *locator)
832+
: ContextualFailure(cs, fromType, toType, locator) {}
833+
834+
bool diagnoseAsError() override;
835+
836+
private:
837+
Type getBaseType() const {
838+
return resolveType(getFromType(), /*reconstituteSugar=*/true);
839+
}
840+
841+
Type getUnwrappedType() const {
842+
return resolveType(getBaseType()->getOptionalObjectType(),
843+
/*reconstituteSugar=*/true);
844+
}
845+
846+
/// Suggest a default value via `?? <default value>`
847+
void offerDefaultValueUnwrapFixIt(DeclContext *DC, Expr *expr) const;
848+
/// Suggest a force optional unwrap via `!`
849+
void offerForceUnwrapFixIt(Expr *expr) const;
850+
};
851+
855852
/// Diagnostics for mismatched generic arguments e.g
856853
/// ```swift
857854
/// struct F<G> {}

lib/Sema/CSFix.cpp

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -69,16 +69,14 @@ ForceDowncast *ForceDowncast::create(ConstraintSystem &cs, Type fromType,
6969
}
7070

7171
bool ForceOptional::diagnose(bool asNote) const {
72-
MissingOptionalUnwrapFailure failure(getConstraintSystem(), BaseType,
73-
UnwrappedType, getLocator());
72+
MissingOptionalUnwrapFailure failure(getConstraintSystem(), getFromType(),
73+
getToType(), getLocator());
7474
return failure.diagnose(asNote);
7575
}
7676

77-
ForceOptional *ForceOptional::create(ConstraintSystem &cs, Type baseType,
78-
Type unwrappedType,
79-
ConstraintLocator *locator) {
80-
return new (cs.getAllocator())
81-
ForceOptional(cs, baseType, unwrappedType, locator);
77+
ForceOptional *ForceOptional::create(ConstraintSystem &cs, Type fromType,
78+
Type toType, ConstraintLocator *locator) {
79+
return new (cs.getAllocator()) ForceOptional(cs, fromType, toType, locator);
8280
}
8381

8482
bool UnwrapOptionalBase::diagnose(bool asNote) const {

lib/Sema/CSFix.h

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -278,28 +278,6 @@ class ConstraintFix {
278278
ConstraintSystem &getConstraintSystem() const { return CS; }
279279
};
280280

281-
/// Introduce a '!' to force an optional unwrap.
282-
class ForceOptional final : public ConstraintFix {
283-
Type BaseType;
284-
Type UnwrappedType;
285-
286-
ForceOptional(ConstraintSystem &cs, Type baseType, Type unwrappedType,
287-
ConstraintLocator *locator)
288-
: ConstraintFix(cs, FixKind::ForceOptional, locator), BaseType(baseType),
289-
UnwrappedType(unwrappedType) {
290-
assert(baseType && "Base type must not be null");
291-
assert(unwrappedType && "Unwrapped type must not be null");
292-
}
293-
294-
public:
295-
std::string getName() const override { return "force optional"; }
296-
297-
bool diagnose(bool asNote = false) const override;
298-
299-
static ForceOptional *create(ConstraintSystem &cs, Type baseType,
300-
Type unwrappedType, ConstraintLocator *locator);
301-
};
302-
303281
/// Unwrap an optional base when we have a member access.
304282
class UnwrapOptionalBase final : public ConstraintFix {
305283
DeclName MemberName;
@@ -514,6 +492,26 @@ class ContextualMismatch : public ConstraintFix {
514492
ConstraintLocator *locator);
515493
};
516494

495+
/// Introduce a '!' to force an optional unwrap.
496+
class ForceOptional final : public ContextualMismatch {
497+
ForceOptional(ConstraintSystem &cs, Type fromType, Type toType,
498+
ConstraintLocator *locator)
499+
: ContextualMismatch(cs, FixKind::ForceOptional, fromType, toType,
500+
locator) {
501+
assert(fromType && "Base type must not be null");
502+
assert(fromType->getOptionalObjectType() &&
503+
"Unwrapped type must not be null");
504+
}
505+
506+
public:
507+
std::string getName() const override { return "force optional"; }
508+
509+
bool diagnose(bool asNote = false) const override;
510+
511+
static ForceOptional *create(ConstraintSystem &cs, Type fromType, Type toType,
512+
ConstraintLocator *locator);
513+
};
514+
517515
/// This is a contextual mismatch between throwing and non-throwing
518516
/// function types, repair it by dropping `throws` attribute.
519517
class DropThrowsAttribute final : public ContextualMismatch {

0 commit comments

Comments
 (0)