@@ -1195,7 +1195,12 @@ void MissingOptionalUnwrapFailure::offerForceUnwrapFixIt(
11951195 }
11961196}
11971197
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.
11981202class VarDeclMultipleReferencesChecker : public ASTWalker {
1203+ DeclContext *DC;
11991204 VarDecl *varDecl;
12001205 int count;
12011206
@@ -1204,11 +1209,30 @@ class VarDeclMultipleReferencesChecker : public ASTWalker {
12041209 if (DRE->getDecl () == varDecl)
12051210 ++count;
12061211 }
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+
12071230 return { true , E };
12081231 }
12091232
12101233public:
1211- VarDeclMultipleReferencesChecker (VarDecl *varDecl) : varDecl(varDecl),count(0 ) {}
1234+ VarDeclMultipleReferencesChecker (DeclContext *DC, VarDecl *varDecl)
1235+ : DC(DC), varDecl(varDecl),count(0 ) {}
12121236 int referencesCount () { return count; }
12131237};
12141238
@@ -1267,12 +1291,10 @@ bool MissingOptionalUnwrapFailure::diagnoseAsError() {
12671291 if (auto varDecl = dyn_cast<VarDecl>(declRef->getDecl ())) {
12681292 bool singleUse = false ;
12691293 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 ;
12761298 }
12771299
12781300 PatternBindingDecl *binding = varDecl->getParentPatternBinding ();
0 commit comments