Boo
  1. Boo
  2. BOO-450

Error msg when accessing non-static outer class member

    Details

    • Type: Bug Bug
    • Status: Resolved Resolved
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 0.5.6
    • Fix Version/s: 0.7
    • Component/s: Compiler
    • Labels:
      None
    • Number of attachments :
      1

      Description

      See: http://groups-beta.google.com/group/boolang/browse_frm/thread/5668b195c6dec549/0939ef078aed3db3#0939ef078aed3db3

      Boo should throw an error if accessing a non-static member of outer class. (Actually, C# just says the reference cannot be found I believe)

      One fix is around line 2029 in the processmethodbodies step, add:

      //check if found entity can't possibly be a member of self:
      if (member.DeclaringType != CurrentType &&
      !(CurrentType.IsSubclassOf(member.DeclaringType)))

      { Error(CompilerErrorFactory.InstanceRequired(node, member.DeclaringType.ToString(), member.Name)); }

      That 'fix' doesn't change name resolution though, to exclude non-static members in outer classes.

        Issue Links

          Activity

          Hide
          Daniel Grunwald added a comment -

          C# shows this error:
          error CS0038: Cannot access a nonstatic member of outer type 'OuterClass' via nested type 'OuterClass.InnerClass'

          Show
          Daniel Grunwald added a comment - C# shows this error: error CS0038: Cannot access a nonstatic member of outer type 'OuterClass' via nested type 'OuterClass.InnerClass'
          Hide
          Daniel Grunwald added a comment -

          Btw: I think an inner class has a reference to an outer class instance in most cases, so why shouldn't boo use a different inner class model as C#?
          It would be great if inner classes would get the reference automatically inserted by the compiler. Constructing an inner class would then only be possible on an instance of the outer class.
          Boo: a = instanceOfOuterClass.InnerClass()
          C#: a = new OuterClass.InnerClass(instanceOfOuterClass);

          Show
          Daniel Grunwald added a comment - Btw: I think an inner class has a reference to an outer class instance in most cases, so why shouldn't boo use a different inner class model as C#? It would be great if inner classes would get the reference automatically inserted by the compiler. Constructing an inner class would then only be possible on an instance of the outer class. Boo: a = instanceOfOuterClass.InnerClass() C#: a = new OuterClass.InnerClass(instanceOfOuterClass);
          Hide
          Doug H added a comment -

          OK, if that's the error C# gives, then probably my fix is the way to do it. We can't change name resolution to handle this special case. The error message boo will give is:
          An instance of type 'Outer' is required to access non-static member 'whatever'.

          About your 2nd comment, I thought maybe we could insert a field in the inner class that stores an instance of the outer class. But what instance would we use? What if the Outer class doesn't have a zero-param constructor? But if there is a solution to do what you are proposing, that's great.

          For Arron, here is how to do your example using a stored instance of the outer class (this is how C# does it too):

          class foo:
          types = ['hello', 'world!']
          def fu():
          b = bar(self)
          b.fark()
          class bar:
          _outer as foo
          def constructor(outer as foo):
          _outer = outer
          def fark():
          print _outer.types //should work even if types is a private field

          f = foo()
          f.fu()

          Show
          Doug H added a comment - OK, if that's the error C# gives, then probably my fix is the way to do it. We can't change name resolution to handle this special case. The error message boo will give is: An instance of type 'Outer' is required to access non-static member 'whatever'. About your 2nd comment, I thought maybe we could insert a field in the inner class that stores an instance of the outer class. But what instance would we use? What if the Outer class doesn't have a zero-param constructor? But if there is a solution to do what you are proposing, that's great. For Arron, here is how to do your example using a stored instance of the outer class (this is how C# does it too): class foo: types = ['hello', 'world!'] def fu(): b = bar(self) b.fark() class bar: _outer as foo def constructor(outer as foo): _outer = outer def fark(): print _outer.types //should work even if types is a private field f = foo() f.fu()
          Hide
          Daniel Grunwald added a comment -

          > But what instance would we use?
          The instance that created the inner class.
          Inner classes would automatically get a constructor that accepts an instance of the outer class as parameter.
          If the inner class already has constructors, the compiler would add the parameter that accepts an instance of the outer class.
          The constructors would assign the value of that parameter into a field.

          When calling the constructor, the compiler could automatically insert the reference to the outer class to the argument list.
          You would call the constructor on the instance of the outer class, thus "self.InnerClass()" would be a valid constructor call. (maybe this could be implemented by renaming the inner class internally and creating a instance method on the outer class with the inner classes' old name)

          References to outer classes' instance fields would then be redirectly to use the compiler generated field.

          So the effect would be that the original code (first post in the thread mentioned in the description) would be valid.

          Show
          Daniel Grunwald added a comment - > But what instance would we use? The instance that created the inner class. Inner classes would automatically get a constructor that accepts an instance of the outer class as parameter. If the inner class already has constructors, the compiler would add the parameter that accepts an instance of the outer class. The constructors would assign the value of that parameter into a field. When calling the constructor, the compiler could automatically insert the reference to the outer class to the argument list. You would call the constructor on the instance of the outer class, thus "self.InnerClass()" would be a valid constructor call. (maybe this could be implemented by renaming the inner class internally and creating a instance method on the outer class with the inner classes' old name) References to outer classes' instance fields would then be redirectly to use the compiler generated field. So the effect would be that the original code (first post in the thread mentioned in the description) would be valid.
          Show
          Doug H added a comment - http://groups-beta.google.com/group/boolang/msg/aa2f2c25090b6d64
          Hide
          Doug H added a comment -

          Put in patch form with test case.

          Show
          Doug H added a comment - Put in patch form with test case.
          Hide
          Rodrigo B. de Oliveira added a comment -

          Patch applied. Thanks!

          Show
          Rodrigo B. de Oliveira added a comment - Patch applied. Thanks!

            People

            • Assignee:
              Doug H
              Reporter:
              Doug H
            • Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: