Skip to content

Commit 68d25a2

Browse files
authored
Merge pull request #26376 from xedin/rdar-53238058
[CSFix] Delay `missing unwrap` locator simplification until diagnostic
2 parents a078c33 + 795a84a commit 68d25a2

File tree

6 files changed

+39
-16
lines changed

6 files changed

+39
-16
lines changed

lib/Sema/CSDiagnostics.cpp

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

10861086
auto *anchor = getAnchor();
10871087

1088+
// If this is an unresolved member expr e.g. `.foo` its
1089+
// base type is going to be the same as result type minus
1090+
// r-value adjustment because base could be an l-value type.
1091+
// We want to fix both cases by only diagnose one of them,
1092+
// otherwise this is just going to result in a duplcate diagnostic.
1093+
if (getLocator()->isLastElement(ConstraintLocator::UnresolvedMember))
1094+
return false;
1095+
10881096
if (auto assignExpr = dyn_cast<AssignExpr>(anchor))
10891097
anchor = assignExpr->getSrc();
10901098

lib/Sema/CSFix.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,17 +67,15 @@ ForceDowncast *ForceDowncast::create(ConstraintSystem &cs, Type toType,
6767

6868
bool ForceOptional::diagnose(Expr *root, bool asNote) const {
6969
MissingOptionalUnwrapFailure failure(root, getConstraintSystem(), BaseType,
70-
UnwrappedType, FullLocator);
70+
UnwrappedType, getLocator());
7171
return failure.diagnose(asNote);
7272
}
7373

7474
ForceOptional *ForceOptional::create(ConstraintSystem &cs, Type baseType,
7575
Type unwrappedType,
7676
ConstraintLocator *locator) {
77-
auto *simplifiedLocator =
78-
cs.getConstraintLocator(simplifyLocatorToAnchor(cs, locator));
7977
return new (cs.getAllocator())
80-
ForceOptional(cs, baseType, unwrappedType, simplifiedLocator, locator);
78+
ForceOptional(cs, baseType, unwrappedType, locator);
8179
}
8280

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

lib/Sema/CSFix.h

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -255,14 +255,11 @@ class ForceDowncast final : public ConstraintFix {
255255
class ForceOptional final : public ConstraintFix {
256256
Type BaseType;
257257
Type UnwrappedType;
258-
ConstraintLocator *FullLocator;
259258

260259
ForceOptional(ConstraintSystem &cs, Type baseType, Type unwrappedType,
261-
ConstraintLocator *simplifiedLocator,
262-
ConstraintLocator *fullLocator)
263-
: ConstraintFix(cs, FixKind::ForceOptional, simplifiedLocator),
264-
BaseType(baseType), UnwrappedType(unwrappedType),
265-
FullLocator(fullLocator) {
260+
ConstraintLocator *locator)
261+
: ConstraintFix(cs, FixKind::ForceOptional, locator), BaseType(baseType),
262+
UnwrappedType(unwrappedType) {
266263
assert(baseType && "Base type must not be null");
267264
assert(unwrappedType && "Unwrapped type must not be null");
268265
}

lib/Sema/ConstraintLocator.cpp

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

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

179179
bool ConstraintLocator::isForGenericParameter() const {
180-
return isLastElement(this, ConstraintLocator::GenericParameter);
180+
return isLastElement(ConstraintLocator::GenericParameter);
181181
}
182182

183183
bool ConstraintLocator::isForSequenceElementType() const {
184-
return isLastElement(this, ConstraintLocator::SequenceElementType);
184+
return isLastElement(ConstraintLocator::SequenceElementType);
185185
}
186186

187187
bool ConstraintLocator::isForContextualType() const {
188-
return isLastElement(this, ConstraintLocator::ContextualType);
188+
return isLastElement(ConstraintLocator::ContextualType);
189189
}
190190

191191
GenericTypeParamType *ConstraintLocator::getGenericParameter() const {

lib/Sema/ConstraintLocator.h

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

596+
/// Check whether the last element in the path of this locator
597+
/// is of a given kind.
598+
bool isLastElement(ConstraintLocator::PathElementKind kind) const;
599+
596600
/// If this locator points to generic parameter return its type.
597601
GenericTypeParamType *getGenericParameter() const;
598602

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)