Skip to content

Commit d55eed4

Browse files
[Sema][CSApply] Moving some checked cast diagnostics to a fix format (#34980)
* [Sema] Implementing is runtime check always true diagnostic as a fix * [AST] Implement getWithoutThrows on function type * [CSSimplify] Detect that checked cast types conversion is always true and record warning fix * [test] Some additional test cases for SR-13789 * [Sema] Fixing typo on fix name * [Sema] Move and adjust the ConditionalCast diagnostics to the fix format * [Sema] Remove some checked cast diagnostics from check constraints and move to fix * [Sema] Renaming checked cast coercible types fix * [Sema] Some adjustments and rewrite on the logic for downcast record fix * [Sema] Move logic of runtime function type to AllowUnsupportedRuntimeCheckedCast::attempt * [Sema] Abstract checked cast fix logic to static function and minor adjustments * [Sema] Renamings from review
1 parent a2996b7 commit d55eed4

16 files changed

+688
-144
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1019,6 +1019,13 @@ WARNING(isa_is_always_true,none, "'%0' test is always true",
10191019
WARNING(isa_is_foreign_check,none,
10201020
"'is' test is always true because %0 is a Core Foundation type",
10211021
(Type))
1022+
WARNING(checked_cast_not_supported,none,
1023+
"runtime conversion from %0 to %1 is not supported; "
1024+
"%select{'is' test|cast}2 always fails",
1025+
(Type, Type, unsigned))
1026+
NOTE(checked_cast_not_supported_coerce_instead,none,
1027+
"consider using 'as' coercion instead", ())
1028+
10221029
WARNING(conditional_downcast_coercion,none,
10231030
"conditional cast from %0 to %1 always succeeds",
10241031
(Type, Type))

include/swift/AST/Types.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3139,6 +3139,9 @@ class AnyFunctionType : public TypeBase {
31393139

31403140
AnyFunctionType *getWithoutDifferentiability() const;
31413141

3142+
/// Return the function type without the throwing.
3143+
AnyFunctionType *getWithoutThrowing() const;
3144+
31423145
/// True if the parameter declaration it is attached to is guaranteed
31433146
/// to not persist the closure for longer than the duration of the call.
31443147
bool isNoEscape() const {

include/swift/Sema/CSFix.h

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,19 @@ enum class FixKind : uint8_t {
294294
/// Explicitly specify the type to disambiguate between possible member base
295295
/// types.
296296
SpecifyBaseTypeForOptionalUnresolvedMember,
297+
298+
/// Allow a runtime checked cast from an optional type where we statically
299+
/// know the result is always succeed.
300+
AllowCheckedCastCoercibleOptionalType,
301+
302+
/// Allow a runtime checked cast where we statically know the result
303+
/// is always succeed.
304+
AllowAlwaysSucceedCheckedCast,
305+
306+
/// Allow a runtime checked cast where at compile time the from is
307+
/// convertible, but runtime does not support such convertions. e.g.
308+
/// function type casts.
309+
AllowUnsupportedRuntimeCheckedCast,
297310
};
298311

299312
class ConstraintFix {
@@ -2196,6 +2209,80 @@ class SpecifyBaseTypeForOptionalUnresolvedMember final : public ConstraintFix {
21962209
MemberLookupResult result, ConstraintLocator *locator);
21972210
};
21982211

2212+
class CheckedCastContextualMismatchWarning : public ContextualMismatch {
2213+
protected:
2214+
CheckedCastContextualMismatchWarning(ConstraintSystem &cs, FixKind fixKind,
2215+
Type fromType, Type toType,
2216+
CheckedCastKind kind,
2217+
ConstraintLocator *locator)
2218+
: ContextualMismatch(cs, fixKind, fromType, toType, locator,
2219+
/*isWarning*/ true),
2220+
CastKind(kind) {}
2221+
CheckedCastKind CastKind;
2222+
};
2223+
2224+
class AllowCheckedCastCoercibleOptionalType final
2225+
: public CheckedCastContextualMismatchWarning {
2226+
AllowCheckedCastCoercibleOptionalType(ConstraintSystem &cs, Type fromType,
2227+
Type toType, CheckedCastKind kind,
2228+
ConstraintLocator *locator)
2229+
: CheckedCastContextualMismatchWarning(
2230+
cs, FixKind::AllowCheckedCastCoercibleOptionalType, fromType,
2231+
toType, kind, locator) {}
2232+
2233+
public:
2234+
std::string getName() const override {
2235+
return "checked cast coercible optional";
2236+
}
2237+
bool diagnose(const Solution &solution, bool asNote = false) const override;
2238+
2239+
static AllowCheckedCastCoercibleOptionalType *
2240+
create(ConstraintSystem &cs, Type fromType, Type toType, CheckedCastKind kind,
2241+
ConstraintLocator *locator);
2242+
};
2243+
2244+
class AllowAlwaysSucceedCheckedCast final
2245+
: public CheckedCastContextualMismatchWarning {
2246+
AllowAlwaysSucceedCheckedCast(ConstraintSystem &cs, Type fromType,
2247+
Type toType, CheckedCastKind kind,
2248+
ConstraintLocator *locator)
2249+
: CheckedCastContextualMismatchWarning(
2250+
cs, FixKind::AllowUnsupportedRuntimeCheckedCast, fromType, toType,
2251+
kind, locator) {}
2252+
2253+
public:
2254+
std::string getName() const override { return "checked cast always succeed"; }
2255+
bool diagnose(const Solution &solution, bool asNote = false) const override;
2256+
2257+
static AllowAlwaysSucceedCheckedCast *create(ConstraintSystem &cs,
2258+
Type fromType, Type toType,
2259+
CheckedCastKind kind,
2260+
ConstraintLocator *locator);
2261+
};
2262+
2263+
class AllowUnsupportedRuntimeCheckedCast final
2264+
: public CheckedCastContextualMismatchWarning {
2265+
AllowUnsupportedRuntimeCheckedCast(ConstraintSystem &cs, Type fromType,
2266+
Type toType, CheckedCastKind kind,
2267+
ConstraintLocator *locator)
2268+
: CheckedCastContextualMismatchWarning(
2269+
cs, FixKind::AllowUnsupportedRuntimeCheckedCast, fromType, toType,
2270+
kind, locator) {}
2271+
2272+
public:
2273+
std::string getName() const override {
2274+
return "runtime unsupported checked cast";
2275+
}
2276+
bool diagnose(const Solution &solution, bool asNote = false) const override;
2277+
2278+
static bool runtimeSupportedFunctionTypeCast(FunctionType *fnFromType,
2279+
FunctionType *fnToType);
2280+
2281+
static AllowUnsupportedRuntimeCheckedCast *
2282+
attempt(ConstraintSystem &cs, Type fromType, Type toType,
2283+
CheckedCastKind kind, ConstraintLocator *locator);
2284+
};
2285+
21992286
} // end namespace constraints
22002287
} // end namespace swift
22012288

lib/AST/Type.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5115,6 +5115,11 @@ AnyFunctionType *AnyFunctionType::getWithoutDifferentiability() const {
51155115
getResult(), nonDiffExtInfo);
51165116
}
51175117

5118+
AnyFunctionType *AnyFunctionType::getWithoutThrowing() const {
5119+
auto info = getExtInfo().intoBuilder().withThrows(false).build();
5120+
return withExtInfo(info);
5121+
}
5122+
51185123
Optional<TangentSpace>
51195124
TypeBase::getAutoDiffTangentSpace(LookupConformanceFn lookupConformance) {
51205125
assert(lookupConformance);

lib/Sema/CSApply.cpp

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3558,8 +3558,6 @@ namespace {
35583558

35593559
case CheckedCastKind::Coercion:
35603560
case CheckedCastKind::BridgingCoercion:
3561-
// Check is trivially true.
3562-
ctx.Diags.diagnose(expr->getLoc(), diag::isa_is_always_true, "is");
35633561
expr->setCastKind(castKind);
35643562
break;
35653563
case CheckedCastKind::ValueCast:
@@ -3979,7 +3977,6 @@ namespace {
39793977
// Rewrite ForcedCheckedCastExpr based on what the solver computed.
39803978
Expr *visitForcedCheckedCastExpr(ForcedCheckedCastExpr *expr) {
39813979
// The subexpression is always an rvalue.
3982-
auto &ctx = cs.getASTContext();
39833980
auto sub = cs.coerceToRValue(expr->getSubExpr());
39843981
expr->setSubExpr(sub);
39853982

@@ -4007,19 +4004,6 @@ namespace {
40074004
return nullptr;
40084005
case CheckedCastKind::Coercion:
40094006
case CheckedCastKind::BridgingCoercion: {
4010-
if (cs.getType(sub)->isEqual(toType)) {
4011-
ctx.Diags.diagnose(expr->getLoc(), diag::forced_downcast_noop, toType)
4012-
.fixItRemove(SourceRange(expr->getLoc(),
4013-
castTypeRepr->getSourceRange().End));
4014-
4015-
} else {
4016-
ctx.Diags
4017-
.diagnose(expr->getLoc(), diag::forced_downcast_coercion,
4018-
cs.getType(sub), toType)
4019-
.fixItReplace(SourceRange(expr->getLoc(), expr->getExclaimLoc()),
4020-
"as");
4021-
}
4022-
40234007
expr->setCastKind(castKind);
40244008
cs.setType(expr, toType);
40254009
return expr;
@@ -4111,8 +4095,6 @@ namespace {
41114095

41124096
case CheckedCastKind::Coercion:
41134097
case CheckedCastKind::BridgingCoercion: {
4114-
ctx.Diags.diagnose(expr->getLoc(), diag::conditional_downcast_coercion,
4115-
fromType, toType);
41164098
expr->setCastKind(castKind);
41174099
cs.setType(expr, OptionalType::get(toType));
41184100
return expr;

0 commit comments

Comments
 (0)