Skip to content

Commit ae46805

Browse files
authored
Merge pull request #63330 from xedin/diag-fixes-5.8
[5.8][Diagnostics] Collection of diagnostic fixes/improvements
2 parents 1c90299 + 9dd7ccc commit ae46805

File tree

10 files changed

+376
-55
lines changed

10 files changed

+376
-55
lines changed

include/swift/Sema/CSFix.h

Lines changed: 40 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -587,21 +587,38 @@ class RelabelArguments final
587587
}
588588
};
589589

590+
class RequirementFix : public ConstraintFix {
591+
protected:
592+
Type LHS;
593+
Type RHS;
594+
595+
RequirementFix(ConstraintSystem &cs, FixKind kind, Type lhs, Type rhs,
596+
ConstraintLocator *locator)
597+
: ConstraintFix(cs, kind, locator), LHS(lhs), RHS(rhs) {}
598+
599+
public:
600+
std::string getName() const override = 0;
601+
602+
Type lhsType() const { return LHS; }
603+
Type rhsType() const { return RHS; }
604+
605+
bool diagnoseForAmbiguity(CommonFixesArray commonFixes) const override;
606+
607+
bool diagnose(const Solution &solution,
608+
bool asNote = false) const override = 0;
609+
};
610+
590611
/// Add a new conformance to the type to satisfy a requirement.
591-
class MissingConformance final : public ConstraintFix {
612+
class MissingConformance final : public RequirementFix {
592613
// Determines whether given protocol type comes from the context e.g.
593614
// assignment destination or argument comparison.
594615
bool IsContextual;
595616

596-
Type NonConformingType;
597-
// This could either be a protocol or protocol composition.
598-
Type ProtocolType;
599-
600617
MissingConformance(ConstraintSystem &cs, bool isContextual, Type type,
601618
Type protocolType, ConstraintLocator *locator)
602-
: ConstraintFix(cs, FixKind::AddConformance, locator),
603-
IsContextual(isContextual), NonConformingType(type),
604-
ProtocolType(protocolType) {}
619+
: RequirementFix(cs, FixKind::AddConformance, type, protocolType,
620+
locator),
621+
IsContextual(isContextual) {}
605622

606623
public:
607624
std::string getName() const override {
@@ -610,8 +627,6 @@ class MissingConformance final : public ConstraintFix {
610627

611628
bool diagnose(const Solution &solution, bool asNote = false) const override;
612629

613-
bool diagnoseForAmbiguity(CommonFixesArray commonFixes) const override;
614-
615630
static MissingConformance *forRequirement(ConstraintSystem &cs, Type type,
616631
Type protocolType,
617632
ConstraintLocator *locator);
@@ -620,9 +635,9 @@ class MissingConformance final : public ConstraintFix {
620635
Type protocolType,
621636
ConstraintLocator *locator);
622637

623-
Type getNonConformingType() { return NonConformingType; }
638+
Type getNonConformingType() const { return LHS; }
624639

625-
Type getProtocolType() { return ProtocolType; }
640+
Type getProtocolType() const { return RHS; }
626641

627642
bool isEqual(const ConstraintFix *other) const;
628643

@@ -633,13 +648,11 @@ class MissingConformance final : public ConstraintFix {
633648

634649
/// Skip same-type generic requirement constraint,
635650
/// and assume that types are equal.
636-
class SkipSameTypeRequirement final : public ConstraintFix {
637-
Type LHS, RHS;
638-
651+
class SkipSameTypeRequirement final : public RequirementFix {
639652
SkipSameTypeRequirement(ConstraintSystem &cs, Type lhs, Type rhs,
640653
ConstraintLocator *locator)
641-
: ConstraintFix(cs, FixKind::SkipSameTypeRequirement, locator), LHS(lhs),
642-
RHS(rhs) {}
654+
: RequirementFix(cs, FixKind::SkipSameTypeRequirement, lhs, rhs,
655+
locator) {}
643656

644657
public:
645658
std::string getName() const override {
@@ -648,9 +661,6 @@ class SkipSameTypeRequirement final : public ConstraintFix {
648661

649662
bool diagnose(const Solution &solution, bool asNote = false) const override;
650663

651-
Type lhsType() { return LHS; }
652-
Type rhsType() { return RHS; }
653-
654664
static SkipSameTypeRequirement *create(ConstraintSystem &cs, Type lhs,
655665
Type rhs, ConstraintLocator *locator);
656666

@@ -661,13 +671,11 @@ class SkipSameTypeRequirement final : public ConstraintFix {
661671

662672
/// Skip same-shape generic requirement constraint,
663673
/// and assume that types are equal.
664-
class SkipSameShapeRequirement final : public ConstraintFix {
665-
Type LHS, RHS;
666-
674+
class SkipSameShapeRequirement final : public RequirementFix {
667675
SkipSameShapeRequirement(ConstraintSystem &cs, Type lhs, Type rhs,
668676
ConstraintLocator *locator)
669-
: ConstraintFix(cs, FixKind::SkipSameShapeRequirement, locator), LHS(lhs),
670-
RHS(rhs) {}
677+
: RequirementFix(cs, FixKind::SkipSameShapeRequirement, lhs, rhs,
678+
locator) {}
671679

672680
public:
673681
std::string getName() const override {
@@ -676,9 +684,6 @@ class SkipSameShapeRequirement final : public ConstraintFix {
676684

677685
bool diagnose(const Solution &solution, bool asNote = false) const override;
678686

679-
Type lhsType() { return LHS; }
680-
Type rhsType() { return RHS; }
681-
682687
static SkipSameShapeRequirement *create(ConstraintSystem &cs, Type lhs,
683688
Type rhs, ConstraintLocator *locator);
684689

@@ -689,13 +694,11 @@ class SkipSameShapeRequirement final : public ConstraintFix {
689694

690695
/// Skip 'superclass' generic requirement constraint,
691696
/// and assume that types are equal.
692-
class SkipSuperclassRequirement final : public ConstraintFix {
693-
Type LHS, RHS;
694-
697+
class SkipSuperclassRequirement final : public RequirementFix {
695698
SkipSuperclassRequirement(ConstraintSystem &cs, Type lhs, Type rhs,
696699
ConstraintLocator *locator)
697-
: ConstraintFix(cs, FixKind::SkipSuperclassRequirement, locator),
698-
LHS(lhs), RHS(rhs) {}
700+
: RequirementFix(cs, FixKind::SkipSuperclassRequirement, lhs, rhs,
701+
locator) {}
699702

700703
public:
701704
std::string getName() const override {
@@ -1839,6 +1842,10 @@ class AllowInaccessibleMember final : public AllowInvalidMemberRef {
18391842

18401843
bool diagnose(const Solution &solution, bool asNote = false) const override;
18411844

1845+
bool diagnoseForAmbiguity(CommonFixesArray commonFixes) const override {
1846+
return diagnose(*commonFixes.front().first);
1847+
}
1848+
18421849
static AllowInaccessibleMember *create(ConstraintSystem &cs, Type baseType,
18431850
ValueDecl *member, DeclNameRef name,
18441851
ConstraintLocator *locator);

lib/Sema/BuilderTransform.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2480,8 +2480,10 @@ ConstraintSystem::matchResultBuilder(AnyFunctionRef fn, Type builderType,
24802480
}
24812481

24822482
// Record the first unhandled construct as a fix.
2483-
if (recordFix(SkipUnhandledConstructInResultBuilder::create(
2484-
*this, unsupported, builder, getConstraintLocator(locator)))) {
2483+
if (recordFix(
2484+
SkipUnhandledConstructInResultBuilder::create(
2485+
*this, unsupported, builder, getConstraintLocator(locator)),
2486+
/*impact=*/100)) {
24852487
return getTypeMatchFailure(locator);
24862488
}
24872489

lib/Sema/CSFix.cpp

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -400,25 +400,26 @@ bool MissingConformance::diagnose(const Solution &solution, bool asNote) const {
400400
auto &cs = solution.getConstraintSystem();
401401
auto context = cs.getContextualTypePurpose(locator->getAnchor());
402402
MissingContextualConformanceFailure failure(
403-
solution, context, NonConformingType, ProtocolType, locator);
403+
solution, context, getNonConformingType(), getProtocolType(), locator);
404404
return failure.diagnose(asNote);
405405
}
406406

407407
MissingConformanceFailure failure(
408-
solution, locator, std::make_pair(NonConformingType, ProtocolType));
408+
solution, locator,
409+
std::make_pair(getNonConformingType(), getProtocolType()));
409410
return failure.diagnose(asNote);
410411
}
411412

412-
bool MissingConformance::diagnoseForAmbiguity(
413+
bool RequirementFix::diagnoseForAmbiguity(
413414
CommonFixesArray commonFixes) const {
414-
auto *primaryFix = commonFixes.front().second->getAs<MissingConformance>();
415+
auto *primaryFix = commonFixes.front().second;
415416
assert(primaryFix);
416417

417418
if (llvm::all_of(
418419
commonFixes,
419420
[&primaryFix](
420421
const std::pair<const Solution *, const ConstraintFix *> &entry) {
421-
return primaryFix->isEqual(entry.second);
422+
return primaryFix->getLocator() == entry.second->getLocator();
422423
}))
423424
return diagnose(*commonFixes.front().first);
424425

@@ -433,8 +434,9 @@ bool MissingConformance::isEqual(const ConstraintFix *other) const {
433434
return false;
434435

435436
return IsContextual == conformanceFix->IsContextual &&
436-
NonConformingType->isEqual(conformanceFix->NonConformingType) &&
437-
ProtocolType->isEqual(conformanceFix->ProtocolType);
437+
getNonConformingType()->isEqual(
438+
conformanceFix->getNonConformingType()) &&
439+
getProtocolType()->isEqual(conformanceFix->getProtocolType());
438440
}
439441

440442
MissingConformance *

lib/Sema/CSSimplify.cpp

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4542,14 +4542,30 @@ repairViaOptionalUnwrap(ConstraintSystem &cs, Type fromType, Type toType,
45424542
if (!anchor)
45434543
return false;
45444544

4545-
bool possibleContextualMismatch = false;
45464545
// If this is a conversion to a non-optional contextual type e.g.
45474546
// `let _: Bool = try? foo()` and `foo()` produces `Int`
45484547
// we should diagnose it as type mismatch instead of missing unwrap.
4549-
if (auto last = locator.last()) {
4550-
possibleContextualMismatch = last->is<LocatorPathElt::ContextualType>() &&
4551-
!toType->getOptionalObjectType();
4552-
}
4548+
bool possibleContextualMismatch = [&]() {
4549+
auto last = locator.last();
4550+
if (!(last && last->is<LocatorPathElt::ContextualType>()))
4551+
return false;
4552+
4553+
// If the contextual type is optional as well, it's definitely a
4554+
// missing unwrap.
4555+
if (toType->getOptionalObjectType())
4556+
return false;
4557+
4558+
// If this is a leading-dot syntax member chain with `?.`
4559+
// notation, it wouldn't be possible to infer the base type
4560+
// without the contextual type, so we have to treat it as
4561+
// a missing unwrap.
4562+
if (auto *OEE = getAsExpr<OptionalEvaluationExpr>(anchor)) {
4563+
if (isExpr<UnresolvedMemberChainResultExpr>(OEE->getSubExpr()))
4564+
return false;
4565+
}
4566+
4567+
return true;
4568+
}();
45534569

45544570
// `OptionalEvaluationExpr` doesn't add a new level of
45554571
// optionality but it could be hiding concrete types
@@ -6014,6 +6030,12 @@ bool ConstraintSystem::repairFailures(
60146030
}
60156031

60166032
case ConstraintLocator::TupleElement: {
6033+
if (lhs->isPlaceholder() || rhs->isPlaceholder()) {
6034+
recordAnyTypeVarAsPotentialHole(lhs);
6035+
recordAnyTypeVarAsPotentialHole(rhs);
6036+
return true;
6037+
}
6038+
60176039
if (isExpr<ArrayExpr>(anchor) || isExpr<DictionaryExpr>(anchor)) {
60186040
// If we could record a generic arguments mismatch instead of this fix,
60196041
// don't record a ContextualMismatch here.
@@ -6152,6 +6174,17 @@ bool ConstraintSystem::repairFailures(
61526174
if (rhs->isPlaceholder())
61536175
return true;
61546176

6177+
// The base is a placeholder, let's report an unknown base issue.
6178+
if (lhs->isPlaceholder()) {
6179+
auto *baseExpr =
6180+
castToExpr<UnresolvedMemberChainResultExpr>(anchor)->getChainBase();
6181+
6182+
auto *fix = SpecifyBaseTypeForContextualMember::create(
6183+
*this, baseExpr->getName(), getConstraintLocator(locator));
6184+
conversionsOrFixes.push_back(fix);
6185+
break;
6186+
}
6187+
61556188
if (repairViaOptionalUnwrap(*this, lhs, rhs, matchKind, conversionsOrFixes,
61566189
locator))
61576190
break;

0 commit comments

Comments
 (0)