Skip to content

Commit beb2371

Browse files
committed
[Diagnostics] Improve diagnostics related to pointer initialization
- Increase impact of a generic pointer-to-pointer mismatch fix to match that of a contextual type failure. This allows more specific fixes to take precedence. - De-prioritize generic argument mismatch fix when both types are pointers. This allows pointer-to-pointer conversion produce a more specific fix. - De-prioritize fixes that involve `Builtin.RawPointer` or `OpaquePointer` in parameter positions. This helps to produce better diagnostics for argument mismatches during pointer initialization e.g. `UnsafeRawPointer(<pointer>)`.
1 parent 5f268cc commit beb2371

File tree

3 files changed

+48
-23
lines changed

3 files changed

+48
-23
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2714,14 +2714,25 @@ ConstraintSystem::matchDeepEqualityTypes(Type type1, Type type2,
27142714
}
27152715
}
27162716

2717+
unsigned impact = 1;
2718+
2719+
if (type1->getAnyPointerElementType() &&
2720+
type2->getAnyPointerElementType()) {
2721+
// If this is a pointer <-> pointer conversion of different kind,
2722+
// there is a dedicated restriction/fix for that in some cases.
2723+
// To accommodate that, let's increase the impact of this fix.
2724+
impact += 2;
2725+
} else {
2726+
// Increase the solution's score for each mismtach this fixes.
2727+
impact += mismatches.size() - 1;
2728+
}
2729+
27172730
auto *fix = GenericArgumentsMismatch::create(
27182731
*this, type1, type2, mismatches, getConstraintLocator(locator));
27192732

2720-
if (!recordFix(fix)) {
2721-
// Increase the solution's score for each mismtach this fixes.
2722-
increaseScore(SK_Fix, mismatches.size() - 1);
2733+
if (!recordFix(fix, impact))
27232734
return getTypeMatchSuccess();
2724-
}
2735+
27252736
return result;
27262737
}
27272738
return matchDeepTypeArguments(*this, subflags, args1, args2, locator);
@@ -10744,12 +10755,13 @@ ConstraintSystem::simplifyRestrictedConstraintImpl(
1074410755
auto *fix = GenericArgumentsMismatch::create(*this, ptr1, ptr2, {0},
1074510756
getConstraintLocator(locator));
1074610757

10758+
// Treat this as a contextual type mismatch.
10759+
unsigned baseImpact = 2;
1074710760
// It's possible to implicitly promote pointer into an optional
1074810761
// before matching base types if other side is an optional, so
1074910762
// score needs to account for number of such promotions.
1075010763
int optionalWraps = baseType2.getInt() - baseType1.getInt();
10751-
return recordFix(fix,
10752-
/*impact=*/1 + abs(optionalWraps))
10764+
return recordFix(fix, baseImpact + abs(optionalWraps))
1075310765
? SolutionKind::Error
1075410766
: SolutionKind::Solved;
1075510767
};
@@ -11553,6 +11565,23 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint(
1155311565
}
1155411566
}
1155511567

11568+
// De-prioritize `Builtin.RawPointer` and `OpaquePointer` parameters
11569+
// because they usually clash with generic parameter mismatches e.g.
11570+
//
11571+
// let ptr: UnsafePointer<String> = ...
11572+
// _ = UnsafePointer<Int>(ups)
11573+
//
11574+
// Here initializer overloads have both `Builtin.RawPointer` and
11575+
// `OpaquePointer` variants, but the actual issue is that generic argument
11576+
// `String` doesn't match `Int`.
11577+
{
11578+
if (type2->is<BuiltinRawPointerType>())
11579+
impact += 1;
11580+
11581+
if (type2->getAnyNominal() == getASTContext().getOpaquePointerDecl())
11582+
impact += 1;
11583+
}
11584+
1155611585
return recordFix(fix, impact) ? SolutionKind::Error : SolutionKind::Solved;
1155711586
}
1155811587

test/Sema/diag_ambiguous_overloads.swift

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -136,15 +136,11 @@ array.withUnsafeBufferPointer {
136136
// expected-error@-1 {{no exact matches in call to initializer}}
137137
// expected-note@-2 {{candidate expects value of type 'UnsafeRawPointer' for parameter #1}}
138138
// expected-note@-3 {{candidate expects value of type 'UnsafeMutableRawPointer' for parameter #1}}
139-
// expected-note@-4 {{candidate expects value of type 'OpaquePointer' for parameter #1}}
140-
// expected-note@-5 {{candidate expects value of type 'Builtin.RawPointer' for parameter #1}}
141139

142140
UnsafeRawPointer($0) as UnsafeBufferPointer<UInt16> // expected-error {{cannot convert value of type 'UnsafeRawPointer' to type 'UnsafeBufferPointer<UInt16>' in coercion}}
143141
// expected-error@-1 {{no exact matches in call to initializer}}
144142
// expected-note@-2 {{found candidate with type '(UnsafeRawPointer) -> UnsafeRawPointer'}}
145-
// expected-note@-3 {{found candidate with type '(Builtin.RawPointer) -> UnsafeRawPointer'}}
146-
// expected-note@-4 {{found candidate with type '(OpaquePointer) -> UnsafeRawPointer'}}
147-
// expected-note@-5 {{found candidate with type '(UnsafeMutableRawPointer) -> UnsafeRawPointer'}}
143+
// expected-note@-3 {{found candidate with type '(UnsafeMutableRawPointer) -> UnsafeRawPointer'}}
148144
}
149145

150146
func SR12689_1(_ u: Int) -> String { "" } // expected-note {{found this candidate}} expected-note {{candidate expects value of type 'Int' for parameter #1 (got 'Double')}}

test/stdlib/UnsafePointerDiagnostics.swift

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -61,30 +61,30 @@ func unsafePointerConversionAvailability(
6161
_ = UnsafeMutablePointer<Int>(umpi)
6262
_ = UnsafeMutablePointer<Int>(oumpi)
6363

64-
_ = UnsafeMutablePointer<Void>(rp) // expected-error {{no exact matches in call to initializer}} expected-warning {{UnsafeMutablePointer<Void> has been replaced by UnsafeMutableRawPointer}}
65-
_ = UnsafeMutablePointer<Void>(mrp) // expected-error {{no exact matches in call to initializer}} expected-warning {{UnsafeMutablePointer<Void> has been replaced by UnsafeMutableRawPointer}}
64+
_ = UnsafeMutablePointer<Void>(rp) // expected-error {{cannot convert value of type 'UnsafeRawPointer' to expected argument type 'UnsafeMutablePointer<Void>'}} expected-warning {{UnsafeMutablePointer<Void> has been replaced by UnsafeMutableRawPointer}}
65+
_ = UnsafeMutablePointer<Void>(mrp) // expected-error {{cannot convert value of type 'UnsafeMutableRawPointer' to expected argument type 'UnsafeMutablePointer<Void>'}} expected-warning {{UnsafeMutablePointer<Void> has been replaced by UnsafeMutableRawPointer}}
6666
_ = UnsafeMutablePointer<Void>(umpv) // expected-warning {{UnsafeMutablePointer<Void> has been replaced by UnsafeMutableRawPointer}}
6767
_ = UnsafeMutablePointer<Void>(umpi) // expected-warning {{UnsafeMutablePointer<Void> has been replaced by UnsafeMutableRawPointer}}
6868
_ = UnsafeMutablePointer<Void>(umps) // expected-warning {{UnsafeMutablePointer<Void> has been replaced by UnsafeMutableRawPointer}}
6969

70-
_ = UnsafePointer<Void>(rp) // expected-error {{no exact matches in call to initializer}} expected-warning {{UnsafePointer<Void> has been replaced by UnsafeRawPointer}}
71-
_ = UnsafePointer<Void>(mrp) // expected-error {{no exact matches in call to initializer}} expected-warning {{UnsafePointer<Void> has been replaced by UnsafeRawPointer}}
70+
_ = UnsafePointer<Void>(rp) // expected-error {{cannot convert value of type 'UnsafeRawPointer' to expected argument type 'UnsafePointer<Void>'}} expected-warning {{UnsafePointer<Void> has been replaced by UnsafeRawPointer}}
71+
_ = UnsafePointer<Void>(mrp) // expected-error {{cannot convert value of type 'UnsafeMutableRawPointer' to expected argument type 'UnsafePointer<Void>'}} expected-warning {{UnsafePointer<Void> has been replaced by UnsafeRawPointer}}
7272
_ = UnsafePointer<Void>(umpv) // expected-warning {{UnsafePointer<Void> has been replaced by UnsafeRawPointer}}
7373
_ = UnsafePointer<Void>(upv) // expected-warning {{UnsafePointer<Void> has been replaced by UnsafeRawPointer}}
7474
_ = UnsafePointer<Void>(umpi) // expected-warning {{UnsafePointer<Void> has been replaced by UnsafeRawPointer}}
7575
_ = UnsafePointer<Void>(upi) // expected-warning {{UnsafePointer<Void> has been replaced by UnsafeRawPointer}}
7676
_ = UnsafePointer<Void>(umps) // expected-warning {{UnsafePointer<Void> has been replaced by UnsafeRawPointer}}
7777
_ = UnsafePointer<Void>(ups) // expected-warning {{UnsafePointer<Void> has been replaced by UnsafeRawPointer}}
7878

79-
_ = UnsafeMutablePointer<Int>(rp) // expected-error {{no exact matches in call to initializer}}
80-
_ = UnsafeMutablePointer<Int>(mrp) // expected-error {{no exact matches in call to initializer}}
81-
_ = UnsafeMutablePointer<Int>(orp) // expected-error {{no exact matches in call to initializer}}
82-
_ = UnsafeMutablePointer<Int>(omrp) // expected-error {{no exact matches in call to initializer}}
79+
_ = UnsafeMutablePointer<Int>(rp) // expected-error {{cannot convert value of type 'UnsafeRawPointer' to expected argument type 'UnsafeMutablePointer<Int>'}}
80+
_ = UnsafeMutablePointer<Int>(mrp) // expected-error {{cannot convert value of type 'UnsafeMutableRawPointer' to expected argument type 'UnsafeMutablePointer<Int>'}}
81+
_ = UnsafeMutablePointer<Int>(orp) // expected-error {{cannot convert value of type 'UnsafeRawPointer?' to expected argument type 'UnsafeMutablePointer<Int>'}}
82+
_ = UnsafeMutablePointer<Int>(omrp) // expected-error {{cannot convert value of type 'UnsafeMutableRawPointer?' to expected argument type 'UnsafeMutablePointer<Int>'}}
8383

84-
_ = UnsafePointer<Int>(rp) // expected-error {{no exact matches in call to initializer}}
85-
_ = UnsafePointer<Int>(mrp) // expected-error {{no exact matches in call to initializer}}
86-
_ = UnsafePointer<Int>(orp) // expected-error {{no exact matches in call to initializer}}
87-
_ = UnsafePointer<Int>(omrp) // expected-error {{no exact matches in call to initializer}}
84+
_ = UnsafePointer<Int>(rp) // expected-error {{cannot convert value of type 'UnsafeRawPointer' to expected argument type 'UnsafePointer<Int>'}}
85+
_ = UnsafePointer<Int>(mrp) // expected-error {{cannot convert value of type 'UnsafeMutableRawPointer' to expected argument type 'UnsafePointer<Int>'}}
86+
_ = UnsafePointer<Int>(orp) // expected-error {{cannot convert value of type 'UnsafeRawPointer?' to expected argument type 'UnsafePointer<Int>'}}
87+
_ = UnsafePointer<Int>(omrp) // expected-error {{cannot convert value of type 'UnsafeMutableRawPointer?' to expected argument type 'UnsafePointer<Int>'}}
8888

8989
_ = UnsafePointer<Int>(ups) // expected-error {{cannot convert value of type 'UnsafePointer<String>' to expected argument type 'UnsafePointer<Int>'}}
9090
// expected-note@-1 {{arguments to generic parameter 'Pointee' ('String' and 'Int') are expected to be equal}}

0 commit comments

Comments
 (0)