Skip to content

Commit 252a072

Browse files
authored
Merge pull request #26413 from xedin/rdar-53238058-5.1
[5.1][CSFix] Delay `missing unwrap` locator simplification until diagnostic
2 parents 5d2cb9a + 1d44ff7 commit 252a072

File tree

5 files changed

+36
-9
lines changed

5 files changed

+36
-9
lines changed

lib/Sema/CSDiagnostics.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -797,6 +797,14 @@ bool MissingOptionalUnwrapFailure::diagnoseAsError() {
797797

798798
auto *anchor = getAnchor();
799799

800+
// If this is an unresolved member expr e.g. `.foo` its
801+
// base type is going to be the same as result type minus
802+
// r-value adjustment because base could be an l-value type.
803+
// We want to fix both cases by only diagnose one of them,
804+
// otherwise this is just going to result in a duplcate diagnostic.
805+
if (getLocator()->isLastElement(ConstraintLocator::UnresolvedMember))
806+
return false;
807+
800808
if (auto assignExpr = dyn_cast<AssignExpr>(anchor))
801809
anchor = assignExpr->getSrc();
802810

lib/Sema/CSFix.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,8 @@ bool ForceOptional::diagnose(Expr *root, bool asNote) const {
7474
ForceOptional *ForceOptional::create(ConstraintSystem &cs, Type baseType,
7575
Type unwrappedType,
7676
ConstraintLocator *locator) {
77-
return new (cs.getAllocator()) ForceOptional(
78-
cs, baseType, unwrappedType,
79-
cs.getConstraintLocator(simplifyLocatorToAnchor(cs, locator)));
77+
return new (cs.getAllocator())
78+
ForceOptional(cs, baseType, unwrappedType, locator);
8079
}
8180

8281
bool UnwrapOptionalBase::diagnose(Expr *root, bool asNote) const {

lib/Sema/ConstraintLocator.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -168,22 +168,22 @@ bool ConstraintLocator::isForKeyPathComponent() const {
168168
});
169169
}
170170

171-
static bool isLastElement(const ConstraintLocator *locator,
172-
ConstraintLocator::PathElementKind expectedKind) {
173-
auto path = locator->getPath();
171+
bool ConstraintLocator::isLastElement(
172+
ConstraintLocator::PathElementKind expectedKind) const {
173+
auto path = getPath();
174174
return !path.empty() && path.back().getKind() == expectedKind;
175175
}
176176

177177
bool ConstraintLocator::isForGenericParameter() const {
178-
return isLastElement(this, ConstraintLocator::GenericParameter);
178+
return isLastElement(ConstraintLocator::GenericParameter);
179179
}
180180

181181
bool ConstraintLocator::isForSequenceElementType() const {
182-
return isLastElement(this, ConstraintLocator::SequenceElementType);
182+
return isLastElement(ConstraintLocator::SequenceElementType);
183183
}
184184

185185
bool ConstraintLocator::isForContextualType() const {
186-
return isLastElement(this, ConstraintLocator::ContextualType);
186+
return isLastElement(ConstraintLocator::ContextualType);
187187
}
188188

189189
GenericTypeParamType *ConstraintLocator::getGenericParameter() const {

lib/Sema/ConstraintLocator.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -585,6 +585,10 @@ class ConstraintLocator : public llvm::FoldingSetNode {
585585
/// Determine whether this locator points to the contextual type.
586586
bool isForContextualType() const;
587587

588+
/// Check whether the last element in the path of this locator
589+
/// is of a given kind.
590+
bool isLastElement(ConstraintLocator::PathElementKind kind) const;
591+
588592
/// If this locator points to generic parameter return its type.
589593
GenericTypeParamType *getGenericParameter() const;
590594

test/Constraints/optional.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,3 +357,19 @@ struct S {
357357
}
358358
}
359359
}
360+
361+
// rdar://problem/53238058 - Crash in getCalleeLocator while trying to produce a diagnostic about missing optional unwrap
362+
// associated with an argument to a call
363+
364+
func rdar_53238058() {
365+
struct S {
366+
init(_: Double) {}
367+
init<T>(_ value: T) where T : BinaryFloatingPoint {}
368+
}
369+
370+
func test(_ str: String) {
371+
_ = S(Double(str)) // expected-error {{value of optional type 'Double?' must be unwrapped to a value of type 'Double'}}
372+
// expected-note@-1 {{coalesce using '??' to provide a default when the optional value contains 'nil'}}
373+
// expected-note@-2 {{force-unwrap using '!' to abort execution if the optional value contains 'nil'}}
374+
}
375+
}

0 commit comments

Comments
 (0)