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) {
25822582 // unsafe, then the conformance must be unsafe.
25832583 if (auto witness = conformance->getWitnessUncached (valueRequirement)) {
25842584 if (isUnsafe (witness.getDeclRef ()) &&
2585- !isUnsafe (
2586- ConcreteDeclRef (
2587- valueRequirement,
2588- witness.getRequirementToWitnessThunkSubs ()))) {
2585+ !isUnsafeInConformance (valueRequirement, witness, conformance)) {
25892586 unsafeUses.push_back (
25902587 UnsafeUse::forWitness (
25912588 witness.getDecl (), requirement, conformance));
Original file line number Diff line number Diff line change @@ -300,3 +300,21 @@ bool swift::isUnsafe(ConcreteDeclRef declRef) {
300300
301301 return false ;
302302}
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 1717
1818namespace swift {
1919
20+ class Witness ;
21+
2022// / Diagnose the given unsafe use right now.
2123void diagnoseUnsafeUse (const UnsafeUse &use, bool asNote = false );
2224
@@ -28,6 +30,11 @@ void diagnoseUnsafeUsesIn(const Decl *decl);
2830// / either explicitly (@unsafe) or because it references an unsafe type.
2931bool isUnsafe (ConcreteDeclRef declRef);
3032
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);
3138}
3239
3340#endif // SWIFT_SEMA_TYPE_CHECK_UNSAFE_H
Original file line number Diff line number Diff line change @@ -53,6 +53,18 @@ extension ConformsToMultiP: MultiP {
5353 @unsafe func f( ) -> UnsafeSuper { . init( ) }
5454}
5555
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+
5668// -----------------------------------------------------------------------
5769// Overrides
5870// -----------------------------------------------------------------------
You can’t perform that action at this time.
0 commit comments