Silver's non-generic generic type subclass produce weird error in while building

IDE: Android Studio
Version: 8.4.96.1995
Target (If relevant): Android
Description:
Java is giving extremely weird error when compiling android project with Elements generated .jar,
when you define a non-generic type that is subclass of generic type with a concrete type.

Error:(44, 29) error: cannot access TilesetEnumerator

bad class file: /Users/hurden/Developer/asset_core/geoMapper/GeoMapper.Android/app/libs/geoBingAnCore.Android.jar(geobingancore/android/TilesetEnumerator.class)
undeclared type variable: T
Please remove or make sure it appears in the correct subdirectory of the class path.

Reference code:

public class TilesetEnumerator: Enumerator<TileID> {
	
	#if !COOPER
	public enum Error: ErrorType {
		case StartingNodeOutsideTileset
	}
	#endif
	
	let tileset: Set<TileID>
	let startingTile: TileID
	
	private var _nonLazyTileSequence = [TileID]()
	private var _nonLazySequenceIteretorIndex: Int = 0
	
	public init(tileset: Set<TileID>, startingTile: TileID) throws {
		
		if !tileset.contains(startingTile){
			#if COOPER
			throw Exception("Starting node outside tileset")
			#else
			throw Error.StartingNodeOutsideTileset
			#endif
		}
		
		self.tileset = tileset
		self.startingTile = startingTile
		
		super.init()
		_breadthFirstSequenceRecursiveGenerate(withTileset: tileset, notToVisit: Set<TileID>(), nextToVisit: [startingTile])
	}
	
	public override func nextObject() -> TileID? {
		let entityToReturn: TileID? = (_nonLazySequenceIteretorIndex < _nonLazyTileSequence.count) ? _nonLazyTileSequence[_nonLazySequenceIteretorIndex] : nil
		_nonLazySequenceIteretorIndex += 1
		return entityToReturn
	}

	//clockwise from top
	private func _breadthFirstSequenceRecursiveGenerate(withTileset tileset: Set<TileID>, notToVisit: Set<TileID>, nextToVisit:[TileID]){
		
		if let currentElement = nextToVisit.first {
			_nonLazyTileSequence.append(currentElement)
			
			var next__NextToVisit = nextToVisit
			var next__NotToVisit = notToVisit
			next__NextToVisit.removeAtIndex(0)
			
			//yes it will insert any element except very first for a second time, don't really care, it is a set anyway
			next__NotToVisit.insert(currentElement)
			
			//if we are not on the edge of the world, check if
			if let nextTop = try? TileID(x: currentElement.x, y: currentElement.y + 1, level: currentElement.level)
				where tileset.contains(nextTop) && !notToVisit.contains(nextTop) {
				
				next__NextToVisit.append(nextTop)
				next__NotToVisit.insert(nextTop)
			}
			if let nextRight = try? TileID(x: currentElement.x + 1, y: currentElement.y , level: currentElement.level)
				where tileset.contains(nextRight) && !notToVisit.contains(nextRight) {
				
				next__NextToVisit.append(nextRight)
				next__NotToVisit.insert(nextRight)
			}
			if let nextBottom = try? TileID(x: currentElement.x, y: currentElement.y - 1 , level: currentElement.level)
				where tileset.contains(nextBottom) && !notToVisit.contains(nextBottom) {
				
				next__NextToVisit.append(nextBottom)
				next__NotToVisit.insert(nextBottom)
			}
			if let nextLeft = try? TileID(x: currentElement.x - 1, y: currentElement.y, level: currentElement.level)
				where tileset.contains(nextLeft) && !notToVisit.contains(nextLeft) {
				
				next__NextToVisit.append(nextLeft)
				next__NotToVisit.insert(nextLeft)
			}
			
			_breadthFirstSequenceRecursiveGenerate(withTileset: tileset, notToVisit: next__NotToVisit, nextToVisit: next__NextToVisit)
		}
	}
}

Enumerator:


#if COOPER
	import java.util
#elseif ECHOES
	import System.Collections.Generic
#elseif NOUGAT
	import Foundation
#endif

#if NOUGAT
__mapped public class Enumerator<T> => Foundation.NSEnumerator {
	
	public func nextObject() -> T? { return __mapped.nextObject() }
	public var allObjects: Array<T> { return __mapped.allObjects.mutableCopy }
}
#else

public class Enumerator<T> {
	
	public func nextObject() -> T? {
		RequiresConcreteImplementation()
	}
}

extension Enumerator {
	public var allObjects: Array<T> {
		var allObjectCollection = [T]()
		
		let element: T?
		while ( (element = self.nextObject()) != nil ){
			allObjectCollection.append(element!)
		}
		
		return allObjectCollection
	}
}

#if COOPER
extension Enumerator: Iterable<T> {
	
	internal class Iterator<T>: java.util.Iterator<T> {
		private let _enumerator: Enumerator<T>
		init(enumerator: Enumerator<T>){
			_enumerator = enumerator
		}
		
		//java.util.Iterator<T>
		public func next() -> T {
			return _enumerator.nextObject()!
		}
		
		public func hasNext() -> Bool {
			return ((_enumerator.nextObject() != nil) ? true : false)
		}
		
		public func remove() {
			_enumerator.remove()
		}
	}
	
	public func iterator() -> java.util.Iterator<T>! {
		return Iterator(enumerator: self)
	}
	
	//for glueing it to java.util.Iterator
	public func remove() {
		RequiresConcreteImplementation()
	}
}

#elseif ECHOES
extension Enumerator: IEnumerable<T> {
	
	internal class EchoesEnumerator: IEnumerator<T> {
		private let _enumerator: Enumerator<T>
		private var _savedValue: T?
		
		init(enumerator: Enumerator<T>){
			_enumerator = enumerator
			_savedValue = _enumerator.nextObject()
		}
		
		//IEnumerator<T>
		@Implements(System.Collections.IEnumerator.Type, "Current")
		public var CurrentI: Object! {
			return self.Current
		}
		public var Current: T {
			//if enumerator returns nil for the first element - NullReferenceException will follow...
			return _savedValue!
		}
		
		public func MoveNext() -> Bool {
			_savedValue = _enumerator.nextObject()
			return (_savedValue != nil)
		}
		
		public func Reset() {
			_enumerator.Reset()
		}
		
		//IDisposable
		public func Dispose() {
			_enumerator.Dispose()
		}
	}
	  
	@Implements(System.Collections.IEnumerable.Type, "GetEnumerator")
	public func GetEnumeratorI() -> System.Collections.IEnumerator!  {
		return EchoesEnumerator(enumerator: self)
	}
	public func GetEnumerator() -> IEnumerator<T> {
		return EchoesEnumerator(enumerator: self)
	}
	
	//for glueing it to System.Collections.Generic.IEnumerator<T>
	public func Reset() {
		RequiresConcreteImplementation()
	}
	
	public func Dispose() {
		//override if IDisposable functionality needed 
	}
}
#endif

#endif

/* A Mirrored Implementation for Swift 2.2

public class Enumerator<T> {
	
	public func nextObject() -> T? {
		RequiresConcreteImplementation()
	}
}

extension Enumerator {
	
	public var allObjects: [T] {
		return Array(self)
	}
}

extension Enumerator: SequenceType {
	
	public func generate() -> Generator<T> {
		return Generator(enumerator: self)
	}
}

public struct Generator<T>: GeneratorType {
	
	let enumerator: Enumerator<T>
	public mutating func next() -> T? {
		return enumerator.nextObject()
	}
}

@noreturn internal func RequiresConcreteImplementation(fn fn: String = #function){
	fatalError("\(fn) must be overriden in subclass implementations")
}
*/

If this can be resolved I guess It will be meaningful to contribute this Enumerator as the cross-platform SequenceType abstraction inside SwiftBaseLibrary…

More feedback:
There is no such problem when TilesetEnumerator is itself generic type.

Thanks, logged as bugs://75330

Hi,

Just tried to compile this (had to comment out 1 method because I didn’t have tileid) and I’m not getting an error like that. When do you get that error?

My testcase:

import java.util

public class TileID {
}

public class TilesetEnumerator: Enumerator<TileID> {
    
    
    let tileset: Set<TileID>
    let startingTile: TileID
    
    private var _nonLazyTileSequence = [TileID]()
    private var _nonLazySequenceIteretorIndex: Int = 0
    
    public init(tileset: Set<TileID>, startingTile: TileID) throws {
        
        if !tileset.contains(startingTile){
            #if COOPER
            throw Exception("Starting node outside tileset")
            #else
            throw Error.StartingNodeOutsideTileset
            #endif
        }
        
        self.tileset = tileset
        self.startingTile = startingTile
        
        super.init()
        //_breadthFirstSequenceRecursiveGenerate(withTileset: tileset, notToVisit: Set<TileID>(), nextToVisit: [startingTile])
    }
    
    public override func nextObject() -> TileID? {
        let entityToReturn: TileID? = (_nonLazySequenceIteretorIndex < _nonLazyTileSequence.count) ? _nonLazyTileSequence[_nonLazySequenceIteretorIndex] : nil
        _nonLazySequenceIteretorIndex += 1
        return entityToReturn
    }

    
}

public class Enumerator<T> {
    
    public func nextObject() -> T? {
        //RequiresConcreteImplementation()
    }
}

extension Enumerator {
    public var allObjects: Array<T> {
        var allObjectCollection = [T]()
        
        let element: T?
        while ( (element = self.nextObject()) != nil ){
            allObjectCollection.append(element!)
        }
        
        return allObjectCollection
    }
}

extension Enumerator: Iterable<T> {
    
    internal class Iterator<T>: java.util.Iterator<T> {
        private let _enumerator: Enumerator<T>
        init(enumerator: Enumerator<T>){
            _enumerator = enumerator
        }
        
        //java.util.Iterator<T>
        public func next() -> T {
            return _enumerator.nextObject()!
        }
        
        public func hasNext() -> Bool {
            return ((_enumerator.nextObject() != nil) ? true : false)
        }
        
        public func remove() {
            _enumerator.remove()
        }
    }
    
    public func iterator() -> java.util.Iterator<T>! {
        return Iterator(enumerator: self)
    }
    
    //for glueing it to java.util.Iterator
    public func remove() {
        //RequiresConcreteImplementation()
    }
}


Not sure if I can reproduce it anymore…
The error was when building android project with already pre-build .jar…

I will update this thread if I can reproduce this.

bugs://75330 got closed with status cannotrepro.

I’m getting exactly that Carlo
Fire 2151
will investigate if it has anything to do with generics…
definitely a possibility

the simplest I can get it down to… (although there are a lot of generics around in this file…)

runAfterDelay(10) { _ = self.updatesQueue.call() { } }

hope that’s a clue

the other place I’m getting the same error…
there is a closure () -> T passed in to a generic methods do()

but it seems to be on the method declaration … I can comment out the whole method but I still get the error.

Any chance of a simple testcase/repro?

Logged as bugs://i63318.

bugs://i63318 was closed as unable to reproduce.