[Strict memory safety] Show issues with unsafe constructs in the for..in loop

We weren't showing the unsafe uses when we determine that a for..in
loop is unsafe. Do so, which generally means complaining about `next()`
being unsafe. Fixes rdar://151237127
This commit is contained in:
Doug Gregor
2025-05-30 18:42:50 -07:00
parent 73031240fa
commit efacceeacd
3 changed files with 10 additions and 0 deletions

View File

@@ -4597,6 +4597,10 @@ private:
auto insertionLoc = S->getPattern()->getStartLoc();
Ctx.Diags.diagnose(S->getForLoc(), diag::for_unsafe_without_unsafe)
.fixItInsert(insertionLoc, "unsafe ");
for (const auto &unsafeUse : classification.getUnsafeUses()) {
diagnoseUnsafeUse(unsafeUse);
}
}
} else if (S->getUnsafeLoc().isValid()) {
// Extraneous "unsafe" on the sequence.

View File

@@ -89,10 +89,12 @@ struct UnsafeAsSequence: @unsafe Sequence, @unsafe IteratorProtocol {
func testUnsafeAsSequenceForEach() {
let uas = UnsafeAsSequence()
// expected-note@+2{{reference to unsafe instance method 'next()'}}
// expected-warning@+1{{expression uses unsafe constructs but is not marked with 'unsafe'}}{{12-12=unsafe }}
for _ in uas { } // expected-note{{conformance}}
// expected-warning@-1{{for-in loop uses unsafe constructs but is not marked with 'unsafe'}}{{documentation-file=strict-memory-safety}}{{7-7=unsafe }}
// expected-note@+1{{reference to unsafe instance method 'next()'}}
for _ in unsafe uas { } // expected-warning{{for-in loop uses unsafe constructs but is not marked with 'unsafe'}}{{documentation-file=strict-memory-safety}}{{7-7=unsafe }}
for unsafe _ in unsafe uas { } // okay
@@ -118,6 +120,7 @@ struct SequenceWithUnsafeIterator: Sequence {
func testUnsafeIteratorForEach() {
let swui = SequenceWithUnsafeIterator()
// expected-note@+1{{reference to unsafe instance method 'next()'}}
for _ in swui { } // expected-warning{{for-in loop uses unsafe constructs but is not marked with 'unsafe'}}{{7-7=unsafe }}
for unsafe _ in swui { } // okay, it's only the iterator that's unsafe
}

View File

@@ -144,9 +144,12 @@ struct UnsafeSequence: @unsafe IteratorProtocol, @unsafe Sequence {
}
func forEachLoop(us: UnsafeSequence) {
// expected-note@+1{{reference to unsafe instance method 'next()'}}
for _ in us { } // expected-warning{{expression uses unsafe constructs but is not marked with 'unsafe'}}{{documentation-file=strict-memory-safety}}{{12-12=unsafe }}
// expected-note@-1{{'@unsafe' conformance of 'UnsafeSequence' to protocol 'Sequence' involves unsafe code}}
// expected-warning@-2{{for-in loop uses unsafe constructs but is not marked with 'unsafe'}}{{documentation-file=strict-memory-safety}}
// expected-note@+1{{reference to unsafe instance method 'next()'}}
for _ in unsafe us { }
// expected-warning@-1{{for-in loop uses unsafe constructs but is not marked with 'unsafe'}}{{documentation-file=strict-memory-safety}}
}