digitalmars.D.learn - Error "Outer Function Context is Needed" when class declared in
- Vijay Nayar (95/95) Jan 05 2023 I've run into an unexpected problem that only seems to happen in
- Adam D Ruppe (7/9) Jan 05 2023 A unittest is just a special function, it can run code and have
- Vijay Nayar (7/16) Jan 05 2023 That's very informative, I didn't realize that `unittest` is
- Adam D Ruppe (2/4) Jan 05 2023 yup. They can see the local variables from the function.
- Vijay Nayar (6/10) Jan 05 2023 Glad to learn that. Having worked many years in the Java world,
- Jim Balter (8/17) Jan 21 Why doesn't the compiler just create the instance with the
- Kagamin (2/2) Jan 25 Looks like the context is currently passed for nested functions,
I've run into an unexpected problem that only seems to happen in unittests, but not outside of them. Consider the following example: ``` unittest { class Ab { int a; string b; static class Builder { int _a; string _b; Builder a(int a) { _a = a; return this; } Builder b(string b) { _b = b; return this; } Ab build() { Ab t = new Ab(); t.a = _a; t.b = _b; return t; } } } Ab ab = new Ab.Builder() .a(1) .b("ham") .build(); assert(ab.a == 1); assert(ab.b == "ham"); } ``` This fails to compile with the following error: ``` Generating test runner configuration 'builder-test-library' for 'library' (library). Starting Performing "unittest" build using /usr/bin/dmd for x86_64. Building builder ~master: building configuration [builder-test-library] source/builder.d(58,16): Error: outer function context of `builder.__unittest_L41_C1` is needed to `new` nested class `builder.__unittest_L41_C1.Ab` Error /usr/bin/dmd failed with exit code 1. ``` However, if I move the class definition outside of the unittest block, then everything works fine: ``` class Ab { int a; string b; static class Builder { int _a; string _b; Builder a(int a) { _a = a; return this; } Builder b(string b) { _b = b; return this; } Ab build() { Ab t = new Ab(); t.a = _a; t.b = _b; return t; } } } unittest { Ab ab = new Ab.Builder() .a(1) .b("ham") .build(); assert(ab.a == 1); assert(ab.b == "ham"); } ``` ``` Generating test runner configuration 'builder-test-library' for 'library' (library). Starting Performing "unittest" build using /usr/bin/dmd for x86_64. Building builder ~master: building configuration [builder-test-library] Linking builder-test-library Running builder-test-library 2 modules passed unittests ``` Why is this error only found when declaring a class in the unittest?
Jan 05 2023
On Thursday, 5 January 2023 at 13:27:23 UTC, Vijay Nayar wrote:Why is this error only found when declaring a class in the unittest?A unittest is just a special function, it can run code and have local variables. classes and structs declared inside it have access to those local contexts, which it calls the outer function context. Make the outer class `static` too to lift it out of this and your error should go away.
Jan 05 2023
On Thursday, 5 January 2023 at 13:47:24 UTC, Adam D Ruppe wrote:On Thursday, 5 January 2023 at 13:27:23 UTC, Vijay Nayar wrote:That's very informative, I didn't realize that `unittest` is actually a function. It raises another question one step deeper, what does it mean to define a non-static class within a function? Does that class inherit the scope of the function it is inside, similar to how an inner class does with an outer class?Why is this error only found when declaring a class in the unittest?A unittest is just a special function, it can run code and have local variables. classes and structs declared inside it have access to those local contexts, which it calls the outer function context. Make the outer class `static` too to lift it out of this and your error should go away.
Jan 05 2023
On Thursday, 5 January 2023 at 16:38:49 UTC, Vijay Nayar wrote:Does that class inherit the scope of the function it is inside, similar to how an inner class does with an outer class?yup. They can see the local variables from the function.
Jan 05 2023
On Thursday, 5 January 2023 at 16:41:32 UTC, Adam D Ruppe wrote:On Thursday, 5 January 2023 at 16:38:49 UTC, Vijay Nayar wrote:Glad to learn that. Having worked many years in the Java world, where basically "class" and "scope" are nearly synonymous, I just assumed that classes could only get the scope of other classes, it never occurred to me that it could get a scope from a function. Thanks for the explanation!Does that class inherit the scope of the function it is inside, similar to how an inner class does with an outer class?yup. They can see the local variables from the function.
Jan 05 2023
On Thursday, 5 January 2023 at 13:47:24 UTC, Adam D Ruppe wrote:On Thursday, 5 January 2023 at 13:27:23 UTC, Vijay Nayar wrote:Why doesn't the compiler just create the instance with the correct context pointer? And if it won't, how does one provide it? I have a template function which creates new instances of a type that is an argument to the template, and it fails miserably when the type is a nested class. How do I create such instances? Dlang is supposed to be "turtles all the way down", but I keep finding that to be far from reality.Why is this error only found when declaring a class in the unittest?A unittest is just a special function, it can run code and have local variables. classes and structs declared inside it have access to those local contexts, which it calls the outer function context. Make the outer class `static` too to lift it out of this and your error should go away.
Jan 21
Looks like the context is currently passed for nested functions, not for nested classes.
Jan 25