@@ -76,41 +76,44 @@ void VariableLookupAnalysis::emitEnvLivenessWarning(
7676
7777void VariableLookupAnalysis::lookupVar (const ExprVar &Var,
7878 const std::shared_ptr<EnvNode> &Env) {
79- const std::string &Name = Var.id ().name ();
80-
81- bool EnclosedWith = false ; // If there is a "With" enclosed this var name.
82- EnvNode *WithEnv = nullptr ;
83- EnvNode *CurEnv = Env.get ();
79+ const auto &Name = Var.id ().name ();
80+ const auto *CurEnv = Env.get ();
8481 std::shared_ptr<Definition> Def;
82+ std::vector<const EnvNode *> WithEnvs;
8583 for (; CurEnv; CurEnv = CurEnv->parent ()) {
8684 if (CurEnv->defs ().contains (Name)) {
8785 Def = CurEnv->defs ().at (Name);
8886 break ;
8987 }
90- // Find the most nested `with` expression, and set uses.
91- if (CurEnv->isWith () && !EnclosedWith) {
92- EnclosedWith = true ;
93- WithEnv = CurEnv;
88+ // Find all nested "with" expression, variables potentially come from those.
89+ // For example
90+ // with lib;
91+ // with builtins;
92+ // generators <--- this variable may come from "lib" | "builtins"
93+ //
94+ // We cannot determine where it precisely come from, thus mark all Envs
95+ // alive.
96+ if (CurEnv->isWith ()) {
97+ WithEnvs.emplace_back (CurEnv);
9498 }
9599 }
96100
97101 if (Def) {
98102 Def->usedBy (Var);
99103 Results.insert ({&Var, LookupResult{LookupResultKind::Defined, Def}});
100- return ;
101- }
102- if (EnclosedWith) {
103- Def = WithDefs. at (WithEnv-> syntax () );
104- Def-> usedBy (Var);
104+ } else if (!WithEnvs. empty ()) { // comes from enclosed "with" expressions.
105+ for ( const auto *WithEnv : WithEnvs) {
106+ Def = WithDefs. at (WithEnv-> syntax ());
107+ Def-> usedBy (Var );
108+ }
105109 Results.insert ({&Var, LookupResult{LookupResultKind::FromWith, Def}});
106- return ;
110+ } else {
111+ // Otherwise, this variable is undefined.
112+ Results.insert ({&Var, LookupResult{LookupResultKind::Undefined, nullptr }});
113+ Diagnostic &Diag =
114+ Diags.emplace_back (Diagnostic::DK_UndefinedVariable, Var.range ());
115+ Diag << Var.id ().name ();
107116 }
108-
109- // Otherwise, this variable is undefined.
110- Results.insert ({&Var, LookupResult{LookupResultKind::Undefined, nullptr }});
111- Diagnostic &Diag =
112- Diags.emplace_back (Diagnostic::DK_UndefinedVariable, Var.range ());
113- Diag << Var.id ().name ();
114117}
115118
116119void VariableLookupAnalysis::dfs (const ExprLambda &Lambda,
0 commit comments