diff options
3 files changed, 30 insertions, 5 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/Environment.java b/src/main/java/com/google/devtools/build/lib/syntax/Environment.java index d4e6403312..eb06a10862 100644 --- a/src/main/java/com/google/devtools/build/lib/syntax/Environment.java +++ b/src/main/java/com/google/devtools/build/lib/syntax/Environment.java @@ -142,6 +142,11 @@ public final class Environment implements Freezable { ? ImmutableEmptyLexicalFrame.INSTANCE : new MutableLexicalFrame(mutability); } + + static LexicalFrame createForUserDefinedFunctionCall(Mutability mutability, int numArgs) { + Preconditions.checkState(!mutability.isFrozen()); + return new MutableLexicalFrame(mutability, /*initialCapacity=*/ numArgs); + } } private static final class ImmutableEmptyLexicalFrame implements LexicalFrame { @@ -184,10 +189,16 @@ public final class Environment implements Freezable { private static final class MutableLexicalFrame implements LexicalFrame { private final Mutability mutability; /** Bindings are maintained in order of creation. */ - private final LinkedHashMap<String, Object> bindings = new LinkedHashMap<>(); + private final LinkedHashMap<String, Object> bindings; - public MutableLexicalFrame(Mutability mutability) { + private MutableLexicalFrame(Mutability mutability, int initialCapacity) { this.mutability = mutability; + this.bindings = new LinkedHashMap<>(initialCapacity); + } + + private MutableLexicalFrame(Mutability mutability) { + this.mutability = mutability; + this.bindings = new LinkedHashMap<>(); } @Override diff --git a/src/main/java/com/google/devtools/build/lib/syntax/UserDefinedFunction.java b/src/main/java/com/google/devtools/build/lib/syntax/UserDefinedFunction.java index b4fc95f5aa..485bac26e8 100644 --- a/src/main/java/com/google/devtools/build/lib/syntax/UserDefinedFunction.java +++ b/src/main/java/com/google/devtools/build/lib/syntax/UserDefinedFunction.java @@ -63,10 +63,12 @@ public class UserDefinedFunction extends BaseFunction { getName(), env.getCurrentFunction().getName())); } - Profiler.instance().startTask(ProfilerTask.SKYLARK_USER_FN, getName()); + ImmutableList<String> names = signature.getSignature().getNames(); + LexicalFrame lexicalFrame = + LexicalFrame.createForUserDefinedFunctionCall(env.mutability(), /*numArgs=*/ names.size()); try { - env.enterScope(this, LexicalFrame.create(env.mutability()), ast, definitionGlobals); - ImmutableList<String> names = signature.getSignature().getNames(); + Profiler.instance().startTask(ProfilerTask.SKYLARK_USER_FN, getName()); + env.enterScope(this, lexicalFrame, ast, definitionGlobals); // Registering the functions's arguments as variables in the local Environment int i = 0; diff --git a/src/test/java/com/google/devtools/build/lib/syntax/FunctionTest.java b/src/test/java/com/google/devtools/build/lib/syntax/FunctionTest.java index ff8dddc596..f91e2a8a72 100644 --- a/src/test/java/com/google/devtools/build/lib/syntax/FunctionTest.java +++ b/src/test/java/com/google/devtools/build/lib/syntax/FunctionTest.java @@ -200,6 +200,18 @@ public class FunctionTest extends EvaluationTestCase { } @Test + public void testFunctionParamCanShadowGlobalVarAfterGlobalVarIsRead() throws Exception { + eval("a = 1", + "def func2(a):", + " return 0", + "def func1():", + " dummy = a", + " return func2(2)", + "b = func1()\n"); + assertThat(lookup("b")).isEqualTo(0); + } + + @Test public void testSingleLineFunction() throws Exception { eval("def func(): return 'a'", "s = func()\n"); |