Skip to content

Commit 0cdfda0

Browse files
authored
Merge pull request #26541 from hborla/autoclosure-optional-ptr-conversion-diag
[Diagnostics] Improve the diagnostic for invalid optional pointer conversions for an autoclosure result type.
2 parents bebc27f + 34b6241 commit 0cdfda0

File tree

4 files changed

+39
-35
lines changed

4 files changed

+39
-35
lines changed

lib/Sema/CSFix.h

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,6 @@ enum class FixKind : uint8_t {
9898
/// Swift version 5.
9999
AutoClosureForwarding,
100100

101-
/// Allow invalid pointer conversions for autoclosure result types as if the
102-
/// pointer type is a function parameter rather than an autoclosure result.
103-
AllowAutoClosurePointerConversion,
104-
105101
/// Remove `!` or `?` because base is not an optional type.
106102
RemoveUnwrap,
107103

@@ -658,11 +654,12 @@ class AutoClosureForwarding final : public ConstraintFix {
658654
ConstraintLocator *locator);
659655
};
660656

657+
/// Allow invalid pointer conversions for autoclosure result types as if the
658+
/// pointer type is a function parameter rather than an autoclosure result.
661659
class AllowAutoClosurePointerConversion final : public ContextualMismatch {
662660
AllowAutoClosurePointerConversion(ConstraintSystem &cs, Type pointeeType,
663661
Type pointerType, ConstraintLocator *locator)
664-
: ContextualMismatch(cs, FixKind::AllowAutoClosurePointerConversion,
665-
pointeeType, pointerType, locator) {}
662+
: ContextualMismatch(cs, pointeeType, pointerType, locator) {}
666663

667664
public:
668665
std::string getName() const override {

lib/Sema/CSSimplify.cpp

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2618,6 +2618,14 @@ bool ConstraintSystem::repairFailures(
26182618
case ConstraintLocator::AutoclosureResult: {
26192619
if (repairByInsertingExplicitCall(lhs, rhs))
26202620
return true;
2621+
2622+
auto result = matchTypes(lhs, rhs, ConstraintKind::ArgumentConversion,
2623+
TypeMatchFlags::TMF_ApplyingFix,
2624+
locator.withPathElement(ConstraintLocator::FunctionArgument));
2625+
2626+
if (result.isSuccess())
2627+
conversionsOrFixes.push_back(AllowAutoClosurePointerConversion::create(
2628+
*this, lhs, rhs, getConstraintLocator(locator)));
26212629
break;
26222630
}
26232631

@@ -3224,10 +3232,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
32243232
if (kind >= ConstraintKind::Conversion) {
32253233
// It is never legal to form an autoclosure that results in these
32263234
// implicit conversions to pointer types.
3227-
bool isAutoClosureArgument = false;
3228-
if (auto last = locator.last())
3229-
if (last->getKind() == ConstraintLocator::AutoclosureResult)
3230-
isAutoClosureArgument = true;
3235+
bool isAutoClosureArgument = locator.isForAutoclosureResult();
32313236

32323237
// Pointer arguments can be converted from pointer-compatible types.
32333238
if (kind >= ConstraintKind::ArgumentConversion) {
@@ -3263,11 +3268,6 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
32633268
}
32643269
conversionsOrFixes.push_back(
32653270
ConversionRestrictionKind::InoutToPointer);
3266-
} else {
3267-
Type pointeeType = inoutType1->getObjectType();
3268-
auto *fix = AllowAutoClosurePointerConversion::create(*this,
3269-
pointeeType, type2, getConstraintLocator(locator));
3270-
conversionsOrFixes.push_back(fix);
32713271
}
32723272
}
32733273

@@ -7200,13 +7200,6 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint(
72007200
return matchTupleTypes(matchingType, smaller, matchKind, subflags, locator);
72017201
}
72027202

7203-
case FixKind::AllowAutoClosurePointerConversion: {
7204-
if (recordFix(fix))
7205-
return SolutionKind::Error;
7206-
return matchTypes(type1, type2, matchKind, subflags,
7207-
locator.withPathElement(ConstraintLocator::FunctionArgument));
7208-
}
7209-
72107203
case FixKind::InsertCall:
72117204
case FixKind::RemoveReturn:
72127205
case FixKind::AddConformance:

lib/Sema/ConstraintLocator.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -945,6 +945,22 @@ class ConstraintLocatorBuilder {
945945
return (getSummaryFlags() & ConstraintLocator::IsFunctionConversion);
946946
}
947947

948+
bool isForAutoclosureResult() const {
949+
SmallVector<LocatorPathElt, 4> path;
950+
getLocatorParts(path);
951+
952+
auto last = std::find_if(
953+
path.rbegin(), path.rend(), [](LocatorPathElt &elt) -> bool {
954+
return elt.getKind() != ConstraintLocator::OptionalPayload &&
955+
elt.getKind() != ConstraintLocator::GenericArgument;
956+
});
957+
958+
if (last != path.rend())
959+
return last->getKind() == ConstraintLocator::AutoclosureResult;
960+
961+
return false;
962+
}
963+
948964
/// Retrieve the base constraint locator, on which this builder's
949965
/// path is based.
950966
ConstraintLocator *getBaseLocator() const {

test/Constraints/invalid_implicit_conversions.swift

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,12 @@ func test(
99
_ ptr: UnsafePointer<Int>,
1010
_ ptrI8: UnsafePointer<Int8>,
1111
_ ptrU8: UnsafePointer<UInt8>,
12-
_ ptrVoid: UnsafePointer<Void> // expected-warning {{UnsafePointer<Void> has been replaced by UnsafeRawPointer}}
12+
_ ptrVoid: UnsafePointer<Void>, // expected-warning {{UnsafePointer<Void> has been replaced by UnsafeRawPointer}}
13+
_ optPtr: UnsafePointer<Int>?
1314
) {
1415
var i: Int = 0
1516
var a: [Int] = [0]
17+
var b: [Int]? = [0]
1618
let s = "string"
1719

1820
takesAutoclosure(rawPtr, &i) // expected-error {{cannot perform pointer conversion of value of type 'Int' to autoclosure result type 'UnsafeRawPointer'}}
@@ -23,18 +25,14 @@ func test(
2325
takesAutoclosure(mutRawPtr, &a) // expected-error {{cannot perform pointer conversion of value of type '[Int]' to autoclosure result type 'UnsafeMutableRawPointer'}}
2426
takesAutoclosure(mutPtr, &a) // expected-error {{cannot perform pointer conversion of value of type '[Int]' to autoclosure result type 'UnsafeMutablePointer<Int>'}}
2527
takesAutoclosure(ptr, &a) // expected-error {{cannot perform pointer conversion of value of type '[Int]' to autoclosure result type 'UnsafePointer<Int>'}}
28+
takesAutoclosure(optPtr, &i) // expected-error {{cannot perform pointer conversion of value of type 'Int' to autoclosure result type 'UnsafePointer<Int>?'}}
2629

27-
takesAutoclosure(rawPtr, a) // expected-error {{cannot invoke 'takesAutoclosure' with an argument list of type '(UnsafeRawPointer, [Int])'}}
28-
// expected-note@-1 {{expected an argument list of type '(T, @autoclosure () throws -> T)'}}
29-
takesAutoclosure(ptr, a) // expected-error {{cannot invoke 'takesAutoclosure' with an argument list of type '(UnsafePointer<Int>, [Int])'}}
30-
// expected-note@-1 {{expected an argument list of type '(T, @autoclosure () throws -> T)'}}
30+
takesAutoclosure(rawPtr, a) // expected-error {{cannot perform pointer conversion of value of type '[Int]' to autoclosure result type 'UnsafeRawPointer'}}
31+
takesAutoclosure(ptr, a) // expected-error {{cannot perform pointer conversion of value of type '[Int]' to autoclosure result type 'UnsafePointer<Int>'}}
32+
takesAutoclosure(optPtr, b) // expected-error {{cannot perform pointer conversion of value of type '[Int]?' to autoclosure result type 'UnsafePointer<Int>?'}}
3133

32-
takesAutoclosure(rawPtr, s) // expected-error {{cannot invoke 'takesAutoclosure' with an argument list of type '(UnsafeRawPointer, String)'}}
33-
// expected-note@-1 {{expected an argument list of type '(T, @autoclosure () throws -> T)'}}
34-
takesAutoclosure(ptrI8, s) // expected-error {{cannot invoke 'takesAutoclosure' with an argument list of type '(UnsafePointer<Int8>, String)'}}
35-
// expected-note@-1 {{expected an argument list of type '(T, @autoclosure () throws -> T)'}}
36-
takesAutoclosure(ptrU8, s) // expected-error {{cannot invoke 'takesAutoclosure' with an argument list of type '(UnsafePointer<UInt8>, String)'}}
37-
// expected-note@-1 {{expected an argument list of type '(T, @autoclosure () throws -> T)'}}
38-
takesAutoclosure(ptrVoid, s) // expected-error {{cannot invoke 'takesAutoclosure' with an argument list of type '(UnsafePointer<Void>, String)'}}
39-
// expected-note@-1 {{expected an argument list of type '(T, @autoclosure () throws -> T)'}}
34+
takesAutoclosure(rawPtr, s) // expected-error {{cannot perform pointer conversion of value of type 'String' to autoclosure result type 'UnsafeRawPointer'}}
35+
takesAutoclosure(ptrI8, s) // expected-error {{cannot perform pointer conversion of value of type 'String' to autoclosure result type 'UnsafePointer<Int8>'}}
36+
takesAutoclosure(ptrU8, s) // expected-error {{cannot perform pointer conversion of value of type 'String' to autoclosure result type 'UnsafePointer<UInt8>'}}
37+
takesAutoclosure(ptrVoid, s) // expected-error {{cannot perform pointer conversion of value of type 'String' to autoclosure result type 'UnsafePointer<Void>'}}
4038
}

0 commit comments

Comments
 (0)