Skip to content

Commit 808e2e3

Browse files
stepanchegfacebook-github-bot
authored andcommitted
Option to run scope resolved without globals
Summary: Following diff D48941531 implements unused loads removal. To find unused loads, the easiest way is to run scope resolved. Before this diff, scope resolver required globals (because it populates globals in AST). Now scope resolver can be run without globals, so every unknown name is resolved to some string. Which is sufficient to find unused globals. Reviewed By: ianlevesque Differential Revision: D48941533 fbshipit-source-id: 1657b352196196d9b2e31dd8b8a23ccf68fc3706
1 parent 7a96cf5 commit 808e2e3

File tree

5 files changed

+69
-16
lines changed

5 files changed

+69
-16
lines changed

starlark/src/eval/compiler/scope/mod.rs

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
*/
1717

1818
pub(crate) mod payload;
19+
pub(crate) mod scope_resolver_globals;
1920
mod tests;
2021

2122
use std::collections::HashMap;
@@ -50,7 +51,6 @@ use crate::codemap::CodeMap;
5051
use crate::codemap::Span;
5152
use crate::environment::names::MutableNames;
5253
use crate::environment::slots::ModuleSlotId;
53-
use crate::environment::Globals;
5454
use crate::environment::Module;
5555
use crate::errors::did_you_mean::did_you_mean;
5656
use crate::eval::compiler::def::CopySlotFromParent;
@@ -63,6 +63,7 @@ use crate::eval::compiler::scope::payload::CstPayload;
6363
use crate::eval::compiler::scope::payload::CstStmt;
6464
use crate::eval::compiler::scope::payload::CstStmtFromAst;
6565
use crate::eval::compiler::scope::payload::CstTypeExpr;
66+
use crate::eval::compiler::scope::scope_resolver_globals::ScopeResolverGlobals;
6667
use crate::eval::runtime::slots::LocalSlotIdCapturedOrNot;
6768
use crate::syntax::Dialect;
6869
use crate::typing::error::InternalError;
@@ -93,7 +94,7 @@ struct ModuleScopeBuilder<'a> {
9394
locals: Vec<ScopeId>,
9495
unscopes: Vec<Unscope>,
9596
codemap: FrozenRef<'static, CodeMap>,
96-
globals: FrozenRef<'static, Globals>,
97+
globals: ScopeResolverGlobals,
9798
errors: Vec<EvalException>,
9899
top_level_stmt_count: usize,
99100
}
@@ -265,7 +266,7 @@ impl<'f> ModuleScopeBuilder<'f> {
265266
frozen_heap: &'f FrozenHeap,
266267
loads: &HashMap<String, Interface>,
267268
stmt: AstStmt,
268-
globals: FrozenRef<'static, Globals>,
269+
globals: ScopeResolverGlobals,
269270
codemap: FrozenRef<'static, CodeMap>,
270271
dialect: &Dialect,
271272
) -> (CstStmt, ModuleScopeBuilder<'f>) {
@@ -371,7 +372,7 @@ impl<'f> ModuleScopes<'f> {
371372
frozen_heap: &'f FrozenHeap,
372373
loads: &HashMap<String, Interface>,
373374
stmt: AstStmt,
374-
globals: FrozenRef<'static, Globals>,
375+
globals: ScopeResolverGlobals,
375376
codemap: FrozenRef<'static, CodeMap>,
376377
dialect: &Dialect,
377378
) -> anyhow::Result<ModuleScopes<'f>> {
@@ -388,7 +389,7 @@ impl<'f> ModuleScopes<'f> {
388389
frozen_heap: &'f FrozenHeap,
389390
loads: &HashMap<String, Interface>,
390391
stmt: AstStmt,
391-
globals: FrozenRef<'static, Globals>,
392+
globals: ScopeResolverGlobals,
392393
codemap: FrozenRef<'static, CodeMap>,
393394
dialect: &Dialect,
394395
) -> (Vec<EvalException>, ModuleScopes<'f>) {
@@ -635,20 +636,23 @@ impl<'f> ModuleScopeBuilder<'f> {
635636
);
636637
}
637638

638-
fn current_scope_all_visible_names_for_did_you_mean(&self) -> Vec<FrozenStringValue> {
639+
fn current_scope_all_visible_names_for_did_you_mean(&self) -> Option<Vec<String>> {
639640
// It is OK to return non-unique identifiers
640-
let mut r: Vec<FrozenStringValue> = Vec::new();
641+
let mut r: Vec<String> = Vec::new();
641642
for &scope_id in self.locals.iter().rev() {
642643
let scope = self.scope_data.get_scope(scope_id);
643-
r.extend(scope.mp.keys().copied());
644+
r.extend(scope.mp.keys().map(|s| s.as_str().to_owned()));
644645
}
645-
r.extend(self.module_bindings.keys().copied());
646-
r.extend(self.globals.names());
647-
r
646+
r.extend(self.module_bindings.keys().map(|s| s.as_str().to_owned()));
647+
r.extend(self.globals.names()?);
648+
Some(r)
648649
}
649650

651+
#[cold]
650652
fn variable_not_found_err(&self, ident: &CstIdent) -> EvalException {
651-
let variants = self.current_scope_all_visible_names_for_did_you_mean();
653+
let variants = self
654+
.current_scope_all_visible_names_for_did_you_mean()
655+
.unwrap_or(Vec::new());
652656
let better = did_you_mean(
653657
ident.node.ident.as_str(),
654658
variants.iter().map(|s| s.as_str()),
@@ -672,7 +676,7 @@ impl<'f> ModuleScopeBuilder<'f> {
672676
let resolved = match self.get_name(self.frozen_heap.alloc_str_intern(&ident.node.ident)) {
673677
None => {
674678
// Must be a global, since we know all variables
675-
match self.globals.get_frozen(&ident.node.ident) {
679+
match self.globals.get_global(&ident.node.ident) {
676680
None => {
677681
self.errors.push(self.variable_not_found_err(ident));
678682
return;
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Copyright 2019 The Starlark in Rust Authors.
3+
* Copyright (c) Facebook, Inc. and its affiliates.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* https://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
use crate::const_frozen_string;
19+
use crate::environment::Globals;
20+
use crate::values::FrozenRef;
21+
use crate::values::FrozenValue;
22+
23+
pub(crate) struct ScopeResolverGlobals {
24+
/// None if unknown.
25+
pub(crate) globals: Option<FrozenRef<'static, Globals>>,
26+
}
27+
28+
impl ScopeResolverGlobals {
29+
pub(crate) fn get_global(&self, name: &str) -> Option<FrozenValue> {
30+
match self.globals {
31+
Some(globals) => globals.get_frozen(name),
32+
None => Some(const_frozen_string!("unknown-global").to_frozen_value()),
33+
}
34+
}
35+
36+
pub(crate) fn names(&self) -> Option<Vec<String>> {
37+
self.globals
38+
.map(|g| g.names().map(|s| s.as_str().to_owned()).collect())
39+
}
40+
}

starlark/src/eval/compiler/scope/tests.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ use crate::eval::compiler::scope::payload::CstAssignIdent;
3333
use crate::eval::compiler::scope::payload::CstAssignTarget;
3434
use crate::eval::compiler::scope::payload::CstExpr;
3535
use crate::eval::compiler::scope::payload::CstStmt;
36+
use crate::eval::compiler::scope::scope_resolver_globals::ScopeResolverGlobals;
3637
use crate::eval::compiler::scope::AssignCount;
3738
use crate::eval::compiler::scope::Captured;
3839
use crate::eval::compiler::scope::ModuleScopes;
@@ -54,7 +55,9 @@ fn test_with_module(program: &str, expected: &str, module: &MutableNames) {
5455
&frozen_heap,
5556
&HashMap::new(),
5657
ast.statement,
57-
FrozenRef::new(Globals::empty()),
58+
ScopeResolverGlobals {
59+
globals: Some(FrozenRef::new(Globals::empty())),
60+
},
5861
codemap,
5962
&Dialect::Extended,
6063
)

starlark/src/eval/mod.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ use crate::collections::symbol_map::Symbol;
4646
use crate::docs::DocString;
4747
use crate::environment::Globals;
4848
use crate::eval::compiler::def::DefInfo;
49+
use crate::eval::compiler::scope::scope_resolver_globals::ScopeResolverGlobals;
4950
use crate::eval::compiler::scope::ModuleScopes;
5051
use crate::eval::compiler::scope::ScopeId;
5152
use crate::eval::compiler::Compiler;
@@ -91,7 +92,9 @@ impl<'v, 'a> Evaluator<'v, 'a> {
9192
self.module_env.frozen_heap(),
9293
&HashMap::new(),
9394
statement,
94-
globals,
95+
ScopeResolverGlobals {
96+
globals: Some(globals),
97+
},
9598
codemap,
9699
&dialect,
97100
)?;

starlark/src/typing/typecheck.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ use crate::codemap::Spanned;
3434
use crate::environment::names::MutableNames;
3535
use crate::environment::Globals;
3636
use crate::eval::compiler::scope::payload::CstStmt;
37+
use crate::eval::compiler::scope::scope_resolver_globals::ScopeResolverGlobals;
3738
use crate::eval::compiler::scope::BindingId;
3839
use crate::eval::compiler::scope::BindingSource;
3940
use crate::eval::compiler::scope::ModuleScopes;
@@ -200,7 +201,9 @@ impl AstModuleTypecheck for AstModule {
200201
&frozen_heap,
201202
loads,
202203
self.statement,
203-
frozen_heap.alloc_any_display_from_debug(globals.dupe()),
204+
ScopeResolverGlobals {
205+
globals: Some(frozen_heap.alloc_any_display_from_debug(globals.dupe())),
206+
},
204207
frozen_heap.alloc_any_display_from_debug(self.codemap.dupe()),
205208
&Dialect::Extended,
206209
);

0 commit comments

Comments
 (0)