Thirty-one apps carry the same banner component. It must not appear in store screenshots, so I bulk-inserted one guard line into all 31.
For verification I ran a parse:
xcrun swiftc -parse <file>All 31 passed.
When you make a bulk edit, is the checker you picked capable of catching the mistake you're able to make?
Then I ran a typecheck
All 31 failed.
error: type 'PromoConfig' has no member 'isScreenshotMode'I had planted the call to the guard and not its definition.
-parse only looks at syntax. Code calling a nonexistent member is syntactically perfect, so it passes. Had I committed that, 31 apps would have broken simultaneously.
The earlier mistake
Why was the definition missing? Because my pre-check concluded "the definition already exists."
The basis for that conclusion: I had grepped the file for the string isScreenshotMode.
The string was in the file. It was a member of a different type.
The presence of a string tells you nothing about membership. The other direction of wrong verification is in when my verification cried wolf. To check which type owns a member, cut out that type's declaration block and read it — don't grep the file.
What would you do?
You've put the same line into 31 repositories. What gates the commit?
- Parse — 31 files in seconds. And it catches none of the mistakes you just made.
- Typecheck — slower, but catches "no such member." It doesn't know other files' types, so harmless errors mix in.
- A real build — conclusive, and far too expensive to run across 31.
I made the second the gate and ran the third as a per-shape sample.
swiftc -typecheck \
-sdk $(xcrun --sdk iphonesimulator --show-sdk-path) \
-target arm64-apple-ios17.0-simulator <file>A typecheck isn't simply green or red either
Single-file typechecking doesn't know types declared in other files. So errors unrelated to your edit come out mixed in.
That doesn't filter itself. You separate them one by one by checking whether the pre-change original produces the same error.
git show HEAD:<path> > /tmp/before.swift # same error there = not my editTwo apps were that case this time.
Three checks
- Was your bulk-edit checker chosen for being fast? Find out why it's fast. Usually because it doesn't look at something.
- Did you decide "already defined" with a grep? The string can be in the file while the member belongs to another type.
- Are you treating a passing check as a successful build? It isn't. Build at least one of each shape for real.
The honest part
A passing typecheck doesn't guarantee the app builds. The only conclusive check is a real build, and that's too expensive to run 31 times.
The edits fell into three shapes, so I built one per shape — two runs. Which means the remaining risk is still there. I'm writing this paragraph so I don't record a sampled check as if it were exhaustive.
The numbers: -parse 31/31 pass → -typecheck 31/31 fail → definition planted, re-check passes → 2 real builds, one per shape, pass.