File tree Expand file tree Collapse file tree 4 files changed +38
-4
lines changed Expand file tree Collapse file tree 4 files changed +38
-4
lines changed Original file line number Diff line number Diff line change @@ -2582,10 +2582,7 @@ checkIndividualConformance(NormalProtocolConformance *conformance) {
2582
2582
// unsafe, then the conformance must be unsafe.
2583
2583
if (auto witness = conformance->getWitnessUncached (valueRequirement)) {
2584
2584
if (isUnsafe (witness.getDeclRef ()) &&
2585
- !isUnsafe (
2586
- ConcreteDeclRef (
2587
- valueRequirement,
2588
- witness.getRequirementToWitnessThunkSubs ()))) {
2585
+ !isUnsafeInConformance (valueRequirement, witness, conformance)) {
2589
2586
unsafeUses.push_back (
2590
2587
UnsafeUse::forWitness (
2591
2588
witness.getDecl (), requirement, conformance));
Original file line number Diff line number Diff line change @@ -300,3 +300,21 @@ bool swift::isUnsafe(ConcreteDeclRef declRef) {
300
300
301
301
return false ;
302
302
}
303
+
304
+ bool swift::isUnsafeInConformance (const ValueDecl *requirement,
305
+ const Witness &witness,
306
+ NormalProtocolConformance *conformance) {
307
+ if (requirement->isUnsafe ())
308
+ return true ;
309
+
310
+ Type requirementType = requirement->getInterfaceType ();
311
+ Type requirementTypeInContext;
312
+ auto requirementSubs = witness.getRequirementToWitnessThunkSubs ();
313
+ if (auto genericFnType = requirementType->getAs <GenericFunctionType>()) {
314
+ requirementTypeInContext =
315
+ genericFnType->substGenericArgs (requirementSubs);
316
+ } else {
317
+ requirementTypeInContext = requirementType.subst (requirementSubs);
318
+ }
319
+ return requirementTypeInContext->isUnsafe ();
320
+ }
Original file line number Diff line number Diff line change 17
17
18
18
namespace swift {
19
19
20
+ class Witness ;
21
+
20
22
// / Diagnose the given unsafe use right now.
21
23
void diagnoseUnsafeUse (const UnsafeUse &use, bool asNote = false );
22
24
@@ -28,6 +30,11 @@ void diagnoseUnsafeUsesIn(const Decl *decl);
28
30
// / either explicitly (@unsafe) or because it references an unsafe type.
29
31
bool isUnsafe (ConcreteDeclRef declRef);
30
32
33
+ // / Whether the given requirement should be considered unsafe for the given
34
+ // / conformance.
35
+ bool isUnsafeInConformance (const ValueDecl *requirement,
36
+ const Witness &witness,
37
+ NormalProtocolConformance *conformance);
31
38
}
32
39
33
40
#endif // SWIFT_SEMA_TYPE_CHECK_UNSAFE_H
Original file line number Diff line number Diff line change @@ -53,6 +53,18 @@ extension ConformsToMultiP: MultiP {
53
53
@unsafe func f( ) -> UnsafeSuper { . init( ) }
54
54
}
55
55
56
+ protocol GenericP {
57
+ associatedtype Ptr
58
+
59
+ func f< T> ( _: T , _: Ptr )
60
+ }
61
+
62
+ // expected-warning@+1{{conformance of 'ConformsToGenericP' to protocol 'GenericP' involves unsafe code; use '@unsafe' to indicate that the conformance is not memory-safe}}
63
+ struct ConformsToGenericP : GenericP {
64
+ typealias Ptr = Int
65
+ @unsafe func f< T> ( _: T , _: Ptr ) { } // expected-note{{unsafe instance method 'f' cannot satisfy safe requirement}}
66
+ }
67
+
56
68
// -----------------------------------------------------------------------
57
69
// Overrides
58
70
// -----------------------------------------------------------------------
You can’t perform that action at this time.
0 commit comments