Skip to content

Commit 4385dd8

Browse files
Creating UnnecessaryCoercion warning fix
1 parent 1c6e35a commit 4385dd8

File tree

7 files changed

+127
-11
lines changed

7 files changed

+127
-11
lines changed

lib/Sema/CSDiagnostics.cpp

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4400,9 +4400,7 @@ bool InaccessibleMemberFailure::diagnoseAsError() {
44004400
auto &cs = getConstraintSystem();
44014401
auto *locator =
44024402
cs.getConstraintLocator(baseExpr, ConstraintLocator::Member);
4403-
if (llvm::any_of(cs.getFixes(), [&](const ConstraintFix *fix) {
4404-
return fix->getLocator() == locator;
4405-
}))
4403+
if (cs.hasFixFor(locator))
44064404
return false;
44074405
}
44084406

@@ -5031,6 +5029,36 @@ bool ThrowingFunctionConversionFailure::diagnoseAsError() {
50315029
return true;
50325030
}
50335031

5032+
bool UnnecessaryCoercionFailure::diagnoseAsError() {
5033+
auto expr = cast<CoerceExpr>(getAnchor());
5034+
auto sourceRange =
5035+
SourceRange(expr->getLoc(), expr->getCastTypeLoc().getSourceRange().End);
5036+
5037+
if (isa<TypeAliasType>(getFromType().getPointer()) &&
5038+
isa<TypeAliasType>(getToType().getPointer())) {
5039+
auto fromTypeAlias = cast<TypeAliasType>(getFromType().getPointer());
5040+
auto toTypeAlias = cast<TypeAliasType>(getToType().getPointer());
5041+
// If the typealias are different, we need a warning
5042+
// mentioning both types.
5043+
if (fromTypeAlias->getDecl() != toTypeAlias->getDecl()) {
5044+
emitDiagnostic(expr->getLoc(),
5045+
diag::unnecessary_same_typealias_type_coercion,
5046+
getFromType(), getToType())
5047+
5048+
.fixItRemove(sourceRange);
5049+
} else {
5050+
emitDiagnostic(expr->getLoc(), diag::unnecessary_same_type_coercion,
5051+
getToType())
5052+
.fixItRemove(sourceRange);
5053+
}
5054+
} else {
5055+
emitDiagnostic(expr->getLoc(), diag::unnecessary_same_type_coercion,
5056+
getToType())
5057+
.fixItRemove(sourceRange);
5058+
}
5059+
return true;
5060+
}
5061+
50345062
bool InOutConversionFailure::diagnoseAsError() {
50355063
auto *anchor = getAnchor();
50365064
auto *locator = getLocator();

lib/Sema/CSDiagnostics.h

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,13 @@ class FailureDiagnostic {
156156
}
157157

158158
/// \returns true is locator hasn't been simplified down to expression.
159-
bool hasComplexLocator() const { return HasComplexLocator; }
159+
bool hasComplexLocator() const {
160+
bool isExplicitCoercion =
161+
getLocator()
162+
->isLastElement<
163+
ConstraintLocator::PathElement::ExplicitTypeCoercion>();
164+
return HasComplexLocator && !isExplicitCoercion;
165+
}
160166

161167
/// \returns A parent expression if sub-expression is contained anywhere
162168
/// in the root expression or `nullptr` otherwise.
@@ -707,8 +713,8 @@ class ContextualFailure : public FailureDiagnostic {
707713
/// If we're trying to convert something to `nil`.
708714
bool diagnoseConversionToNil() const;
709715

710-
// If we're trying to convert something of type "() -> T" to T,
711-
// then we probably meant to call the value.
716+
/// If we're trying to convert something of type "() -> T" to T,
717+
/// then we probably meant to call the value.
712718
bool diagnoseMissingFunctionCall() const;
713719

714720
/// Produce a specialized diagnostic if this is an invalid conversion to Bool.
@@ -1460,11 +1466,11 @@ class MutatingMemberRefOnImmutableBase final : public FailureDiagnostic {
14601466
bool diagnoseAsError() override;
14611467
};
14621468

1463-
// Diagnose an attempt to use AnyObject as the root type of a KeyPath
1464-
//
1465-
// ```swift
1466-
// let keyPath = \AnyObject.bar
1467-
// ```
1469+
/// Diagnose an attempt to use AnyObject as the root type of a KeyPath
1470+
///
1471+
/// ```swift
1472+
/// let keyPath = \AnyObject.bar
1473+
/// ```
14681474
class AnyObjectKeyPathRootFailure final : public FailureDiagnostic {
14691475

14701476
public:
@@ -1774,6 +1780,27 @@ class ExpandArrayIntoVarargsFailure final : public ContextualFailure {
17741780
void tryDropArrayBracketsFixIt(Expr *anchor) const;
17751781
};
17761782

1783+
/// Diagnose a situation where there is an explicit type coercion
1784+
/// to the same type e.g.:
1785+
///
1786+
/// ```swift
1787+
/// Double(1) as Double // redundant cast to 'Double' has no effect
1788+
/// 1 as Double as Double // redundant cast to 'Double' has no effect
1789+
/// let string = "String"
1790+
/// let s = string as String // redundant cast to 'String' has no effect
1791+
/// ```
1792+
class UnnecessaryCoercionFailure final
1793+
: public ContextualFailure {
1794+
1795+
public:
1796+
UnnecessaryCoercionFailure(Expr *root, ConstraintSystem &cs,
1797+
Type fromType, Type toType,
1798+
ConstraintLocator *locator)
1799+
: ContextualFailure(root, cs, fromType, toType, locator) {}
1800+
1801+
bool diagnoseAsError() override;
1802+
};
1803+
17771804
/// Diagnose a situation there is a mismatch between argument and parameter
17781805
/// types e.g.:
17791806
///

lib/Sema/CSFix.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -857,6 +857,36 @@ IgnoreContextualType *IgnoreContextualType::create(ConstraintSystem &cs,
857857
IgnoreContextualType(cs, resultTy, specifiedTy, locator);
858858
}
859859

860+
bool RemoveUnnecessaryCoercion::diagnose(Expr *root, bool asNote) const {
861+
auto &cs = getConstraintSystem();
862+
UnnecessaryCoercionFailure failure(root, cs, getFromType(), getToType(),
863+
getLocator());
864+
return failure.diagnose(asNote);
865+
}
866+
867+
bool RemoveUnnecessaryCoercion::attempt(ConstraintSystem &cs, Type fromType,
868+
Type toType,
869+
ConstraintLocatorBuilder locator) {
870+
if (auto last = locator.last()) {
871+
if (last->is<LocatorPathElt::ExplicitTypeCoercion>()) {
872+
auto expr = cast<CoerceExpr>(locator.getAnchor());
873+
auto toTypeRepr = expr->getCastTypeLoc().getTypeRepr();
874+
875+
// only diagnosing for coercion where the left-side is a DeclRefExpr
876+
// or a explicit/implicit coercion e.g. Double(1) as Double
877+
if (!isa<ImplicitlyUnwrappedOptionalTypeRepr>(toTypeRepr) &&
878+
(isa<DeclRefExpr>(expr->getSubExpr()) ||
879+
isa<CoerceExpr>(expr->getSubExpr()))) {
880+
auto *fix = new (cs.getAllocator()) RemoveUnnecessaryCoercion(
881+
cs, fromType, toType, cs.getConstraintLocator(locator));
882+
883+
return cs.recordFix(fix);
884+
}
885+
}
886+
}
887+
return false;
888+
}
889+
860890
bool IgnoreAssignmentDestinationType::diagnose(Expr *root, bool asNote) const {
861891
auto &cs = getConstraintSystem();
862892
auto *AE = cast<AssignExpr>(getAnchor());

lib/Sema/CSFix.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,9 @@ enum class FixKind : uint8_t {
196196
/// Allow a single tuple parameter to be matched with N arguments
197197
/// by forming all of the given arguments into a single tuple.
198198
AllowTupleSplatForSingleParameter,
199+
200+
/// Remove an unnecessary coercion ('as') if the types are already equal. e.g. Double(1) as Double
201+
RemoveUnnecessaryCoercion,
199202

200203
/// Allow a single argument type mismatch. This is the most generic
201204
/// failure related to argument-to-parameter conversions.
@@ -1340,6 +1343,24 @@ class IgnoreContextualType : public ContextualMismatch {
13401343
ConstraintLocator *locator);
13411344
};
13421345

1346+
class RemoveUnnecessaryCoercion : public ContextualMismatch {
1347+
protected:
1348+
RemoveUnnecessaryCoercion(ConstraintSystem &cs,
1349+
Type fromType, Type toType,
1350+
ConstraintLocator *locator)
1351+
: ContextualMismatch(cs, FixKind::RemoveUnnecessaryCoercion, fromType, toType,
1352+
locator, /*isWarning*/ true) {}
1353+
1354+
public:
1355+
std::string getName() const override { return "remove unnecessary explicit type coercion"; }
1356+
1357+
bool diagnose(Expr *root, bool asNote = false) const override;
1358+
1359+
static bool attempt(ConstraintSystem &cs,
1360+
Type fromType, Type toType,
1361+
ConstraintLocatorBuilder locator);
1362+
};
1363+
13431364
class IgnoreAssignmentDestinationType final : public ContextualMismatch {
13441365
IgnoreAssignmentDestinationType(ConstraintSystem &cs, Type sourceTy,
13451366
Type destTy, ConstraintLocator *locator)

lib/Sema/ConstraintLocator.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ void ConstraintLocator::Profile(llvm::FoldingSetNodeID &id, Expr *anchor,
8686
case KeyPathRoot:
8787
case KeyPathValue:
8888
case KeyPathComponentResult:
89+
case ExplicitTypeCoercion:
8990
auto numValues = numNumericValuesInPathElement(elt.getKind());
9091
for (unsigned i = 0; i < numValues; ++i)
9192
id.AddInteger(elt.getValue(i));
@@ -132,6 +133,7 @@ unsigned LocatorPathElt::getNewSummaryFlags() const {
132133
case ConstraintLocator::KeyPathRoot:
133134
case ConstraintLocator::KeyPathValue:
134135
case ConstraintLocator::KeyPathComponentResult:
136+
case ConstraintLocator::ExplicitTypeCoercion:
135137
return 0;
136138

137139
case ConstraintLocator::FunctionArgument:
@@ -456,6 +458,10 @@ void ConstraintLocator::dump(SourceManager *sm, raw_ostream &out) {
456458
case KeyPathComponentResult:
457459
out << "key path component result";
458460
break;
461+
462+
case ExplicitTypeCoercion:
463+
out << "type coercion";
464+
break;
459465
}
460466
}
461467
out << ']';

lib/Sema/ConstraintLocator.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ class ConstraintLocator : public llvm::FoldingSetNode {
8989
case KeyPathRoot:
9090
case KeyPathValue:
9191
case KeyPathComponentResult:
92+
case ExplicitTypeCoercion:
9293
return 0;
9394

9495
case ContextualType:

lib/Sema/ConstraintLocatorPathElts.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,9 @@ SIMPLE_LOCATOR_PATH_ELT(UnresolvedMember)
164164
/// The candidate witness during protocol conformance checking.
165165
CUSTOM_LOCATOR_PATH_ELT(Witness)
166166

167+
/// An explicit type coercion.
168+
SIMPLE_LOCATOR_PATH_ELT(ExplicitTypeCoercion)
169+
167170
#undef LOCATOR_PATH_ELT
168171
#undef CUSTOM_LOCATOR_PATH_ELT
169172
#undef SIMPLE_LOCATOR_PATH_ELT

0 commit comments

Comments
 (0)