@@ -1195,7 +1195,12 @@ void MissingOptionalUnwrapFailure::offerForceUnwrapFixIt(
1195
1195
}
1196
1196
}
1197
1197
1198
+ // FIXME: This walks a partially-type checked function body, which
1199
+ // is not guaranteed to yield consistent results. We should come up
1200
+ // with another way of performing this analysis, for example by moving
1201
+ // it to a post-type checking pass in MiscDiagnostics.
1198
1202
class VarDeclMultipleReferencesChecker : public ASTWalker {
1203
+ DeclContext *DC;
1199
1204
VarDecl *varDecl;
1200
1205
int count;
1201
1206
@@ -1204,11 +1209,30 @@ class VarDeclMultipleReferencesChecker : public ASTWalker {
1204
1209
if (DRE->getDecl () == varDecl)
1205
1210
++count;
1206
1211
}
1212
+
1213
+ // FIXME: We can see UnresolvedDeclRefExprs here because we have
1214
+ // not yet run preCheckExpression() on the entire function body
1215
+ // yet.
1216
+ //
1217
+ // We could consider pre-checking more eagerly.
1218
+ if (auto *UDRE = dyn_cast<UnresolvedDeclRefExpr>(E)) {
1219
+ auto name = UDRE->getName ();
1220
+ auto loc = UDRE->getLoc ();
1221
+ if (name.isSimpleName (varDecl->getName ()) && loc.isValid ()) {
1222
+ auto *otherDecl =
1223
+ ASTScope::lookupSingleLocalDecl (DC->getParentSourceFile (),
1224
+ name.getFullName (), loc);
1225
+ if (otherDecl == varDecl)
1226
+ ++count;
1227
+ }
1228
+ }
1229
+
1207
1230
return { true , E };
1208
1231
}
1209
1232
1210
1233
public:
1211
- VarDeclMultipleReferencesChecker (VarDecl *varDecl) : varDecl(varDecl),count(0 ) {}
1234
+ VarDeclMultipleReferencesChecker (DeclContext *DC, VarDecl *varDecl)
1235
+ : DC(DC), varDecl(varDecl),count(0 ) {}
1212
1236
int referencesCount () { return count; }
1213
1237
};
1214
1238
@@ -1267,12 +1291,10 @@ bool MissingOptionalUnwrapFailure::diagnoseAsError() {
1267
1291
if (auto varDecl = dyn_cast<VarDecl>(declRef->getDecl ())) {
1268
1292
bool singleUse = false ;
1269
1293
AbstractFunctionDecl *AFD = nullptr ;
1270
- if (auto contextDecl = varDecl->getDeclContext ()->getAsDecl ()) {
1271
- if ((AFD = dyn_cast<AbstractFunctionDecl>(contextDecl))) {
1272
- auto checker = VarDeclMultipleReferencesChecker (varDecl);
1273
- AFD->getBody ()->walk (checker);
1274
- singleUse = checker.referencesCount () == 1 ;
1275
- }
1294
+ if ((AFD = dyn_cast<AbstractFunctionDecl>(varDecl->getDeclContext ()))) {
1295
+ auto checker = VarDeclMultipleReferencesChecker (getDC (), varDecl);
1296
+ AFD->getBody ()->walk (checker);
1297
+ singleUse = checker.referencesCount () == 1 ;
1276
1298
}
1277
1299
1278
1300
PatternBindingDecl *binding = varDecl->getParentPatternBinding ();
0 commit comments