X10
  1. X10
  2. XTENLANG-1

"inconvertible types ... found ... required ... this.new ..." for new X() for nested classes

    Details

    • Number of attachments :
      0

      Description

      public class C[T] {
      
          private class It implements Iterator[T] {
              incomplete public def hasNext(): boolean;
              incomplete public def next(): T;
              incomplete public def remove(): void;
          }
      
          public def iterator(): Iterator[T] {
              return new It();
          }
      }
      

      classes\C.java:102: inconvertible types
      found : C<T>.It
      required: C<T>
      this.new It();
      ^
      2 errors

        Activity

        Hide
        Vijay Saraswat added a comment -

        Added parentheses around code emitted by X10Cast_c.

        Show
        Vijay Saraswat added a comment - Added parentheses around code emitted by X10Cast_c.
        Hide
        Igor Peshansky added a comment -

        This is probably better fixed by using printSubExpr() to print n.qualifier() in the handling of X10New_c...

        Show
        Igor Peshansky added a comment - This is probably better fixed by using printSubExpr() to print n.qualifier() in the handling of X10New_c...
        Hide
        Vijay Saraswat added a comment -

        But this is not about XNew_c. The same problem arises with casting the subject of a method invocation — you may need ((Type) m).foo() and not (Type) m. foo().

        Seems to me that it is always correct to translate [[m as Type]] to [[((Type) m)]] (assuming Type has no dependent clauses...?

        Show
        Vijay Saraswat added a comment - But this is not about XNew_c. The same problem arises with casting the subject of a method invocation — you may need ((Type) m).foo() and not (Type) m. foo(). Seems to me that it is always correct to translate [ [m as Type] ] to [ [((Type) m)] ] (assuming Type has no dependent clauses...?
        Hide
        Bruce Lucas added a comment -

        fix verified

        Show
        Bruce Lucas added a comment - fix verified
        Hide
        Mikio Takeuchi added a comment -

        This is another persistent failure.
        Is this test case is still valid?

        Show
        Mikio Takeuchi added a comment - This is another persistent failure. Is this test case is still valid?
        Hide
        Vijay Saraswat added a comment -

        The code needs to be

        public class C[T] {
        
            private class It implements Iterator[T] {
                incomplete public def hasNext(): boolean;
                incomplete public def next(): T;
                incomplete public def remove(): void;
            }
        
            public def iterator(): Iterator[T] {
                return new It[T]();
            }
        }
        
        Show
        Vijay Saraswat added a comment - The code needs to be public class C[T] { private class It implements Iterator[T] { incomplete public def hasNext(): boolean ; incomplete public def next(): T; incomplete public def remove(): void; } public def iterator(): Iterator[T] { return new It[T](); } }
        Hide
        Igor Peshansky added a comment -

        Why? It is not declared to be a generic class. An instance of it is created in a non-static context, which means that the parameter T of the outer class should be in scope. The class itself is an inner class, so it should have access to the outer instance (C[T].this), and thus to T.

        Granted, the code could have been rewritten to use a nested class (T alpha-renamed to U for clarity):

        public class C[T] {
        
            private static class It[U] implements Iterator[U] {
                private val obj: C[U];
                public def this(o: C[U]) { obj = o; }
                incomplete public def hasNext(): boolean;
                incomplete public def next(): U;
                incomplete public def remove(): void;
            }
        
            public def iterator(): Iterator[T] {
                return new It[T](this);
            }
        }
        

        but as it is written now, it's not at all clear that It can be (or should be) generic.

        Show
        Igor Peshansky added a comment - Why? It is not declared to be a generic class. An instance of it is created in a non-static context, which means that the parameter T of the outer class should be in scope. The class itself is an inner class, so it should have access to the outer instance ( C [T] .this ), and thus to T . Granted, the code could have been rewritten to use a nested class ( T alpha-renamed to U for clarity): public class C[T] { private static class It[U] implements Iterator[U] { private val obj: C[U]; public def this (o: C[U]) { obj = o; } incomplete public def hasNext(): boolean ; incomplete public def next(): U; incomplete public def remove(): void; } public def iterator(): Iterator[T] { return new It[T]( this ); } } but as it is written now, it's not at all clear that It can be (or should be) generic.
        Hide
        Bard Bloom added a comment -

        Like Igor, I don't see why It should have a [T]. I don't even see why
        it can have [T].

        Second point first: It is not defined as a generic class. It is
        intimately related to a generic class, but it isn't one. I can't think of
        any mechanism we have by which it might inherit a generic argument.

        For the first point: It isn't exactly defined relative to T. It's
        defined relative to an instance of C[T]. If I were writing its type from
        outside, I'd write the type of the outer class as C[String], say, and the
        type of the inner class as C[String].It I guess. I'd be pretty surprised
        if it somehow became either C[String].It[String] or C.It[String].

        I looked at what Java does with this. (I don't think that we are constrained
        by what Java does, but a great deal of thought went into getting that
        particular bear to polka, and X10's concepts are similar enough to Java's that
        we can be informed by them.)

        Java's story is (1) in line with what Igor and I expect, and (2) you're not
        supposed to do much more than that.

        (1) The following code compiles in Java. It precisely parallels the code in the initial example. If I add a <T> to parallel Vijay's variation, it doesn't compile.

        package javapook;
        
        import java.util.Iterator;
        
        public class GenericAndInnerClass<T> {
        	public class Snit implements Iterator<T> {
        		public void remove() {
        		}
        		public boolean hasNext() {
        			return false;
        		}
        		public T next() {
        			return null;
        		};
        	}
        
        	public Snit sniterator() {
        		return new Snit();
        	}
        }
        

        If you want to create a new Snit from outside, you need to create a new
        GenericAndInnerClass<T> first, and use that to create the Snit, as in
        the sn2 line below:

        public class UsingGenericAndInnerClass {
        	public static void main(String[] args) {
        		GenericAndInnerClass<String> gaic = new GenericAndInnerClass<String>();
        		GenericAndInnerClass<String>.Snit sniterator = gaic.sniterator();
        		GenericAndInnerClass<String>.Snit sn2 = gaic.new Snit();
        	}
        }
        

        This makes sense to me – Snit is not a standalone class; it is
        impossible to have a Snit without a GenericAndInnerClass<T>.

        (2) The Java spec says of this topic:

        Deeply nesting types is even more of a problem when the nested types are
        generic. Both nested types and generic types add an extra degree of
        complexity to programs, and their combination can greatly compound that
        complexity.

        Which I interpret to mean that the Java designers weren't very comfortable
        with the deeper consequences of their decisions. I'm certainly not, either.

        Show
        Bard Bloom added a comment - Like Igor, I don't see why It should have a [T] . I don't even see why it can have [T] . Second point first: It is not defined as a generic class. It is intimately related to a generic class, but it isn't one. I can't think of any mechanism we have by which it might inherit a generic argument. For the first point: It isn't exactly defined relative to T . It's defined relative to an instance of C [T] . If I were writing its type from outside, I'd write the type of the outer class as C [String] , say, and the type of the inner class as C [String] .It I guess. I'd be pretty surprised if it somehow became either C [String] .It [String] or C.It [String] . I looked at what Java does with this. (I don't think that we are constrained by what Java does, but a great deal of thought went into getting that particular bear to polka, and X10's concepts are similar enough to Java's that we can be informed by them.) Java's story is (1) in line with what Igor and I expect, and (2) you're not supposed to do much more than that. (1) The following code compiles in Java. It precisely parallels the code in the initial example. If I add a <T> to parallel Vijay's variation, it doesn't compile. package javapook; import java.util.Iterator; public class GenericAndInnerClass<T> { public class Snit implements Iterator<T> { public void remove() { } public boolean hasNext() { return false ; } public T next() { return null ; }; } public Snit sniterator() { return new Snit(); } } If you want to create a new Snit from outside, you need to create a new GenericAndInnerClass<T> first, and use that to create the Snit , as in the sn2 line below: public class UsingGenericAndInnerClass { public static void main( String [] args) { GenericAndInnerClass< String > gaic = new GenericAndInnerClass< String >(); GenericAndInnerClass< String >.Snit sniterator = gaic.sniterator(); GenericAndInnerClass< String >.Snit sn2 = gaic. new Snit(); } } This makes sense to me – Snit is not a standalone class; it is impossible to have a Snit without a GenericAndInnerClass<T> . (2) The Java spec says of this topic: Deeply nesting types is even more of a problem when the nested types are generic. Both nested types and generic types add an extra degree of complexity to programs, and their combination can greatly compound that complexity. Which I interpret to mean that the Java designers weren't very comfortable with the deeper consequences of their decisions. I'm certainly not, either.

          People

          • Assignee:
            Vijay Saraswat
            Reporter:
            Bruce Lucas
          • Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: