mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[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`.
This commit is contained in:
@@ -3135,6 +3135,39 @@ bool ConstraintSystem::repairFailures(
|
||||
return false;
|
||||
};
|
||||
|
||||
// Check whether given `rawReprType` does indeed conform to `RawRepresentable`
|
||||
// and if so check that given `valueType` matches its `RawValue` type. If that
|
||||
// condition holds add a tailored fix which is going to suggest to explicitly
|
||||
// construct a raw representable type from a given value type.
|
||||
auto repairByExplicitRawRepresentativeUse =
|
||||
[&](Type origValueType, Type origRawReprType) -> bool {
|
||||
auto rawReprType = origRawReprType;
|
||||
// Let's unwrap a single level of optionality since
|
||||
// diagnostic is going to suggest failable initializer anyway.
|
||||
if (auto objType = rawReprType->getOptionalObjectType())
|
||||
rawReprType = objType;
|
||||
|
||||
auto valueType = origValueType;
|
||||
// If value is optional diagnostic would suggest using `Optional.map` in
|
||||
// combination with `<Type>(rawValue: ...)` initializer.
|
||||
if (auto objType = valueType->getOptionalObjectType())
|
||||
valueType = objType;
|
||||
|
||||
auto rawValue = isRawRepresentable(*this, rawReprType);
|
||||
if (!rawValue)
|
||||
return false;
|
||||
|
||||
auto result = matchTypes(valueType, rawValue, ConstraintKind::Conversion,
|
||||
TMF_ApplyingFix, locator);
|
||||
|
||||
if (result.isFailure())
|
||||
return false;
|
||||
|
||||
conversionsOrFixes.push_back(ExplicitlyConstructRawRepresentable::create(
|
||||
*this, origRawReprType, origValueType, getConstraintLocator(locator)));
|
||||
return true;
|
||||
};
|
||||
|
||||
auto hasConversionOrRestriction = [&](ConversionRestrictionKind kind) {
|
||||
return llvm::any_of(conversionsOrFixes,
|
||||
[kind](const RestrictionOrFix correction) {
|
||||
@@ -3351,6 +3384,10 @@ bool ConstraintSystem::repairFailures(
|
||||
conversionsOrFixes, locator))
|
||||
return true;
|
||||
|
||||
// `rhs` - is an assignment destination and `lhs` is its source.
|
||||
if (repairByExplicitRawRepresentativeUse(lhs, rhs))
|
||||
return true;
|
||||
|
||||
// Let's try to match source and destination types one more
|
||||
// time to see whether they line up, if they do - the problem is
|
||||
// related to immutability, otherwise it's a type mismatch.
|
||||
@@ -3583,12 +3620,6 @@ bool ConstraintSystem::repairFailures(
|
||||
break;
|
||||
}
|
||||
|
||||
if (auto *fix = ExplicitlyConstructRawRepresentable::attempt(
|
||||
*this, lhs, rhs, locator)) {
|
||||
conversionsOrFixes.push_back(fix);
|
||||
break;
|
||||
}
|
||||
|
||||
if (auto *fix = UseValueTypeOfRawRepresentative::attempt(*this, lhs, rhs,
|
||||
locator)) {
|
||||
conversionsOrFixes.push_back(fix);
|
||||
@@ -3624,6 +3655,10 @@ bool ConstraintSystem::repairFailures(
|
||||
if (lhs->hasHole() || rhs->hasHole())
|
||||
return true;
|
||||
|
||||
// `lhs` - is an argument and `rhs` is a parameter type.
|
||||
if (repairByExplicitRawRepresentativeUse(lhs, rhs))
|
||||
break;
|
||||
|
||||
if (repairViaOptionalUnwrap(*this, lhs, rhs, matchKind, conversionsOrFixes,
|
||||
locator))
|
||||
break;
|
||||
@@ -3854,6 +3889,10 @@ bool ConstraintSystem::repairFailures(
|
||||
}))
|
||||
break;
|
||||
|
||||
// `lhs` - is an result type and `rhs` is a contextual type.
|
||||
if (repairByExplicitRawRepresentativeUse(lhs, rhs))
|
||||
break;
|
||||
|
||||
conversionsOrFixes.push_back(IgnoreContextualType::create(
|
||||
*this, lhs, rhs, getConstraintLocator(locator)));
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user