object Main {
	def fun( x: Int ) : Int = { print( "Int " ); return 3 }
	def fun( x: Double ) : Int = { print( "Double " ); return 3 }
	def fun( x: Int, y: Int ) : Int = { print( "Int, Int " ); return 3 }
	def fun() : Int = { print( "() " ); return 3 }
	def fun() : Double = { return 3.5 } // disallowed, ambiguous
    def fun[T]( x: T ) : T = { print( "T " ); return x }
    def fun[T,T]( x: T, y: T ) : T = { print( "T,T " ); return y }
    def fun[T,U]( x: T, y: U ) : U = { print( "T,U " ); return y } // disallowed, ambiguous
	val i: int = fun( 3, 3 );
	val d2: double = fun( 3, 3.5 );
	val d: Double = fun( 3.5 )
	val s: String = fun( "def" )
	def main( args: Array[String] ) = {
        println( fun( 3 ) )
        println( fun( 3.5 ) )
        println( fun( 3, 3 ) )
        println( fun() )
        println( fun( "abc" ) )
    }

	// // https://scastie.scala-lang.org/CuNcusyPTUKgZiVNWdyqZA
	// needs scala 3.0

	// trait HasFoo[T] { def foo: T }

	// given HasFoo[String]:
	// def foo = "string"
	// given HasFoo[Int]:
	// def foo = 42

	// def generic[T](using hasFoo: HasFoo[T]): T = hasFoo.foo

	// val i: Int = generic
	// val s: String = generic

	// println(i) (): scala.Unit
	// println(s) (): scala.Unit
}

// scalac test.scala
