Skip to content

Commit f048652

Browse files
committed
[ConstraintSystem] Do more checking before suggesting to explicitly contruct raw representable
Introduce `repairByExplicitRawRepresentativeUse` which is used for assignment, argument-to-parameter conversions and contextual mismatches. It checks whether `to` side is a raw representable type and tries to match `from` side to its `rawValue`.
1 parent 7034fb3 commit f048652

File tree

3 files changed

+62
-13
lines changed

3 files changed

+62
-13
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3135,6 +3135,39 @@ bool ConstraintSystem::repairFailures(
31353135
return false;
31363136
};
31373137

3138+
// Check whether given `rawReprType` does indeed conform to `RawRepresentable`
3139+
// and if so check that given `valueType` matches its `RawValue` type. If that
3140+
// condition holds add a tailored fix which is going to suggest to explicitly
3141+
// construct a raw representable type from a given value type.
3142+
auto repairByExplicitRawRepresentativeUse =
3143+
[&](Type origValueType, Type origRawReprType) -> bool {
3144+
auto rawReprType = origRawReprType;
3145+
// Let's unwrap a single level of optionality since
3146+
// diagnostic is going to suggest failable initializer anyway.
3147+
if (auto objType = rawReprType->getOptionalObjectType())
3148+
rawReprType = objType;
3149+
3150+
auto valueType = origValueType;
3151+
// If value is optional diagnostic would suggest using `Optional.map` in
3152+
// combination with `<Type>(rawValue: ...)` initializer.
3153+
if (auto objType = valueType->getOptionalObjectType())
3154+
valueType = objType;
3155+
3156+
auto rawValue = isRawRepresentable(*this, rawReprType);
3157+
if (!rawValue)
3158+
return false;
3159+
3160+
auto result = matchTypes(valueType, rawValue, ConstraintKind::Conversion,
3161+
TMF_ApplyingFix, locator);
3162+
3163+
if (result.isFailure())
3164+
return false;
3165+
3166+
conversionsOrFixes.push_back(ExplicitlyConstructRawRepresentable::create(
3167+
*this, origRawReprType, origValueType, getConstraintLocator(locator)));
3168+
return true;
3169+
};
3170+
31383171
auto hasConversionOrRestriction = [&](ConversionRestrictionKind kind) {
31393172
return llvm::any_of(conversionsOrFixes,
31403173
[kind](const RestrictionOrFix correction) {
@@ -3351,6 +3384,10 @@ bool ConstraintSystem::repairFailures(
33513384
conversionsOrFixes, locator))
33523385
return true;
33533386

3387+
// `rhs` - is an assignment destination and `lhs` is its source.
3388+
if (repairByExplicitRawRepresentativeUse(lhs, rhs))
3389+
return true;
3390+
33543391
// Let's try to match source and destination types one more
33553392
// time to see whether they line up, if they do - the problem is
33563393
// related to immutability, otherwise it's a type mismatch.
@@ -3583,12 +3620,6 @@ bool ConstraintSystem::repairFailures(
35833620
break;
35843621
}
35853622

3586-
if (auto *fix = ExplicitlyConstructRawRepresentable::attempt(
3587-
*this, lhs, rhs, locator)) {
3588-
conversionsOrFixes.push_back(fix);
3589-
break;
3590-
}
3591-
35923623
if (auto *fix = UseValueTypeOfRawRepresentative::attempt(*this, lhs, rhs,
35933624
locator)) {
35943625
conversionsOrFixes.push_back(fix);
@@ -3624,6 +3655,10 @@ bool ConstraintSystem::repairFailures(
36243655
if (lhs->hasHole() || rhs->hasHole())
36253656
return true;
36263657

3658+
// `lhs` - is an argument and `rhs` is a parameter type.
3659+
if (repairByExplicitRawRepresentativeUse(lhs, rhs))
3660+
break;
3661+
36273662
if (repairViaOptionalUnwrap(*this, lhs, rhs, matchKind, conversionsOrFixes,
36283663
locator))
36293664
break;
@@ -3854,6 +3889,10 @@ bool ConstraintSystem::repairFailures(
38543889
}))
38553890
break;
38563891

3892+
// `lhs` - is an result type and `rhs` is a contextual type.
3893+
if (repairByExplicitRawRepresentativeUse(lhs, rhs))
3894+
break;
3895+
38573896
conversionsOrFixes.push_back(IgnoreContextualType::create(
38583897
*this, lhs, rhs, getConstraintLocator(locator)));
38593898
break;

test/Migrator/rdar31892850.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,6 @@ func foo() {
2121
// CHECK: {
2222
// CHECK: "file": "{{.*}}rdar31892850.swift",
2323
// CHECK: "offset": 329,
24-
// CHECK: "text": ")"
24+
// CHECK: "text": ") ?? <#default value#>"
2525
// CHECK: }
2626
// CHECK:]

test/Sema/enum_raw_representable.swift

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -97,11 +97,11 @@ func rdar32431736() {
9797

9898
let myE1: E = items1.first
9999
// expected-error@-1 {{cannot convert value of type 'String?' to specified type 'E'}}
100-
// expected-note@-2 {{construct 'E' from unwrapped 'String' value}} {{17-17=E(rawValue: }} {{29-29=!)}}
100+
// expected-note@-2 {{construct 'E' from unwrapped 'String' value}} {{17-17=E(rawValue: }} {{29-29=!) ?? <#default value#>}}
101101

102102
let myE2: E = items2?.first
103103
// expected-error@-1 {{cannot convert value of type 'String?' to specified type 'E'}}
104-
// expected-note@-2 {{construct 'E' from unwrapped 'String' value}} {{17-17=E(rawValue: (}} {{30-30=)!)}}
104+
// expected-note@-2 {{construct 'E' from unwrapped 'String' value}} {{17-17=E(rawValue: (}} {{30-30=)!) ?? <#default value#>}}
105105
}
106106

107107
// rdar://problem/32431165 - improve diagnostic for raw representable argument mismatch
@@ -122,9 +122,9 @@ rdar32431165_1(.baz)
122122
// expected-error@-1 {{reference to member 'baz' cannot be resolved without a contextual type}}
123123

124124
rdar32431165_1("")
125-
// expected-error@-1 {{cannot convert value of type 'String' to expected argument type 'E_32431165'}} {{16-16=E_32431165(rawValue: }} {{18-18=)}}
125+
// expected-error@-1 {{cannot convert value of type 'String' to expected argument type 'E_32431165'}}
126126
rdar32431165_1(42, "")
127-
// expected-error@-1 {{cannot convert value of type 'String' to expected argument type 'E_32431165'}} {{20-20=E_32431165(rawValue: }} {{22-22=)}}
127+
// expected-error@-1 {{cannot convert value of type 'String' to expected argument type 'E_32431165'}} {{20-20=E_32431165(rawValue: }} {{22-22=) ?? <#default value#>}}
128128

129129
func rdar32431165_2(_: String) {}
130130
func rdar32431165_2(_: Int) {}
@@ -141,6 +141,16 @@ E_32431165.bar == "bar"
141141
"bar" == E_32431165.bar
142142
// expected-error@-1 {{cannot convert value of type 'E_32431165' to expected argument type 'String}} {{10-10=}} {{24-24=.rawValue}}
143143

144+
func rdar32431165_overloaded() -> Int { 42 } // expected-note {{found candidate with type 'Int'}}
145+
func rdar32431165_overloaded() -> String { "A" } // expected-note {{'rdar32431165_overloaded()' produces 'String', not the expected contextual result type 'E_32431165'}}
146+
147+
func test_candidate_diagnostic() {
148+
func test_argument(_: E_32431165) {}
149+
150+
let _: E_32431165 = rdar32431165_overloaded() // expected-error {{no exact matches in call to global function 'rdar32431165_overloaded'}}
151+
test_argument(rdar32431165_overloaded()) // expected-error {{cannot convert value of type 'String' to expected argument type 'E_32431165'}} {{17-17=E_32431165(rawValue: }} {{42-42=) ?? <#default value#>}}
152+
}
153+
144154
func rdar32432253(_ condition: Bool = false) {
145155
let choice: E_32431165 = condition ? .foo : .bar
146156
let _ = choice == "bar"
@@ -165,9 +175,9 @@ func sr8150(bar: Bar) {
165175
sr8150_helper2(bar)
166176
// expected-error@-1 {{cannot convert value of type 'Bar' to expected argument type 'Double'}} {{18-18=}} {{21-21=.rawValue}}
167177
sr8150_helper3(0.0)
168-
// expected-error@-1 {{cannot convert value of type 'Double' to expected argument type 'Bar'}} {{18-18=Bar(rawValue: }} {{21-21=)}}
178+
// expected-error@-1 {{cannot convert value of type 'Double' to expected argument type 'Bar'}} {{18-18=Bar(rawValue: }} {{21-21=) ?? <#default value#>}}
169179
sr8150_helper4(0.0)
170-
// expected-error@-1 {{cannot convert value of type 'Double' to expected argument type 'Bar'}} {{18-18=Bar(rawValue: }} {{21-21=)}}
180+
// expected-error@-1 {{cannot convert value of type 'Double' to expected argument type 'Bar'}} {{18-18=Bar(rawValue: }} {{21-21=) ?? <#default value#>}}
171181
}
172182

173183
class SR8150Box {

0 commit comments

Comments
 (0)