Skip to content

Commit 37455b6

Browse files
committed
Optimizer: use formal types instead of SIL types for classifying dynamic casts.
Casts always work with formal rather than lowered types. This fixes a potential bug when lowered types are different than formal types, like function types.
1 parent d52f7d1 commit 37455b6

File tree

5 files changed

+45
-11
lines changed

5 files changed

+45
-11
lines changed

SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyBuiltin.swift

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -269,10 +269,8 @@ private func typesOfValuesAreEqual(_ lhs: Value, _ rhs: Value, in function: Func
269269
return nil
270270
}
271271

272-
let lhsMetatype = lhsExistential.metatype.type
273-
let rhsMetatype = rhsExistential.metatype.type
274-
let lhsTy = lhsMetatype.loweredInstanceTypeOfMetatype(in: function)
275-
let rhsTy = rhsMetatype.loweredInstanceTypeOfMetatype(in: function)
272+
let lhsTy = lhsExistential.metatype.type.canonicalType.instanceTypeOfMetatype
273+
let rhsTy = rhsExistential.metatype.type.canonicalType.instanceTypeOfMetatype
276274
if lhsTy.isDynamicSelf != rhsTy.isDynamicSelf {
277275
return nil
278276
}
@@ -288,14 +286,20 @@ private func typesOfValuesAreEqual(_ lhs: Value, _ rhs: Value, in function: Func
288286
// ((Int, Int) -> ())
289287
// (((Int, Int)) -> ())
290288
//
291-
if lhsMetatype == rhsMetatype {
289+
if lhsTy == rhsTy {
292290
return true
293291
}
294292
// Comparing types of different classes which are in a sub-class relation is not handled by the
295293
// cast optimizer (below).
296294
if lhsTy.isClass && rhsTy.isClass && lhsTy.nominal != rhsTy.nominal {
297295
return false
298296
}
297+
298+
// Failing function casts are not supported by the cast optimizer (below).
299+
// (Reason: "Be conservative about function type relationships we may add in the future.")
300+
if lhsTy.isFunction && rhsTy.isFunction && lhsTy != rhsTy && !lhsTy.hasArchetype && !rhsTy.hasArchetype {
301+
return false
302+
}
299303
}
300304

301305
// If casting in either direction doesn't work, the types cannot be equal.

SwiftCompilerSources/Sources/Optimizer/Utilities/OptUtils.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -899,7 +899,9 @@ func getGlobalInitialization(
899899
return nil
900900
}
901901

902-
func canDynamicallyCast(from sourceType: Type, to destType: Type, in function: Function, sourceTypeIsExact: Bool) -> Bool? {
902+
func canDynamicallyCast(from sourceType: CanonicalType, to destType: CanonicalType,
903+
in function: Function, sourceTypeIsExact: Bool
904+
) -> Bool? {
903905
switch classifyDynamicCastBridged(sourceType.bridged, destType.bridged, function.bridged, sourceTypeIsExact) {
904906
case .willSucceed: return true
905907
case .maySucceed: return nil

include/swift/SILOptimizer/OptimizerBridging.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,7 @@ enum class BridgedDynamicCastResult {
403403
willFail
404404
};
405405

406-
BridgedDynamicCastResult classifyDynamicCastBridged(BridgedType sourceTy, BridgedType destTy,
406+
BridgedDynamicCastResult classifyDynamicCastBridged(BridgedCanType sourceTy, BridgedCanType destTy,
407407
BridgedFunction function,
408408
bool sourceTypeIsExact);
409409

lib/SILOptimizer/PassManager/PassManager.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2120,7 +2120,7 @@ bool BeginApply_canInline(BridgedInstruction beginApply) {
21202120
return swift::SILInliner::canInlineBeginApply(beginApply.getAs<BeginApplyInst>());
21212121
}
21222122

2123-
BridgedDynamicCastResult classifyDynamicCastBridged(BridgedType sourceTy, BridgedType destTy,
2123+
BridgedDynamicCastResult classifyDynamicCastBridged(BridgedCanType sourceTy, BridgedCanType destTy,
21242124
BridgedFunction function,
21252125
bool sourceTypeIsExact) {
21262126
static_assert((int)DynamicCastFeasibility::WillSucceed == (int)BridgedDynamicCastResult::willSucceed);
@@ -2129,8 +2129,8 @@ BridgedDynamicCastResult classifyDynamicCastBridged(BridgedType sourceTy, Bridge
21292129

21302130
return static_cast<BridgedDynamicCastResult>(
21312131
classifyDynamicCast(function.getFunction()->getModule().getSwiftModule(),
2132-
sourceTy.unbridged().getASTType(),
2133-
destTy.unbridged().getASTType(),
2132+
sourceTy.unbridged(),
2133+
destTy.unbridged(),
21342134
sourceTypeIsExact));
21352135
}
21362136

test/SILOptimizer/simplify_builtin.sil

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ bb0:
273273
}
274274

275275
// CHECK-LABEL: sil @different_function_metatype2
276-
// CHECK: [[R:%.*]] = builtin "is_same_metatype"
276+
// CHECK: [[R:%.*]] = integer_literal $Builtin.Int1, 0
277277
// CHECK: return [[R]]
278278
// CHECK: } // end sil function 'different_function_metatype2'
279279
sil @different_function_metatype2 : $@convention(thin) () -> Builtin.Int1 {
@@ -286,6 +286,34 @@ bb0:
286286
return %4 : $Builtin.Int1
287287
}
288288

289+
// CHECK-LABEL: sil @unknown_function_metatype1 :
290+
// CHECK: [[R:%.*]] = builtin "is_same_metatype"
291+
// CHECK: return [[R]]
292+
// CHECK: } // end sil function 'unknown_function_metatype1'
293+
sil @unknown_function_metatype1 : $@convention(thin) <T> () -> Builtin.Int1 {
294+
bb0:
295+
%0 = metatype $@thick ((T) -> Bool).Type
296+
%1 = metatype $@thick ((Int) -> Bool).Type
297+
%2 = init_existential_metatype %0, $@thick Any.Type
298+
%3 = init_existential_metatype %1, $@thick Any.Type
299+
%4 = builtin "is_same_metatype"(%2, %3) : $Builtin.Int1
300+
return %4 : $Builtin.Int1
301+
}
302+
303+
// CHECK-LABEL: sil @unknown_function_metatype2 :
304+
// CHECK: [[R:%.*]] = builtin "is_same_metatype"
305+
// CHECK: return [[R]]
306+
// CHECK: } // end sil function 'unknown_function_metatype2'
307+
sil @unknown_function_metatype2 : $@convention(thin) <T> () -> Builtin.Int1 {
308+
bb0:
309+
%0 = metatype $@thick ((Int) -> Bool).Type
310+
%1 = metatype $@thick ((T) -> Bool).Type
311+
%2 = init_existential_metatype %0, $@thick Any.Type
312+
%3 = init_existential_metatype %1, $@thick Any.Type
313+
%4 = builtin "is_same_metatype"(%2, %3) : $Builtin.Int1
314+
return %4 : $Builtin.Int1
315+
}
316+
289317
// CHECK-LABEL: sil @same_metatype_dynamic_self
290318
// CHECK: [[R:%.*]] = integer_literal $Builtin.Int1, -1
291319
// CHECK-NEXT: return [[R]]

0 commit comments

Comments
 (0)