From 9fb2f6d99723796a6638bf9b5a82f46c236c5689 Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Fri, 25 Nov 2022 02:52:10 -0800 Subject: [PATCH 01/64] Partial fix #3005: j.n.InetAddress now uses more UnknownHostExceptions (#3007) (#3011) Co-authored-by: LeeTibbert --- .../src/main/scala/java/net/InetAddress.scala | 52 ++++++++++++++----- 1 file changed, 40 insertions(+), 12 deletions(-) diff --git a/javalib/src/main/scala/java/net/InetAddress.scala b/javalib/src/main/scala/java/net/InetAddress.scala index 0050b63fe0..55839cda2a 100644 --- a/javalib/src/main/scala/java/net/InetAddress.scala +++ b/javalib/src/main/scala/java/net/InetAddress.scala @@ -29,6 +29,8 @@ import scala.scalanative.posix.sys.socket._ import scala.scalanative.posix.time.{time_t, time, difftime} import scala.scalanative.posix.unistd +import scala.scalanative.meta.LinktimeInfo.{isLinux, isMac} + /* Design note: * Much of java.net, both in JVM and Scala Native defines or assumes * the ipAddress field to have either 4 or 16 bytes. @@ -333,7 +335,8 @@ object InetAddress { val gaiStatus = getaddrinfo(toCString(host), null, hints, addrinfo) if (gaiStatus != 0) { - if (gaiStatus == EAI_NONAME) { + val mappedStatus = mapGaiStatus(gaiStatus) + if (mappedStatus == EAI_NONAME) { val ifIndex = host.indexOf('%') val hasInterface = (ifIndex >= 0) if (!hasInterface) { @@ -355,8 +358,8 @@ object InetAddress { ) } } else { - val gaiMsg = SocketHelpers.getGaiErrorMessage(gaiStatus) - throw new IOException(gaiMsg) + val gaiMsg = SocketHelpers.getGaiErrorMessage(mappedStatus) + throw new UnknownHostException(host + ": " + gaiMsg) } } else try { @@ -436,12 +439,7 @@ object InetAddress { if (gaiStatus != 0) { val gaiMsg = SocketHelpers.getGaiErrorMessage(gaiStatus) - val ex = - if (gaiStatus == EAI_NONAME) - new UnknownHostException(host + ": " + gaiMsg) - else - new IOException(gaiMsg) - throw ex + throw new UnknownHostException(host + ": " + gaiMsg) } else try { val preferIPv6 = SocketHelpers.getPreferIPv6Addresses() @@ -624,9 +622,10 @@ object InetAddress { val gaiStatus = getaddrinfo(toCString(host), null, hints, ret) if (gaiStatus != 0) { - if (gaiStatus != EAI_NONAME) { - val gaiMsg = SocketHelpers.getGaiErrorMessage(gaiStatus) - throw new IOException(gaiMsg) + val mappedStatus = mapGaiStatus(gaiStatus) + if (mappedStatus != EAI_NONAME) { + val gaiMsg = SocketHelpers.getGaiErrorMessage(mappedStatus) + throw new UnknownHostException(host + ": " + gaiMsg) } } else try { @@ -645,6 +644,35 @@ object InetAddress { (ptrInt(2) == 0xffff0000) && (ptrLong(0) == 0x0L) } + private def mapGaiStatus(gaiStatus: Int): Int = { + /* This is where some arcane Operating System specific behavior + * comes to puddle and pool. This method is not for small children + * or maintainers with good taste & practice. + * + * EAI_NODATA was removed from RFC3493 "Basic Socket Interface Extensions + * for IPv6" in February 2003. EAI_NONAME was introduced and is the + * contemporary idiom. Although it is remove (i.e. well past deprecated), + * EAI_NODATA can be returned by Linux & macOS in some poorly defined + * circumstances. + * + * The magic integer values for Linux & macOS are hardcoded + * because they are extremely unlikely to change after all this time. + * + * For consistency of the reported message, map EAI_NODATA to EAI_NONAME. + * Both will return "UnknownHostException". + */ + + // EAI_NODATA was removed from FreeBSD a decade or more ago. + val EAI_NODATA = + if (isLinux) -5 + else if (isMac) 7 + else Integer.MAX_VALUE // placeholder, will never match + + if (gaiStatus == EAI_NONAME) gaiStatus + else if (gaiStatus == EAI_NODATA) EAI_NONAME + else gaiStatus + } + def getAllByName(host: String): Array[InetAddress] = { if ((host == null) || (host.length == 0)) { /* The obvious recursive call to getAllByName("localhost") does not From 51b6b29cb8175194126208ae172d0b08f03cbc56 Mon Sep 17 00:00:00 2001 From: Ben Iofel Date: Wed, 7 Dec 2022 19:53:36 +0100 Subject: [PATCH 02/64] Fix 0.4.9 release date (#3029) --- docs/changelog/0.4.9.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/changelog/0.4.9.md b/docs/changelog/0.4.9.md index 98247011c0..eb33b6d7dc 100644 --- a/docs/changelog/0.4.9.md +++ b/docs/changelog/0.4.9.md @@ -1,5 +1,5 @@ -# 0.4.9 (2022-12-23) +# 0.4.9 (2022-11-23) We're happy to announce the release of Scala Native 0.4.9. From 067b65af1edc2b00b63819a4e68ba50e87056770 Mon Sep 17 00:00:00 2001 From: "Lan, Jian" <45252210+ShapelessCat@users.noreply.github.com> Date: Thu, 26 Jan 2023 05:18:32 +0800 Subject: [PATCH 03/64] Fix the 0.4.9 version release date in its changelog (#3106) --- docs/changelog/0.4.9.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/docs/changelog/0.4.9.md b/docs/changelog/0.4.9.md index eb33b6d7dc..6cedbc1e8b 100644 --- a/docs/changelog/0.4.9.md +++ b/docs/changelog/0.4.9.md @@ -1,11 +1,11 @@ # 0.4.9 (2022-11-23) -We're happy to announce the release of Scala Native 0.4.9. +We're happy to announce the release of Scala Native 0.4.9. It's a patch release fixing linkage errors when building Scala 2.13 libraries using Scala 3 dependenices. -It does also reverse version policy changes leading to problems in sbt-crossproject. Improved version policy would be restored in Scala Native 0.5.x. +It does also reverse version policy changes leading to problems in sbt-crossproject. Improved version policy would be restored in Scala Native 0.5.x. Scala Native 0.4.9 introduces a new feature - an experimental support for incremental compilation. @@ -67,7 +67,6 @@ nativeConfig ~= { } ``` - ## Contributors Big thanks to everybody who contributed to this release or reported an issue! @@ -82,7 +81,7 @@ $ git shortlog -sn --no-merges v0.4.8..v0.4.9 ## Merged PRs -## [v0.4.9](https://github.com/scala-native/scala-native/tree/v0.4.9) (2022-12-23) +## [v0.4.9](https://github.com/scala-native/scala-native/tree/v0.4.9) (2022-11-23) [Full Changelog](https://github.com/scala-native/scala-native/compare/v0.4.8...v0.4.9) From a6f473dcb7f1c06d7cc64c43ddabc6c7b199726f Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Tue, 29 Nov 2022 01:39:03 -0800 Subject: [PATCH 04/64] Move `MathTestOnJDK9` to correct package/directory (#3016) (cherry picked from commit 8a973b49c7cd6b666d74141dd58eebb7399dd382) --- .../testsuite/javalib/{ => lang}/MathTestOnJDK9.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename unit-tests/shared/src/test/require-jdk9/org/scalanative/testsuite/javalib/{ => lang}/MathTestOnJDK9.scala (91%) diff --git a/unit-tests/shared/src/test/require-jdk9/org/scalanative/testsuite/javalib/MathTestOnJDK9.scala b/unit-tests/shared/src/test/require-jdk9/org/scalanative/testsuite/javalib/lang/MathTestOnJDK9.scala similarity index 91% rename from unit-tests/shared/src/test/require-jdk9/org/scalanative/testsuite/javalib/MathTestOnJDK9.scala rename to unit-tests/shared/src/test/require-jdk9/org/scalanative/testsuite/javalib/lang/MathTestOnJDK9.scala index 5eb12f4213..cec4f03b3c 100644 --- a/unit-tests/shared/src/test/require-jdk9/org/scalanative/testsuite/javalib/MathTestOnJDK9.scala +++ b/unit-tests/shared/src/test/require-jdk9/org/scalanative/testsuite/javalib/lang/MathTestOnJDK9.scala @@ -1,4 +1,4 @@ -package javalib.math +package javalib.lang import org.junit.Test import org.junit.Assert._ From 8167b9013a790f64fa027c3761d2adba2c1b28dc Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Tue, 29 Nov 2022 10:40:38 +0100 Subject: [PATCH 05/64] Better error handling for `Files#createLink` (#3012) (cherry picked from commit b593f850d712c36c3ffa9a748b7c663c1be9b586) --- .../src/main/scala/java/nio/file/Files.scala | 47 ++++++++++++------- 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/javalib/src/main/scala/java/nio/file/Files.scala b/javalib/src/main/scala/java/nio/file/Files.scala index cac6d515ab..9965ea2472 100644 --- a/javalib/src/main/scala/java/nio/file/Files.scala +++ b/javalib/src/main/scala/java/nio/file/Files.scala @@ -33,7 +33,7 @@ import scalanative.unsafe._ import scalanative.libc._ import scalanative.posix.{dirent, fcntl, limits, unistd} import dirent._ -import scalanative.posix.errno.{EEXIST, ENOTEMPTY} +import scalanative.posix.errno.{EEXIST, ENOENT, ENOTEMPTY} import java.nio.file.StandardCopyOption.{COPY_ATTRIBUTES, REPLACE_EXISTING} import scalanative.nio.fs.unix.UnixException @@ -201,26 +201,41 @@ object Files { throw new IOException() } - def createLink(link: Path, existing: Path): Path = { - def tryCreateHardLink() = Zone { implicit z => - if (isWindows) - CreateHardLinkW( + def createLink(link: Path, existing: Path): Path = Zone { implicit z => + if (isWindows) { + if (exists(link, Array.empty)) { + throw new FileAlreadyExistsException(link.toString) + } else { + val created = CreateHardLinkW( toCWideStringUTF16LE(link.toString), toCWideStringUTF16LE(existing.toString), securityAttributes = null ) - else - unistd.link( - toCString(existing.toString()), - toCString(link.toString()) - ) == 0 - } - if (exists(link, Array.empty)) { - throw new FileAlreadyExistsException(link.toString) - } else if (tryCreateHardLink()) { - link + if (created) { + link + } else { + throw new IOException("Cannot create link") + } + } + } else { - throw new IOException("Cannot create link") + val rtn = unistd.link( + toCString(existing.toString()), + toCString(link.toString()) + ) + + if (rtn == 0) { + link + } else { + val e = errno + if (e == EEXIST) + throw new FileAlreadyExistsException(link.toString) + else if (e == ENOENT) + throw new NoSuchFileException(link.toString, existing.toString, null) + else + throw new IOException(fromCString(string.strerror(e))) + } + } } From 22fa37a7518ca64a8cc12e7b92e3e5e91ac29089 Mon Sep 17 00:00:00 2001 From: LeeTibbert Date: Tue, 6 Dec 2022 11:18:51 +0100 Subject: [PATCH 06/64] Implement j.net.NetworkInterface & InterfaceAddress classes (#3015) The javalib java.net.NetworkInterface and InterfaceAddress classes allow to enumerate & query the network interfaces on a system. This PR implements these classes on Linux & macOS. A Windows implementation should be possible but is not part of this PR. (cherry picked from commit cac64ad7222b4734f7018badce1514dc21a238d7) --- docs/lib/javalib.rst | 3 +- .../src/main/resources/scala-native/ifaddrs.c | 86 ++ .../main/resources/scala-native/net/if_dl.c | 82 ++ .../resources/scala-native/netinet/unixIf.c | 55 + .../src/main/scala/java/net/InetAddress.scala | 51 +- .../scala/java/net/InterfaceAddress.scala | 43 + .../scala/java/net/NetworkInterface.scala | 982 ++++++++++++++++++ .../main/scala/java/net/SocketHelpers.scala | 27 + .../net/NetworkInterfaceTestOnJDK9.scala | 44 + .../javalib/net/InterfaceAddressTest.scala | 170 +++ .../javalib/net/NetworkInterfaceTest.scala | 234 +++++ 11 files changed, 1736 insertions(+), 41 deletions(-) create mode 100644 javalib/src/main/resources/scala-native/ifaddrs.c create mode 100644 javalib/src/main/resources/scala-native/net/if_dl.c create mode 100644 javalib/src/main/resources/scala-native/netinet/unixIf.c create mode 100644 javalib/src/main/scala/java/net/InterfaceAddress.scala create mode 100644 javalib/src/main/scala/java/net/NetworkInterface.scala create mode 100644 unit-tests/shared/src/test/require-jdk9/org/scalanative/testsuite/javalib/net/NetworkInterfaceTestOnJDK9.scala create mode 100644 unit-tests/shared/src/test/scala/javalib/net/InterfaceAddressTest.scala create mode 100644 unit-tests/shared/src/test/scala/javalib/net/NetworkInterfaceTest.scala diff --git a/docs/lib/javalib.rst b/docs/lib/javalib.rst index 00301c8579..52f1094771 100644 --- a/docs/lib/javalib.rst +++ b/docs/lib/javalib.rst @@ -192,9 +192,10 @@ Here is the list of currently available classes: * ``java.net.Inet4Address`` * ``java.net.Inet6Address`` * ``java.net.InetAddress`` -* ``java.net.InetAddressBase`` * ``java.net.InetSocketAddress`` +* ``java.net.InterfaceAddress`` * ``java.net.MalformedURLException`` +* ``java.net.NetworkInterface`` * ``java.net.NoRouteToHostException`` * ``java.net.PortUnreachableException`` * ``java.net.ServerSocket`` diff --git a/javalib/src/main/resources/scala-native/ifaddrs.c b/javalib/src/main/resources/scala-native/ifaddrs.c new file mode 100644 index 0000000000..6d31d87ea9 --- /dev/null +++ b/javalib/src/main/resources/scala-native/ifaddrs.c @@ -0,0 +1,86 @@ +#if defined(_WIN32) +// No Windows support. These are dummies for linking. +int getifaddrs(void *dummy) { return -1; }; +void freeifaddrs(void *dummy){}; +#else +#include +#include + +#if !(defined __STDC_VERSION__) || (__STDC_VERSION__ < 201112L) +#ifndef SCALANATIVE_SUPPRESS_STRUCT_CHECK_WARNING +#warning "Size and order of C structures are not checked when -std < c11." +#endif +#else +/* Check that the fields defined by Scala Native match "closely enough" those + * defined by the operating system. + */ + +/* Reference: man getifaddrs + * #include + */ + +/* type ifaddrs = CStruct7[ + * Ptr[Byte], // Ptr[ifaddrs] ifa_next: Next item in list + * CString, // ifa_name: Name of interface + * CUnsignedInt, // ifa_flags: Flags from SIOCGIFFLAGS + * Ptr[sockaddr], // ifa_addr: Address of interface + * Ptr[sockaddr], // ifa_netmask: Netmask of interface + * Ptr[sockaddr], // union: + * // ifu_broadaddr: Broadcast address of interface + * // ifu_dstaddr: Point-to-point destination address + * Ptr[Byte] // ifa_data: Address-specific data + * ] + */ + +struct scalanative_ifaddrs { + struct ifaddrs *ifa_next; /* Next item in list */ + char *ifa_name; /* Name of interface */ + unsigned int ifa_flags; /* Flags from SIOCGIFFLAGS */ + struct sockaddr *ifa_addr; /* Address of interface */ + struct sockaddr *ifa_netmask; /* Netmask of interface */ +#ifndef __linux__ + struct sockaddr *ifa_dstaddr; // macOS/BSD #define's ifa_broadcast to this. +#else + union { + struct sockaddr *ifu_broadaddr; + /* Broadcast address of interface */ + struct sockaddr *ifu_dstaddr; + /* Point-to-point destination address */ + } ifa_ifu; +#endif + void *ifa_data; /* Address-specific data */ +}; + +_Static_assert(sizeof(struct scalanative_ifaddrs) <= sizeof(struct ifaddrs), + "unexpected size for ifaddrs"); + +_Static_assert(offsetof(struct scalanative_ifaddrs, ifa_next) == + offsetof(struct ifaddrs, ifa_next), + "Unexpected offset: ifaddrs ifa_next"); + +_Static_assert(offsetof(struct scalanative_ifaddrs, ifa_name) == + offsetof(struct ifaddrs, ifa_name), + "Unexpected offset: ifaddrs ifa_name"); + +_Static_assert(offsetof(struct scalanative_ifaddrs, ifa_flags) == + offsetof(struct ifaddrs, ifa_flags), + "Unexpected offset: ifaddrs ifa_flags"); + +_Static_assert(offsetof(struct scalanative_ifaddrs, ifa_addr) == + offsetof(struct ifaddrs, ifa_addr), + "Unexpected offset: ifaddrs ifa_addr"); + +_Static_assert(offsetof(struct scalanative_ifaddrs, ifa_netmask) == + offsetof(struct ifaddrs, ifa_netmask), + "Unexpected offset: ifaddrs ifa_netmask"); + +_Static_assert(offsetof(struct scalanative_ifaddrs, ifa_broadaddr) == + offsetof(struct ifaddrs, ifa_broadaddr), + "Unexpected offset: ifaddrs ifa_broadaddr"); + +_Static_assert(offsetof(struct scalanative_ifaddrs, ifa_data) == + offsetof(struct ifaddrs, ifa_data), + "Unexpected offset: ifaddrs ifa_data"); + +#endif +#endif // not _WIN32 diff --git a/javalib/src/main/resources/scala-native/net/if_dl.c b/javalib/src/main/resources/scala-native/net/if_dl.c new file mode 100644 index 0000000000..9427273482 --- /dev/null +++ b/javalib/src/main/resources/scala-native/net/if_dl.c @@ -0,0 +1,82 @@ +#ifdef _WIN32 +// NO Windows support +#elif defined(__linux__) +// Does not exist on Linux, so no check +#else // macOS, FreeBSD, etc. +#include +#include +#include + +#if !(defined __STDC_VERSION__) || (__STDC_VERSION__ < 201112L) +#ifndef SCALANATIVE_SUPPRESS_STRUCT_CHECK_WARNING +#warning "Size and order of C structures are not checked when -std < c11." +#endif +#else +/* Check that the fields defined by Scala Native match "closely enough" those + * defined by the operating system. + */ + +/* Reference: macOs: man sockaddr_dl + * #include + */ + +/* type sockaddr_dl = CStruct7[ + * CShort, // sdl_family; // address family + * CShort, // sdl_index + * Byte, // sdl_type + * Byte, // sdl_nlen + * Byte, // sdl_alen + * Byte, // sdl_slen + * CArray[CChar, _46] // sdl_data, max(macOs == 12, FreeBsd == 46) + * ] + */ + +struct scalanative_sockaddr_dl { + unsigned char sdl_len; // Total length of sockaddr + unsigned char sdl_family; // address family + unsigned short sdl_index; // if != 0, system interface index + unsigned char sdl_type; // interface type + unsigned char sdl_nlen; // interface name length + unsigned char sdl_alen; // link level address length + unsigned char sdl_slen; // link layer selector length + char sdl_data[46]; // contains both if name and ll address + // sdl_data, max(macOs == 12, FreeBsd == 46) +}; + +/* SN >= os because macOS declares sdl_data to have size 12 but uses + * it as a longer variable length buffer. + * SN uses the FreeBSD 46 to make it easier to avoid array index errors. + */ +_Static_assert(sizeof(struct scalanative_sockaddr_dl) >= + sizeof(struct sockaddr_dl), + "unexpected size for sockaddr_dl"); + +_Static_assert(offsetof(struct scalanative_sockaddr_dl, sdl_family) == + offsetof(struct sockaddr_dl, sdl_family), + "Unexpected offset: ifaddrs sdl_family"); + +_Static_assert(offsetof(struct scalanative_sockaddr_dl, sdl_index) == + offsetof(struct sockaddr_dl, sdl_index), + "Unexpected offset: ifaddrs sdl_index"); + +_Static_assert(offsetof(struct scalanative_sockaddr_dl, sdl_type) == + offsetof(struct sockaddr_dl, sdl_type), + "Unexpected offset: ifaddrs sdl_type"); + +_Static_assert(offsetof(struct scalanative_sockaddr_dl, sdl_nlen) == + offsetof(struct sockaddr_dl, sdl_nlen), + "Unexpected offset: ifaddrs sdl_nlen"); + +_Static_assert(offsetof(struct scalanative_sockaddr_dl, sdl_alen) == + offsetof(struct sockaddr_dl, sdl_alen), + "Unexpected offset: ifaddrs sdl_alen"); + +_Static_assert(offsetof(struct scalanative_sockaddr_dl, sdl_slen) == + offsetof(struct sockaddr_dl, sdl_slen), + "Unexpected offset: ifaddrs sdl_slen"); + +_Static_assert(offsetof(struct scalanative_sockaddr_dl, sdl_data) == + offsetof(struct sockaddr_dl, sdl_data), + "Unexpected offset: ifaddrs sdl_data"); +#endif +#endif // not _WIN32 diff --git a/javalib/src/main/resources/scala-native/netinet/unixIf.c b/javalib/src/main/resources/scala-native/netinet/unixIf.c new file mode 100644 index 0000000000..a29c81c95f --- /dev/null +++ b/javalib/src/main/resources/scala-native/netinet/unixIf.c @@ -0,0 +1,55 @@ +#if defined(_WIN32) +// No Windows support. These are dummies for linking. +int scalanative_iff_loopback() { return 0; } +int scalanative_iff_multicast() { return 0; } +int scalanative_iff_pointopoint() { return 0; } +int scalanative_iff_up() { return 0; } +void *if_nameindex(void) { return (void *)0; } +void if_freenameindex(void *dummy){}; +#else +#include +#include + +// Possibility for macOS, which lacks SIOCGIFHWADDR +// https://stackoverflow.com/questions/10593736/ +// mac-address-from-interface-on-os-x-c + +// Ref: "man 7 netdevice" + +// Symbolic constants + +int scalanative_ifnamesiz() { return IFNAMSIZ; } + +/* Broadcast address valid. */ +int scalanative_iff_broadcast() { return IFF_BROADCAST; } + +/* Is a loopback net. */ +int scalanative_iff_loopback() { return IFF_LOOPBACK; } + +/* Supports multicast. */ +int scalanative_iff_multicast() { return IFF_MULTICAST; } + +/* Interface is point-to-point link. */ +int scalanative_iff_pointopoint() { return IFF_POINTOPOINT; } + +/* Resources allocated. */ +int scalanative_iff_running() { return IFF_RUNNING; } + +/* get flags */ +int scalanative_siocgifflags() { return SIOCGIFFLAGS; } + +// FIXME macOS appears to not have this ioctl. Hard to find replacement. + +#ifndef SIOCGIFHWADDR +#define SIOCGIFHWADDR 0 // cause failure +#endif +/* Get hardware address */ +int scalanative_siocgifhwaddr() { return SIOCGIFHWADDR; } + +/* get MTU size */ +int scalanative_siocgifmtu() { return SIOCGIFMTU; } + +/* Interface is up. */ +int scalanative_iff_up() { return IFF_UP; } + +#endif // !_WIN32 diff --git a/javalib/src/main/scala/java/net/InetAddress.scala b/javalib/src/main/scala/java/net/InetAddress.scala index 55839cda2a..384b977969 100644 --- a/javalib/src/main/scala/java/net/InetAddress.scala +++ b/javalib/src/main/scala/java/net/InetAddress.scala @@ -12,6 +12,7 @@ import scala.scalanative.unsigned._ import scala.annotation.tailrec import java.io.IOException +import java.net.SocketHelpers.sockaddrToByteArray import java.{util => ju} import scala.scalanative.annotation.alwaysinline @@ -24,7 +25,7 @@ import scala.scalanative.posix.netinet.in._ import scala.scalanative.posix.netinet.inOps._ import scala.scalanative.posix.netdb._ import scala.scalanative.posix.netdbOps._ -import scala.scalanative.posix.string.strerror +import scala.scalanative.posix.string.{memcpy, strerror} import scala.scalanative.posix.sys.socket._ import scala.scalanative.posix.time.{time_t, time, difftime} import scala.scalanative.posix.unistd @@ -87,13 +88,12 @@ class InetAddress protected (ipAddress: Array[Byte], originalHost: String) } def getHostAddress(): String = { + val bytes = ipAddress.at(0) if (ipAddress.length == 4) { - formatIn4Addr(arrayByteToPtrByte(ipAddress)) + formatIn4Addr(bytes) } else if (ipAddress.length == 16) { - if (isIPv4MappedAddress(arrayByteToPtrByte(ipAddress))) { - formatIn4Addr( - arrayByteToPtrByte(extractIP4Bytes(arrayByteToPtrByte(ipAddress))) - ) + if (isIPv4MappedAddress(bytes)) { + formatIn4Addr(extractIP4Bytes(bytes).at(0)) } else { Inet6Address.formatInet6Address(this.asInstanceOf[Inet6Address]) } @@ -259,42 +259,12 @@ object InetAddress { } } - /* This is for littleEndian machines. It may need to detect BigEndian - * machines and do something different, at worst a byte-by-byte copy. - */ private def addrinfoToByteArray( addrinfoP: Ptr[addrinfo] ): Array[Byte] = { - - if (addrinfoP.ai_family == AF_INET6) { - val bufSize = 16 - val buf = new Array[Byte](bufSize) - - val addr = addrinfoP.ai_addr.asInstanceOf[Ptr[sockaddr_in6]] - val addrBytes = addr.sin6_addr.at1.asInstanceOf[Ptr[Byte]] - - memcpy(arrayByteToPtrByte(buf), addrBytes, bufSize.toUInt) - - buf - } else if (addrinfoP.ai_family == AF_INET) { - val buf = new Array[Byte](4) - - val v4addr = addrinfoP.ai_addr.asInstanceOf[Ptr[sockaddr_in]] - val sinAddr = v4addr.sin_addr - - val dst = arrayByteToPtrByte(buf).asInstanceOf[Ptr[in_addr]] - !dst = sinAddr // Structure copy - - buf - } else { - // caller should have detected & thrown before getting this far. - Array.empty[Byte] - } + sockaddrToByteArray(addrinfoP.ai_addr) } - @alwaysinline private def arrayByteToPtrByte(ab: Array[Byte]): Ptr[Byte] = - ab.asInstanceOf[scala.scalanative.runtime.ByteArray].at(0) - private def extractIP4Bytes(pb: Ptr[Byte]): Array[Byte] = { val buf = new Array[Byte](4) buf(0) = pb(12) @@ -317,7 +287,9 @@ object InetAddress { ) if (result == null) - throw new IOException(s"inet_ntop IPv4 failed, errno: ${errno}") + throw new IOException( + s"inet_ntop IPv4 failed,${fromCString(strerror(errno))}" + ) fromCString(dst) } @@ -487,8 +459,7 @@ object InetAddress { val MAXDNAME = 1025.toUInt /* maximum presentation domain name */ def tailorSockaddr(ipBA: Array[Byte], addr: Ptr[sockaddr]): Unit = { - val from = - ipBA.asInstanceOf[scala.scalanative.runtime.Array[Byte]].at(0) + val from = ipBA.at(0) // By contract the 'sockaddr' argument passed in is cleared/all_zeros. if (ipBA.length == 16) { diff --git a/javalib/src/main/scala/java/net/InterfaceAddress.scala b/javalib/src/main/scala/java/net/InterfaceAddress.scala new file mode 100644 index 0000000000..d09045c4c1 --- /dev/null +++ b/javalib/src/main/scala/java/net/InterfaceAddress.scala @@ -0,0 +1,43 @@ +package java.net + +class InterfaceAddress private[net] ( + inetAddr: InetAddress, + broadcastAddr: Option[Array[Byte]], + prefixLength: Short +) { + + override def equals(that: Any): Boolean = that match { + case that: InterfaceAddress => this.hashCode() == that.hashCode() + case _ => false + } + + def getAddress(): InetAddress = inetAddr + + lazy val bcAddress = { + if (broadcastAddr.isEmpty) null + else InetAddress.getByAddress(broadcastAddr.get) + } + + def getBroadcast(): InetAddress = bcAddress + + def getNetworkPrefixLength(): Short = prefixLength + + /** This hashCode is not intended or guaranteed to match Java. + */ + override def hashCode(): Int = + inetAddr.hashCode() + broadcastAddr.hashCode() + prefixLength + + override def toString(): String = { + val iaPart = inetAddr.getHostAddress() + + val broadcastPart = + if (broadcastAddr.isEmpty) "null" + else { + // Not the most runtime efficient algorithm, but easy to implement. + InetAddress.getByAddress(broadcastAddr.get).toString() + } + + s"/${iaPart}/${prefixLength} [${broadcastPart}]" + } + +} diff --git a/javalib/src/main/scala/java/net/NetworkInterface.scala b/javalib/src/main/scala/java/net/NetworkInterface.scala new file mode 100644 index 0000000000..df152ae1ae --- /dev/null +++ b/javalib/src/main/scala/java/net/NetworkInterface.scala @@ -0,0 +1,982 @@ +package java.net + +import scala.scalanative.unsafe._ +import scala.scalanative.unsigned._ + +import scala.annotation.tailrec + +import java.net.SocketHelpers.sockaddrToByteArray + +import java.{util => ju} +import ju.Objects +import ju.stream.Stream + +import scala.scalanative.posix.errno.{errno, ENXIO} +import scala.scalanative.posix.net.`if`._ +import scala.scalanative.posix.net.ifOps._ +import scala.scalanative.posix.netinet.in._ +import scala.scalanative.posix.netinet.inOps._ +import scala.scalanative.posix.sys.ioctl.ioctl +import scala.scalanative.posix.sys.socket._ +import scala.scalanative.posix.sys.socketOps._ +import scala.scalanative.posix.string._ +import scala.scalanative.posix.unistd + +import scala.scalanative.meta.LinktimeInfo +import scala.scalanative.runtime.Platform + +import macOsIf._ +import macOsIfDl._ + +/* Design Notes: + * 1) This code is Unix only. On Windows, "empty" values are returned. + * A Windows implementation is left as an exercise for the reader. + * + * 2) The Unix implementation often splits into a Linux path and a + * macOS/BSD path. The former uses ioctl() calls and lets the + * operating system search for the named interface. Such a kernel + * search should be marginally faster and less error prone than + * the user land search of getifaddrs() results done on the + * macOS/BSD path. + * + * 3) Virtual and/or sub-interface methods rely on the convention that such + * interfaces have a colon (:) in the name. Improvements are welcome. + * + * 4) For future reference: + * GetAdaptersAddresses() function exist on Windows Vista and later. + * Function returns a linked list of detailed adapter information + * (much more than just addresses). + * C examples are provided in the documentation on MSDN. + */ + +class NetworkInterface private (ifName: String) { + + override def equals(that: Any): Boolean = that match { + case that: NetworkInterface => this.hashCode() == that.hashCode() + case _ => false + } + + def getDisplayName(): String = getName() + + def getHardwareAddress(): Array[Byte] = { + if (Platform.isWindows()) new Array[Byte](0) // No Windows support + else { + NetworkInterface.unixImplGetHardwareAddress(ifName) + } + } + + def getIndex(): Int = { + if (Platform.isWindows()) 0 // No Windows support + else { + NetworkInterface.unixImplGetIndex(ifName) + } + } + + def getInetAddresses(): ju.Enumeration[InetAddress] = { + if (Platform.isWindows()) { // No Windows support + ju.Collections.enumeration[InetAddress](new ju.ArrayList[InetAddress]) + } else { + NetworkInterface.unixImplGetInetAddresses(ifName) + } + } + + def getInterfaceAddresses(): ju.List[InterfaceAddress] = { + if (Platform.isWindows()) { // No Windows support + ju.Collections.emptyList[InterfaceAddress]() + } else { + NetworkInterface.unixImplGetInterfaceAddresses(ifName) + } + } + + def getMTU(): Int = { + if (Platform.isWindows()) 0 // No Windows support + else { + NetworkInterface.unixImplGetIfMTU(ifName) + } + } + + def getName(): String = ifName + + def getParent(): NetworkInterface = { + if (Platform.isWindows()) null // No Windows support + else if (!this.isVirtual()) null + else { + val parentName = ifName.split(":")(0) + NetworkInterface.getByName(parentName) + } + } + + def getSubInterfaces(): ju.Enumeration[NetworkInterface] = { + val ifList = new ju.ArrayList[NetworkInterface]() + + // No Windows support, so empty Enumeration will be returned. + if (!Platform.isWindows()) { + val allIfs = NetworkInterface.getNetworkInterfaces() + val matchMe = s"${ifName}:" + while (allIfs.hasMoreElements()) { + val elem = allIfs.nextElement() + val elemName = elem.getName() + if (elemName.startsWith(matchMe)) + ifList.add(elem) + } + } + ju.Collections.enumeration[NetworkInterface](ifList) + } + + def inetAddresses(): Stream[InetAddress] = { + if (Platform.isWindows()) Stream.empty[InetAddress]() // No Windows support + else { + NetworkInterface.unixImplInetAddresses(ifName) + } + } + + def isLoopback(): Boolean = { + if (Platform.isWindows()) false // No Windows support + else { + val ifFlags = NetworkInterface.unixImplGetIfFlags(ifName) + (ifFlags & unixIf.IFF_LOOPBACK) == unixIf.IFF_LOOPBACK + } + } + + def isPointToPoint(): Boolean = { + if (Platform.isWindows()) false // No Windows support + else { + val ifFlags = NetworkInterface.unixImplGetIfFlags(ifName) + (ifFlags & unixIf.IFF_POINTOPOINT) == unixIf.IFF_POINTOPOINT + } + } + + def isUp(): Boolean = { + if (Platform.isWindows()) false // No Windows support + else { + val ifFlags = NetworkInterface.unixImplGetIfFlags(ifName) + (ifFlags & unixIf.IFF_UP) == unixIf.IFF_UP + } + } + + // relies upon convention that Virtual or sub-interfaces have colon in name. + def isVirtual(): Boolean = ifName.indexOf(':') >= 0 // a best guess + + override def hashCode(): Int = ifName.hashCode() + + def subInterfaces(): Stream[NetworkInterface] = { + val allIfs = NetworkInterface.networkInterfaces() + val matchMe = s"${ifName}:" + allIfs.filter(_.getName().startsWith(matchMe)) + } + + def supportsMulticast(): Boolean = { + if (Platform.isWindows()) false // No Windows support + else { + val ifFlags = NetworkInterface.unixImplGetIfFlags(ifName) + (ifFlags & unixIf.IFF_MULTICAST) == unixIf.IFF_MULTICAST + } + } + + override def toString(): String = s"name:${ifName} (${ifName})" + +} + +object NetworkInterface { + import unixIfaddrs._ + import unixIfaddrsOps._ + + def getByIndex(index: Int): NetworkInterface = { + if (index < 0) + throw new IllegalArgumentException("Interface index can't be negative") + + if (Platform.isWindows()) { + null + } else { + unixGetByIndex(index) + } + } + + def getByInetAddress(addr: InetAddress): NetworkInterface = { + Objects.requireNonNull(addr) + if (Platform.isWindows()) { + null + } else { + unixGetByInetAddress(addr) + } + } + + def getByName(name: String): NetworkInterface = { + Objects.requireNonNull(name) + if (Platform.isWindows()) { + null + } else { + unixGetByName(name) + } + } + + def getNetworkInterfaces(): ju.Enumeration[NetworkInterface] = { + if (Platform.isWindows()) { + null + } else { + unixGetNetworkInterfaces() + } + } + + /** networkInterfaces() method is Java 9. It is provided because Streams are + * less clumsy than Enumerations. + */ + def networkInterfaces(): Stream[NetworkInterface] = { + if (Platform.isWindows()) { + null + } else { + unixNetworkInterfaces() + } + } + + private def createInetAddress( + ifa: Ptr[ifaddrs], + ifName: String + ): Option[InetAddress] = { + val sa = ifa.ifa_addr + val af = sa.sa_family.toInt + + if (!((af == AF_INET) || (af == AF_INET6))) None + else { + val bytes = sockaddrToByteArray(sa) + if (af == AF_INET) { + Some(InetAddress.getByAddress(bytes)) + } else { + val scopeId = sa.asInstanceOf[Ptr[sockaddr_in6]].sin6_scope_id.toInt + Some(Inet6Address(bytes, "", scopeId, ifName)) + } + } + } + + private def createInterfaceAddress( + ifa: Ptr[ifaddrs], + interfaceName: String + ): Option[InterfaceAddress] = { + + def decodePrefixLength(sa: Ptr[sockaddr]): Short = { + val result = + if (sa.sa_family.toInt == AF_INET) { + val sin4 = sa.asInstanceOf[Ptr[sockaddr_in]] + val mask = sin4.sin_addr.s_addr.toInt + Integer.bitCount(mask) + } else if (sa.sa_family.toInt == AF_INET6) { + val sin6 = sa.asInstanceOf[Ptr[sockaddr_in6]] + val longs = + sin6.sin6_addr.at1.asInstanceOf[Ptr[scala.Long]] + java.lang.Long.bitCount(longs(0)) + java.lang.Long.bitCount(longs(1)) + } else { + 0 // Blivet! Unknown address family, assume zero length prefix. + } + result.toShort + } + + val sa = ifa.ifa_addr + val af = sa.sa_family.toInt + if (!((af == AF_INET) || (af == AF_INET6))) { + None // Silently skip AF_PACKET (17) and such. + } else { + val bytes = sockaddrToByteArray(sa) + val inetAddress = if (af == AF_INET) { + InetAddress.getByAddress(bytes) + } else { + val scopeId = sa.asInstanceOf[Ptr[sockaddr_in6]].sin6_scope_id + Inet6Address(bytes, "", scopeId.toInt, interfaceName) + } + + val broadcastAddress: Option[Array[Byte]] = + if (sa.sa_family.toInt == AF_INET6) None + else if ((ifa.ifa_flags & unixIf.IFF_LOOPBACK.toUInt) != 0.toUInt) None + else Some(sockaddrToByteArray(ifa.ifa_broadaddr)) + + val prefixLen = decodePrefixLength(ifa.ifa_netmask) + + val ifAddress = + new InterfaceAddress(inetAddress, broadcastAddress, prefixLen) + + Some(ifAddress) + } + } + + private def createNetworkInterface(ifa: Ptr[ifaddrs]): NetworkInterface = { + val ifName = fromCString(ifa.ifa_name) + new NetworkInterface(ifName) + } + + private def unixGetByIndex(index: Int): NetworkInterface = { + val buf = stackalloc[Byte](IF_NAMESIZE.toUInt) + + val ret = if_indextoname(index.toUInt, buf) + + if (ret != null) unixGetByName(fromCString(ret)) + else if (errno == ENXIO) null // no interface has that index + else + throw new SocketException(fromCString(strerror(errno))) + } + + private def unixGetByInetAddress(addr: InetAddress): NetworkInterface = { + + def found(addr: Array[Byte], addrLen: Int, sa: Ptr[sockaddr]): Boolean = { + val sa_family = sa.sa_family.toInt + if (sa_family == AF_INET6) { + if (addrLen != 16) false + else { + val sa6 = sa.asInstanceOf[Ptr[sockaddr_in6]] + val sin6Addr = sa6.sin6_addr.at1.asInstanceOf[Ptr[Byte]] + memcmp(addr.at(0), sin6Addr, addrLen.toUInt) == 0 + } + } else if (sa_family == AF_INET) { + val sa4 = sa.asInstanceOf[Ptr[sockaddr_in]] + val sin4Addr = sa4.sin_addr.at1.asInstanceOf[Ptr[Byte]] + memcmp(addr.at(0), sin4Addr, addrLen.toUInt) == 0 + } else false + } + + @tailrec + def findIfInetAddress( + ipAddress: Array[Byte], + addrLen: Int, + ifa: Ptr[ifaddrs] + ): NetworkInterface = { + if (ifa == null) null + else if (found(ipAddress, addrLen, ifa.ifa_addr)) + createNetworkInterface(ifa) + else + findIfInetAddress( + ipAddress, + addrLen, + ifa.ifa_next.asInstanceOf[Ptr[ifaddrs]] + ) + } + + val addrBytes = addr.getAddress() + val len = addrBytes.length // check this once, not N times + + if (!((len == 4) || (len == 16))) + throw new SocketException( + s"unixGetByInetAddress: wrong Array[Byte] length: ${len}" + ) + else { + val ifap = stackalloc[Ptr[ifaddrs]]() + + val gifStatus = getifaddrs(ifap) + if (gifStatus == -1) + throw new SocketException( + s"getifaddrs failed: ${fromCString(strerror(errno))}" + ) + + val result = + try { + findIfInetAddress(addrBytes, len, !ifap) + } finally { + freeifaddrs(!ifap) + } + + result + } + } + + private def unixGetByName(name: String): NetworkInterface = Zone { + implicit z => + @tailrec + def findIfName( + cName: CString, + ifa: Ptr[ifaddrs] + ): NetworkInterface = { + if (ifa == null) null + else if (strcmp(ifa.ifa_name, cName) == 0) + createNetworkInterface(ifa) + else findIfName(cName, ifa.ifa_next.asInstanceOf[Ptr[ifaddrs]]) + } + + val cName = toCString(name) + val ifap = stackalloc[Ptr[ifaddrs]]() + + val gifStatus = getifaddrs(ifap) + if (gifStatus == -1) + throw new SocketException( + s"getifaddrs failed: ${fromCString(strerror(errno))}" + ) + + val result = + try { + findIfName(cName, !ifap) + } finally { + freeifaddrs(!ifap) + } + + result + } + + private def unixAccumulateNetworkInterfaces( + accumulator: (NetworkInterface) => Unit + ): Unit = { + + @tailrec + def accumulateNetIfs( + ni: Ptr[if_nameindex], + addOne: (NetworkInterface) => Unit + ): Unit = { + if ((ni.if_index.toInt != 0) || (ni.if_name != null)) { + val ifName = + if (ni.if_name == null) "" + else fromCString(ni.if_name) + + addOne(new NetworkInterface(ifName)) + + accumulateNetIfs( + ni + 1, // + 1 should skip entire structure + accumulator + ) + } + } + + val nameIndex = if_nameindex() + + if (nameIndex == null) + throw new SocketException( + s"if_nameindex() failed: ${fromCString(strerror(errno))}" + ) + + try { + accumulateNetIfs(nameIndex, accumulator) + } finally { + if_freenameindex(nameIndex) + } + } + + private def unixGetNetworkInterfaces(): ju.Enumeration[NetworkInterface] = { + val ifList = new ju.ArrayList[NetworkInterface]() + unixAccumulateNetworkInterfaces((netIf: NetworkInterface) => { + ifList.add(netIf); () + }) + ju.Collections.enumeration[NetworkInterface](ifList) + } + + private def unixNetworkInterfaces(): Stream[NetworkInterface] = { + val builder = Stream.builder[NetworkInterface]() + unixAccumulateNetworkInterfaces((netIf: NetworkInterface) => { + builder.add(netIf); () + }) + builder.build() + } + + /* Implement OS specific class & helper methods + */ + + private def linuxImplGetIoctlFd(): Int = { + val fd = socket(AF_INET, SOCK_DGRAM, 0) + + if (fd == -1) { + val msg = fromCString(strerror(errno)) + throw new SocketException(s"socket(AF_INET, SOCK_DGRAM) failed: ${msg}\n") + } + + fd + } + + private def macOsImplExecCallback( + ifName: String, + callback: Ptr[ifaddrs] => Tuple2[Int, Array[Byte]] + ): Tuple2[Int, Array[Byte]] = { + @tailrec + def findAfLinkIfName( + ifNameC: CString, + ifa: Ptr[ifaddrs] + ): Ptr[ifaddrs] = { + if (ifa == null) null + else if ((strcmp(ifNameC, ifa.ifa_name) == 0) + && (ifa.ifa_addr.sa_family.toInt == 18 /* AF_LINK */ )) + ifa + else + findAfLinkIfName(ifNameC, ifa.ifa_next) + } + + val ifap = stackalloc[Ptr[ifaddrs]]() + + val gifStatus = getifaddrs(ifap) + if (gifStatus == -1) + throw new SocketException( + s"getifaddrs failed: ${fromCString(strerror(errno))}" + ) + + try + Zone { implicit z => + val foundIfa = findAfLinkIfName(toCString(ifName), !ifap) + callback(foundIfa) + } + finally { + freeifaddrs(!ifap) + } + } + + private def unixImplGetIndex(ifName: String): Int = Zone { implicit z => + // toInt truncation OK, since index will never be larger than MAX_INT + if_nametoindex(toCString(ifName)).toInt + // Return 0 on error. Do not give errno error message. + } + + private def unixImplGetHardwareAddress(ifName: String): Array[Byte] = { + if (LinktimeInfo.isLinux) + linuxImplGetHardwareAddress(ifName) + else + macOsImplGetHardwareAddress(ifName) + } + + private def macOsImplGetHardwareAddress(ifName: String): Array[Byte] = { + def decodeSocketDl(sockaddrDl: Ptr[macOsIfDl.sockaddr_dl]): Array[Byte] = { + + val nBytes = if (sockaddrDl == null) 0 else sockaddrDl.sdl_alen.toInt + val bytes = new Array[Byte](nBytes) + + if (nBytes > 0) { // skip name + val src = sockaddrDl.sdl_data.at(sockaddrDl.sdl_nlen.toInt) + val dst = bytes.at(0) + memcpy(dst, src, nBytes.toUInt) + } + bytes + } + + def cb(ifa: Ptr[ifaddrs]): Tuple2[Int, Array[Byte]] = { + val arr = + if (ifa == null) new Array[Byte](0) + else + decodeSocketDl(ifa.ifa_addr.asInstanceOf[Ptr[sockaddr_dl]]) + + (0, arr) + } + + macOsImplExecCallback(ifName, cb)._2 + } + + private def linuxImplGetHardwareAddress(ifName: String): Array[Byte] = Zone { + implicit z => + // acknowledge: + // https://www.geekpage.jp/en/programming/linux-network/get-macaddr.php + + val request = stackalloc[unixIf.ifreq_hwaddress]() + + strncpy( + request.at1.asInstanceOf[CString], + toCString(ifName), + (unixIf.IFNAMSIZ - 1).toUSize + ) + + val saP = request.at2.asInstanceOf[Ptr[sockaddr]] + saP.sa_family = AF_INET.toUShort + + val fd = linuxImplGetIoctlFd() + + try { + val status = + ioctl(fd, unixIf.SIOCGIFHWADDR, request.asInstanceOf[Ptr[Byte]]); + if (status != 0) { + val msg = fromCString(strerror(errno)) + throw new SocketException(s"ioctl SIOCGIFHWADDR failed: ${msg}\n") + } + } finally { + unistd.close(fd) + } + + val hwAddress = new Array[Byte](6) + val hwAddrBytes = request.at2.sa_data + + for (j <- 0 until 6) + hwAddress(j) = hwAddrBytes(j) + + hwAddress + } + + private def unixImplGetIfMTU(ifName: String): Int = { + if (LinktimeInfo.isLinux) + linuxImplGetIfMTU(ifName) + else + macOsImplGetIfMTU(ifName) + } + + private def macOsImplGetIfMTU(ifName: String): Int = { + def cb(ifa: Ptr[ifaddrs]): Tuple2[Int, Array[Byte]] = { + val result = + if (ifa == null) 0 + else + ifa.ifa_data.asInstanceOf[Ptr[macOsIf.if_data]].ifi_mtu.toInt + + (result, null) + } + + macOsImplExecCallback(ifName, cb)._1 + } + + private def linuxImplGetIfMTU(ifName: String): Int = Zone { implicit z => + val request = stackalloc[unixIf.ifreq_mtu]() + + strncpy( + request.at1.asInstanceOf[CString], + toCString(ifName), + (unixIf.IFNAMSIZ - 1).toUSize + ) + + val saP = request.at2.asInstanceOf[Ptr[sockaddr]] + saP.sa_family = AF_INET.toUShort + + val fd = linuxImplGetIoctlFd() + + try { + val status = + ioctl(fd, unixIf.SIOCGIFMTU, request.asInstanceOf[Ptr[Byte]]); + if (status != 0) + throw new SocketException( + s"ioctl SIOCGIFMTU failed: ${fromCString(strerror(errno))}" + ) + + } finally { + unistd.close(fd) + } + + request._2 // ifr_mtu + } + + private def unixImplGetIfFlags(ifName: String): Short = { + if (LinktimeInfo.isLinux) + linuxImplGetIfFlags(ifName) + else + macOsImplGetIfFlags(ifName) + } + + private def macOsImplGetIfFlags(ifName: String): Short = { + def cb(ifa: Ptr[ifaddrs]): Tuple2[Int, Array[Byte]] = { + val result = + if (ifa == null) 0 + else ifa.ifa_flags.toInt + + (result, null) + } + + macOsImplExecCallback(ifName, cb)._1.toShort + } + + private def linuxImplGetIfFlags(ifName: String): Short = Zone { implicit z => + val request = stackalloc[unixIf.ifreq_flags]() + + strncpy( + request.at1.asInstanceOf[CString], + toCString(ifName), + (unixIf.IFNAMSIZ - 1).toUSize + ) + + val saP = request.at2.asInstanceOf[Ptr[sockaddr]] + saP.sa_family = AF_INET.toUShort + + val fd = linuxImplGetIoctlFd() + + try { + val status = + ioctl(fd, unixIf.SIOCGIFFLAGS, request.asInstanceOf[Ptr[Byte]]); + + if (status != 0) { + val msg = fromCString(strerror(errno)) + throw new SocketException(s"ioctl SIOCGIFFLAGS failed: ${msg}\n") + } + } finally { + unistd.close(fd) + } + + request._2 // ifr_flags + } + + private def unixAccumulateInetAddresses( + ifNameJ: String, + accumulator: (InetAddress) => Unit + ): Unit = Zone { implicit z => + @tailrec + def accumulateInetAddresses( + ifNameC: CString, + addOne: (InetAddress) => Unit, + ifa: Ptr[ifaddrs] + ): Unit = { + if (ifa != null) { + if (strcmp(ifNameC, ifa.ifa_name) == 0) { + createInetAddress(ifa, ifNameJ).map(ia => addOne(ia)) + } + accumulateInetAddresses( + ifNameC, + addOne, + ifa.ifa_next.asInstanceOf[Ptr[ifaddrs]] + ) + } + } + + val ifap = stackalloc[Ptr[ifaddrs]]() + + val gifStatus = getifaddrs(ifap) + + if (gifStatus == -1) + throw new SocketException( + s"getifaddrs failed: ${fromCString(strerror(errno))}" + ) + + try { + accumulateInetAddresses(toCString(ifNameJ), accumulator, !ifap) + } finally { + freeifaddrs(!ifap) + } + } + + private def unixAccumulateInterfaceAddresses( + ifName: String, + accumulator: (InterfaceAddress) => Unit + ): Unit = Zone { implicit z => + @tailrec + def accumulateInterfaceAddresses( + ifNameJ: String, + ifNameC: CString, + addOne: (InterfaceAddress) => Unit, + ifa: Ptr[ifaddrs] + ): Unit = { + if (ifa != null) { + if (strcmp(ifNameC, ifa.ifa_name) == 0) { + createInterfaceAddress(ifa, ifNameJ).map(ia => addOne(ia)) + } + accumulateInterfaceAddresses( + ifNameJ, + ifNameC, + addOne, + ifa.ifa_next.asInstanceOf[Ptr[ifaddrs]] + ) + } + } + + val ifap = stackalloc[Ptr[ifaddrs]]() + + val gifStatus = getifaddrs(ifap) + + if (gifStatus == -1) + throw new SocketException( + s"getifaddrs failed: ${fromCString(strerror(errno))}" + ) + + try { + accumulateInterfaceAddresses( + ifName, + toCString(ifName), + accumulator, + !ifap + ) + } finally { + freeifaddrs(!ifap) + } + } + + private def unixImplGetInterfaceAddresses( + ifName: String + ): ju.List[InterfaceAddress] = { + val ifaList = new ju.ArrayList[InterfaceAddress]() + unixAccumulateInterfaceAddresses( + ifName, + (ifa: InterfaceAddress) => { ifaList.add(ifa); () } + ) + ifaList + } + + private def unixImplGetInetAddresses( + ifName: String + ): ju.Enumeration[InetAddress] = { + val ifList = new ju.ArrayList[InetAddress]() + unixAccumulateInetAddresses( + ifName, + (ia: InetAddress) => { ifList.add(ia); () } + ) + ju.Collections.enumeration[InetAddress](ifList) + } + + private def unixImplInetAddresses(ifName: String): Stream[InetAddress] = { + val builder = Stream.builder[InetAddress]() + unixAccumulateInetAddresses( + ifName, + (ia: InetAddress) => { builder.add(ia); () } + ) + builder.build() + } + +} + +@extern +private object unixIfaddrs { + /* Reference: man getifaddrs + * #include + */ + + // format: off + type ifaddrs = CStruct7[ + Ptr[Byte], /* Ptr[ifaddrs] */ // ifa_next: Next item in list + CString, // ifa_name: Name of interface + CUnsignedInt, // ifa_flags: Flags from SIOCGIFFLAGS + Ptr[sockaddr], // ifa_addr: Address of interface + Ptr[sockaddr], // ifa_netmask: Netmask of interface + // ifu_broadaddr: Broadcast address of interface + // ifu_dstaddr: Point-to-point destination address + Ptr[sockaddr], // union: ifu_broadaddr, ifu_dstaddr + Ptr[Byte] // ifa_data: Address-specific data + ] + // format: on + + def getifaddrs(ifap: Ptr[Ptr[ifaddrs]]): CInt = extern + + def freeifaddrs(ifa: Ptr[ifaddrs]): Unit = extern +} + +private object unixIfaddrsOps { + import unixIfaddrs._ + + implicit class unixIfaddrOps(val ptr: Ptr[ifaddrs]) extends AnyVal { + def ifa_next: Ptr[ifaddrs] = ptr._1.asInstanceOf[Ptr[ifaddrs]] + def ifa_name: CString = ptr._2 + def ifa_flags: CUnsignedInt = ptr._3 + def ifa_addr: Ptr[sockaddr] = ptr._4 + def ifa_netmask: Ptr[sockaddr] = ptr._5 + def ifa_broadaddr: Ptr[sockaddr] = ptr._6 + def ifa_dstaddr: Ptr[sockaddr] = ptr._6 + def ifa_data: Ptr[Byte] = ptr._7 + + // ifa fields are read-only in use, so no Ops here to set them. + } +} + +@extern +private object unixIf { + /* Reference: man 7 netdevice + * #include + */ + + // Three SN-only types used to facilitate retrieving specific types of data. + type ifreq_hwaddress = CStruct2[ + CArray[CChar, Nat.Digit2[Nat._1, Nat._6]], + sockaddr + ] + + type ifreq_mtu = CStruct2[ + CArray[CChar, Nat.Digit2[Nat._1, Nat._6]], + CInt + ] + + type ifreq_flags = CStruct2[ + CArray[CChar, Nat.Digit2[Nat._1, Nat._6]], + CShort + ] + + @name("scalanative_ifnamesiz") + def IFNAMSIZ: CInt = extern + + @name("scalanative_iff_broadcast") + def IFF_BROADCAST: CInt = extern + + @name("scalanative_iff_loopback") + def IFF_LOOPBACK: CInt = extern + + @name("scalanative_iff_multicast") + def IFF_MULTICAST: CInt = extern + + @name("scalanative_iff_pointopoint") + def IFF_POINTOPOINT: CInt = extern + + @name("scalanative_iff_running") + def IFF_RUNNING: CInt = extern + + @name("scalanative_siocgifflags") + def SIOCGIFFLAGS: CInt = extern + + @name("scalanative_siocgifhwaddr") + def SIOCGIFHWADDR: CInt = extern + + @name("scalanative_siocgifmtu") + def SIOCGIFMTU: CInt = extern + + @name("scalanative_iff_up") + def IFF_UP: CInt = extern +} + +private object macOsIf { + + /* Scala if_data & corresponding ifDataOps definitions are not complete. + * Only items used in NetworkInterface are declared. + */ + + /* Reference: macOS + * /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include + * /net/if_var.h + * + * struct if_data { + * // generic interface information + * u_char ifi_type; // ethernet, tokenring, etc + * u_char ifi_typelen; // Length of frame type id + * u_char ifi_physical; // e.g., AUI, Thinnet, 10base-T, etc + * u_char ifi_addrlen; // media address length + * u_char ifi_hdrlen; // media header length + * u_char ifi_recvquota; // polling quota for receive intrs + * u_char ifi_xmitquota; // polling quota for xmit intrs + * u_char ifi_unused1; // for future use + * u_int32_t ifi_mtu; // maximum transmission unit + */ + + // Incomplete + type if_data = CStruct2[ + CLongLong, // Placeholder, consolidate & skip fields of no interest. + CUnsignedInt // ifi_mtu + ] + + // Incomplete, corresponding to incomplete if_data just above. + implicit class ifDataOps(val ptr: Ptr[if_data]) extends AnyVal { + def ifi_mtu: CUnsignedInt = ptr._2 + } + // ifi fields read-only fields in use, so no Ops here to set them. +} + +private object macOsIfDl { + /* Scala sockaddr_dl & corresponding sockaddrDlOps definitions are not + * complete. They are only what NetworkInterface uses. + */ + + /* Reference: FreeBSD man sockaddr_dl + * #include + * + * For sdl_data field, use the larger of macOS defined 12 and + * FreeBSD defined 46. + * + * struct sockaddr_dl + * The sockaddr_dl structure is used to describe a layer 2 link-level + * address. The structure has the following members: + * + * ushort_t sdl_family; // address family + * ushort_t sdl_index; // if != 0, system interface index + * uchar_t sdl_type; // interface type + * uchar_t sdl_nlen; // interface name length + * uchar_t sdl_alen; // link level address length + * uchar_t sdl_slen; // link layer selector length + * char sdl_data[46]; // contains both if name and ll address + */ + + // sdl_data, max(macOs == 12, FreeBsd == 46) + type _46 = Nat.Digit2[Nat._4, Nat._6] + type sdl_data_t = CArray[CChar, _46] + + type sockaddr_dl = CStruct8[ + Byte, // sdl_len; // Total length of sockaddr + Byte, // sdl_family; // address family + CShort, // sdl_index + Byte, // sdl_type + Byte, // sdl_nlen + Byte, // sdl_alen + Byte, // sdl_slen + sdl_data_t + ] + + implicit class sockaddrDlOps(val ptr: Ptr[sockaddr_dl]) extends AnyVal { + def sdl_len: UByte = ptr._1.toUByte + def sdl_family: UByte = ptr._2.toUByte + def sdl_index: UShort = ptr._3.toUShort + def sdl_type: UByte = ptr._4.toUByte + def sdl_nlen: UByte = ptr._5.toUByte + def sdl_alen: UByte = ptr._6.toUByte + def sdl_slen: UByte = ptr._7.toUByte + def sdl_data: sdl_data_t = ptr._8 + } +} diff --git a/javalib/src/main/scala/java/net/SocketHelpers.scala b/javalib/src/main/scala/java/net/SocketHelpers.scala index 9caa1a7c8c..30ebab2216 100644 --- a/javalib/src/main/scala/java/net/SocketHelpers.scala +++ b/javalib/src/main/scala/java/net/SocketHelpers.scala @@ -5,8 +5,10 @@ import scala.scalanative.unsafe._ import scala.scalanative.posix.{netdb, netdbOps}, netdb._, netdbOps._ import scala.scalanative.posix.netinet.in +import scala.scalanative.posix.netinet.inOps._ import scala.scalanative.posix.sys.socket._ import scala.scalanative.posix.sys.socketOps._ +import scala.scalanative.posix.string.memcpy import scala.scalanative.meta.LinktimeInfo.isWindows @@ -130,6 +132,31 @@ object SocketHelpers { } } + private[net] def sockaddrToByteArray(sockAddr: Ptr[sockaddr]): Array[Byte] = { + + val (src, byteArraySize) = { + val af = sockAddr.sa_family.toInt + if (af == AF_INET6) { + val v6addr = sockAddr.asInstanceOf[Ptr[in.sockaddr_in6]] + val sin6Addr = v6addr.sin6_addr.at1.asInstanceOf[Ptr[Byte]] + val arraySize = 16 + (sin6Addr, arraySize) + } else if (af == AF_INET) { + val v4addr = sockAddr.asInstanceOf[Ptr[in.sockaddr_in]] + val sin4Addr = v4addr.sin_addr.at1.asInstanceOf[Ptr[Byte]] + val arraySize = 4 + (sin4Addr, arraySize) + } else { + throw new SocketException(s"Unsupported address family: ${af}") + } + } + + val byteArray = new Array[Byte](byteArraySize) + memcpy(byteArray.at(0), src, byteArraySize.toUInt) + + byteArray + } + // Create copies of loopback & wildcard, so that originals never get changed // ScalaJVM shows loopbacks with null host, wildcards with numeric host. diff --git a/unit-tests/shared/src/test/require-jdk9/org/scalanative/testsuite/javalib/net/NetworkInterfaceTestOnJDK9.scala b/unit-tests/shared/src/test/require-jdk9/org/scalanative/testsuite/javalib/net/NetworkInterfaceTestOnJDK9.scala new file mode 100644 index 0000000000..cf7c04a284 --- /dev/null +++ b/unit-tests/shared/src/test/require-jdk9/org/scalanative/testsuite/javalib/net/NetworkInterfaceTestOnJDK9.scala @@ -0,0 +1,44 @@ +package javalib.net + +import java.net._ + +import org.junit.Test +import org.junit.Assert._ +import org.junit.Assume._ + +import org.scalanative.testsuite.utils.Platform + +/* Design Notes: + * 1) See Design Notes in NetworkInterfaceTest.scala + */ + +class NetworkInterfaceTestOnJDK9 { + + val localhostIf = + if (Platform.isLinux) "lo" + else "lo0" + +// Test instance method(s) + + @Test def instanceInetAddresses(): Unit = { + assumeFalse("Not implemented in Windows", Platform.isWindows) + + val lbIf = NetworkInterface.getByName(localhostIf) + assertNotNull(lbIf) + + // SN Stream implements neither Stream.count() nor Stream.reduce() + val iaStream = lbIf.inetAddresses() + + var count = 0 + + val itr = iaStream.iterator() + + while (itr.hasNext()) { + itr.next() + count += 1 + } + + assertTrue("count > 0", count > 0) + } + +} diff --git a/unit-tests/shared/src/test/scala/javalib/net/InterfaceAddressTest.scala b/unit-tests/shared/src/test/scala/javalib/net/InterfaceAddressTest.scala new file mode 100644 index 0000000000..3cf2264fb6 --- /dev/null +++ b/unit-tests/shared/src/test/scala/javalib/net/InterfaceAddressTest.scala @@ -0,0 +1,170 @@ +package javalib.net + +import java.net._ + +import org.junit.Test +import org.junit.Assert._ +import org.junit.Assume._ + +import org.scalanative.testsuite.utils.AssertThrows.assertThrows +import org.scalanative.testsuite.utils.Platform + +import java.util.function.Consumer + +/* Design Notes: + * 1) As the underlying implementation is Unix only, so are these Tests. + * + * 2) Network interface configuration is can and does vary greatly from + * system to system. These tests are written to succeed with the + * configuration used by the Scala Native Continuous Integration systems. + * + * They may fail if used outside of that environment and require + * editing to reflect that local configuration. + */ + +class InterfaceAddressTest { + + /* The tests in this class depend upon a competent NetworkInterface class. + * They also assume, perhaps unwisely, that the loopback address has index 1. + */ + + val localhostIf = + if (Platform.isLinux) "lo" + else "lo0" + + val osIPv6PrefixLength = + if (Platform.isMacOs) 64 + else 128 + + val osIPv6LoopbackSuffix = + s":0:0:0:0:0:0:1%${localhostIf}" + + val osIPv6LoopbackAddress = + if (Platform.isMacOs) s"fe80${osIPv6LoopbackSuffix}" + else s"0${osIPv6LoopbackSuffix}" + + /* Test equals() but there is no good, simple way to test corresponding + * hashCode(). The contents of the components used in the hash vary by + * operating system. + * + * equals() calls hashCode() showing that the latter at least executes. + */ + @Test def testEquals(): Unit = { + assumeFalse("Not implemented in Windows", Platform.isWindows) + + val netIf = NetworkInterface.getByIndex(1) // loopback + assertNotNull(netIf) + + val ifAddresses = netIf.getInterfaceAddresses() + assertTrue("No InterfaceAddress found", ifAddresses.size > 0) + + assumeTrue("not enough ifAddresses for test", ifAddresses.size >= 2) + + val ifa1 = ifAddresses.get(0) + val ifa2 = ifAddresses.get(1) + + assertEquals("InterfaceAddress equal", ifa1, ifa1) + assertNotEquals("InterfaceAddress not equal", ifa1, ifa2) + } + + @Test def testGetAddress(): Unit = { + assumeFalse("Not implemented in Windows", Platform.isWindows) + + val netIf = NetworkInterface.getByIndex(1) // loopback + assertNotNull(netIf) + + val ifAddresses = netIf.getInterfaceAddresses() + assertTrue("No InterfaceAddress found", ifAddresses.size > 0) + + // Scala 2.11 demands this gronking forEach idiom. + val consumer = new Consumer[InterfaceAddress] { + def accept(addr: InterfaceAddress): Unit = { + val hostAddr = addr.getAddress().getHostAddress() + // macOS can have two forms of IPv6 loopback address. + val expected = + if (!hostAddr.contains(":")) { + "127.0.0.1" + } else if (hostAddr.startsWith("0")) { + s"0:0:0:0:0:0:0:1%${localhostIf}" + } else if (hostAddr.startsWith("f")) { + s"${osIPv6LoopbackAddress}" + } else "" // fail in a way that will print out ifAddrString + + assertEquals("Unexpected result", expected, hostAddr) + } + } + + ifAddresses.forEach(consumer) + } + + /* @Test def testGetBroadcast(): Unit = {} + * Not implemented - system dependent. + * Loopback addresses have not broadcast address to get. + * Non-loopback primary interface varies and can not be determined. + */ + + @Test def testGetNetworkPrefixLength(): Unit = { + assumeFalse("Not implemented in Windows", Platform.isWindows) + + val netIf = NetworkInterface.getByIndex(1) // loopback + assertNotNull(netIf) + + val ifAddresses = netIf.getInterfaceAddresses() + assertTrue("No InterfaceAddress found", ifAddresses.size > 0) + + // Scala 2.11 demands this gronking forEach idiom. + val consumer = new Consumer[InterfaceAddress] { + def accept(addr: InterfaceAddress): Unit = { + val ia = addr.getAddress().getAddress() + val len = ia.length + + val expected = + if (len == 4) 8.toShort // IPv4 + else if (len != 16) -1.toShort // fail but print prefixLen + else if (ia(0) == 0) 128.toShort // Linux & macOS ::1 form + else osIPv6PrefixLength.toShort // macOs ff80::1 form + + val prefixLen = addr.getNetworkPrefixLength() + assertEquals("unexpected prefix length", expected, prefixLen) + } + } + + ifAddresses.forEach(consumer) + } + + @Test def testLoopbackToString(): Unit = { + assumeFalse("Not implemented in Windows", Platform.isWindows) + + /* The toString should have the form: + * InetAddress / prefix length [ broadcast address ] + */ + + val netIf = NetworkInterface.getByIndex(1) // loopback + assertNotNull(netIf) + + val ifAddresses = netIf.getInterfaceAddresses() + assertTrue("No InterfaceAddress found", ifAddresses.size > 0) + + // Scala 2.11 demands this gronking forEach idiom. + val consumer = new Consumer[InterfaceAddress] { + def accept(addr: InterfaceAddress): Unit = { + val ifAddrString = addr.toString + + // macOS can have two forms of IPv6 loopback address. + val expected = + if (!ifAddrString.contains(":")) { + "/127.0.0.1/8 [null]" + } else if (ifAddrString.startsWith("/0")) { + s"/0:0:0:0:0:0:0:1%${localhostIf}/128 [null]" + } else if (ifAddrString.startsWith("/f")) { + s"/${osIPv6LoopbackAddress}/${osIPv6PrefixLength} [null]" + } else "" // fail in a way that will print out ifAddrString + + assertEquals("InterfaceAddress", expected, ifAddrString) + } + } + + ifAddresses.forEach(consumer) + } + +} diff --git a/unit-tests/shared/src/test/scala/javalib/net/NetworkInterfaceTest.scala b/unit-tests/shared/src/test/scala/javalib/net/NetworkInterfaceTest.scala new file mode 100644 index 0000000000..5633fbff28 --- /dev/null +++ b/unit-tests/shared/src/test/scala/javalib/net/NetworkInterfaceTest.scala @@ -0,0 +1,234 @@ +package javalib.net + +import java.net._ + +import org.junit.Test +import org.junit.Assert._ +import org.junit.Assume._ + +import org.scalanative.testsuite.utils.AssertThrows.assertThrows +import org.scalanative.testsuite.utils.Platform + +/* Design Notes: + * 1) As the underlying implementation is Unix only, so are these Tests. + * + * 2) Network interface configuration is can and does vary greatly from + * system to system. These tests are written to succeed with the + * configuration used by the Scala Native Continuous Integration systems. + * + * They may fail if used outside of that environment and require + * editing to reflect that local configuration. + */ + +class NetworkInterfaceTest { + + val localhostIf = + if (Platform.isLinux) "lo" + else "lo0" + +// Test static (object) methods + + @Test def getByIndexMinusTwo(): Unit = { + assumeFalse("Not implemented in Windows", Platform.isWindows) + assertThrows( + "getByIndex(-2)", + classOf[IllegalArgumentException], + NetworkInterface.getByIndex(-2) + ) + } + + @Test def getByIndexZero(): Unit = { + assumeFalse("Not implemented in Windows", Platform.isWindows) + assertNull(NetworkInterface.getByIndex(0)) + } + + @Test def getByIndexOne(): Unit = { + assumeFalse("Not implemented in Windows", Platform.isWindows) + val netIf = NetworkInterface.getByIndex(1) // loopback + + assertNotNull("a1", netIf) + + val sought = localhostIf + val ifName = netIf.getName() + assertEquals("a2", sought, ifName) + } + + @Test def getByIndexMaxValue(): Unit = { + assumeFalse("Not implemented in Windows", Platform.isWindows) + val netIf = NetworkInterface.getByIndex(Integer.MAX_VALUE) + assertNull("Unlikely interface found for MAX_VALUE index", netIf) + } + + @Test def getByInetAddressNull(): Unit = { + assumeFalse("Not implemented in Windows", Platform.isWindows) + assertThrows( + "getByInetAddress(null)", + classOf[NullPointerException], + NetworkInterface.getByInetAddress(null) + ) + } + + @Test def getByInetAddressLoopbackIPv4(): Unit = { + assumeFalse("Not implemented in Windows", Platform.isWindows) + val lba4 = InetAddress.getByName("127.0.0.1") + + val netIf = NetworkInterface.getByInetAddress(lba4) + + assertNotNull("a1", netIf) + + val sought = localhostIf + val ifName = netIf.getName() + assertEquals("a1", sought, ifName) + } + + @Test def getByInetAddressLoopbackIPv6(): Unit = { + assumeFalse("Not implemented in Windows", Platform.isWindows) + val lba6 = InetAddress.getByName("::1") + + val netIf = NetworkInterface.getByInetAddress(lba6) + + // Do not fail on null. IPv6 might not be enabled on the system. + if (netIf != null) { + val sought = localhostIf + val ifName = netIf.getName() + assertEquals("a1", sought, ifName) + } + } + + @Test def getByNameNull(): Unit = { + assumeFalse("Not implemented in Windows", Platform.isWindows) + assertThrows( + "getByName(null)", + classOf[NullPointerException], + NetworkInterface.getByName(null) + ) + } + + @Test def getByName(): Unit = { + assumeFalse("Not implemented in Windows", Platform.isWindows) + + val sought = localhostIf + val netIf = NetworkInterface.getByName(sought) + assertNotNull(netIf) + + val ifName = netIf.getName() + + assertEquals("a1", sought, ifName) + } + + @Test def testToString(): Unit = { + assumeFalse("Not implemented in Windows", Platform.isWindows) + + val netIf = NetworkInterface.getByIndex(1) // loopback + assertNotNull(netIf) + + val ifName = netIf.getName() + + // "lo" is Linux, systemd, "lo0" is macOS + if ((ifName == "lo") || (ifName == "lo0")) { + assertEquals("a1", s"name:${ifName} (${ifName})", netIf.toString) + } // else unknown configuration; skip, not fail. + } + + @Test def getNetworkInterfaces(): Unit = { + assumeFalse("Not implemented in Windows", Platform.isWindows) + + val netIfs = NetworkInterface.getNetworkInterfaces() + assertNotNull(netIfs) + + var count = 0 + + while (netIfs.hasMoreElements()) { + netIfs.nextElement() + count += 1 + } + + // count != 0 1 for loopback, 1 for World and possibly many more (macOS). + assertTrue("count >= 2", count >= 2) + } + +// Test instance methods + + @Test def instanceGetIndex(): Unit = { + assumeFalse("Not implemented in Windows", Platform.isWindows) + + val lbIf1 = NetworkInterface.getByName(localhostIf) + assertNotNull(lbIf1) + assertEquals(1, lbIf1.getIndex()) + } + + /* @Test def instanceGetHardwareAddress(): Unit = { + * Not implemented - system dependent. + * Loopback addresses do not have hardware address to get. + * Non-loopback primary interface varies and can not be determined. + */ + + @Test def instanceGetMTU(): Unit = { + assumeFalse("Not implemented in Windows", Platform.isWindows) + + val lbIf = NetworkInterface.getByName(localhostIf) + assertNotNull(lbIf) + + val mtu = lbIf.getMTU() + + // To get tighter bounds, one would need to know config specific info. + assertTrue("mtu > 0", mtu > 0) + assertTrue("mtu <= 65536", mtu <= 65536) + } + + @Test def instanceIsLoopback(): Unit = { + assumeFalse("Not implemented in Windows", Platform.isWindows) + + val lbIf = NetworkInterface.getByName(localhostIf) + assertNotNull(lbIf) + assertEquals("a1", true, lbIf.isLoopback()) + } + + @Test def instanceIsPoinToPoint(): Unit = { + assumeFalse("Not implemented in Windows", Platform.isWindows) + + val lbIf = NetworkInterface.getByName(localhostIf) + assertNotNull(lbIf) + assertEquals("a1", false, lbIf.isPointToPoint()) + } + + @Test def instanceIsUp(): Unit = { + assumeFalse("Not implemented in Windows", Platform.isWindows) + + val lbIf = NetworkInterface.getByName(localhostIf) + assertNotNull(lbIf) + assertEquals("a1", true, lbIf.isUp()) + } + + @Test def instanceSupportsMulticast(): Unit = { + assumeFalse("Not implemented in Windows", Platform.isWindows) + + val lbIf = NetworkInterface.getByName(localhostIf) + assertNotNull(lbIf) + + val expected = + if (Platform.isMacOs) true + else false // Linux + // else (FreeBSD?) + + assertEquals("a1", expected, lbIf.supportsMulticast()) + } + + @Test def instanceGetInetAddresses(): Unit = { + assumeFalse("Not implemented in Windows", Platform.isWindows) + + val lbIf = NetworkInterface.getByName(localhostIf) + assertNotNull(lbIf) + + val iaEnumeration = lbIf.getInetAddresses() + + var count = 0 + while (iaEnumeration.hasMoreElements()) { + iaEnumeration.nextElement() + count += 1 + } + + assertTrue("count > 0", count > 0) + } + +} From f371bbc8146473830df81976d8942937fba0857d Mon Sep 17 00:00:00 2001 From: LeeTibbert Date: Tue, 6 Dec 2022 11:36:54 +0100 Subject: [PATCH 07/64] Fix #2291, #2764: Document long standing fact that unsafe.stackalloc[T] zeros memory (#3023) (cherry picked from commit 2a49dddb2e3783c571aec792e1d12839ff2a8de6) --- docs/user/interop.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/user/interop.rst b/docs/user/interop.rst index 1546925bf8..d68c01fe01 100644 --- a/docs/user/interop.rst +++ b/docs/user/interop.rst @@ -338,7 +338,7 @@ runtime system, one has to be extra careful when working with unmanaged memory. This code will allocate 256 bytes that are going to be available until the enclosing method returns. Number of elements to be allocated is optional - and defaults to 1 otherwise. Memory is not zeroed out by default. + and defaults to 1 otherwise. Memory **is zeroed out** by default. When using stack allocated memory one has to be careful not to capture this memory beyond the lifetime of the method. Dereferencing stack allocated From 8612e392c696e58db65ea773f7c43192082099c1 Mon Sep 17 00:00:00 2001 From: LeeTibbert Date: Tue, 6 Dec 2022 05:39:47 -0500 Subject: [PATCH 08/64] Fix #2900: Implement posixlib un.scala (#3025) * Fix #2900: Implement posixlib un.scala * Remove include which some Scala versions do not like (cherry picked from commit 437fc4793d659908f89898c570847af7f26d0141) --- docs/lib/posixlib.rst | 3 +- .../src/main/resources/scala-native/sys/un.c | 35 ++++++++++ .../scala/scalanative/posix/sys/un.scala | 67 +++++++++++++++++++ 3 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 posixlib/src/main/resources/scala-native/sys/un.c create mode 100644 posixlib/src/main/scala/scala/scalanative/posix/sys/un.scala diff --git a/docs/lib/posixlib.rst b/docs/lib/posixlib.rst index 9823175c48..a190953bde 100644 --- a/docs/lib/posixlib.rst +++ b/docs/lib/posixlib.rst @@ -76,7 +76,7 @@ C Header Scala Native Module `sys/times.h`_ N/A `sys/types.h`_ scala.scalanative.posix.sys.types_ `sys/uio.h`_ scala.scalanative.posix.sys.uio_ -`sys/un.h`_ N/A +`sys/un.h`_ scala.scalanative.posix.sys.un_ `sys/utsname.h`_ scala.scalanative.posix.sys.utsname_ `sys/wait.h`_ N/A `syslog.h`_ scala.scalanative.posix.syslog_ @@ -215,6 +215,7 @@ C Header Scala Native Module .. _scala.scalanative.posix.sys.time: https://github.com/scala-native/scala-native/blob/main/posixlib/src/main/scala/scala/scalanative/posix/sys/time.scala .. _scala.scalanative.posix.sys.types: https://github.com/scala-native/scala-native/blob/main/posixlib/src/main/scala/scala/scalanative/posix/sys/types.scala .. _scala.scalanative.posix.sys.uio: https://github.com/scala-native/scala-native/blob/main/posixlib/src/main/scala/scala/scalanative/posix/sys/uio.scala +.. _scala.scalanative.posix.sys.un: https://github.com/scala-native/scala-native/blob/main/posixlib/src/main/scala/scala/scalanative/posix/sys/un.scala .. _scala.scalanative.posix.sys.utsname: https://github.com/scala-native/scala-native/blob/main/posixlib/src/main/scala/scala/scalanative/posix/sys/utsname.scala .. _scala.scalanative.posix.syslog: https://github.com/scala-native/scala-native/blob/main/posixlib/src/main/scala/scala/scalanative/posix/syslog.scala .. _scala.scalanative.posix.termios: https://github.com/scala-native/scala-native/blob/main/posixlib/src/main/scala/scala/scalanative/posix/termios.scala diff --git a/posixlib/src/main/resources/scala-native/sys/un.c b/posixlib/src/main/resources/scala-native/sys/un.c new file mode 100644 index 0000000000..93d853eecb --- /dev/null +++ b/posixlib/src/main/resources/scala-native/sys/un.c @@ -0,0 +1,35 @@ +#ifdef _WIN32 +// Recent Windows has , which uses 108 for sun_path. +// No code here to assure that. +#else +#include +#if !(defined __STDC_VERSION__) || (__STDC_VERSION__ < 201112L) +#ifndef SCALANATIVE_SUPPRESS_STRUCT_CHECK_WARNING +#warning "Size and order of C structures are not checked when -std < c11." +#endif +#else // POSIX +#include +#include + +typedef unsigned short scalanative_sa_family_t; + +// 108 for sun_path is the Linux value is >= macOS value of 104. Checked below. +struct scalanative_sockaddr_un { + scalanative_sa_family_t sun_family; + char sun_path[108]; +}; + +// Also verifies that Scala Native sun_family field has the traditional size. +_Static_assert(offsetof(struct scalanative_sockaddr_un, sun_path) == 2, + "Unexpected size: scalanative_sockaddr_un sun_family"); + +_Static_assert(offsetof(struct scalanative_sockaddr_un, sun_path) == + offsetof(struct sockaddr_un, sun_path), + "offset mismatch: sockaddr_un sun_path"); + +_Static_assert(sizeof(struct sockaddr_un) <= + sizeof(struct scalanative_sockaddr_un), + "size mismatch: sockaddr_un sun_path"); + +#endif // POSIX +#endif // ! _WIN32 diff --git a/posixlib/src/main/scala/scala/scalanative/posix/sys/un.scala b/posixlib/src/main/scala/scala/scalanative/posix/sys/un.scala new file mode 100644 index 0000000000..1f0b0b5c88 --- /dev/null +++ b/posixlib/src/main/scala/scala/scalanative/posix/sys/un.scala @@ -0,0 +1,67 @@ +package scala.scalanative +package posix +package sys + +import scalanative.unsafe._ +import scalanative.unsigned._ + +import scalanative.runtime.Platform + +/** POSIX sys/un.h for Scala + */ + +@extern +object un { + type _108 = Nat.Digit3[Nat._1, Nat._0, Nat._8] + + type sa_family_t = socket.sa_family_t + + /* _Static_assert guard code in the un.c assures the SN sockaddr_un is + * >= the corresponding Unix operating system version. + * 108 for sun_path is the Linux & Windows value. It is >= macOS 104 bytes. + */ + + type sockaddr_un = CStruct2[ + sa_family_t, // sun_family, sun_len is synthesized if needed + CArray[CChar, _108] // sun_path + ] +} + +/** Allow using C names to access socket_un structure fields. + */ +object unOps { + import un._ + import posix.inttypes.uint8_t + + val useSinXLen = !Platform.isLinux() && + (Platform.isMac() || Platform.isFreeBSD()) + + implicit class sockaddr_unOps(val ptr: Ptr[sockaddr_un]) extends AnyVal { + def sun_len: uint8_t = if (!useSinXLen) { + sizeof[sockaddr_un].toUByte // length is synthesized + } else { + ptr._1.toUByte + } + + def sun_family: sa_family_t = if (!useSinXLen) { + ptr._1 + } else { + (ptr._1 >>> 8).toUByte + } + + def sun_path: CArray[CChar, _108] = ptr._2 + + def sun_len_=(v: uint8_t): Unit = if (useSinXLen) { + ptr._1 = ((ptr._1 & 0xff00.toUShort) + v).toUShort + } // else silently do nothing + + def sun_family_=(v: sa_family_t): Unit = + if (!useSinXLen) { + ptr._1 = v + } else { + ptr._1 = ((v << 8) + ptr.sun_len).toUShort + } + + def sun_path_=(v: CArray[CChar, _108]): Unit = ptr._2 = v + } +} From 0bc4e15332a65e27465476cd77e4fb47db8d1c93 Mon Sep 17 00:00:00 2001 From: LeeTibbert Date: Tue, 6 Dec 2022 05:42:19 -0500 Subject: [PATCH 09/64] Fix #2867: Align j.net.Connect Exception message with JVM (#3027) * Align j.net.Connect Exception message with JVM * Rework poll revents testing to please scripted-tests (cherry picked from commit c4346445e4815e70e2ac60c62bb97ac65ff1eed3) --- .../scala/java/net/UnixPlainSocketImpl.scala | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/javalib/src/main/scala/java/net/UnixPlainSocketImpl.scala b/javalib/src/main/scala/java/net/UnixPlainSocketImpl.scala index 9e9280ff3c..1b45e3c546 100644 --- a/javalib/src/main/scala/java/net/UnixPlainSocketImpl.scala +++ b/javalib/src/main/scala/java/net/UnixPlainSocketImpl.scala @@ -57,14 +57,16 @@ private[net] class UnixPlainSocketImpl extends AbstractPlainSocketImpl { case _ => if ((revents & POLLNVAL) != 0) { - throw new ConnectException( - s"connect failed, invalid poll request: ${revents}" - ) - } else if ((revents & (POLLERR | POLLHUP)) != 0) { - throw new ConnectException( - s"connect failed, POLLERR or POLLHUP set: ${revents}" - ) - } + val msg = s"connect failed, invalid poll request: ${revents}" + throw new ConnectException(msg) + } else if ((revents & (POLLIN | POLLHUP)) != 0) { + // Not enough information at this point to report remote host:port. + val msg = "Connection refused" + throw new ConnectException(msg) + } else if ((revents & POLLERR) != 0) { // an error was recognized. + val msg = s"connect failed, poll POLLERR: ${revents}" + throw new ConnectException(msg) + } // else should be POLLOUT - Open for Business, ignore XSI bits if set } } From 1c531bdc8d27dcce3e907ca8ee7ce6b8cd84567b Mon Sep 17 00:00:00 2001 From: LeeTibbert Date: Wed, 7 Dec 2022 13:55:43 -0500 Subject: [PATCH 10/64] Add sys/wait to posixlib doc (#3019) * Add sys/wait to posixlib doc * Fix type found by reviewer (cherry picked from commit 21f7401e4b52ae80a9b345d86255db01c91b7316) --- docs/lib/posixlib.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/lib/posixlib.rst b/docs/lib/posixlib.rst index a190953bde..3b7c32ed0e 100644 --- a/docs/lib/posixlib.rst +++ b/docs/lib/posixlib.rst @@ -78,7 +78,7 @@ C Header Scala Native Module `sys/uio.h`_ scala.scalanative.posix.sys.uio_ `sys/un.h`_ scala.scalanative.posix.sys.un_ `sys/utsname.h`_ scala.scalanative.posix.sys.utsname_ -`sys/wait.h`_ N/A +`sys/wait.h`_ scala.scalanative.posix.sys.wait_ `syslog.h`_ scala.scalanative.posix.syslog_ `tar.h`_ N/A `termios.h`_ scala.scalanative.posix.termios_ @@ -217,6 +217,7 @@ C Header Scala Native Module .. _scala.scalanative.posix.sys.uio: https://github.com/scala-native/scala-native/blob/main/posixlib/src/main/scala/scala/scalanative/posix/sys/uio.scala .. _scala.scalanative.posix.sys.un: https://github.com/scala-native/scala-native/blob/main/posixlib/src/main/scala/scala/scalanative/posix/sys/un.scala .. _scala.scalanative.posix.sys.utsname: https://github.com/scala-native/scala-native/blob/main/posixlib/src/main/scala/scala/scalanative/posix/sys/utsname.scala +.. _scala.scalanative.posix.sys.wait: https://github.com/scala-native/scala-native/blob/main/posixlib/src/main/scala/scala/scalanative/posix/sys/wait.scala .. _scala.scalanative.posix.syslog: https://github.com/scala-native/scala-native/blob/main/posixlib/src/main/scala/scala/scalanative/posix/syslog.scala .. _scala.scalanative.posix.termios: https://github.com/scala-native/scala-native/blob/main/posixlib/src/main/scala/scala/scalanative/posix/termios.scala .. _scala.scalanative.posix.time: https://github.com/scala-native/scala-native/blob/main/posixlib/src/main/scala/scala/scalanative/posix/time.scala From 55c4a15f04d7d093d4cf975a961653017bb838d6 Mon Sep 17 00:00:00 2001 From: LeeTibbert Date: Wed, 7 Dec 2022 14:00:11 -0500 Subject: [PATCH 11/64] Fix #2755: j.nio.Files#readAllBytes reports failed Unix file open call (#3026) (cherry picked from commit fbcc94379890bd8e7c002c4486963c5e7a7416d2) --- javalib/src/main/scala/java/nio/file/Files.scala | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/javalib/src/main/scala/java/nio/file/Files.scala b/javalib/src/main/scala/java/nio/file/Files.scala index 9965ea2472..bb92c1952f 100644 --- a/javalib/src/main/scala/java/nio/file/Files.scala +++ b/javalib/src/main/scala/java/nio/file/Files.scala @@ -661,6 +661,9 @@ object Files { !exists(path, options) def readAllBytes(path: Path): Array[Byte] = Zone { implicit z => + /* if 'path' does not exist at all, should get + * java.nio.file.NoSuchFileException here. + */ val pathSize: Long = size(path) if (!pathSize.isValidInt) { throw new OutOfMemoryError("Required array size too large") @@ -687,8 +690,15 @@ object Files { } } } else { + errno = 0 val pathCString = toCString(path.toString) val fd = fcntl.open(pathCString, fcntl.O_RDONLY, 0.toUInt) + + if (fd == -1) { + val msg = fromCString(string.strerror(errno)) + throw new IOException(s"error opening path '${path}': ${msg}") + } + try { var offset = 0 var read = 0 From d3b5112fb9a3f4e19d3c2534ea2e2ebc3d9286cb Mon Sep 17 00:00:00 2001 From: LeeTibbert Date: Thu, 8 Dec 2022 05:06:25 -0500 Subject: [PATCH 12/64] Fix #2973: Implement some requested j.io.InputStream Java 9 &11 methods (#3031) (cherry picked from commit 7012a72e74d66dad2326cdcad44d6a9d0b07bed2) --- .../src/main/scala/java/io/InputStream.scala | 98 +++++++++++++++++ .../javalib/io/InputStreamTestOnJDK11.scala | 38 +++++++ .../javalib/io/InputStreamTestOnJDK9.scala | 102 ++++++++++++++++++ 3 files changed, 238 insertions(+) create mode 100644 unit-tests/shared/src/test/require-jdk11/org/scalanative/testsuite/javalib/io/InputStreamTestOnJDK11.scala create mode 100644 unit-tests/shared/src/test/require-jdk9/org/scalanative/testsuite/javalib/io/InputStreamTestOnJDK9.scala diff --git a/javalib/src/main/scala/java/io/InputStream.scala b/javalib/src/main/scala/java/io/InputStream.scala index 62e9437e7d..e4f56122ec 100644 --- a/javalib/src/main/scala/java/io/InputStream.scala +++ b/javalib/src/main/scala/java/io/InputStream.scala @@ -1,5 +1,7 @@ package java.io +import java.{util => ju} + abstract class InputStream extends Closeable { def read(): Int @@ -32,6 +34,81 @@ abstract class InputStream extends Closeable { } } + // Allow obvious implementation of readAllBytes() to work on both Java 9 & 11 + def readNBytesImpl(len: Int): Array[Byte] = { + if (len < 0) + throw new IllegalArgumentException("len < 0") + + def readBytes(len: Int): ByteArrayOutputStream = { + val limit = Math.min(len, 1024) + + val storage = new ByteArrayOutputStream(limit) // can grow itself + val buffer = new Array[Byte](limit) + + var remaining = len + + while (remaining > 0) { + val nRead = read(buffer, 0, limit) + + if (nRead == -1) remaining = 0 // EOF + else { + storage.write(buffer, 0, nRead) + remaining -= nRead + } + } + + storage + } + + /* To stay within the documented 2 * len memory bound for this method, + * ensure that the temporary intermediate read buffer is out of scope + * and released before calling toByteArray(). + */ + + readBytes(len).toByteArray() + } + + /** Java 9 + */ + def readAllBytes(): Array[Byte] = readNBytesImpl(Integer.MAX_VALUE) + + /** Java 9 + */ + def readNBytes(buffer: Array[Byte], off: Int, len: Int): Int = { + ju.Objects.requireNonNull(buffer) + + if ((off < 0) || (len < 0) || (len > buffer.length - off)) { + val range = s"Range [${off}, ${off} + ${len})" + throw new IndexOutOfBoundsException( + s"${range} out of bounds for length ${buffer.length}" + ) + } + + if (len == 0) 0 + else { + var totalBytesRead = 0 + var remaining = len + var offset = off + + while (remaining > 0) { + val nRead = read(buffer, offset, remaining) + + if (nRead == -1) remaining = 0 // EOF + else { + totalBytesRead += nRead + remaining -= nRead + offset += nRead + } + } + + totalBytesRead + } + } + + /** Java 11 + */ + def readNBytes(len: Int): Array[Byte] = readNBytesImpl(len) + def skip(n: Long): Long = { var skipped = 0 while (skipped < n && read() != -1) skipped += 1 @@ -48,4 +125,25 @@ abstract class InputStream extends Closeable { throw new IOException("Reset not supported") def markSupported(): Boolean = false + + /** Java 9 + */ + def transferTo(out: OutputStream): Long = { + val limit = 1024 + val buffer = new Array[Byte](limit) + + var nTransferred = 0L + var done = false + + while (!done) { + val nRead = readNBytes(buffer, 0, limit) + if (nRead == 0) done = true // EOF + else { + out.write(buffer, 0, nRead) + nTransferred += nRead + } + } + + nTransferred + } } diff --git a/unit-tests/shared/src/test/require-jdk11/org/scalanative/testsuite/javalib/io/InputStreamTestOnJDK11.scala b/unit-tests/shared/src/test/require-jdk11/org/scalanative/testsuite/javalib/io/InputStreamTestOnJDK11.scala new file mode 100644 index 0000000000..b0d90cf826 --- /dev/null +++ b/unit-tests/shared/src/test/require-jdk11/org/scalanative/testsuite/javalib/io/InputStreamTestOnJDK11.scala @@ -0,0 +1,38 @@ +package javalib.io + +import java.io._ + +import org.junit.Test +import org.junit.Assert._ + +import org.scalanative.testsuite.utils.AssertThrows.assertThrows + +class InputStreamTestOnJDK11 { + + @Test def readNBytesLenNegativeLength(): Unit = { + val inputBytes = + List(255, 254, 253, 252) + .map(_.toByte) + .toArray[Byte] + + val streamIn = new ByteArrayInputStream(inputBytes) + + assertThrows( + classOf[IllegalArgumentException], + streamIn.readNBytes(-3) + ) + } + + @Test def readNBytesLen(): Unit = { + val inputBytes = + List(255, 254, 253, 252, 251, 128, 127, 2, 1, 0) + .map(_.toByte) + .toArray[Byte] + + val streamIn = new ByteArrayInputStream(inputBytes) + val len = 5 + val result = streamIn.readNBytes(len) + + assertEquals("result length", len, result.length) + } +} diff --git a/unit-tests/shared/src/test/require-jdk9/org/scalanative/testsuite/javalib/io/InputStreamTestOnJDK9.scala b/unit-tests/shared/src/test/require-jdk9/org/scalanative/testsuite/javalib/io/InputStreamTestOnJDK9.scala new file mode 100644 index 0000000000..c7086eba98 --- /dev/null +++ b/unit-tests/shared/src/test/require-jdk9/org/scalanative/testsuite/javalib/io/InputStreamTestOnJDK9.scala @@ -0,0 +1,102 @@ +package javalib.io + +import java.io._ + +import org.junit.Test +import org.junit.Assert._ + +import org.scalanative.testsuite.utils.AssertThrows.assertThrows + +class InputStreamTestOnJDK9 { + + @Test def readAllBytes(): Unit = { + + val inputBytes = + List(255, 254, 253, 252, 251, 128, 127, 2, 1, 0) + .map(_.toByte) + .toArray[Byte] + + val streamIn = new ByteArrayInputStream(inputBytes) + val result = streamIn.readAllBytes() + + assertEquals("result length", inputBytes.length, result.length) + } + + @Test def readNBytesBufferOffLenExceptions(): Unit = { + val inputBytes = + List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9).map(_.toByte).toArray[Byte] + + val streamIn = new ByteArrayInputStream(inputBytes) + val receiver = new Array[Byte](10) + val nRead = streamIn.readNBytes(receiver, 0, receiver.length) + + assertThrows( + classOf[NullPointerException], + streamIn.readNBytes(null, 0, receiver.length) + ) + + assertThrows( + classOf[IndexOutOfBoundsException], + streamIn.readNBytes(receiver, -2, receiver.length) + ) + + assertThrows( + classOf[IndexOutOfBoundsException], + streamIn.readNBytes(receiver, 0, -3) + ) + + assertThrows( + classOf[IndexOutOfBoundsException], + streamIn.readNBytes(receiver, 0, Integer.MAX_VALUE) + ) + } + + @Test def readNBytesBufferOffLen(): Unit = { + val inputBytes = + List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9).map(_.toByte).toArray[Byte] + + val streamIn = new ByteArrayInputStream(inputBytes) + val receiver = new Array[Byte](10) + val nRead = streamIn.readNBytes(receiver, 0, receiver.length) + + assertEquals("nRead", receiver.length, nRead) + + val expected = 9 + assertEquals("expected content", expected, receiver(expected)) + } + + @Test def transferToNullOutStream(): Unit = { + val inputBytes = + List(255, 254, 253, 252, 251, 128, 127, 2, 1, 0) + .map(_.toByte) + .toArray[Byte] + + val streamIn = new ByteArrayInputStream(inputBytes) + val streamOut = null.asInstanceOf[ByteArrayOutputStream] + + assertThrows( + classOf[NullPointerException], + streamIn.transferTo(streamOut) + ) + } + + @Test def transferTo(): Unit = { + val inputBytes = + List(255, 254, 253, 252, 251, 128, 127, 2, 1, 0) + .map(_.toByte) + .toArray[Byte] + + val streamIn = new ByteArrayInputStream(inputBytes) + val streamOut = new ByteArrayOutputStream() + + val nTransferred = streamIn.transferTo(streamOut).toInt + + assertEquals("nBytes transferred", inputBytes.length, nTransferred) + assertEquals("streamOut size", nTransferred, streamOut.size()) + + val outputBytes = streamOut.toByteArray() + for (j <- 0 until inputBytes.length) + assertEquals(s"in(${j}) != out(${j})", inputBytes(j), outputBytes(j)) + } + +} From f089cd29cff440512b496b07908691b97654f5d0 Mon Sep 17 00:00:00 2001 From: LeeTibbert Date: Mon, 12 Dec 2022 13:56:02 -0500 Subject: [PATCH 13/64] Add posixlib sys/times (#3032) * Implement posixlib sys/times * Document the addition (cherry picked from commit 5b38bd8dca71f127f7a69789aaa78956fbdf55cb) --- docs/lib/posixlib.rst | 3 +- .../main/resources/scala-native/sys/times.c | 40 +++++++++++++++++ .../scala/scalanative/posix/sys/times.scala | 44 +++++++++++++++++++ 3 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 posixlib/src/main/resources/scala-native/sys/times.c create mode 100644 posixlib/src/main/scala/scala/scalanative/posix/sys/times.scala diff --git a/docs/lib/posixlib.rst b/docs/lib/posixlib.rst index 3b7c32ed0e..92527c92eb 100644 --- a/docs/lib/posixlib.rst +++ b/docs/lib/posixlib.rst @@ -73,7 +73,7 @@ C Header Scala Native Module `sys/stat.h`_ scala.scalanative.posix.sys.stat_ `sys/statvfs.h`_ scala.scalanative.posix.sys.statvfs_ `sys/time.h`_ scala.scalanative.posix.sys.time_ -`sys/times.h`_ N/A +`sys/times.h`_ scala.scalanative.posix.sys.times_ `sys/types.h`_ scala.scalanative.posix.sys.types_ `sys/uio.h`_ scala.scalanative.posix.sys.uio_ `sys/un.h`_ scala.scalanative.posix.sys.un_ @@ -213,6 +213,7 @@ C Header Scala Native Module .. _scala.scalanative.posix.sys.stat: https://github.com/scala-native/scala-native/blob/main/posixlib/src/main/scala/scala/scalanative/posix/sys/stat.scala .. _scala.scalanative.posix.sys.statvfs: https://github.com/scala-native/scala-native/blob/main/posixlib/src/main/scala/scala/scalanative/posix/sys/statvfs.scala .. _scala.scalanative.posix.sys.time: https://github.com/scala-native/scala-native/blob/main/posixlib/src/main/scala/scala/scalanative/posix/sys/time.scala +.. _scala.scalanative.posix.sys.times: https://github.com/scala-native/scala-native/blob/main/posixlib/src/main/scala/scala/scalanative/posix/sys/times.scala .. _scala.scalanative.posix.sys.types: https://github.com/scala-native/scala-native/blob/main/posixlib/src/main/scala/scala/scalanative/posix/sys/types.scala .. _scala.scalanative.posix.sys.uio: https://github.com/scala-native/scala-native/blob/main/posixlib/src/main/scala/scala/scalanative/posix/sys/uio.scala .. _scala.scalanative.posix.sys.un: https://github.com/scala-native/scala-native/blob/main/posixlib/src/main/scala/scala/scalanative/posix/sys/un.scala diff --git a/posixlib/src/main/resources/scala-native/sys/times.c b/posixlib/src/main/resources/scala-native/sys/times.c new file mode 100644 index 0000000000..ea254d5882 --- /dev/null +++ b/posixlib/src/main/resources/scala-native/sys/times.c @@ -0,0 +1,40 @@ +#ifdef _WIN32 +// No Windows support +#else +#if !(defined __STDC_VERSION__) || (__STDC_VERSION__ < 201112L) +#ifndef SCALANATIVE_SUPPRESS_STRUCT_CHECK_WARNING +#warning "Size and order of C structures are not checked when -std < c11." +#endif +#else // POSIX +#include +#include + +typedef long scalanative_clock_t; + +struct scalanative_tms { + scalanative_clock_t tms_utime; // User CPU time + scalanative_clock_t tms_stime; // System CPU time + scalanative_clock_t tms_cutime; // User CPU time terminated children + scalanative_clock_t tms_cstime; // System CPU time of terminated children +}; + +_Static_assert(sizeof(struct scalanative_tms) <= sizeof(struct tms), + "size mismatch: scalanative_tms"); + +_Static_assert(offsetof(struct scalanative_tms, tms_utime) == + offsetof(struct tms, tms_utime), + "offset mismatch: tms tms_utime"); + +_Static_assert(offsetof(struct scalanative_tms, tms_stime) == + offsetof(struct tms, tms_stime), + "offset mismatch: tms tms_stime"); + +_Static_assert(offsetof(struct scalanative_tms, tms_cutime) == + offsetof(struct tms, tms_cutime), + "offset mismatch: tms tms_cutime"); + +_Static_assert(offsetof(struct scalanative_tms, tms_cstime) == + offsetof(struct tms, tms_cstime), + "offset mismatch: tms tms_cstime"); +#endif // POSIX +#endif // ! _WIN32 diff --git a/posixlib/src/main/scala/scala/scalanative/posix/sys/times.scala b/posixlib/src/main/scala/scala/scalanative/posix/sys/times.scala new file mode 100644 index 0000000000..009822d532 --- /dev/null +++ b/posixlib/src/main/scala/scala/scalanative/posix/sys/times.scala @@ -0,0 +1,44 @@ +package scala.scalanative +package posix +package sys + +import scalanative.unsafe._ + +/** POSIX sys/times.h for Scala + * + * The Open Group Base Specifications + * [[https://pubs.opengroup.org/onlinepubs/9699919799 Issue 7, 2018]] edition. + */ + +@extern +object times { + type clock_t = types.clock_t + + type tms = CStruct4[ + clock_t, // tms_utime User CPU time + clock_t, // tms_stime System CPU time + clock_t, // tms_cutime User CPU time of terminated child processes. + clock_t // tms_cstime System CPU time of terminated child processes. + ] + + def times(buf: Ptr[tms]): clock_t = extern +} + +/** Allow using C names to access tms structure fields. + */ +object timesOps { + import times._ + + implicit class tmsOps(val ptr: Ptr[tms]) extends AnyVal { + def tms_utime(): clock_t = ptr._1 + def tms_stime(): clock_t = ptr._2 + def tms_cutime(): clock_t = ptr._3 + def tms_cstime(): clock_t = ptr._4 + + // The fields are query-only in use. Provide setters for completeness. + def tms_utime_=(c: clock_t): Unit = ptr._1 = c + def tms_stime_=(c: clock_t): Unit = ptr._2 = c + def tms_cutime_=(c: clock_t): Unit = ptr._3 = c + def tms_cstime_=(c: clock_t): Unit = ptr._4 = c + } +} From a203873a4c61a19917a47b55db469dee136f48b3 Mon Sep 17 00:00:00 2001 From: Eric K Richardson Date: Tue, 13 Dec 2022 10:28:19 +0100 Subject: [PATCH 14/64] Fix #2780: Drop Scala 2.11 (#3028) * Remove Scala 2.11 from build * Remove Scala 2.11 from CI * Remove Scala 2.11 scalalib overrides * Update tests and script * Update tools test * Remove unused in TraitReachabilitySuite * Update PtrBoxingTest to remove function types on use * Update changelog and javalib.py script * Remove compiler setting for Scala 2.11 SAM support * Remove JavaDefaultMethod definition and codegen * Remove Scala 2.11 specific PrepNativeInterop handling * Remove Scala 2.11 partests config * Remove special handling for ImplClasses * Remove handling for implClasses in NIR Co-authored-by: Wojciech Mazur (cherry picked from commit b9cfd6bf2634e16f2604008f3b5e7e7f71087721) --- .github/workflows/run-tests-linux.yml | 8 +- .github/workflows/run-tests-macos.yml | 6 +- .github/workflows/run-tests-windows.yml | 4 - .../scala/runtime/function/JProcedure.scala | 24 - .../runtime/function/JProcedure.scala.gyb | 3 - .../main/scala/java/lang/IEEE754Helpers.scala | 2 +- .../src/main/scala/java/lang/Iterable.scala | 3 - .../src/main/scala/java/util/Collection.scala | 3 - .../src/main/scala/java/util/Comparator.scala | 4 - .../src/main/scala/java/util/Iterator.scala | 4 - javalib/src/main/scala/java/util/List.scala | 4 - javalib/src/main/scala/java/util/Map.scala | 13 - .../main/scala/java/util/Spliterator.scala | 5 - .../scala/java/util/function/BiConsumer.scala | 6 +- .../scala/java/util/function/BiFunction.scala | 6 +- .../java/util/function/BiPredicate.scala | 7 +- .../scala/java/util/function/Consumer.scala | 3 - .../scala/java/util/function/Function.scala | 9 +- .../java/util/function/IntUnaryOperator.scala | 4 - .../scala/java/util/function/Predicate.scala | 5 - .../annotation/JavaDefaultMethod.scala | 14 - .../scala/scala/scalanative/nir/Sig.scala | 3 +- .../scalanative/nscplugin/NirCompat.scala | 50 +- .../nscplugin/NirDefinitions.scala | 2 - .../scalanative/nscplugin/NirGenExpr.scala | 49 +- .../scalanative/nscplugin/NirGenName.scala | 10 +- .../scalanative/nscplugin/NirGenStat.scala | 158 ++- .../scalanative/nscplugin/NirGenType.scala | 4 +- .../nscplugin/PrepNativeInterop.scala | 8 - project/Build.scala | 25 +- project/Commands.scala | 2 +- project/Deps.scala | 17 +- project/MultiScalaProject.scala | 5 +- project/ScalaVersions.scala | 4 +- project/Settings.scala | 9 - .../resources/2.11.12/BlacklistedTests.txt | 74 -- .../scalanative/2.11.12/BlacklistedTests.txt | 955 ------------------ .../2.11.12/neg/t6446-additional.check | 30 - .../scalanative/2.11.12/neg/t6446-list.check | 2 - .../2.11.12/neg/t6446-missing.check | 30 - .../2.11.12/neg/t6446-show-phases.check | 29 - .../2.11.12/neg/t7494-no-options.check | 31 - .../scalanative/2.11.12/run/classof.check | 22 - .../2.11.12/run/classtags_contextbound.check | 1 - .../2.11.12/run/classtags_multi.check | 5 - .../2.11.12/run/getClassTest-valueClass.check | 2 - ...interop_classtags_are_classmanifests.check | 3 - .../scalanative/2.11.12/run/t4753.check | 1 - .../scalanative/2.11.12/run/t5568.check | 9 - .../scalanative/2.11.12/run/t5680.check | 3 - .../scalanative/2.11.12/run/t5923b.check | 3 - .../scalanative/2.11.12/run/t6102.check | 28 - .../2.11.12/run/t6318_primitives.check | 54 - .../scalanative/2.11.12/run/t8764.check | 5 - .../overrides-2.11/scala/Array.scala.patch | 237 ----- .../overrides-2.11/scala/Predef.scala.patch | 285 ------ .../collection/immutable/Set.scala.patch | 14 - .../collection/immutable/Stream.scala.patch | 33 - .../mutable/DoubleLinkedList.scala.patch | 14 - .../collection/mutable/LinkedList.scala.patch | 20 - .../mutable/StringBuilder.scala.patch | 33 - .../concurrent/ExecutionContext.scala.patch | 12 - .../concurrent/impl/AbstractPromise.scala | 29 - .../overrides-2.11/scala/package.scala.patch | 120 --- .../scala/reflect/ClassTag.scala.patch | 69 -- .../scala/reflect/Manifest.scala.patch | 146 --- .../scala/reflect/ScalaLongSignature.scala | 3 - .../scala/reflect/ScalaSignature.scala | 3 - .../scala/runtime/ScalaRunTime.scala.patch | 91 -- scripts/changelog.sc | 4 - scripts/gyb.py | 2 +- scripts/javalib.py | 2 +- scripts/scalalib-patch-all.sc | 3 +- scripts/travis_setup.sh | 42 - .../scala-2/scalanative/NIRCompiler.scala | 4 - .../scala/scalanative/interflow/Inline.scala | 2 +- .../scala/scalanative/NativePlatform.scala | 1 - .../linker/TraitReachabilitySuite.scala | 45 +- .../src/test/resources/BlacklistedTests.txt | 3 - .../scalanative/unsafe/PtrBoxingTest.scala | 11 +- .../scala-2.11/scala/annotation/nowarn.scala | 4 - .../test/scala/scala/AsInstanceOfTest.scala | 19 - .../src/test/scala/scala/HashCodeTest.scala | 7 +- 83 files changed, 112 insertions(+), 2916 deletions(-) delete mode 100644 nativelib/src/main/scala/scala/scalanative/annotation/JavaDefaultMethod.scala delete mode 100644 scala-partest-junit-tests/src/test/resources/2.11.12/BlacklistedTests.txt delete mode 100644 scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/BlacklistedTests.txt delete mode 100644 scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/neg/t6446-additional.check delete mode 100644 scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/neg/t6446-list.check delete mode 100644 scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/neg/t6446-missing.check delete mode 100644 scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/neg/t6446-show-phases.check delete mode 100644 scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/neg/t7494-no-options.check delete mode 100644 scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/run/classof.check delete mode 100644 scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/run/classtags_contextbound.check delete mode 100644 scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/run/classtags_multi.check delete mode 100644 scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/run/getClassTest-valueClass.check delete mode 100644 scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/run/interop_classtags_are_classmanifests.check delete mode 100644 scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/run/t4753.check delete mode 100644 scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/run/t5568.check delete mode 100644 scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/run/t5680.check delete mode 100644 scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/run/t5923b.check delete mode 100644 scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/run/t6102.check delete mode 100644 scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/run/t6318_primitives.check delete mode 100644 scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/run/t8764.check delete mode 100644 scalalib/overrides-2.11/scala/Array.scala.patch delete mode 100644 scalalib/overrides-2.11/scala/Predef.scala.patch delete mode 100644 scalalib/overrides-2.11/scala/collection/immutable/Set.scala.patch delete mode 100644 scalalib/overrides-2.11/scala/collection/immutable/Stream.scala.patch delete mode 100644 scalalib/overrides-2.11/scala/collection/mutable/DoubleLinkedList.scala.patch delete mode 100644 scalalib/overrides-2.11/scala/collection/mutable/LinkedList.scala.patch delete mode 100644 scalalib/overrides-2.11/scala/collection/mutable/StringBuilder.scala.patch delete mode 100644 scalalib/overrides-2.11/scala/concurrent/ExecutionContext.scala.patch delete mode 100644 scalalib/overrides-2.11/scala/concurrent/impl/AbstractPromise.scala delete mode 100644 scalalib/overrides-2.11/scala/package.scala.patch delete mode 100644 scalalib/overrides-2.11/scala/reflect/ClassTag.scala.patch delete mode 100644 scalalib/overrides-2.11/scala/reflect/Manifest.scala.patch delete mode 100644 scalalib/overrides-2.11/scala/reflect/ScalaLongSignature.scala delete mode 100644 scalalib/overrides-2.11/scala/reflect/ScalaSignature.scala delete mode 100644 scalalib/overrides-2.11/scala/runtime/ScalaRunTime.scala.patch delete mode 100755 scripts/travis_setup.sh delete mode 100644 unit-tests/shared/src/test/scala-2.11/scala/annotation/nowarn.scala diff --git a/.github/workflows/run-tests-linux.yml b/.github/workflows/run-tests-linux.yml index bfb925153e..d1b4508a32 100644 --- a/.github/workflows/run-tests-linux.yml +++ b/.github/workflows/run-tests-linux.yml @@ -19,7 +19,7 @@ jobs: strategy: fail-fast: false matrix: - scala: [3.2.1, 2.13.10, 2.12.17, 2.11.12] + scala: [3.2.1, 2.13.10, 2.12.17] steps: - uses: actions/checkout@v3 - uses: ./.github/actions/linux-setup-env @@ -72,12 +72,6 @@ jobs: build-mode: debug gc: immix include: - - scala: 2.11.12 - build-mode: debug - gc: immix - - scala: 2.11.12 - build-mode: release-fast - gc: commix - scala: 2.12.17 build-mode: debug gc: immix diff --git a/.github/workflows/run-tests-macos.yml b/.github/workflows/run-tests-macos.yml index 26100bdd25..7700a7f184 100644 --- a/.github/workflows/run-tests-macos.yml +++ b/.github/workflows/run-tests-macos.yml @@ -17,15 +17,15 @@ jobs: strategy: fail-fast: false matrix: - scala: [3.2.1, 2.13.10, 2.12.17, 2.11.12] + scala: [3.2.1, 2.13.10, 2.12.17] gc: [immix] include: - scala: 2.13.10 gc: commix + - scala: 2.13.10 + gc: none - scala: 2.12.17 gc: boehm - - scala: 2.11.12 - gc: none - scala: 3.1.3 gc: immix diff --git a/.github/workflows/run-tests-windows.yml b/.github/workflows/run-tests-windows.yml index 0a99a0f062..892dcf4bb3 100644 --- a/.github/workflows/run-tests-windows.yml +++ b/.github/workflows/run-tests-windows.yml @@ -20,10 +20,6 @@ jobs: scala: [3.2.1, 2.13.10] gc: [boehm, immix, commix] include: - - scala: 2.11.12 - gc: immix - - scala: 2.11.12 - gc: commix - scala: 2.12.17 gc: immix - scala: 2.12.17 diff --git a/auxlib/src/main/scala-3/scala/runtime/function/JProcedure.scala b/auxlib/src/main/scala-3/scala/runtime/function/JProcedure.scala index ae889cfd0b..5a0203ed1a 100644 --- a/auxlib/src/main/scala-3/scala/runtime/function/JProcedure.scala +++ b/auxlib/src/main/scala-3/scala/runtime/function/JProcedure.scala @@ -10,12 +10,10 @@ package scala.runtime.function import scala.runtime.BoxedUnit -import scala.scalanative.annotation.JavaDefaultMethod trait JProcedure0 extends scala.Function0[Object] with java.io.Serializable { def applyVoid(): Unit - @JavaDefaultMethod def apply(): Object = { applyVoid() return BoxedUnit.UNIT @@ -28,7 +26,6 @@ trait JProcedure1[T1] with java.io.Serializable { def applyVoid(t1: T1): Unit - @JavaDefaultMethod def apply(t1: T1): Object = { applyVoid(t1) return BoxedUnit.UNIT @@ -40,7 +37,6 @@ trait JProcedure2[T1, T2] with java.io.Serializable { def applyVoid(t1: T1, t2: T2): Unit - @JavaDefaultMethod def apply(t1: T1, t2: T2): Object = { applyVoid(t1, t2) return BoxedUnit.UNIT @@ -52,7 +48,6 @@ trait JProcedure3[T1, T2, T3] with java.io.Serializable { def applyVoid(t1: T1, t2: T2, t3: T3): Unit - @JavaDefaultMethod def apply(t1: T1, t2: T2, t3: T3): Object = { applyVoid(t1, t2, t3) return BoxedUnit.UNIT @@ -64,7 +59,6 @@ trait JProcedure4[T1, T2, T3, T4] with java.io.Serializable { def applyVoid(t1: T1, t2: T2, t3: T3, t4: T4): Unit - @JavaDefaultMethod def apply(t1: T1, t2: T2, t3: T3, t4: T4): Object = { applyVoid(t1, t2, t3, t4) return BoxedUnit.UNIT @@ -76,7 +70,6 @@ trait JProcedure5[T1, T2, T3, T4, T5] with java.io.Serializable { def applyVoid(t1: T1, t2: T2, t3: T3, t4: T4, t5: T5): Unit - @JavaDefaultMethod def apply(t1: T1, t2: T2, t3: T3, t4: T4, t5: T5): Object = { applyVoid(t1, t2, t3, t4, t5) return BoxedUnit.UNIT @@ -88,7 +81,6 @@ trait JProcedure6[T1, T2, T3, T4, T5, T6] with java.io.Serializable { def applyVoid(t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, t6: T6): Unit - @JavaDefaultMethod def apply(t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, t6: T6): Object = { applyVoid(t1, t2, t3, t4, t5, t6) return BoxedUnit.UNIT @@ -100,7 +92,6 @@ trait JProcedure7[T1, T2, T3, T4, T5, T6, T7] with java.io.Serializable { def applyVoid(t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, t6: T6, t7: T7): Unit - @JavaDefaultMethod def apply(t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, t6: T6, t7: T7): Object = { applyVoid(t1, t2, t3, t4, t5, t6, t7) return BoxedUnit.UNIT @@ -113,7 +104,6 @@ trait JProcedure8[T1, T2, T3, T4, T5, T6, T7, T8] def applyVoid(t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, t6: T6, t7: T7, t8: T8) : Unit - @JavaDefaultMethod def apply(t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, t6: T6, t7: T7, t8: T8) : Object = { applyVoid(t1, t2, t3, t4, t5, t6, t7, t8) @@ -136,7 +126,6 @@ trait JProcedure9[T1, T2, T3, T4, T5, T6, T7, T8, T9] t9: T9 ): Unit - @JavaDefaultMethod def apply( t1: T1, t2: T2, @@ -169,7 +158,6 @@ trait JProcedure10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10] t10: T10 ): Unit - @JavaDefaultMethod def apply( t1: T1, t2: T2, @@ -217,7 +205,6 @@ trait JProcedure11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11] t11: T11 ): Unit - @JavaDefaultMethod def apply( t1: T1, t2: T2, @@ -268,7 +255,6 @@ trait JProcedure12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12] t12: T12 ): Unit - @JavaDefaultMethod def apply( t1: T1, t2: T2, @@ -322,7 +308,6 @@ trait JProcedure13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13] t13: T13 ): Unit - @JavaDefaultMethod def apply( t1: T1, t2: T2, @@ -379,7 +364,6 @@ trait JProcedure14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14] t14: T14 ): Unit - @JavaDefaultMethod def apply( t1: T1, t2: T2, @@ -454,7 +438,6 @@ trait JProcedure15[ t15: T15 ): Unit - @JavaDefaultMethod def apply( t1: T1, t2: T2, @@ -533,7 +516,6 @@ trait JProcedure16[ t16: T16 ): Unit - @JavaDefaultMethod def apply( t1: T1, t2: T2, @@ -633,7 +615,6 @@ trait JProcedure17[ t17: T17 ): Unit - @JavaDefaultMethod def apply( t1: T1, t2: T2, @@ -738,7 +719,6 @@ trait JProcedure18[ t18: T18 ): Unit - @JavaDefaultMethod def apply( t1: T1, t2: T2, @@ -848,7 +828,6 @@ trait JProcedure19[ t19: T19 ): Unit - @JavaDefaultMethod def apply( t1: T1, t2: T2, @@ -963,7 +942,6 @@ trait JProcedure20[ t20: T20 ): Unit - @JavaDefaultMethod def apply( t1: T1, t2: T2, @@ -1083,7 +1061,6 @@ trait JProcedure21[ t21: T21 ): Unit - @JavaDefaultMethod def apply( t1: T1, t2: T2, @@ -1208,7 +1185,6 @@ trait JProcedure22[ t22: T22 ): Unit - @JavaDefaultMethod def apply( t1: T1, t2: T2, diff --git a/auxlib/src/main/scala-3/scala/runtime/function/JProcedure.scala.gyb b/auxlib/src/main/scala-3/scala/runtime/function/JProcedure.scala.gyb index a3b69a6383..8c23b0aeed 100644 --- a/auxlib/src/main/scala-3/scala/runtime/function/JProcedure.scala.gyb +++ b/auxlib/src/main/scala-3/scala/runtime/function/JProcedure.scala.gyb @@ -9,13 +9,11 @@ package scala.runtime.function import scala.runtime.BoxedUnit -import scala.scalanative.annotation.JavaDefaultMethod trait JProcedure0 extends scala.Function0[Object] with java.io.Serializable { def applyVoid(): Unit - @JavaDefaultMethod def apply(): Object = { applyVoid() return BoxedUnit.UNIT @@ -32,7 +30,6 @@ trait JProcedure${N}[${TpsDecl}] with java.io.Serializable { def applyVoid(${args}): Unit - @JavaDefaultMethod def apply(${args}): Object = { applyVoid(${argNames}) return BoxedUnit.UNIT diff --git a/javalib/src/main/scala/java/lang/IEEE754Helpers.scala b/javalib/src/main/scala/java/lang/IEEE754Helpers.scala index a87620f8c7..8c75810e48 100644 --- a/javalib/src/main/scala/java/lang/IEEE754Helpers.scala +++ b/javalib/src/main/scala/java/lang/IEEE754Helpers.scala @@ -21,7 +21,7 @@ private[java] object IEEE754Helpers { // DO NOT USE STRING INTERPOLATION with an interior double quote ("), // a.k.a Unicode "QUOTATION MARK" (\u0022). // Double quote failing interpolated strings is a longstanding - // bug in many Scala versions, including 2.11.n, 2.12.n, & 2.13.2. + // bug in many Scala versions, including 2.12.n, & 2.13.2. // See URLS: // https://github.com/scala/bug/issues/6476 // https://github.com/scala/scala/pull/8830 diff --git a/javalib/src/main/scala/java/lang/Iterable.scala b/javalib/src/main/scala/java/lang/Iterable.scala index d69e0a2dba..f0276e25b6 100644 --- a/javalib/src/main/scala/java/lang/Iterable.scala +++ b/javalib/src/main/scala/java/lang/Iterable.scala @@ -5,12 +5,9 @@ package java.lang import java.util.Iterator import java.util.function.Consumer -import scala.scalanative.annotation.JavaDefaultMethod - trait Iterable[T] { def iterator(): Iterator[T] - @JavaDefaultMethod def forEach(action: Consumer[_ >: T]): Unit = { val iter = iterator() while (iter.hasNext()) diff --git a/javalib/src/main/scala/java/util/Collection.scala b/javalib/src/main/scala/java/util/Collection.scala index f71808912b..c9bfff6382 100644 --- a/javalib/src/main/scala/java/util/Collection.scala +++ b/javalib/src/main/scala/java/util/Collection.scala @@ -4,8 +4,6 @@ package java.util import java.util.function.Predicate -import scala.scalanative.annotation.JavaDefaultMethod - trait Collection[E] extends java.lang.Iterable[E] { def size(): Int def isEmpty(): Boolean @@ -19,7 +17,6 @@ trait Collection[E] extends java.lang.Iterable[E] { def addAll(c: Collection[_ <: E]): Boolean def removeAll(c: Collection[_]): Boolean - @JavaDefaultMethod def removeIf(filter: Predicate[_ >: E]): Boolean = { var result = false val iter = iterator() diff --git a/javalib/src/main/scala/java/util/Comparator.scala b/javalib/src/main/scala/java/util/Comparator.scala index e06d0d41b0..139f2df3db 100644 --- a/javalib/src/main/scala/java/util/Comparator.scala +++ b/javalib/src/main/scala/java/util/Comparator.scala @@ -2,13 +2,9 @@ package java.util -import scala.scalanative.annotation.JavaDefaultMethod - trait Comparator[A] { def compare(o1: A, o2: A): Int def equals(obj: Any): Boolean - - @JavaDefaultMethod def reversed(): Comparator[A] = Collections.reverseOrder(this) } diff --git a/javalib/src/main/scala/java/util/Iterator.scala b/javalib/src/main/scala/java/util/Iterator.scala index 3f38145e84..0200d1a44a 100644 --- a/javalib/src/main/scala/java/util/Iterator.scala +++ b/javalib/src/main/scala/java/util/Iterator.scala @@ -2,19 +2,15 @@ package java.util -import scala.scalanative.annotation.JavaDefaultMethod - import java.util.function.Consumer trait Iterator[E] { def hasNext(): Boolean def next(): E - @JavaDefaultMethod def remove(): Unit = throw new UnsupportedOperationException("remove") - @JavaDefaultMethod def forEachRemaining(action: Consumer[_ >: E]): Unit = { while (hasNext()) action.accept(next()) diff --git a/javalib/src/main/scala/java/util/List.scala b/javalib/src/main/scala/java/util/List.scala index 44a4202430..fc7ba3ff04 100644 --- a/javalib/src/main/scala/java/util/List.scala +++ b/javalib/src/main/scala/java/util/List.scala @@ -4,17 +4,13 @@ package java.util import java.util.function.UnaryOperator -import scala.scalanative.annotation.JavaDefaultMethod - trait List[E] extends Collection[E] { - @JavaDefaultMethod def replaceAll(operator: UnaryOperator[E]): Unit = { val iter = listIterator() while (iter.hasNext()) iter.set(operator.apply(iter.next())) } - @JavaDefaultMethod def sort(c: Comparator[_ >: E]): Unit = { val arrayBuf = toArray() Arrays.sort[AnyRef with E](arrayBuf.asInstanceOf[Array[AnyRef with E]], c) diff --git a/javalib/src/main/scala/java/util/Map.scala b/javalib/src/main/scala/java/util/Map.scala index 4cf8b96b74..e20219d89d 100644 --- a/javalib/src/main/scala/java/util/Map.scala +++ b/javalib/src/main/scala/java/util/Map.scala @@ -4,8 +4,6 @@ package java.util import java.util.function.{BiConsumer, BiFunction, Function} -import scala.scalanative.annotation.JavaDefaultMethod - import ScalaOps._ trait Map[K, V] { @@ -24,24 +22,20 @@ trait Map[K, V] { def equals(o: Any): Boolean def hashCode(): Int - @JavaDefaultMethod def getOrDefault(key: Any, defaultValue: V): V = if (containsKey(key)) get(key) else defaultValue - @JavaDefaultMethod def forEach(action: BiConsumer[_ >: K, _ >: V]): Unit = { for (entry <- entrySet().scalaOps) action.accept(entry.getKey(), entry.getValue()) } - @JavaDefaultMethod def replaceAll(function: BiFunction[_ >: K, _ >: V, _ <: V]): Unit = { for (entry <- entrySet().scalaOps) entry.setValue(function.apply(entry.getKey(), entry.getValue())) } - @JavaDefaultMethod def putIfAbsent(key: K, value: V): V = { val prevValue = get(key) if (prevValue == null) @@ -50,7 +44,6 @@ trait Map[K, V] { prevValue } - @JavaDefaultMethod def remove(key: Any, value: Any): Boolean = { if (containsKey(key) && Objects.equals(get(key), value)) { remove(key) @@ -60,7 +53,6 @@ trait Map[K, V] { } } - @JavaDefaultMethod def replace(key: K, oldValue: V, newValue: V): Boolean = { if (containsKey(key) && Objects.equals(get(key), oldValue)) { put(key, newValue) @@ -70,12 +62,10 @@ trait Map[K, V] { } } - @JavaDefaultMethod def replace(key: K, value: V): V = if (containsKey(key)) put(key, value) else null.asInstanceOf[V] - @JavaDefaultMethod def computeIfAbsent(key: K, mappingFunction: Function[_ >: K, _ <: V]): V = { val oldValue = get(key) if (oldValue != null) { @@ -88,7 +78,6 @@ trait Map[K, V] { } } - @JavaDefaultMethod def computeIfPresent( key: K, remappingFunction: BiFunction[_ >: K, _ >: V, _ <: V] @@ -103,7 +92,6 @@ trait Map[K, V] { } } - @JavaDefaultMethod def compute( key: K, remappingFunction: BiFunction[_ >: K, _ >: V, _ <: V] @@ -127,7 +115,6 @@ trait Map[K, V] { newValue } - @JavaDefaultMethod def merge( key: K, value: V, diff --git a/javalib/src/main/scala/java/util/Spliterator.scala b/javalib/src/main/scala/java/util/Spliterator.scala index 2ef9cff98c..6e90a3dfd1 100644 --- a/javalib/src/main/scala/java/util/Spliterator.scala +++ b/javalib/src/main/scala/java/util/Spliterator.scala @@ -1,7 +1,6 @@ package java.util import java.util.function.Consumer -import scala.scalanative.annotation.JavaDefaultMethod import Spliterator._ @@ -22,18 +21,14 @@ trait Spliterator[T] { def estimateSize(): Long - @JavaDefaultMethod def forEachRemaining(action: Consumer[_ >: T]): Unit = while (tryAdvance(action)) {} - @JavaDefaultMethod def getComparator(): Comparator[_ >: T] = throw new IllegalStateException() - @JavaDefaultMethod def getExactSizeIfKnown(): Long = if (hasCharacteristics(SIZED)) estimateSize() else -1L - @JavaDefaultMethod def hasCharacteristics(chars: Int): Boolean = (characteristics() & chars) == chars diff --git a/javalib/src/main/scala/java/util/function/BiConsumer.scala b/javalib/src/main/scala/java/util/function/BiConsumer.scala index 77f69cfb85..04d0e1a5ea 100644 --- a/javalib/src/main/scala/java/util/function/BiConsumer.scala +++ b/javalib/src/main/scala/java/util/function/BiConsumer.scala @@ -1,16 +1,12 @@ -// Corresponds to Scala.js commit: f86ed6 c2f5a43 dated: 2020-09-06 -// Design note: Do not use lambdas with Scala Native and Scala 2.11 +// Ported from Scala.js commit: f86ed6 c2f5a43 dated: 2020-09-06 package java.util.function -import scala.scalanative.annotation.JavaDefaultMethod - trait BiConsumer[T, U] { self => def accept(t: T, u: U): Unit - @JavaDefaultMethod def andThen(after: BiConsumer[T, U]): BiConsumer[T, U] = new BiConsumer[T, U]() { override def accept(t: T, u: U): Unit = { diff --git a/javalib/src/main/scala/java/util/function/BiFunction.scala b/javalib/src/main/scala/java/util/function/BiFunction.scala index c4007e2d0a..7eabfeb804 100644 --- a/javalib/src/main/scala/java/util/function/BiFunction.scala +++ b/javalib/src/main/scala/java/util/function/BiFunction.scala @@ -1,14 +1,10 @@ -// Corresponds to Scala.js commit: d3a9711 dated: 2020-09-06 -// Design note: Do not use lambdas with Scala Native and Scala 2.11 +// Ported from Scala.js commit: d3a9711 dated: 2020-09-06 package java.util.function -import scala.scalanative.annotation.JavaDefaultMethod - trait BiFunction[T, U, R] { self => def apply(t: T, u: U): R - @JavaDefaultMethod def andThen[V](after: Function[_ >: R, _ <: V]): BiFunction[T, U, V] = { new BiFunction[T, U, V] { def apply(t: T, u: U): V = after.apply(self.apply(t, u)) diff --git a/javalib/src/main/scala/java/util/function/BiPredicate.scala b/javalib/src/main/scala/java/util/function/BiPredicate.scala index f9df09dbca..bc160335d6 100644 --- a/javalib/src/main/scala/java/util/function/BiPredicate.scala +++ b/javalib/src/main/scala/java/util/function/BiPredicate.scala @@ -1,27 +1,22 @@ -// Influenced by Scala.js commit: 0c27b64 dated: 2020-09-06 +// Ported from Scala.js commit: 0c27b64 dated: 2020-09-06 package java.util.function -import scala.scalanative.annotation.JavaDefaultMethod - trait BiPredicate[T, U] { self => def test(t: T, u: U): Boolean - @JavaDefaultMethod def and(other: BiPredicate[_ >: T, _ >: U]): BiPredicate[T, U] = new BiPredicate[T, U] { override def test(t: T, u: U): Boolean = self.test(t, u) && other.test(t, u) } - @JavaDefaultMethod def negate(): BiPredicate[T, U] = new BiPredicate[T, U] { override def test(t: T, u: U): Boolean = !self.test(t, u) } - @JavaDefaultMethod def or(other: BiPredicate[_ >: T, _ >: U]): BiPredicate[T, U] = new BiPredicate[T, U] { override def test(t: T, u: U): Boolean = diff --git a/javalib/src/main/scala/java/util/function/Consumer.scala b/javalib/src/main/scala/java/util/function/Consumer.scala index 6aa42c1120..5a093ad3e7 100644 --- a/javalib/src/main/scala/java/util/function/Consumer.scala +++ b/javalib/src/main/scala/java/util/function/Consumer.scala @@ -1,11 +1,8 @@ package java.util.function -import scala.scalanative.annotation.JavaDefaultMethod - trait Consumer[T] { self => def accept(t: T): Unit - @JavaDefaultMethod def andThen(after: Consumer[T]): Consumer[T] = new Consumer[T]() { def accept(t: T): Unit = { self.accept(t) diff --git a/javalib/src/main/scala/java/util/function/Function.scala b/javalib/src/main/scala/java/util/function/Function.scala index ef562c5c7b..9abd8c367e 100644 --- a/javalib/src/main/scala/java/util/function/Function.scala +++ b/javalib/src/main/scala/java/util/function/Function.scala @@ -1,22 +1,15 @@ -// Influenced Scala.js commit: eb637e3 dated: 2020-09-06 -// -// Design Note: Once Scala Native no longer supports Scala 2.11, -// OK to use Scala.js code with lambdas. +// Ported from Scala.js commit: eb637e3 dated: 2020-09-06 package java.util.function -import scala.scalanative.annotation.JavaDefaultMethod - trait Function[T, R] { self => def apply(t: T): R - @JavaDefaultMethod def andThen[V](after: Function[_ >: R, _ <: V]): Function[T, V] = new Function[T, V] { override def apply(t: T): V = after.apply(self.apply(t)) } - @JavaDefaultMethod def compose[V](before: Function[_ >: V, _ <: T]): Function[V, R] = new Function[V, R] { override def apply(v: V): R = self.apply(before.apply(v)) diff --git a/javalib/src/main/scala/java/util/function/IntUnaryOperator.scala b/javalib/src/main/scala/java/util/function/IntUnaryOperator.scala index b57456edb7..821195415a 100644 --- a/javalib/src/main/scala/java/util/function/IntUnaryOperator.scala +++ b/javalib/src/main/scala/java/util/function/IntUnaryOperator.scala @@ -2,18 +2,14 @@ package java.util.function -import scala.scalanative.annotation.JavaDefaultMethod - @FunctionalInterface trait IntUnaryOperator { def applyAsInt(operand: Int): Int - @JavaDefaultMethod def andThen(after: IntUnaryOperator): IntUnaryOperator = { (i: Int) => after.applyAsInt(applyAsInt(i)) } - @JavaDefaultMethod def compose(before: IntUnaryOperator): IntUnaryOperator = { (i: Int) => applyAsInt(before.applyAsInt(i)) } diff --git a/javalib/src/main/scala/java/util/function/Predicate.scala b/javalib/src/main/scala/java/util/function/Predicate.scala index eaaf708d7d..8524858a9d 100644 --- a/javalib/src/main/scala/java/util/function/Predicate.scala +++ b/javalib/src/main/scala/java/util/function/Predicate.scala @@ -4,13 +4,10 @@ package java.util.function import java.{util => ju} -import scala.scalanative.annotation.JavaDefaultMethod - @FunctionalInterface trait Predicate[T] { self => def test(t: T): Boolean - @JavaDefaultMethod def and(other: Predicate[_ >: T]): Predicate[T] = { new Predicate[T] { def test(t: T): Boolean = @@ -18,7 +15,6 @@ trait Predicate[T] { self => } } - @JavaDefaultMethod def negate(): Predicate[T] = { new Predicate[T] { def test(t: T): Boolean = @@ -26,7 +22,6 @@ trait Predicate[T] { self => } } - @JavaDefaultMethod def or(other: Predicate[_ >: T]): Predicate[T] = { new Predicate[T] { def test(t: T): Boolean = diff --git a/nativelib/src/main/scala/scala/scalanative/annotation/JavaDefaultMethod.scala b/nativelib/src/main/scala/scala/scalanative/annotation/JavaDefaultMethod.scala deleted file mode 100644 index 5e0204adec..0000000000 --- a/nativelib/src/main/scala/scala/scalanative/annotation/JavaDefaultMethod.scala +++ /dev/null @@ -1,14 +0,0 @@ -// Ported from Scala.js commit SHA1: 9dc4d5b dated: 2020-10-18 - -package scala.scalanative -package annotation - -/** Mark a concrete trait method as a Java default method. - * - * This annotation can be used on concrete trait methods to mark them as Java - * default methods. This should be used *only* to implement interfaces of the - * JDK that have default methods in Java. - * - * Otherwise using this annotation is unspecified. - */ -class JavaDefaultMethod extends scala.annotation.StaticAnnotation diff --git a/nir/src/main/scala/scala/scalanative/nir/Sig.scala b/nir/src/main/scala/scala/scalanative/nir/Sig.scala index 6dab0f710b..f834605299 100644 --- a/nir/src/main/scala/scala/scalanative/nir/Sig.scala +++ b/nir/src/main/scala/scala/scalanative/nir/Sig.scala @@ -30,14 +30,13 @@ final class Sig(val mangle: String) { final def isField: Boolean = mangle(0) == 'F' final def isCtor: Boolean = mangle(0) == 'R' final def isClinit: Boolean = mangle(0) == 'I' - final def isImplCtor: Boolean = mangle.startsWith("M6$init$") final def isMethod: Boolean = mangle(0) == 'D' final def isProxy: Boolean = mangle(0) == 'P' final def isExtern: Boolean = mangle(0) == 'C' final def isGenerated: Boolean = mangle(0) == 'G' final def isDuplicate: Boolean = mangle(0) == 'K' - final def isVirtual = !(isCtor || isClinit || isImplCtor || isExtern) + final def isVirtual = !(isCtor || isClinit || isExtern) final def isPrivate: Boolean = privateIn.isDefined final def isStatic: Boolean = { def isPublicStatic = mangle.last == 'o' diff --git a/nscplugin/src/main/scala-2/scala/scalanative/nscplugin/NirCompat.scala b/nscplugin/src/main/scala-2/scala/scalanative/nscplugin/NirCompat.scala index 4b96246525..6f13997b53 100644 --- a/nscplugin/src/main/scala-2/scala/scalanative/nscplugin/NirCompat.scala +++ b/nscplugin/src/main/scala-2/scala/scalanative/nscplugin/NirCompat.scala @@ -5,15 +5,13 @@ import scala.reflect.internal.Flags import scala.tools.nsc._ trait NirCompat[G <: Global with Singleton] { self: NirPhase[G] => - import NirCompat.{infiniteLoop, noImplClasses} + import NirCompat.infiniteLoop import global._ /* SAMFunction was introduced in 2.12 for LMF-capable SAM types. * DottyEnumSingleton was introduced in 2.13.6 to identify Scala 3 `enum` singleton cases. */ object AttachmentsCompatDef { - case class SAMFunction(samTp: Type, sam: Symbol, synthCls: Symbol) - extends PlainAttachment object DottyEnumSingleton extends PlainAttachment } @@ -23,20 +21,14 @@ trait NirCompat[G <: Global with Singleton] { self: NirPhase[G] => object Inner { import global._ - type SAMFunctionAlias = SAMFunction - val SAMFunctionAlias = SAMFunction - val DottyEnumSingletonAlias = DottyEnumSingleton } } - type SAMFunctionCompat = AttachmentsCompat.Inner.SAMFunctionAlias - lazy val SAMFunctionCompat = AttachmentsCompat.Inner.SAMFunctionAlias - lazy val DottyEnumSingletonCompat = AttachmentsCompat.Inner.DottyEnumSingletonAlias - implicit final class SAMFunctionCompatOps(self: SAMFunctionCompat) { + implicit final class SAMFunctionCompatOps(self: SAMFunction) { // Introduced in 2.12.5 to synthesize bridges in LMF classes def synthCls: Symbol = NoSymbol } @@ -53,51 +45,13 @@ trait NirCompat[G <: Global with Singleton] { self: NirPhase[G] => } implicit final class SymbolCompat(self: Symbol) { - def originalOwner: Symbol = - global.originalOwner.getOrElse(self, self.rawowner) - - def implClass: Symbol = NoSymbol - def isTraitOrInterface: Boolean = self.isTrait || self.isInterface def isScala3Defined: Boolean = false } - - implicit final class GlobalCompat(self: NirCompat.this.global.type) { - - object originalOwner { - def getOrElse(sym: Symbol, orElse: => Symbol): Symbol = infiniteLoop() - } - } - - private implicit final class FlagsCompat(self: Flags.type) { - def IMPLCLASS: Long = infiniteLoop() - } - - lazy val scalaUsesImplClasses: Boolean = - definitions.SeqClass.implClass != NoSymbol // a trait we know has an impl class - - def isImplClass(sym: Symbol): Boolean = - scalaUsesImplClasses && sym.hasFlag(Flags.IMPLCLASS) - - implicit final class StdTermNamesCompat(self: global.nme.type) { - def IMPL_CLASS_SUFFIX: String = noImplClasses() - - def isImplClassName(name: Name): Boolean = false - } - - implicit final class StdTypeNamesCompat(self: global.tpnme.type) { - def IMPL_CLASS_SUFFIX: String = noImplClasses() - - def interfaceName(implname: Name): TypeName = noImplClasses() - } - } object NirCompat { private def infiniteLoop(): Nothing = throw new AssertionError("Infinite loop in NirCompat") - - private def noImplClasses(): Nothing = - throw new AssertionError("No impl classes in this version") } diff --git a/nscplugin/src/main/scala-2/scala/scalanative/nscplugin/NirDefinitions.scala b/nscplugin/src/main/scala-2/scala/scalanative/nscplugin/NirDefinitions.scala index 9d22b62374..8a9631958d 100644 --- a/nscplugin/src/main/scala-2/scala/scalanative/nscplugin/NirDefinitions.scala +++ b/nscplugin/src/main/scala-2/scala/scalanative/nscplugin/NirDefinitions.scala @@ -393,6 +393,4 @@ trait NirDefinitions { ) } - lazy val JavaDefaultMethodAnnotation = - getRequiredClass("scala.scalanative.annotation.JavaDefaultMethod") } diff --git a/nscplugin/src/main/scala-2/scala/scalanative/nscplugin/NirGenExpr.scala b/nscplugin/src/main/scala-2/scala/scalanative/nscplugin/NirGenExpr.scala index d0aff7b9a3..2d95740abe 100644 --- a/nscplugin/src/main/scala-2/scala/scalanative/nscplugin/NirGenExpr.scala +++ b/nscplugin/src/main/scala-2/scala/scalanative/nscplugin/NirGenExpr.scala @@ -654,14 +654,8 @@ trait NirGenExpr[G <: nsc.Global with Singleton] { self: NirGenPhase[G] => def genStaticMember(receiver: Tree, sym: Symbol)(implicit pos: nir.Position ): Val = { - if (sym == BoxedUnit_UNIT) { - Val.Unit - } else if (!isImplClass(sym.owner)) { - genApplyStaticMethod(sym, receiver, Seq()) - } else { - val module = genModule(sym.owner) - genApplyMethod(sym, statically = true, module, Seq()) - } + if (sym == BoxedUnit_UNIT) Val.Unit + else genApplyStaticMethod(sym, receiver, Seq()) } def genAssign(tree: Assign): Val = { @@ -954,8 +948,7 @@ trait NirGenExpr[G <: nsc.Global with Singleton] { self: NirGenPhase[G] => .filter(_.name.toString == "apply") .toSeq } else { - val samInfo = tree.attachments.get[SAMFunctionCompat].getOrElse { - println(tree.attachments) + val samInfo = tree.attachments.get[SAMFunction].getOrElse { abort( s"Cannot find the SAMFunction attachment on $tree at ${tree.pos}" ) @@ -1354,36 +1347,6 @@ trait NirGenExpr[G <: nsc.Global with Singleton] { self: NirGenPhase[G] => genFunction(fn) }(targetTree.symbol) - case fn @ Apply(target, args) => // Scala 2.11 only - if (args.nonEmpty) { - args match { - case This(_) :: Nil - if args.map(_.tpe.sym) == target.tpe.paramTypes.map(_.sym) => - // Ignore, Scala 2.11 needs reference to outer class to create an instance of ananymous function, - // does not lead to undefined behaviour. However we cannot detect access to member of outer class. - () - case _ => - reportClosingOverLocalState(args) - } - } - - val alternatives = fn.tpe - .member(nme.apply) - .alternatives - - val fnSym = alternatives - .find { sym => - sym.tpe != ObjectTpe || - sym.tpe.params.exists(_.tpe != ObjectTpe) - } - .orElse(alternatives.headOption) - .getOrElse(unsupported(s"not found any apply method in ${fn.tpe}")) - .asMethod - - withGeneratedForwarder { - genExpr(tree) - }(fnSym) - case _ => unsupported( "Failed to resolve function ref for extern forwarder " @@ -2336,8 +2299,6 @@ trait NirGenExpr[G <: nsc.Global with Singleton] { self: NirGenPhase[G] => )(implicit pos: nir.Position): Val = { if (sym.owner.isExternModule && sym.isAccessor) { genApplyExternAccessor(sym, argsp) - } else if (isImplClass(sym.owner)) { - genApplyMethod(sym, statically = true, Val.Null, argsp) } else if (sym.isStaticMember) { genApplyStaticMethod(sym, selfp, argsp) } else { @@ -2351,7 +2312,7 @@ trait NirGenExpr[G <: nsc.Global with Singleton] { self: NirGenPhase[G] => receiver: Tree, argsp: Seq[Tree] )(implicit pos: nir.Position): Val = { - require(!isImplClass(sym.owner) && !sym.owner.isExternModule, sym.owner) + require(!sym.owner.isExternModule, sym.owner) val name = genStaticMemberName(sym, receiver.symbol) val method = Val.Global(name, nir.Type.Ptr) val sig = genMethodSig(sym) @@ -2435,7 +2396,7 @@ trait NirGenExpr[G <: nsc.Global with Singleton] { self: NirGenPhase[G] => } val args = genMethodArgs(sym, argsp) val method = - if (isImplClass(owner) || statically || owner.isStruct || isExtern) { + if (statically || owner.isStruct || isExtern) { Val.Global(name, nir.Type.Ptr) } else { val Global.Member(_, sig) = name diff --git a/nscplugin/src/main/scala-2/scala/scalanative/nscplugin/NirGenName.scala b/nscplugin/src/main/scala-2/scala/scalanative/nscplugin/NirGenName.scala index 4bc1dd4a29..703185a01c 100644 --- a/nscplugin/src/main/scala-2/scala/scalanative/nscplugin/NirGenName.scala +++ b/nscplugin/src/main/scala-2/scala/scalanative/nscplugin/NirGenName.scala @@ -41,8 +41,7 @@ trait NirGenName[G <: Global with Singleton] { case _ if sym.isModule => genTypeName(sym.moduleClass) case _ => - val needsModuleClassSuffix = - sym.isModuleClass && !sym.isJavaDefined && !isImplClass(sym) + val needsModuleClassSuffix = sym.isModuleClass && !sym.isJavaDefined val idWithSuffix = if (needsModuleClassSuffix) id + "$" else id nir.Global.Top(idWithSuffix) } @@ -89,7 +88,7 @@ trait NirGenName[G <: Global with Singleton] { val id = nativeIdOf(sym) val tpe = sym.tpe.widen val scope = - if (sym.isStaticMember && !isImplClass(sym.owner)) { + if (sym.isStaticMember) { if (sym.isPrivate) nir.Sig.Scope.PrivateStatic(owner) else nir.Sig.Scope.PublicStatic } else if (sym.isPrivate) @@ -98,7 +97,9 @@ trait NirGenName[G <: Global with Singleton] { val paramTypes = tpe.params.toSeq.map(p => genType(p.info)) - if (sym == String_+) { + def isExtern = sym.owner.isExternType + + if (sym == String_+) genMethodName(StringConcatMethod) } else if (sym.owner.isExternModule) { owner.member(genExternSigImpl(sym, id)) @@ -128,7 +129,6 @@ trait NirGenName[G <: Global with Singleton] { // in the super class. This is important, becouse (on the JVM) static methods are resolved at // compile time and do never use dynamic method dispatch, however it is possible to shadow // static method in the parent class by defining static method with the same name in the child. - require(!isImplClass(sym.owner), sym.owner) val typeName = genTypeName( Option(explicitOwner) .fold[Symbol](NoSymbol) { diff --git a/nscplugin/src/main/scala-2/scala/scalanative/nscplugin/NirGenStat.scala b/nscplugin/src/main/scala-2/scala/scalanative/nscplugin/NirGenStat.scala index 08a9d5b84e..b61d505592 100644 --- a/nscplugin/src/main/scala-2/scala/scalanative/nscplugin/NirGenStat.scala +++ b/nscplugin/src/main/scala-2/scala/scalanative/nscplugin/NirGenStat.scala @@ -28,10 +28,8 @@ trait NirGenStat[G <: nsc.Global with Singleton] { self: NirGenPhase[G] => forwarders: Seq[nir.Defn.Define] ) - protected val isScala211 = Properties.versionNumberString.startsWith("2.11") - def isStaticModule(sym: Symbol): Boolean = - sym.isModuleClass && !isImplClass(sym) && !sym.isLifted + sym.isModuleClass && !sym.isLifted class MethodEnv(val fresh: Fresh) { private val env = mutable.Map.empty[Symbol, Val] @@ -90,6 +88,8 @@ trait NirGenStat[G <: nsc.Global with Singleton] { self: NirGenPhase[G] => def nonEmpty = buf.nonEmpty def genClass(cd: ClassDef): Unit = { + val sym = cd.symbol + scoped( curClassSym := cd.symbol, curClassFresh := nir.Fresh() @@ -563,43 +563,6 @@ trait NirGenStat[G <: nsc.Global with Singleton] { self: NirGenPhase[G] => buf ++= genTopLevelExports(cd) } - private def genJavaDefaultMethodBody(dd: DefDef): Seq[nir.Inst] = { - val fresh = Fresh() - val buf = new ExprBuffer()(fresh) - - implicit val pos: nir.Position = dd.pos - - val sym = dd.symbol - val implClassFullName = sym.owner.fullName + "$class" - - val implClassSym = findMemberFromRoot(TermName(implClassFullName)) - - val implMethodSym = implClassSym.info - .member(sym.name) - .suchThat { s => - s.isMethod && - s.tpe.params.size == sym.tpe.params.size + 1 && - s.tpe.params.head.tpe =:= sym.owner.toTypeConstructor && - s.tpe.params.tail.zip(sym.tpe.params).forall { - case (sParam, symParam) => - sParam.tpe =:= symParam.tpe - } - } - - val implName = Val.Global(genMethodName(implMethodSym), Type.Ptr) - val implSig = genMethodSig(implMethodSym) - - val Type.Function(paramtys, retty) = implSig - - val params = paramtys.map(ty => Val.Local(fresh(), ty)) - buf.label(fresh(), params) - - val res = buf.call(implSig, implName, params, Next.None) - buf.ret(res) - - buf.toSeq - } - def genMethod(dd: DefDef): Option[nir.Defn] = { val fresh = Fresh() val env = new MethodEnv(fresh) @@ -620,24 +583,9 @@ trait NirGenStat[G <: nsc.Global with Singleton] { self: NirGenPhase[G] => val sig = genMethodSig(sym) dd.rhs match { - case EmptyTree - if (isScala211 && - sym.hasAnnotation(JavaDefaultMethodAnnotation)) => - scoped( - curMethodSig := sig - ) { - val body = genJavaDefaultMethodBody(dd) - Some(Defn.Define(attrs, name, sig, body)) - } - case EmptyTree => Some(Defn.Declare(attrs, name, sig)) - case Apply(TypeApply(Select(retBlock, _), _), _) - if retBlock.tpe == NoType && isScala211 => - // Fix issue #2305 Compile error on macro using Scala 2.11.12 - Some(Defn.Declare(attrs, name, sig)) - case _ if dd.name == nme.CONSTRUCTOR && owner.isExternModule => validateExternCtor(dd.rhs) None @@ -649,14 +597,6 @@ trait NirGenStat[G <: nsc.Global with Singleton] { self: NirGenPhase[G] => checkExplicitReturnTypeAnnotation(dd, "extern method") genExternMethod(attrs, name, sig, rhs) - case rhs - if (isScala211 && - sym.hasAnnotation(JavaDefaultMethodAnnotation) && - !isImplClass(sym.owner)) => - // Have a concrete method with JavaDefaultMethodAnnotation; a blivet. - // Do not emit, not even as abstract. - None - case _ if sym.hasAnnotation(ResolvedAtLinktimeClass) => genLinktimeResolved(dd, name) @@ -752,21 +692,56 @@ trait NirGenStat[G <: nsc.Global with Singleton] { self: NirGenPhase[G] => } def validateExternCtor(rhs: Tree): Unit = { - val Block(_ +: init, _) = rhs - val externs = init.map { - case Assign(ref: RefTree, Apply(extern, Seq())) - if extern.symbol == ExternMethod => - ref.symbol - case _ => - unsupported( - "extern objects may only contain extern fields and methods" - ) - }.toSet - for { - f <- curClassSym.info.decls if f.isField - if !externs.contains(f) - } { - unsupported("extern objects may only contain extern fields") + val classSym = curClassSym.get + def isExternCall(tree: Tree): Boolean = tree match { + case Typed(target, _) => isExternCall(target) + case Apply(extern, _) => extern.symbol == ExternMethod + case _ => false + } + + def isCurClassSetter(sym: Symbol) = + sym.isSetter && sym.owner.tpe <:< classSym.tpe + + rhs match { + case Block(Nil, _) => () // empty mixin constructor + case Block(inits, _) => + val externs = collection.mutable.Set.empty[Symbol] + inits.foreach { + case Assign(ref: RefTree, rhs) if isExternCall(rhs) => + externs += ref.symbol + + case Apply(fun, Seq(arg)) + if isCurClassSetter(fun.symbol) && isExternCall(arg) => + externs += fun.symbol + + case Apply(target, _) if target.symbol.isConstructor => () + + case tree => + reporter.error( + rhs.pos, + "extern objects may only contain extern fields and methods" + ) + } + def isInheritedField(f: Symbol) = { + def hasFieldGetter(cls: Symbol) = f.getterIn(cls) != NoSymbol + def inheritedTraits(cls: Symbol) = + cls.parentSymbols.filter(_.isTraitOrInterface) + def inheritsField(cls: Symbol): Boolean = + hasFieldGetter(cls) || inheritedTraits(cls).exists(inheritsField) + inheritsField(classSym) + } + + // Exclude fields derived from extern trait + for (f <- curClassSym.info.decls) { + if (f.isField && !isInheritedField(f)) { + if (!(externs.contains(f) || externs.contains(f.setter))) { + reporter.error( + f.pos, + "extern objects may only contain extern fields" + ) + } + } + } } } @@ -795,8 +770,9 @@ trait NirGenStat[G <: nsc.Global with Singleton] { self: NirGenPhase[G] => val fresh = curFresh.get val buf = new ExprBuffer()(fresh) val isSynchronized = dd.symbol.hasFlag(SYNCHRONIZED) - val isStatic = dd.symbol.isStaticInNIR || isImplClass(dd.symbol.owner) - val isExtern = dd.symbol.owner.isExternModule + val sym = dd.symbol + val isStatic = sym.isStaticInNIR + val isExtern = sym.owner.isExternType implicit val pos: nir.Position = bodyp.pos @@ -918,7 +894,7 @@ trait NirGenStat[G <: nsc.Global with Singleton] { self: NirGenPhase[G] => * the same tests as the JVM back-end. */ private def isCandidateForForwarders(sym: Symbol): Boolean = { - !settings.noForwarders.value && sym.isStatic && !isImplClass(sym) && { + !settings.noForwarders.value && sym.isStatic && { // Reject non-top-level objects unless opted in via the appropriate option scalaNativeOpts.genStaticForwardersForNonTopLevelObjects || !sym.name.containsChar('$') // this is the same test that scalac performs @@ -950,9 +926,6 @@ trait NirGenStat[G <: nsc.Global with Singleton] { self: NirGenPhase[G] => } } - private lazy val dontUseExitingUncurryForForwarders = - scala.util.Properties.versionNumberString.startsWith("2.11.") - /** Gen the static forwarders for the methods of a module class. * * Precondition: `isCandidateForForwarders(moduleClass)` is true @@ -971,7 +944,7 @@ trait NirGenStat[G <: nsc.Global with Singleton] { self: NirGenPhase[G] => def listMembersBasedOnFlags = { import scala.tools.nsc.symtab.Flags._ - // Copy-pasted from BCodeHelpers (it's somewhere else in 2.11.x) + // Copy-pasted from BCodeHelpers val ExcludedForwarderFlags: Long = { SPECIALIZED | LIFTED | PROTECTED | STATIC | EXPANDEDNAME | PRIVATE | MACRO } @@ -983,20 +956,9 @@ trait NirGenStat[G <: nsc.Global with Singleton] { self: NirGenPhase[G] => } /* See BCodeHelprs.addForwarders in 2.12+ for why we normally use - * exitingUncurry. In 2.11.x we do not use it, because Scala/JVM did not - * use it back then, and using it on that version causes mixed in methods - * not to be found (this notably breaks `extends App` as the `main` - * method that it defines is not found). - * - * This means that in 2.11.x we suffer from - * https://github.com/scala/bug/issues/10812, like upstream Scala/JVM, - * but it does not really affect Scala Native because the NIR methods are not - * used for compilation, only for linking, and for linking it is fine to - * have additional, unexpected bridges. + * exitingUncurry. */ - val members = - if (dontUseExitingUncurryForForwarders) listMembersBasedOnFlags - else exitingUncurry(listMembersBasedOnFlags) + val members = exitingUncurry(listMembersBasedOnFlags) def isExcluded(m: Symbol): Boolean = { def isOfJLObject: Boolean = { diff --git a/nscplugin/src/main/scala-2/scala/scalanative/nscplugin/NirGenType.scala b/nscplugin/src/main/scala-2/scala/scalanative/nscplugin/NirGenType.scala index 289670fbc7..d9c0cb81cb 100644 --- a/nscplugin/src/main/scala-2/scala/scalanative/nscplugin/NirGenType.scala +++ b/nscplugin/src/main/scala-2/scala/scalanative/nscplugin/NirGenType.scala @@ -17,10 +17,10 @@ trait NirGenType[G <: Global with Singleton] { self: NirGenPhase[G] => sym.isInterface def isScalaModule: Boolean = - sym.isModuleClass && !isImplClass(sym) && !sym.isLifted + sym.isModuleClass && !sym.isLifted def isStaticInNIR: Boolean = - sym.owner.isExternModule || sym.isStaticMember || isImplClass(sym.owner) + sym.owner.isExternModule || sym.isStaticMember def isExternModule: Boolean = isScalaModule && sym.annotations.exists(_.symbol == ExternClass) diff --git a/nscplugin/src/main/scala-2/scala/scalanative/nscplugin/PrepNativeInterop.scala b/nscplugin/src/main/scala-2/scala/scalanative/nscplugin/PrepNativeInterop.scala index 064184dd15..bbb6eb4747 100644 --- a/nscplugin/src/main/scala-2/scala/scalanative/nscplugin/PrepNativeInterop.scala +++ b/nscplugin/src/main/scala-2/scala/scalanative/nscplugin/PrepNativeInterop.scala @@ -128,14 +128,6 @@ abstract class PrepNativeInterop[G <: Global with Singleton]( case vddef: ValOrDefDef if vddef.symbol.isLocalToBlock => super.transform(tree) - // `DefDef` that initializes `lazy val scalaProps` in trait `PropertiesTrait` - // We rewrite the body to return a pre-propulated `Properties`. - // - Scala 2.11 - case dd @ DefDef(mods, name, Nil, Nil, tpt, _) - if dd.symbol == PropertiesTrait.info.member(nativenme.scalaProps) => - val nrhs = prepopulatedScalaProperties(dd, unit.freshTermName) - treeCopy.DefDef(tree, mods, name, Nil, Nil, transform(tpt), nrhs) - // `ValDef` that initializes `lazy val scalaProps` in trait `PropertiesTrait` // We rewrite the body to return a pre-propulated `Properties`. // - Scala 2.12 diff --git a/project/Build.scala b/project/Build.scala index 218b819588..e2296c82b6 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -148,9 +148,9 @@ object Build { CrossVersion .partialVersion(scalaVersion.value) .fold(Seq.empty[String]) { - case (2, 11 | 12) => Nil - case (2, 13) => scala213StdLibDeprecations - case (3, _) => scala213StdLibDeprecations + case (2, 12) => Nil + case (2, 13) => scala213StdLibDeprecations + case (3, _) => scala213StdLibDeprecations } }, // Running tests in parallel results in `FileSystemAlreadyExistsException` @@ -309,7 +309,7 @@ object Build { .settings(mavenPublishSettings, disabledDocsSettings) .withNativeCompilerPlugin .mapBinaryVersions { - case version @ ("2.11" | "2.12" | "2.13") => + case version @ ("2.12" | "2.13") => _.settings( commonScalalibSettings("scala-library", None), scalacOptions ++= Seq( @@ -470,7 +470,6 @@ object Build { CrossVersion .partialVersion(scalaVersion.value) .collect { - case (2, 11) => oldCompat case (2, 12) => val revision = scalaVersion.value @@ -612,13 +611,7 @@ object Build { }, Compile / unmanagedSourceDirectories ++= { if (!shouldPartest.value) Nil - else { - Seq(CrossVersion.partialVersion(scalaVersion.value) match { - case Some((2, 11)) => - sourceDirectory.value / "main" / "legacy-partest" - case _ => sourceDirectory.value / "main" / "new-partest" - }) - } + else Seq(sourceDirectory.value / "main" / "new-partest") }, libraryDependencies ++= { if (!shouldPartest.value) Nil @@ -736,11 +729,7 @@ object Build { ), scalacOptions ++= { // Suppress deprecation warnings for Scala partest sources - CrossVersion.partialVersion(scalaVersion.value) match { - case Some((2, 11)) => Nil - case _ => - Seq("-Wconf:cat=deprecation:s") - } + Seq("-Wconf:cat=deprecation:s") }, scalacOptions --= Seq( "-Xfatal-warnings" @@ -757,7 +746,7 @@ object Build { else { val upstreamDir = (scalaPartest / fetchScalaSource).value CrossVersion.partialVersion(scalaVersion.value) match { - case Some((2, 11 | 12)) => Seq.empty[File] + case Some((2, 12)) => Seq.empty[File] case _ => Seq( upstreamDir / "src/testkit/scala/tools/testkit/AssertUtil.scala" diff --git a/project/Commands.scala b/project/Commands.scala index b6d8bb1558..9d7dd15f84 100644 --- a/project/Commands.scala +++ b/project/Commands.scala @@ -147,7 +147,7 @@ object Commands { import ScalaVersions._ val publishEachVersion = for { - version <- List(scala211, scala212, scala213, scala3) + version <- List(scala212, scala213, scala3) } yield if (isSnapshot) s"++$version; publish; crossPublish" else s"++$version; publishSigned; crossPublishSigned" diff --git a/project/Deps.scala b/project/Deps.scala index 25878e452d..69a0f7619c 100644 --- a/project/Deps.scala +++ b/project/Deps.scala @@ -17,11 +17,7 @@ object Deps { }.headOption.getOrElse(throw new RuntimeException("Unknown Scala versions")) def ScalaReflect(version: String) = "org.scala-lang" % "scala-reflect" % version - def ScalaCheck(scalaVersion: String) = scalaVersionsDependendent(scalaVersion) { - case (2, 11) => "org.scalacheck" %% "scalacheck" % "1.15.2" :: Nil // Last released version - case _ => "org.scalacheck" %% "scalacheck" % "1.15.4" :: Nil - }.headOption.getOrElse(throw new RuntimeException("Unknown Scala versions")) - + lazy val ScalaCheck = "org.scalacheck" %% "scalacheck" % "1.15.4" lazy val ScalaTest = "org.scalatest" %% "scalatest" % "3.2.9" lazy val ScalaParCollections = "org.scala-lang.modules" %% "scala-parallel-collections" % "1.0.3" lazy val SbtPlatformDeps = "org.portable-scala" % "sbt-platform-deps" % "1.0.1" @@ -30,10 +26,10 @@ object Deps { lazy val JUnit = "junit" % "junit" % "4.13.2" def Tools(scalaVersion: String) = { - List(ScalaCheck(scalaVersion) % "test", ScalaTest % "test") ++ + List(ScalaCheck % "test", ScalaTest % "test") ++ scalaVersionsDependendent(scalaVersion) { - case (2, 11 | 12) => Nil - case _ => ScalaParCollections :: Nil + case (2, 12) => Nil + case _ => ScalaParCollections :: Nil } } def NativeLib(scalaVersion: String) = scalaVersionsDependendent(scalaVersion) { @@ -41,9 +37,8 @@ object Deps { case _ => Nil } def ScalaPartest(scalaVersion: String) = List(SbtTestInterface) ++ scalaVersionsDependendent(scalaVersion) { - case (2, 11) => "org.scala-lang.modules" %% "scala-partest" % "1.0.16" :: Nil - case (2, _) => "org.scala-lang" % "scala-partest" % scalaVersion :: Nil - case (3, _) => "org.scala-lang" % "scala-partest" % ScalaVersions.scala213 :: Nil + case (2, _) => "org.scala-lang" % "scala-partest" % scalaVersion :: Nil + case (3, _) => "org.scala-lang" % "scala-partest" % ScalaVersions.scala213 :: Nil } lazy val TestRunner = List(SbtTestInterface, JUnitInterface, JUnit) diff --git a/project/MultiScalaProject.scala b/project/MultiScalaProject.scala index 8696759ac9..9d9ba2ad2a 100644 --- a/project/MultiScalaProject.scala +++ b/project/MultiScalaProject.scala @@ -17,12 +17,11 @@ final case class MultiScalaProject private ( ) ) - lazy val v2_11: Project = project("2.11") lazy val v2_12: Project = project("2.12") lazy val v2_13: Project = project("2.13") lazy val v3: Project = project("3") - override def componentProjects: Seq[Project] = Seq(v2_11, v2_12, v2_13, v3) + override def componentProjects: Seq[Project] = Seq(v2_12, v2_13, v3) def mapBinaryVersions( mapping: String => Project => Project @@ -116,14 +115,12 @@ object MultiScalaProject { v.map(v => (v._1, f(v._2))) final val scalaCrossVersions = Map[String, Seq[String]]( - "2.11" -> ScalaVersions.crossScala211, "2.12" -> ScalaVersions.crossScala212, "2.13" -> ScalaVersions.crossScala213, "3" -> ScalaVersions.crossScala3 ) final val scalaVersions = Map[String, String]( - "2.11" -> ScalaVersions.scala211, "2.12" -> ScalaVersions.scala212, "2.13" -> ScalaVersions.scala213, "3" -> ScalaVersions.scala3 diff --git a/project/ScalaVersions.scala b/project/ScalaVersions.scala index 5b4872cde0..6b8bea721b 100644 --- a/project/ScalaVersions.scala +++ b/project/ScalaVersions.scala @@ -2,7 +2,6 @@ package build object ScalaVersions { // Versions of Scala used for publishing compiler plugins - val crossScala211 = Seq("2.11.12") val crossScala212 = (13 to 17).map(v => s"2.12.$v") val crossScala213 = (4 to 10).map(v => s"2.13.$v") val crossScala3 = List( @@ -15,7 +14,6 @@ object ScalaVersions { val scala3libSourcesVersion = crossScala3.last // Scala versions used for publishing libraries - val scala211: String = crossScala211.last val scala212: String = crossScala212.last val scala213: String = crossScala213.last val scala3: String = "3.1.3" @@ -24,5 +22,5 @@ object ScalaVersions { val sbt10ScalaVersion: String = scala212 val libCrossScalaVersions: Seq[String] = - crossScala211 ++ crossScala212 ++ crossScala213 ++ crossScala3 + crossScala212 ++ crossScala213 ++ crossScala3 } diff --git a/project/Settings.scala b/project/Settings.scala index e824589f12..3f21c56819 100644 --- a/project/Settings.scala +++ b/project/Settings.scala @@ -112,7 +112,6 @@ object Settings { Compile / doc / scalacOptions --= scalaVersionsDependendent( scalaVersion.value )(Seq.empty[String]) { - case (2, 11) => Seq("-Xfatal-warnings") case (3, 0 | 1) => val prev = (Compile / doc / scalacOptions).value val version = scalaVersion.value @@ -529,13 +528,6 @@ object Settings { } ) - lazy val ensureSAMSupportSetting: Setting[_] = { - scalacOptions ++= { - if (scalaBinaryVersion.value == "2.11") Seq("-Xexperimental") - else Nil - } - } - lazy val toolSettings: Seq[Setting[_]] = Def.settings( javacOptions ++= Seq("-encoding", "utf8") @@ -550,7 +542,6 @@ object Settings { lazy val commonJavalibSettings = Def.settings( disabledDocsSettings, - ensureSAMSupportSetting, // This is required to have incremental compilation to work in javalib. // We put our classes on scalac's `javabootclasspath` so that it uses them // when compiling rather than the definitions from the JDK. diff --git a/scala-partest-junit-tests/src/test/resources/2.11.12/BlacklistedTests.txt b/scala-partest-junit-tests/src/test/resources/2.11.12/BlacklistedTests.txt deleted file mode 100644 index 49e52a5ac3..0000000000 --- a/scala-partest-junit-tests/src/test/resources/2.11.12/BlacklistedTests.txt +++ /dev/null @@ -1,74 +0,0 @@ -# Do not compile -scala/issues/BytecodeTests.scala -scala/reflect/QTest.scala -scala/reflect/io/ZipArchiveTest.scala -scala/reflect/internal/util/AbstractFileClassLoaderTest.scala -scala/reflect/internal/util/SourceFileTest.scala -scala/reflect/internal/util/StringOpsTest.scala -scala/reflect/internal/PrintersTest.scala -scala/reflect/internal/ScopeTest.scala -scala/reflect/internal/TypesTest.scala -scala/reflect/internal/util/WeakHashSetTest.scala -scala/reflect/internal/MirrorsTest.scala -scala/reflect/internal/NamesTest.scala -scala/tools/nsc/ScriptRunnerTest.scala -scala/tools/nsc/backend/jvm/BTypesTest.scala -scala/tools/nsc/backend/jvm/CodeGenTools.scala -scala/tools/nsc/backend/jvm/DirectCompileTest.scala -scala/tools/nsc/backend/jvm/analysis/NullnessAnalyzerTest.scala -scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzerTest.scala -scala/tools/nsc/backend/jvm/opt/BTypesFromClassfileTest.scala -scala/tools/nsc/backend/jvm/opt/CallGraphTest.scala -scala/tools/nsc/backend/jvm/opt/CompactLocalVariablesTest.scala -scala/tools/nsc/backend/jvm/opt/EmptyExceptionHandlersTest.scala -scala/tools/nsc/backend/jvm/opt/EmptyLabelsAndLineNumbersTest.scala -scala/tools/nsc/backend/jvm/opt/InlineInfoTest.scala -scala/tools/nsc/backend/jvm/opt/InlinerIllegalAccessTest.scala -scala/tools/nsc/backend/jvm/opt/InlinerSeparateCompilationTest.scala -scala/tools/nsc/backend/jvm/opt/InlinerTest.scala -scala/tools/nsc/backend/jvm/opt/InlineWarningTest.scala -scala/tools/nsc/backend/jvm/opt/MethodLevelOpts.scala -scala/tools/nsc/backend/jvm/opt/ScalaInlineInfoTest.scala -scala/tools/nsc/backend/jvm/opt/SimplifyJumpsTest.scala -scala/tools/nsc/backend/jvm/opt/UnreachableCodeTest.scala -scala/tools/nsc/backend/jvm/opt/UnusedLocalVariablesTest.scala -scala/tools/nsc/classpath/AggregateFlatClassPathTest.scala -scala/tools/nsc/classpath/FlatClassPathResolverTest.scala -scala/tools/nsc/doc/html/HtmlDocletTest.scala -scala/tools/nsc/interpreter/CompletionTest.scala -scala/tools/nsc/interpreter/TabulatorTest.scala -scala/tools/nsc/settings/ScalaVersionTest.scala -scala/tools/nsc/settings/SettingsTest.scala -scala/tools/nsc/symtab/CannotHaveAttrsTest.scala -scala/tools/nsc/symtab/FlagsTest.scala -scala/tools/nsc/symtab/FreshNameExtractorTest.scala -scala/tools/nsc/symtab/StdNamesTest.scala -scala/tools/nsc/symtab/SymbolTableForUnitTesting.scala -scala/tools/nsc/symtab/SymbolTableTest.scala -scala/tools/nsc/transform/delambdafy/DelambdafyTest.scala -scala/tools/nsc/transform/patmat/SolvingTest.scala -scala/tools/nsc/util/ClassPathImplComparator.scala -scala/tools/nsc/util/StackTraceTest.scala - -## Do not link -scala/StringContextTest.scala -scala/collection/IteratorTest.scala -scala/collection/ParallelConsistencyTest.scala -scala/collection/immutable/ListTest.scala -scala/collection/immutable/StringLikeTest.scala -scala/collection/mutable/ArrayBufferTest.scala -scala/collection/mutable/MutableListTest.scala -scala/collection/mutable/OpenHashMapTest.scala -scala/collection/mutable/PriorityQueueTest.scala -scala/concurrent/duration/SerializationTest.scala -scala/concurrent/impl/DefaultPromiseTest.scala -scala/io/SourceTest.scala -scala/runtime/ScalaRunTimeTest.scala -scala/tools/testing/AssertUtilTest.scala - -## Tests fail - -#===== -## Assumes JUnit 4.12 -scala/util/matching/RegexTest.scala -scala/util/SpecVersionTest.scala \ No newline at end of file diff --git a/scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/BlacklistedTests.txt b/scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/BlacklistedTests.txt deleted file mode 100644 index 1d0569a0d0..0000000000 --- a/scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/BlacklistedTests.txt +++ /dev/null @@ -1,955 +0,0 @@ -# Ported from Scala.js, might not be exhaustive enough (some blacklisted tests may actually work in SN) - -# -# POS - -# Spuriously fails too often, and causes other subsequent tests to fail too -# Note that this test, by design, stress-tests type checking -pos/t6367.scala - -# Using Jsoup, what's that? -pos/cycle-jsoup.scala - -# Using scala.actors -pos/t533.scala -pos/functions.scala -pos/MailBox.scala - -# -# NEG -# - -# Uses some strange macro cross compile mechanism. -neg/macro-incompatible-macro-engine-c.scala - -# -# RUN -# - -# Relies on the exact toString() representation of Floats/Doubles -run/t2378.scala - -# Uses ClassTags on existentials which are broken in Scala (see #251) -run/valueclasses-classtag-existential.scala - -# Using parts of the javalib we don't plan to support - -run/t5018.scala -run/t2417.scala -run/lazy-concurrent.scala -run/t3667.scala -run/t3038d.scala -run/shutdownhooks.scala -run/t5590.scala -run/t3895b.scala -run/t5974.scala -run/hashset.scala -run/t5262.scala -run/serialize-stream.scala -run/lambda-serialization-gc.scala - -run/t2849.scala - -run/various-flat-classpath-types.scala - -# Uses java.math.BigDecimal / BigInteger : but failures not due to them -run/is-valid-num.scala -run/stringinterpolation_macro-run.scala - -# Using Threads -run/t6969.scala -run/inner-obj-auto.scala -run/predef-cycle.scala -run/synchronized.scala - -# Uses java.security -run/t2318.scala - -# Tries to catch java.lang.StackOverflowError -run/t6154.scala -run/t9841.scala - -# Tries to catch java.lang.OutOfMemoryError -run/t7880.scala - -# Using partest properties - -run/tailcalls.scala -run/t6331b.scala -run/t4294.scala - -# Using IO - -run/t6488.scala -run/t6988.scala - -# Object{Output|Input}Streams -run/t6935.scala -run/t8188.scala -run/t9365.scala -run/t9375.scala - -# Using sys.exit / System.exit - -run/verify-ctor.scala - -# Using Await - -run/t7336.scala -run/t7775.scala -run/future-flatmap-exec-count.scala - -# Using detailed stack trace - -run/t6308.scala - -# Using reflection - -run/t720.scala -run/t6063 - -run/mixin-bridge-methods.scala -run/t5125.scala -run/outertest.scala -run/t6223.scala -run/t5652b -run/elidable-opt.scala -run/nullable-lazyvals.scala -run/t4794.scala -run/t5652 -run/t5652c -run/getClassTest-old.scala -run/t8960.scala -run/t7965.scala -run/t8087.scala -run/t8931.scala -run/delambdafyLambdaClassNames -run/t8445.scala -run/lambda-serialization.scala - -run/reflection-repl-classes.scala -run/t5256e.scala -run/typetags_core.scala -run/reflection-constructormirror-toplevel-badpath.scala -run/t5276_1b.scala -run/reflection-sorted-decls.scala -run/toolbox_typecheck_implicitsdisabled.scala -run/t5418b.scala -run/toolbox_typecheck_macrosdisabled2.scala -run/abstypetags_serialize.scala -run/all-overridden.scala -run/showraw_tree_kinds.scala -run/showraw_tree_types_ids.scala -run/showraw_tree_types_typed.scala -run/showraw_tree_ids.scala -run/showraw_tree_ultimate.scala -run/t5266_2.scala -run/t5274_1.scala -run/t5224.scala -run/reflection-sanitychecks.scala -run/t6086-vanilla.scala -run/t5277_2.scala -run/reflection-methodsymbol-params.scala -run/reflection-valueclasses-standard.scala -run/t5274_2.scala -run/t5423.scala -run/reflection-modulemirror-toplevel-good.scala -run/t5419.scala -run/t5271_3.scala -run/reflection-enclosed-nested-basic.scala -run/reflection-enclosed-nested-nested-basic.scala -run/fail-non-value-types.scala -run/exprs_serialize.scala -run/t5258a.scala -run/typetags_without_scala_reflect_manifest_lookup.scala -run/t4110-new.scala -run/t5273_2b_newpatmat.scala -run/t6277.scala -run/t5335.scala -run/toolbox_typecheck_macrosdisabled.scala -run/reflection-modulemirror-inner-good.scala -run/t5229_2.scala -run/typetags_multi.scala -run/typetags_without_scala_reflect_typetag_manifest_interop.scala -run/reflection-constructormirror-toplevel-good.scala -run/reflection-magicsymbols-invoke.scala -run/t6392b.scala -run/t5229_1.scala -run/reflection-magicsymbols-vanilla.scala -run/t5225_2.scala -run/origins.scala -run/runtimeEval1.scala -run/reflection-implClass.scala -run/reflection-enclosed-nested-inner-basic.scala -run/reflection-fieldmirror-ctorparam.scala -run/t6181.scala -run/reflection-magicsymbols-repl.scala -run/t5272_2_newpatmat.scala -run/t5270.scala -run/t5418a.scala -run/t5276_2b.scala -run/t5256f.scala -run/reflection-enclosed-basic.scala -run/reflection-constructormirror-inner-badpath.scala -run/interop_typetags_are_manifests.scala -run/newTags.scala -run/t5273_1_newpatmat.scala -run/reflection-constructormirror-nested-good.scala -run/t2236-new.scala -run/existentials3-new.scala -run/t6323b.scala -run/t5943a1.scala -run/reflection-fieldmirror-getsetval.scala -run/t5272_1_oldpatmat.scala -run/t5256h.scala -run/t1195-new.scala -run/t5840.scala -run/reflection-methodsymbol-returntype.scala -run/reflection-fieldmirror-accessorsareokay.scala -run/reflection-sorted-members.scala -run/reflection-allmirrors-tostring.scala -run/valueclasses-typetag-existential.scala -run/toolbox_console_reporter.scala -run/reflection-enclosed-inner-inner-basic.scala -run/t5256b.scala -run/bytecodecs.scala -run/elidable.scala -run/freetypes_false_alarm1.scala -run/freetypes_false_alarm2.scala -run/getClassTest-new.scala -run/idempotency-extractors.scala -run/idempotency-case-classes.scala -run/idempotency-this.scala -run/idempotency-labels.scala -run/idempotency-lazy-vals.scala -run/interop_manifests_are_abstypetags.scala -run/interop_manifests_are_typetags.scala -run/abstypetags_core.scala -run/macro-reify-abstypetag-notypeparams -run/macro-reify-abstypetag-typeparams-tags -run/macro-reify-abstypetag-typeparams-notags -run/macro-reify-abstypetag-usetypetag -run/macro-reify-freevars -run/macro-reify-splice-outside-reify -run/macro-reify-tagless-a -run/macro-reify-type -run/macro-reify-typetag-typeparams-tags -run/macro-reify-typetag-notypeparams -run/macro-undetparams-implicitval -run/manifests-new.scala -run/manifests-old.scala -run/no-pickle-skolems -run/position-val-def.scala -run/reflect-priv-ctor.scala -run/primitive-sigs-2-new.scala -run/primitive-sigs-2-old.scala -run/reflection-enclosed-inner-basic.scala -run/reflection-enclosed-inner-nested-basic.scala -run/reflection-constructormirror-inner-good.scala -run/reflection-constructormirror-nested-badpath.scala -run/reflection-fancy-java-classes -run/reflection-fieldsymbol-navigation.scala -run/reflection-fieldmirror-nmelocalsuffixstring.scala -run/reflection-fieldmirror-getsetvar.scala -run/reflection-fieldmirror-privatethis.scala -run/reflection-implicit.scala -run/reflection-mem-glbs.scala -run/reflection-mem-tags.scala -run/reflection-java-annotations -run/reflection-java-crtp -run/reflection-methodsymbol-typeparams.scala -run/reflection-modulemirror-nested-badpath.scala -run/reflection-modulemirror-inner-badpath.scala -run/reflection-modulemirror-nested-good.scala -run/reflection-modulemirror-toplevel-badpath.scala -run/reflection-sync-subtypes.scala -run/reflinit.scala -run/reflection-valueclasses-derived.scala -run/reflection-valueclasses-magic.scala -run/resetattrs-this.scala -run/runtimeEval2.scala -run/showraw_aliases.scala -run/showraw_mods.scala -run/shortClass.scala -run/showraw_nosymbol.scala -run/showraw_tree.scala -run/showraw_tree_types_untyped.scala -run/t1167.scala -run/t2577.scala -run/t2873.scala -run/t2886.scala -run/t2251b.scala -run/t3346j.scala -run/t3507-new.scala -run/t3569.scala -run/t5125b.scala -run/t5225_1.scala -run/t3425b -run/t5256a.scala -run/t5230.scala -run/t5256c.scala -run/t5256g.scala -run/t5266_1.scala -run/t5269.scala -run/t5271_1.scala -run/t5271_2.scala -run/t5271_4.scala -run/t5272_1_newpatmat.scala -run/t5272_2_oldpatmat.scala -run/t5273_1_oldpatmat.scala -run/t5273_2a_newpatmat.scala -run/t5273_2a_oldpatmat.scala -run/t5275.scala -run/t5276_1a.scala -run/t5276_2a.scala -run/t5277_1.scala -run/t5279.scala -run/t5334_1.scala -run/t5334_2.scala -run/t5415.scala -run/t5418.scala -run/t5676.scala -run/t5704.scala -run/t5710-1.scala -run/t5710-2.scala -run/t5770.scala -run/t5894.scala -run/t5816.scala -run/t5824.scala -run/t5912.scala -run/t5942.scala -run/t5943a2.scala -run/t6023.scala -run/t6113.scala -run/t6175.scala -run/t6178.scala -run/t6199-mirror.scala -run/t6199-toolbox.scala -run/t6240-universe-code-gen.scala -run/t6221 -run/t6260b.scala -run/t6259.scala -run/t6287.scala -run/t6344.scala -run/t6392a.scala -run/t6591_1.scala -run/t6591_2.scala -run/t6591_3.scala -run/t6591_5.scala -run/t6591_6.scala -run/t6591_7.scala -run/t6608.scala -run/t6677.scala -run/t6687.scala -run/t6715.scala -run/t6719.scala -run/t6793.scala -run/t6860.scala -run/t6793b.scala -run/t6793c.scala -run/t7045.scala -run/t7046.scala -run/t7008-scala-defined -run/t7120b.scala -run/t7151.scala -run/t7214.scala -run/t7235.scala -run/t7331a.scala -run/t7331b.scala -run/t7331c.scala -run/t7558.scala -run/t7556 -run/t7779.scala -run/t7868b.scala -run/toolbox_current_run_compiles.scala -run/toolbox_default_reporter_is_silent.scala -run/toolbox_expand_macro.scala -run/toolbox_parse_package.scala -run/toolbox_silent_reporter.scala -run/toolbox_typecheck_inferimplicitvalue.scala -run/trait-renaming -run/typetags_serialize.scala -run/valueclasses-typetag-basic.scala -run/WeakHashSetTest.scala -run/valueclasses-typetag-generic.scala -run/t4023.scala -run/t4024.scala -run/t6380.scala -run/t5273_2b_oldpatmat.scala -run/t8104 -run/t8047.scala -run/t6992 -run/var-arity-class-symbol.scala -run/typetags_symbolof_x.scala -run/typecheck -run/t8190.scala -run/t8192 -run/t8177f.scala -run/t8199.scala -run/t7932.scala -run/t7700.scala -run/t7570c.scala -run/t7570b.scala -run/t7533.scala -run/t7570a.scala -run/t7044 -run/t7328.scala -run/t6733.scala -run/t6554.scala -run/t6732.scala -run/t6379 -run/t6411b.scala -run/t6411a.scala -run/t6260c.scala -run/t6260-delambdafy.scala -run/showdecl -run/reflection-sync-potpourri.scala -run/reflection-tags.scala -run/reflection-companiontype.scala -run/reflection-scala-annotations.scala -run/reflection-idtc.scala -run/macro-reify-nested-b2 -run/mixin-signatures.scala -run/reflection-companion.scala -run/macro-reify-nested-b1 -run/macro-reify-nested-a2 -run/macro-reify-nested-a1 -run/macro-reify-chained2 -run/macro-reify-chained1 -run/inferred-type-constructors.scala -run/mirror_symbolof_x.scala -run/t8196.scala -run/t8549b.scala -run/t8574.scala -run/t8549.scala -run/t8637.scala -run/t8253.scala -run/t9027.scala -run/t6622.scala -run/toolbox-varargs -run/t9252.scala -run/t9182.scala -run/t9102.scala -run/t9388-bin-compat.scala - -run/reify_newimpl_29.scala -run/reify_magicsymbols.scala -run/reify_inheritance.scala -run/reify_newimpl_12.scala -run/reify_typerefs_2b.scala -run/reify_csv.scala -run/reify_inner2.scala -run/reify_maps_oldpatmat.scala -run/reify_newimpl_43.scala -run/reify_nested_inner_refers_to_local.scala -run/reify_closure7.scala -run/reify_closure8b.scala -run/reify_typerefs_3b.scala -run/reify_newimpl_44.scala -run/reify_newimpl_06.scala -run/reify_newimpl_05.scala -run/reify_newimpl_20.scala -run/reify_newimpl_23.scala -run/reify_metalevel_breach_-1_refers_to_1.scala -run/reify_newimpl_41.scala -run/reify-repl-fail-gracefully.scala -run/reify_fors_oldpatmat.scala -run/reify_inner3.scala -run/reify_closure8a.scala -run/reify_closures10.scala -run/reify_ann2a.scala -run/reify_newimpl_51.scala -run/reify_newimpl_47.scala -run/reify_extendbuiltins.scala -run/reify_newimpl_30.scala -run/reify_newimpl_38.scala -run/reify_closure2a.scala -run/reify_newimpl_45.scala -run/reify_closure1.scala -run/reify_generic2.scala -run/reify_printf.scala -run/reify_closure6.scala -run/reify_newimpl_37.scala -run/reify_newimpl_35.scala -run/reify_typerefs_3a.scala -run/reify_newimpl_25.scala -run/reify_ann4.scala -run/reify_typerefs_1b.scala -run/reify_newimpl_22.scala -run/reify_this.scala -run/reify_typerefs_2a.scala -run/reify_newimpl_03.scala -run/reify_newimpl_48.scala -run/reify_varargs.scala -run/reify_newimpl_42.scala -run/reify_newimpl_15.scala -run/reify_nested_inner_refers_to_global.scala -run/reify_newimpl_02.scala -run/reify_newimpl_01.scala -run/reify_fors_newpatmat.scala -run/reify_classfileann_a.scala -run/reify_nested_outer_refers_to_local.scala -run/reify_newimpl_13.scala -run/reify_closure5a.scala -run/reify_inner4.scala -run/reify_sort.scala -run/reify_ann1a.scala -run/reify_classfileann_b.scala -run/reify_closure4a.scala -run/reify_newimpl_33.scala -run/reify_sort1.scala -run/reify_properties.scala -run/reify_generic.scala -run/reify_newimpl_27.scala -run/reify-aliases.scala -run/reify_ann3.scala -run/reify-staticXXX.scala -run/reify_ann1b.scala -run/reify_ann5.scala -run/reify_anonymous.scala -run/reify-each-node-type.scala -run/reify_copypaste2.scala -run/reify_closure3a.scala -run/reify_copypaste1.scala -run/reify_complex.scala -run/reify_for1.scala -run/reify_getter.scala -run/reify_implicits-new.scala -run/reify_inner1.scala -run/reify_implicits-old.scala -run/reify_lazyunit.scala -run/reify_lazyevaluation.scala -run/reify_maps_newpatmat.scala -run/reify_metalevel_breach_+0_refers_to_1.scala -run/reify_metalevel_breach_-1_refers_to_0_a.scala -run/reify_metalevel_breach_-1_refers_to_0_b.scala -run/reify_nested_outer_refers_to_global.scala -run/reify_newimpl_04.scala -run/reify_newimpl_14.scala -run/reify_newimpl_11.scala -run/reify_newimpl_18.scala -run/reify_newimpl_19.scala -run/reify_newimpl_31.scala -run/reify_newimpl_21.scala -run/reify_newimpl_36.scala -run/reify_newimpl_39.scala -run/reify_newimpl_40.scala -run/reify_newimpl_49.scala -run/reify_newimpl_50.scala -run/reify_newimpl_52.scala -run/reify_renamed_term_basic.scala -run/reify_renamed_term_local_to_reifee.scala -run/reify_renamed_term_overloaded_method.scala -run/reify_renamed_type_basic.scala -run/reify_renamed_type_local_to_reifee.scala -run/reify_renamed_type_spliceable.scala -run/reify_typerefs_1a.scala -run/reify_timeofday.scala -run/reify_renamed_term_t5841.scala - -run/inferred-type-constructors-hou.scala - -# Uses refletction indirectly through -# scala.runtime.ScalaRunTime.replStringOf -run/t6634.scala - -# Using reflection to invoke macros. These tests actually don't require -# or test reflection, but use it to separate compilation units nicely. -# It's a pity we cannot use them - -run/macro-abort-fresh -run/macro-expand-varargs-explicit-over-nonvarargs-bad -run/macro-invalidret-doesnt-conform-to-def-rettype -run/macro-invalidret-nontypeable -run/macro-invalidusage-badret -run/macro-invalidusage-partialapplication -run/macro-invalidusage-partialapplication-with-tparams -run/macro-reflective-ma-normal-mdmi -run/macro-reflective-mamd-normal-mi - -# Using macros, but indirectly creating calls to reflection -run/macro-reify-unreify - -# Using Enumeration in a way we cannot fix - -run/enums.scala -run/t3719.scala -run/t8611b.scala - -# Playing with classfile format - -run/classfile-format-51.scala -run/classfile-format-52.scala - -# Concurrent collections (TrieMap) -# has too much stuff implemented in *.java, so no support -run/triemap-hash.scala - -# Using parallel collections - -run/t5375.scala -run/t4894.scala -run/ctries-new -run/collection-conversions.scala -run/concurrent-map-conversions.scala -run/t4761.scala -run/concurrent-stream.scala -run/t7498.scala -run/t6448.scala -run/ctries-old -run/map_java_conversions.scala -run/parmap-ops.scala -run/pc-conversions.scala -run/t4459.scala -run/t4608.scala -run/t4723.scala -run/t4895.scala -run/t6052.scala -run/t6410.scala -run/t6467.scala -run/t6908.scala - -# Using scala.xml - -run/t4124.scala - -# Using Swing - -run/t3613.scala - -# Using the REPL - -run/t4285.scala -run/constant-type.scala -run/repl-bare-expr.scala -run/repl-parens.scala -run/repl-assign.scala -run/t5583.scala -run/treePrint.scala -run/constrained-types.scala -run/repl-power.scala -run/t4710.scala -run/repl-paste.scala -run/repl-reset.scala -run/repl-paste-3.scala -run/t6329_repl.scala -run/t6273.scala -run/repl-paste-2.scala -run/t5655.scala -run/t5072.scala -run/repl-colon-type.scala -run/kind-repl-command.scala -run/repl-trim-stack-trace.scala -run/t4594-repl-settings.scala -run/repl-save.scala -run/repl-paste-raw.scala -run/repl-paste-4.scala -run/repl-paste-5.scala -run/t7801.scala -run/repl-backticks.scala -run/t6633.scala - -# Using the Repl (scala.tools.partest.ReplTest) -run/class-symbol-contravariant.scala -run/lub-visibility.scala -run/macro-bundle-repl.scala -run/macro-repl-basic.scala -run/macro-repl-dontexpand.scala -run/macro-system-properties.scala -run/reflection-equality.scala -run/reflection-repl-elementary.scala -run/reify_newimpl_26.scala -run/repl-javap-app.scala -run/repl-out-dir.scala -run/repl-term-macros.scala -run/repl-transcript.scala -run/repl-type-verbose.scala -run/t3376.scala -run/t4025.scala -run/t4172.scala -run/t4216.scala -run/t4542.scala -run/t4671.scala -run/t5256d.scala -run/t5535.scala -run/t5537.scala -run/t5789.scala -run/t6086-repl.scala -run/t6146b.scala -run/t6187.scala -run/t6320.scala -run/t6381.scala -run/t6434.scala -run/t6439.scala -run/t6507.scala -run/t6549.scala -run/t6937.scala -run/t7185.scala -run/t7319.scala -run/t7482a.scala -run/t7634.scala -run/t7747-repl.scala -run/t7805-repl-i.scala -run/tpeCache-tyconCache.scala -run/repl-empty-package -run/repl-javap-def.scala -run/repl-javap-fun.scala -run/repl-javap-mem.scala -run/repl-javap-memfun.scala -run/repl-javap-more-fun.scala -run/repl-javap-outdir -run/repl-javap.scala -run/repl-javap-outdir-funs -run/t6329_repl_bug.scala -run/t4950.scala -run/xMigration.scala -run/t6541-option.scala -run/repl-serialization.scala -run/repl-paste-6.scala -run/repl-no-uescape.scala -run/repl-classbased.scala -run/repl-paste-parse.scala - -# Using Scala Script (partest.ScriptTest) - -run/t7711-script-args.scala -run/t4625.scala -run/t4625b.scala -run/t4625c.scala - -# Using the compiler API - -run/t2512.scala -run/analyzerPlugins.scala -run/test-cpp.scala -run/compiler-asSeenFrom.scala -run/t5603.scala -run/t6440.scala -run/t5545.scala -run/existentials-in-compiler.scala -run/global-showdef.scala -run/inline-ex-handlers.scala -run/stream_length.scala -run/annotatedRetyping.scala -run/imain.scala -run/existential-rangepos.scala -run/delambdafy_uncurry_byname_inline.scala -run/delambdafy_uncurry_byname_method.scala -run/delambdafy_uncurry_inline.scala -run/delambdafy_t6555.scala -run/delambdafy_uncurry_method.scala -run/delambdafy_t6028.scala -run/memberpos.scala -run/programmatic-main.scala -run/reflection-names.scala -run/settings-parse.scala -run/sm-interpolator.scala -run/t1501.scala -run/t1500.scala -run/sammy_java8.scala -run/t1618.scala -run/t2464 -run/t4072.scala -run/t5064.scala -run/t5313.scala -run/t5385.scala -run/t5699.scala -run/t5717.scala -run/t5940.scala -run/t6028.scala -run/t6194.scala -run/t6288b-jump-position.scala -run/t6669.scala -run/t6745-2.scala -run/t6955.scala -run/t6956.scala -run/t7096.scala -run/t7271.scala -run/t7337.scala -run/t7398.scala -run/t7569.scala -run/t7852.scala -run/t7817-tree-gen.scala -run/t7825.scala -run/t4426.scala - -# partest.ParserTest -run/t3368.scala -run/t3368-b.scala -run/t3368-c.scala -run/t3368-d.scala - -# partest.DirectTest -run/t6288.scala -run/t6331.scala -run/t6440b.scala -run/t6555.scala -run/t7876.scala -run/typetags_without_scala_reflect_typetag_lookup.scala -run/dynamic-updateDynamic.scala -run/dynamic-selectDynamic.scala -run/dynamic-applyDynamic.scala -run/dynamic-applyDynamicNamed.scala -run/t4841-isolate-plugins -run/large_code.scala -run/macroPlugins-namerHooks.scala -run/t4287inferredMethodTypes.scala -run/t4841-no-plugin.scala -run/t4332.scala -run/t8029.scala -run/t8046 -run/t5905-features.scala -run/t5905b-features.scala -run/large_class.scala -run/t8708_b -run/icode-reader-dead-code.scala -run/t5938.scala -run/t8502.scala -run/t6502.scala -run/t8907.scala -run/t9097.scala -run/macroPlugins-enterStats.scala -run/sbt-icode-interface.scala - -# Using partest.StoreReporterDirectTest -run/t8502b.scala - -# partest.StubErrorMessageTest -run/StubErrorBInheritsFromA.scala -run/StubErrorComplexInnerClass.scala -run/StubErrorHK.scala -run/StubErrorReturnTypeFunction.scala -run/StubErrorReturnTypeFunction2.scala -run/StubErrorReturnTypePolyFunction.scala -run/StubErrorSubclasses.scala -run/StubErrorTypeclass.scala -run/StubErrorTypeDef.scala - -# partest.CompilerTest -run/t8852a.scala - -# partest.BytecodeTest -run/t6546 -run/t7106 -run/t7974 -run/t8601-closure-elim.scala -run/t4788 -run/t4788-separate-compilation -run/t9403 - -# partest.SessionTest -run/t1931.scala -run/t8843-repl-xlat.scala -run/t9206.scala -run/t9170.scala - -# partest.JavapTest -run/t8608-no-format.scala -run/repl-javap-lambdas.scala - -# Using .java source files -run/t4317 -run/t4238 -run/t2296c -run/t4119 -run/t4283 -run/t4891 -run/t6168 -run/t6168b -run/t6240a -run/t6240b -run/t6548 -run/t6989 -run/t7008 -run/t7246 -run/t7246b -run/t7359 -run/t7439 -run/t7455 -run/t7510 -run/t7582-private-within -run/t7582 -run/t7582b -run/t3897 -run/t7374 -run/t3452e -run/t3452g -run/t3452d -run/t3452b-bcode -run/t3452b -run/t3452a -run/t1430 -run/t4729 -run/t8442 -run/t8601e -run/t9298 -run/t9298b -run/t9359 -run/t7741a -run/t7741b -run/bcodeInlinerMixed -run/t9268 -run/t1459 -run/t1459generic -run/t3236 -run/t9013 -run/sd304 - -# Using scalap -run/scalapInvokedynamic.scala - -# Using scala-script -run/t7791-script-linenums.scala - -# Using Manifests (which use Class.getInterfaces) -run/valueclasses-manifest-existential.scala -run/existentials3-old.scala -run/t2236-old.scala -run/interop_manifests_are_classtags.scala -run/valueclasses-manifest-generic.scala -run/valueclasses-manifest-basic.scala -run/t1195-old.scala -run/t3758-old.scala -run/t4110-old.scala -run/t6246.scala - -# Using ScalaRunTime.stringOf -run/value-class-extractor-seq.scala -run/t3493.scala - -# Using Class.forName -run/private-inline.scala - -### Incorrect partests ### - -### Bugs -## Compiler -run/structural.scala -run/t6443.scala -run/t8888.scala -run/t8017 -run/t8601b.scala -run/t8601d.scala - -## JVM compliance -run/t5680.scala -run/t6253a.scala -run/t6253b.scala -run/t6253c.scala -run/try-catch-unify.scala -run/t2755.scala - - -## Fails -run/number-parsing.scala -run/t0325.scala - -## Check not passing -run/delambdafy-dependent-on-param-subst.scala - - -## Not implemented -# Class.superClass -run/delambdafy-specialized.scala - -run/richs.scala diff --git a/scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/neg/t6446-additional.check b/scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/neg/t6446-additional.check deleted file mode 100644 index 38346f9c46..0000000000 --- a/scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/neg/t6446-additional.check +++ /dev/null @@ -1,30 +0,0 @@ - phase name id description - ---------- -- ----------- - parser 1 parse source into ASTs, perform simple desugaring - namer 2 resolve names, attach symbols to named trees -packageobjects 3 load package objects - typer 4 the meat and potatoes: type the trees - nativeinterop 5 prepare ASTs for Native interop - patmat 6 translate match expressions -superaccessors 7 add super accessors in traits and nested classes - extmethods 8 add extension methods for inline classes - pickler 9 serialize symbol tables - refchecks 10 reference/override checking, translate nested objects - uncurry 11 uncurry, translate function values to anonymous classes - tailcalls 12 replace tail calls by jumps - specialize 13 @specialized-driven class and method specialization - explicitouter 14 this refs to outer pointers - erasure 15 erase types, add interfaces for traits - posterasure 16 clean up erased inline classes - lazyvals 17 allocate bitmaps, translate lazy vals into lazified defs - lambdalift 18 move nested functions to top level - constructors 19 move field definitions into constructors - flatten 20 eliminate inner classes - mixin 21 mixin composition - nir 22 - cleanup 23 platform-specific cleanups, generate reflective calls - delambdafy 24 remove lambdas - icode 25 generate portable intermediate code - jvm 26 generate JVM bytecode - ploogin 27 A sample phase that does so many things it's kind of hard... - terminal 28 the last phase during a compilation run diff --git a/scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/neg/t6446-list.check b/scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/neg/t6446-list.check deleted file mode 100644 index eba706333b..0000000000 --- a/scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/neg/t6446-list.check +++ /dev/null @@ -1,2 +0,0 @@ -ploogin - A sample plugin for testing. -nir - Compile to Scala Native IR (NIR) diff --git a/scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/neg/t6446-missing.check b/scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/neg/t6446-missing.check deleted file mode 100644 index 2d31cdf37f..0000000000 --- a/scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/neg/t6446-missing.check +++ /dev/null @@ -1,30 +0,0 @@ -Error: unable to load class: t6446.Ploogin - phase name id description - ---------- -- ----------- - parser 1 parse source into ASTs, perform simple desugaring - namer 2 resolve names, attach symbols to named trees -packageobjects 3 load package objects - typer 4 the meat and potatoes: type the trees - nativeinterop 5 prepare ASTs for Native interop - patmat 6 translate match expressions -superaccessors 7 add super accessors in traits and nested classes - extmethods 8 add extension methods for inline classes - pickler 9 serialize symbol tables - refchecks 10 reference/override checking, translate nested objects - uncurry 11 uncurry, translate function values to anonymous classes - tailcalls 12 replace tail calls by jumps - specialize 13 @specialized-driven class and method specialization - explicitouter 14 this refs to outer pointers - erasure 15 erase types, add interfaces for traits - posterasure 16 clean up erased inline classes - lazyvals 17 allocate bitmaps, translate lazy vals into lazified defs - lambdalift 18 move nested functions to top level - constructors 19 move field definitions into constructors - flatten 20 eliminate inner classes - mixin 21 mixin composition - nir 22 - cleanup 23 platform-specific cleanups, generate reflective calls - delambdafy 24 remove lambdas - icode 25 generate portable intermediate code - jvm 26 generate JVM bytecode - terminal 27 the last phase during a compilation run diff --git a/scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/neg/t6446-show-phases.check b/scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/neg/t6446-show-phases.check deleted file mode 100644 index 62b0afeab2..0000000000 --- a/scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/neg/t6446-show-phases.check +++ /dev/null @@ -1,29 +0,0 @@ - phase name id description - ---------- -- ----------- - parser 1 parse source into ASTs, perform simple desugaring - namer 2 resolve names, attach symbols to named trees -packageobjects 3 load package objects - typer 4 the meat and potatoes: type the trees - nativeinterop 5 prepare ASTs for Native interop - patmat 6 translate match expressions -superaccessors 7 add super accessors in traits and nested classes - extmethods 8 add extension methods for inline classes - pickler 9 serialize symbol tables - refchecks 10 reference/override checking, translate nested objects - uncurry 11 uncurry, translate function values to anonymous classes - tailcalls 12 replace tail calls by jumps - specialize 13 @specialized-driven class and method specialization - explicitouter 14 this refs to outer pointers - erasure 15 erase types, add interfaces for traits - posterasure 16 clean up erased inline classes - lazyvals 17 allocate bitmaps, translate lazy vals into lazified defs - lambdalift 18 move nested functions to top level - constructors 19 move field definitions into constructors - flatten 20 eliminate inner classes - mixin 21 mixin composition - nir 22 - cleanup 23 platform-specific cleanups, generate reflective calls - delambdafy 24 remove lambdas - icode 25 generate portable intermediate code - jvm 26 generate JVM bytecode - terminal 27 the last phase during a compilation run diff --git a/scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/neg/t7494-no-options.check b/scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/neg/t7494-no-options.check deleted file mode 100644 index b69b87ff0f..0000000000 --- a/scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/neg/t7494-no-options.check +++ /dev/null @@ -1,31 +0,0 @@ -error: Error: ploogin takes no options - phase name id description - ---------- -- ----------- - parser 1 parse source into ASTs, perform simple desugaring - namer 2 resolve names, attach symbols to named trees -packageobjects 3 load package objects - typer 4 the meat and potatoes: type the trees - nativeinterop 5 prepare ASTs for Native interop - patmat 6 translate match expressions -superaccessors 7 add super accessors in traits and nested classes - extmethods 8 add extension methods for inline classes - pickler 9 serialize symbol tables - refchecks 10 reference/override checking, translate nested objects - uncurry 11 uncurry, translate function values to anonymous classes - tailcalls 12 replace tail calls by jumps - specialize 13 @specialized-driven class and method specialization - explicitouter 14 this refs to outer pointers - erasure 15 erase types, add interfaces for traits - posterasure 16 clean up erased inline classes - lazyvals 17 allocate bitmaps, translate lazy vals into lazified defs - lambdalift 18 move nested functions to top level - constructors 19 move field definitions into constructors - flatten 20 eliminate inner classes - mixin 21 mixin composition - nir 22 - cleanup 23 platform-specific cleanups, generate reflective calls - delambdafy 24 remove lambdas - icode 25 generate portable intermediate code - jvm 26 generate JVM bytecode - ploogin 27 A sample phase that does so many things it's kind of hard... - terminal 28 the last phase during a compilation run diff --git a/scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/run/classof.check b/scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/run/classof.check deleted file mode 100644 index 21bf4cfb41..0000000000 --- a/scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/run/classof.check +++ /dev/null @@ -1,22 +0,0 @@ -Value types: -class scala.scalanative.runtime.PrimitiveUnit -class scala.scalanative.runtime.PrimitiveBoolean -class scala.scalanative.runtime.PrimitiveByte -class scala.scalanative.runtime.PrimitiveShort -class scala.scalanative.runtime.PrimitiveChar -class scala.scalanative.runtime.PrimitiveInt -class scala.scalanative.runtime.PrimitiveLong -class scala.scalanative.runtime.PrimitiveFloat -class scala.scalanative.runtime.PrimitiveDouble -Class types -class SomeClass -class scala.collection.immutable.List -class scala.Tuple2 -Arrays: -class scala.scalanative.runtime.ObjectArray -class scala.scalanative.runtime.IntArray -class scala.scalanative.runtime.DoubleArray -class scala.scalanative.runtime.ObjectArray -Functions: -interface scala.Function2 -interface scala.Function1 diff --git a/scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/run/classtags_contextbound.check b/scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/run/classtags_contextbound.check deleted file mode 100644 index 5d3106c9bc..0000000000 --- a/scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/run/classtags_contextbound.check +++ /dev/null @@ -1 +0,0 @@ -class scala.scalanative.runtime.IntArray diff --git a/scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/run/classtags_multi.check b/scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/run/classtags_multi.check deleted file mode 100644 index ab1c14e439..0000000000 --- a/scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/run/classtags_multi.check +++ /dev/null @@ -1,5 +0,0 @@ -Int -Array[scala.scalanative.runtime.PrimitiveInt] -Array[java.lang.Object] -Array[java.lang.Object] -Array[java.lang.Object] diff --git a/scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/run/getClassTest-valueClass.check b/scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/run/getClassTest-valueClass.check deleted file mode 100644 index cee2875fff..0000000000 --- a/scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/run/getClassTest-valueClass.check +++ /dev/null @@ -1,2 +0,0 @@ -class scala.scalanative.runtime.PrimitiveInt -class V diff --git a/scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/run/interop_classtags_are_classmanifests.check b/scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/run/interop_classtags_are_classmanifests.check deleted file mode 100644 index 5ef5b7138c..0000000000 --- a/scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/run/interop_classtags_are_classmanifests.check +++ /dev/null @@ -1,3 +0,0 @@ -Int -java.lang.String -Array[scala.scalanative.runtime.PrimitiveInt] diff --git a/scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/run/t4753.check b/scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/run/t4753.check deleted file mode 100644 index 9a020c1ead..0000000000 --- a/scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/run/t4753.check +++ /dev/null @@ -1 +0,0 @@ -class scala.scalanative.runtime.PrimitiveBoolean diff --git a/scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/run/t5568.check b/scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/run/t5568.check deleted file mode 100644 index 0018046644..0000000000 --- a/scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/run/t5568.check +++ /dev/null @@ -1,9 +0,0 @@ -class scala.scalanative.runtime.PrimitiveUnit -class scala.scalanative.runtime.PrimitiveInt -class scala.runtime.BoxedUnit -class scala.runtime.BoxedUnit -class java.lang.Integer -class java.lang.Integer -5 -5 -5 diff --git a/scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/run/t5680.check b/scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/run/t5680.check deleted file mode 100644 index be03d0f79b..0000000000 --- a/scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/run/t5680.check +++ /dev/null @@ -1,3 +0,0 @@ -class scala.scalanative.runtime.ObjectArray -() -() diff --git a/scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/run/t5923b.check b/scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/run/t5923b.check deleted file mode 100644 index a4885c883f..0000000000 --- a/scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/run/t5923b.check +++ /dev/null @@ -1,3 +0,0 @@ -class scala.scalanative.runtime.ObjectArray -class scala.scalanative.runtime.ObjectArray -class scala.scalanative.runtime.ObjectArray diff --git a/scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/run/t6102.check b/scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/run/t6102.check deleted file mode 100644 index 09b77855ae..0000000000 --- a/scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/run/t6102.check +++ /dev/null @@ -1,28 +0,0 @@ -[running phase parser on t6102.scala] -[running phase namer on t6102.scala] -[running phase packageobjects on t6102.scala] -[running phase typer on t6102.scala] -[running phase nativeinterop on t6102.scala] -[running phase patmat on t6102.scala] -[running phase superaccessors on t6102.scala] -[running phase extmethods on t6102.scala] -[running phase pickler on t6102.scala] -[running phase refchecks on t6102.scala] -[running phase uncurry on t6102.scala] -[running phase tailcalls on t6102.scala] -[running phase specialize on t6102.scala] -[running phase explicitouter on t6102.scala] -[running phase erasure on t6102.scala] -[running phase posterasure on t6102.scala] -[running phase lazyvals on t6102.scala] -[running phase lambdalift on t6102.scala] -[running phase constructors on t6102.scala] -[running phase flatten on t6102.scala] -[running phase mixin on t6102.scala] -[running phase nir on t6102.scala] -[running phase cleanup on t6102.scala] -[running phase delambdafy on t6102.scala] -[running phase icode on t6102.scala] -[running phase dce on t6102.scala] -[running phase jvm on icode] -hello diff --git a/scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/run/t6318_primitives.check b/scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/run/t6318_primitives.check deleted file mode 100644 index 1b64e046c7..0000000000 --- a/scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/run/t6318_primitives.check +++ /dev/null @@ -1,54 +0,0 @@ -Checking if class scala.scalanative.runtime.PrimitiveByte matches class scala.scalanative.runtime.PrimitiveByte -Some(1) -Checking if class scala.scalanative.runtime.PrimitiveByte matches class scala.scalanative.runtime.PrimitiveShort -None -Checking if class java.lang.Byte matches class scala.scalanative.runtime.PrimitiveByte -Some(1) -Checking if class scala.scalanative.runtime.PrimitiveShort matches class scala.scalanative.runtime.PrimitiveShort -Some(1) -Checking if class scala.scalanative.runtime.PrimitiveShort matches class scala.scalanative.runtime.PrimitiveChar -None -Checking if class java.lang.Short matches class scala.scalanative.runtime.PrimitiveShort -Some(1) -Checking if class scala.scalanative.runtime.PrimitiveChar matches class scala.scalanative.runtime.PrimitiveChar -Some() -Checking if class scala.scalanative.runtime.PrimitiveChar matches class scala.scalanative.runtime.PrimitiveInt -None -Checking if class java.lang.Character matches class scala.scalanative.runtime.PrimitiveChar -Some() -Checking if class scala.scalanative.runtime.PrimitiveInt matches class scala.scalanative.runtime.PrimitiveInt -Some(1) -Checking if class scala.scalanative.runtime.PrimitiveInt matches class scala.scalanative.runtime.PrimitiveLong -None -Checking if class java.lang.Integer matches class scala.scalanative.runtime.PrimitiveInt -Some(1) -Checking if class scala.scalanative.runtime.PrimitiveLong matches class scala.scalanative.runtime.PrimitiveLong -Some(1) -Checking if class scala.scalanative.runtime.PrimitiveLong matches class scala.scalanative.runtime.PrimitiveFloat -None -Checking if class java.lang.Long matches class scala.scalanative.runtime.PrimitiveLong -Some(1) -Checking if class scala.scalanative.runtime.PrimitiveFloat matches class scala.scalanative.runtime.PrimitiveFloat -Some(1.0) -Checking if class scala.scalanative.runtime.PrimitiveFloat matches class scala.scalanative.runtime.PrimitiveDouble -None -Checking if class java.lang.Float matches class scala.scalanative.runtime.PrimitiveFloat -Some(1.0) -Checking if class scala.scalanative.runtime.PrimitiveDouble matches class scala.scalanative.runtime.PrimitiveDouble -Some(1.0) -Checking if class scala.scalanative.runtime.PrimitiveDouble matches class scala.scalanative.runtime.PrimitiveBoolean -None -Checking if class java.lang.Double matches class scala.scalanative.runtime.PrimitiveDouble -Some(1.0) -Checking if class scala.scalanative.runtime.PrimitiveBoolean matches class scala.scalanative.runtime.PrimitiveBoolean -Some(true) -Checking if class scala.scalanative.runtime.PrimitiveBoolean matches class scala.scalanative.runtime.PrimitiveUnit -None -Checking if class java.lang.Boolean matches class scala.scalanative.runtime.PrimitiveBoolean -Some(true) -Checking if class scala.scalanative.runtime.PrimitiveUnit matches class scala.scalanative.runtime.PrimitiveUnit -Some(()) -Checking if class scala.scalanative.runtime.PrimitiveUnit matches class scala.scalanative.runtime.PrimitiveByte -None -Checking if class scala.scalanative.runtime.BoxedUnit$ matches class scala.scalanative.runtime.PrimitiveUnit -Some(()) diff --git a/scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/run/t8764.check b/scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/run/t8764.check deleted file mode 100644 index c4d72004e0..0000000000 --- a/scala-partest-tests/src/test/resources/scala/tools/partest/scalanative/2.11.12/run/t8764.check +++ /dev/null @@ -1,5 +0,0 @@ -IntOnly: should return an unboxed int -Int: class scala.scalanative.runtime.PrimitiveInt -IntAndDouble: should just box and return Anyval -Double: class java.lang.Double -Int: class java.lang.Integer diff --git a/scalalib/overrides-2.11/scala/Array.scala.patch b/scalalib/overrides-2.11/scala/Array.scala.patch deleted file mode 100644 index e1b8433972..0000000000 --- a/scalalib/overrides-2.11/scala/Array.scala.patch +++ /dev/null @@ -1,237 +0,0 @@ ---- 2.11.12/scala/Array.scala -+++ overrides-2.11/scala/Array.scala -@@ -14,6 +14,7 @@ - import scala.compat.Platform.arraycopy - import scala.reflect.ClassTag - import scala.runtime.ScalaRunTime.{ array_apply, array_update } -+import scala.collection.mutable.WrappedArray - - /** Contains a fallback builder for arrays when the element type - * does not have a class tag. In that case a generic array is built. -@@ -48,15 +49,15 @@ - * @version 1.0 - */ - object Array extends FallbackArrayBuilding { -- val emptyBooleanArray = new Array[Boolean](0) -- val emptyByteArray = new Array[Byte](0) -- val emptyCharArray = new Array[Char](0) -- val emptyDoubleArray = new Array[Double](0) -- val emptyFloatArray = new Array[Float](0) -- val emptyIntArray = new Array[Int](0) -- val emptyLongArray = new Array[Long](0) -- val emptyShortArray = new Array[Short](0) -- val emptyObjectArray = new Array[Object](0) -+ @inline def emptyBooleanArray = new Array[Boolean](0) -+ @inline def emptyByteArray = new Array[Byte](0) -+ @inline def emptyCharArray = new Array[Char](0) -+ @inline def emptyDoubleArray = new Array[Double](0) -+ @inline def emptyFloatArray = new Array[Float](0) -+ @inline def emptyIntArray = new Array[Int](0) -+ @inline def emptyLongArray = new Array[Long](0) -+ @inline def emptyShortArray = new Array[Short](0) -+ @inline def emptyObjectArray = new Array[Object](0) - - implicit def canBuildFrom[T](implicit t: ClassTag[T]): CanBuildFrom[Array[_], T, Array[T]] = - new CanBuildFrom[Array[_], T, Array[T]] { -@@ -117,11 +118,52 @@ - */ - // Subject to a compiler optimization in Cleanup. - // Array(e0, ..., en) is translated to { val a = new Array(3); a(i) = ei; a } -- def apply[T: ClassTag](xs: T*): Array[T] = { -- val array = new Array[T](xs.length) -- var i = 0 -- for (x <- xs.iterator) { array(i) = x; i += 1 } -- array -+ def apply[T: ClassTag](xs: T*): Array[T] = xs match { -+ case xs: WrappedArray.ofBoolean => -+ val from = xs.array -+ val array = new Array[Boolean](from.length) -+ System.arraycopy(from, 0, array, 0, from.length) -+ array.asInstanceOf[Array[T]] -+ case xs: WrappedArray.ofByte => -+ val from = xs.array -+ val array = new Array[Byte](from.length) -+ System.arraycopy(from, 0, array, 0, from.length) -+ array.asInstanceOf[Array[T]] -+ case xs: WrappedArray.ofShort => -+ val from = xs.array -+ val array = new Array[Short](from.length) -+ System.arraycopy(from, 0, array, 0, from.length) -+ array.asInstanceOf[Array[T]] -+ case xs: WrappedArray.ofChar => -+ val from = xs.array -+ val array = new Array[Char](from.length) -+ System.arraycopy(from, 0, array, 0, from.length) -+ array.asInstanceOf[Array[T]] -+ case xs: WrappedArray.ofInt => -+ val from = xs.array -+ val array = new Array[Int](from.length) -+ System.arraycopy(from, 0, array, 0, from.length) -+ array.asInstanceOf[Array[T]] -+ case xs: WrappedArray.ofLong => -+ val from = xs.array -+ val array = new Array[Long](from.length) -+ System.arraycopy(from, 0, array, 0, from.length) -+ array.asInstanceOf[Array[T]] -+ case xs: WrappedArray.ofFloat => -+ val from = xs.array -+ val array = new Array[Float](from.length) -+ System.arraycopy(from, 0, array, 0, from.length) -+ array.asInstanceOf[Array[T]] -+ case xs: WrappedArray.ofDouble => -+ val from = xs.array -+ val array = new Array[Double](from.length) -+ System.arraycopy(from, 0, array, 0, from.length) -+ array.asInstanceOf[Array[T]] -+ case xs => -+ val array = new Array[T](xs.length) -+ var i = 0 -+ for (x <- xs.iterator) { array(i) = x; i += 1 } -+ array - } - - /** Creates an array of `Boolean` objects */ -@@ -129,8 +171,13 @@ - def apply(x: Boolean, xs: Boolean*): Array[Boolean] = { - val array = new Array[Boolean](xs.length + 1) - array(0) = x -- var i = 1 -- for (x <- xs.iterator) { array(i) = x; i += 1 } -+ xs match { -+ case xs: WrappedArray.ofBoolean => -+ System.arraycopy(xs.array, 0, array, 1, xs.array.length) -+ case xs => -+ var i = 1 -+ for (x <- xs.iterator) { array(i) = x; i += 1 } -+ } - array - } - -@@ -139,8 +186,13 @@ - def apply(x: Byte, xs: Byte*): Array[Byte] = { - val array = new Array[Byte](xs.length + 1) - array(0) = x -- var i = 1 -- for (x <- xs.iterator) { array(i) = x; i += 1 } -+ xs match { -+ case xs: WrappedArray.ofByte => -+ System.arraycopy(xs.array, 0, array, 1, xs.array.length) -+ case xs => -+ var i = 1 -+ for (x <- xs.iterator) { array(i) = x; i += 1 } -+ } - array - } - -@@ -149,8 +201,13 @@ - def apply(x: Short, xs: Short*): Array[Short] = { - val array = new Array[Short](xs.length + 1) - array(0) = x -- var i = 1 -- for (x <- xs.iterator) { array(i) = x; i += 1 } -+ xs match { -+ case xs: WrappedArray.ofShort => -+ System.arraycopy(xs.array, 0, array, 1, xs.array.length) -+ case xs => -+ var i = 1 -+ for (x <- xs.iterator) { array(i) = x; i += 1 } -+ } - array - } - -@@ -159,8 +216,13 @@ - def apply(x: Char, xs: Char*): Array[Char] = { - val array = new Array[Char](xs.length + 1) - array(0) = x -- var i = 1 -- for (x <- xs.iterator) { array(i) = x; i += 1 } -+ xs match { -+ case xs: WrappedArray.ofChar => -+ System.arraycopy(xs.array, 0, array, 1, xs.array.length) -+ case xs => -+ var i = 1 -+ for (x <- xs.iterator) { array(i) = x; i += 1 } -+ } - array - } - -@@ -169,8 +231,13 @@ - def apply(x: Int, xs: Int*): Array[Int] = { - val array = new Array[Int](xs.length + 1) - array(0) = x -- var i = 1 -- for (x <- xs.iterator) { array(i) = x; i += 1 } -+ xs match { -+ case xs: WrappedArray.ofInt => -+ System.arraycopy(xs.array, 0, array, 1, xs.array.length) -+ case xs => -+ var i = 1 -+ for (x <- xs.iterator) { array(i) = x; i += 1 } -+ } - array - } - -@@ -179,8 +246,13 @@ - def apply(x: Long, xs: Long*): Array[Long] = { - val array = new Array[Long](xs.length + 1) - array(0) = x -- var i = 1 -- for (x <- xs.iterator) { array(i) = x; i += 1 } -+ xs match { -+ case xs: WrappedArray.ofLong => -+ System.arraycopy(xs.array, 0, array, 1, xs.array.length) -+ case xs => -+ var i = 1 -+ for (x <- xs.iterator) { array(i) = x; i += 1 } -+ } - array - } - -@@ -189,8 +261,13 @@ - def apply(x: Float, xs: Float*): Array[Float] = { - val array = new Array[Float](xs.length + 1) - array(0) = x -- var i = 1 -- for (x <- xs.iterator) { array(i) = x; i += 1 } -+ xs match { -+ case xs: WrappedArray.ofFloat => -+ System.arraycopy(xs.array, 0, array, 1, xs.array.length) -+ case xs => -+ var i = 1 -+ for (x <- xs.iterator) { array(i) = x; i += 1 } -+ } - array - } - -@@ -199,8 +276,13 @@ - def apply(x: Double, xs: Double*): Array[Double] = { - val array = new Array[Double](xs.length + 1) - array(0) = x -- var i = 1 -- for (x <- xs.iterator) { array(i) = x; i += 1 } -+ xs match { -+ case xs: WrappedArray.ofDouble => -+ System.arraycopy(xs.array, 0, array, 1, xs.array.length) -+ case xs => -+ var i = 1 -+ for (x <- xs.iterator) { array(i) = x; i += 1 } -+ } - array - } - -@@ -208,8 +290,13 @@ - def apply(x: Unit, xs: Unit*): Array[Unit] = { - val array = new Array[Unit](xs.length + 1) - array(0) = x -- var i = 1 -- for (x <- xs.iterator) { array(i) = x; i += 1 } -+ xs match { -+ case xs: WrappedArray.ofUnit => -+ System.arraycopy(xs.array, 0, array, 1, xs.array.length) -+ case xs => -+ var i = 1 -+ for (x <- xs.iterator) { array(i) = x; i += 1 } -+ } - array - } - diff --git a/scalalib/overrides-2.11/scala/Predef.scala.patch b/scalalib/overrides-2.11/scala/Predef.scala.patch deleted file mode 100644 index 88d96d5845..0000000000 --- a/scalalib/overrides-2.11/scala/Predef.scala.patch +++ /dev/null @@ -1,285 +0,0 @@ ---- 2.11.12/scala/Predef.scala -+++ overrides-2.11/scala/Predef.scala -@@ -16,6 +16,7 @@ - import scala.annotation.elidable.ASSERTION - import scala.language.{implicitConversions, existentials} - import scala.io.StdIn -+import scala.scalanative.annotation.alwaysinline - - /** The `Predef` object provides definitions that are accessible in all Scala - * compilation units without explicit qualification. -@@ -98,8 +99,8 @@ - - type Map[A, +B] = immutable.Map[A, B] - type Set[A] = immutable.Set[A] -- val Map = immutable.Map -- val Set = immutable.Set -+ @inline def Map = immutable.Map -+ @inline def Set = immutable.Set - - // Manifest types, companions, and incantations for summoning - @annotation.implicitNotFound(msg = "No ClassManifest available for ${T}.") -@@ -113,26 +114,26 @@ - // @deprecated("Use `scala.reflect.ClassTag` (to capture erasures) or scala.reflect.runtime.universe.TypeTag (to capture types) or both instead", "2.10.0") - type Manifest[T] = scala.reflect.Manifest[T] - @deprecated("Use `scala.reflect.ClassTag` instead", "2.10.0") -- val ClassManifest = scala.reflect.ClassManifest -+ @inline def ClassManifest = scala.reflect.ClassManifest - // TODO undeprecated until Scala reflection becomes non-experimental - // @deprecated("Use `scala.reflect.ClassTag` (to capture erasures) or scala.reflect.runtime.universe.TypeTag (to capture types) or both instead", "2.10.0") -- val Manifest = scala.reflect.Manifest -+ @inline def Manifest = scala.reflect.Manifest - // TODO undeprecated until Scala reflection becomes non-experimental - // @deprecated("This notion doesn't have a corresponding concept in 2.10, because scala.reflect.runtime.universe.TypeTag can capture arbitrary types. Use type tags instead of manifests, and there will be no need in opt manifests.", "2.10.0") -- val NoManifest = scala.reflect.NoManifest -+ @inline def NoManifest = scala.reflect.NoManifest - - // TODO undeprecated until Scala reflection becomes non-experimental - // @deprecated("Use scala.reflect.classTag[T] and scala.reflect.runtime.universe.typeTag[T] instead", "2.10.0") -- def manifest[T](implicit m: Manifest[T]) = m -+ @inline def manifest[T](implicit m: Manifest[T]) = m - @deprecated("Use scala.reflect.classTag[T] instead", "2.10.0") -- def classManifest[T](implicit m: ClassManifest[T]) = m -+ @inline def classManifest[T](implicit m: ClassManifest[T]) = m - // TODO undeprecated until Scala reflection becomes non-experimental - // @deprecated("This notion doesn't have a corresponding concept in 2.10, because scala.reflect.runtime.universe.TypeTag can capture arbitrary types. Use type tags instead of manifests, and there will be no need in opt manifests.", "2.10.0") -- def optManifest[T](implicit m: OptManifest[T]) = m -+ @inline def optManifest[T](implicit m: OptManifest[T]) = m - - // Minor variations on identity functions -- def identity[A](x: A): A = x // @see `conforms` for the implicit version -- @inline def implicitly[T](implicit e: T) = e // for summoning implicit values from the nether world -- TODO: when dependent method types are on by default, give this result type `e.type`, so that inliner has better chance of knowing which method to inline in calls like `implicitly[MatchingStrategy[Option]].zero` -+ @inline def identity[A](x: A): A = x // @see `conforms` for the implicit version -+ @alwaysinline def implicitly[T](implicit e: T) = e // for summoning implicit values from the nether world -- TODO: when dependent method types are on by default, give this result type `e.type`, so that inliner has better chance of knowing which method to inline in calls like `implicitly[MatchingStrategy[Option]].zero` - @inline def locally[T](x: T): T = x // to communicate intent and avoid unmoored statements - - // errors and asserts ------------------------------------------------- -@@ -141,7 +142,7 @@ - // We are stuck with it a while longer because sbt's compiler interface - // still calls it as of 0.12.2. - @deprecated("Use `sys.error(message)` instead", "2.9.0") -- def error(message: String): Nothing = sys.error(message) -+ @inline def error(message: String): Nothing = sys.error(message) - - /** Tests an expression, throwing an `AssertionError` if false. - * Calls to this method will not be generated if `-Xelide-below` -@@ -151,7 +152,7 @@ - * @param assertion the expression to test - */ - @elidable(ASSERTION) -- def assert(assertion: Boolean) { -+ @inline def assert(assertion: Boolean) { - if (!assertion) - throw new java.lang.AssertionError("assertion failed") - } -@@ -180,7 +181,7 @@ - * @param assumption the expression to test - */ - @elidable(ASSERTION) -- def assume(assumption: Boolean) { -+ @inline def assume(assumption: Boolean) { - if (!assumption) - throw new java.lang.AssertionError("assumption failed") - } -@@ -207,7 +208,7 @@ - * - * @param requirement the expression to test - */ -- def require(requirement: Boolean) { -+ @inline def require(requirement: Boolean) { - if (!requirement) - throw new IllegalArgumentException("requirement failed") - } -@@ -227,7 +228,7 @@ - /** `???` can be used for marking methods that remain to be implemented. - * @throws NotImplementedError - */ -- def ??? : Nothing = throw new NotImplementedError -+ @inline def ??? : Nothing = throw new NotImplementedError - - // tupling ------------------------------------------------------------ - -@@ -300,27 +301,29 @@ - override def toString = __arrayOfChars mkString "" - } - -- implicit val StringCanBuildFrom: CanBuildFrom[String, Char, String] = new CanBuildFrom[String, Char, String] { -+ private object StringCanBuildFromInstance extends CanBuildFrom[String, Char, String] { - def apply(from: String) = apply() - def apply() = mutable.StringBuilder.newBuilder - } - -+ @inline implicit def StringCanBuildFrom: CanBuildFrom[String, Char, String] = StringCanBuildFromInstance -+ - @inline implicit def augmentString(x: String): StringOps = new StringOps(x) - @inline implicit def unaugmentString(x: StringOps): String = x.repr - - // printing ----------------------------------------------------------- - -- def print(x: Any) = Console.print(x) -- def println() = Console.println() -- def println(x: Any) = Console.println(x) -- def printf(text: String, xs: Any*) = Console.print(text.format(xs: _*)) -+ @inline def print(x: Any) = Console.print(x) -+ @inline def println() = Console.println() -+ @inline def println(x: Any) = Console.println(x) -+ @inline def printf(text: String, xs: Any*) = Console.print(text.format(xs: _*)) - - // views -------------------------------------------------------------- - -- implicit def tuple2ToZippedOps[T1, T2](x: (T1, T2)) = new runtime.Tuple2Zipped.Ops(x) -- implicit def tuple3ToZippedOps[T1, T2, T3](x: (T1, T2, T3)) = new runtime.Tuple3Zipped.Ops(x) -+ @inline implicit def tuple2ToZippedOps[T1, T2](x: (T1, T2)) = new runtime.Tuple2Zipped.Ops(x) -+ @inline implicit def tuple3ToZippedOps[T1, T2, T3](x: (T1, T2, T3)) = new runtime.Tuple3Zipped.Ops(x) - -- implicit def genericArrayOps[T](xs: Array[T]): ArrayOps[T] = (xs match { -+ @inline implicit def genericArrayOps[T](xs: Array[T]): ArrayOps[T] = (xs match { - case x: Array[AnyRef] => refArrayOps[AnyRef](x) - case x: Array[Boolean] => booleanArrayOps(x) - case x: Array[Byte] => byteArrayOps(x) -@@ -334,36 +337,36 @@ - case null => null - }).asInstanceOf[ArrayOps[T]] - -- implicit def booleanArrayOps(xs: Array[Boolean]): ArrayOps[Boolean] = new ArrayOps.ofBoolean(xs) -- implicit def byteArrayOps(xs: Array[Byte]): ArrayOps[Byte] = new ArrayOps.ofByte(xs) -- implicit def charArrayOps(xs: Array[Char]): ArrayOps[Char] = new ArrayOps.ofChar(xs) -- implicit def doubleArrayOps(xs: Array[Double]): ArrayOps[Double] = new ArrayOps.ofDouble(xs) -- implicit def floatArrayOps(xs: Array[Float]): ArrayOps[Float] = new ArrayOps.ofFloat(xs) -- implicit def intArrayOps(xs: Array[Int]): ArrayOps[Int] = new ArrayOps.ofInt(xs) -- implicit def longArrayOps(xs: Array[Long]): ArrayOps[Long] = new ArrayOps.ofLong(xs) -- implicit def refArrayOps[T <: AnyRef](xs: Array[T]): ArrayOps[T] = new ArrayOps.ofRef[T](xs) -- implicit def shortArrayOps(xs: Array[Short]): ArrayOps[Short] = new ArrayOps.ofShort(xs) -- implicit def unitArrayOps(xs: Array[Unit]): ArrayOps[Unit] = new ArrayOps.ofUnit(xs) -+ @inline implicit def booleanArrayOps(xs: Array[Boolean]): ArrayOps[Boolean] = new ArrayOps.ofBoolean(xs) -+ @inline implicit def byteArrayOps(xs: Array[Byte]): ArrayOps[Byte] = new ArrayOps.ofByte(xs) -+ @inline implicit def charArrayOps(xs: Array[Char]): ArrayOps[Char] = new ArrayOps.ofChar(xs) -+ @inline implicit def doubleArrayOps(xs: Array[Double]): ArrayOps[Double] = new ArrayOps.ofDouble(xs) -+ @inline implicit def floatArrayOps(xs: Array[Float]): ArrayOps[Float] = new ArrayOps.ofFloat(xs) -+ @inline implicit def intArrayOps(xs: Array[Int]): ArrayOps[Int] = new ArrayOps.ofInt(xs) -+ @inline implicit def longArrayOps(xs: Array[Long]): ArrayOps[Long] = new ArrayOps.ofLong(xs) -+ @inline implicit def refArrayOps[T <: AnyRef](xs: Array[T]): ArrayOps[T] = new ArrayOps.ofRef[T](xs) -+ @inline implicit def shortArrayOps(xs: Array[Short]): ArrayOps[Short] = new ArrayOps.ofShort(xs) -+ @inline implicit def unitArrayOps(xs: Array[Unit]): ArrayOps[Unit] = new ArrayOps.ofUnit(xs) - - // "Autoboxing" and "Autounboxing" --------------------------------------------------- - -- implicit def byte2Byte(x: Byte) = java.lang.Byte.valueOf(x) -- implicit def short2Short(x: Short) = java.lang.Short.valueOf(x) -- implicit def char2Character(x: Char) = java.lang.Character.valueOf(x) -- implicit def int2Integer(x: Int) = java.lang.Integer.valueOf(x) -- implicit def long2Long(x: Long) = java.lang.Long.valueOf(x) -- implicit def float2Float(x: Float) = java.lang.Float.valueOf(x) -- implicit def double2Double(x: Double) = java.lang.Double.valueOf(x) -- implicit def boolean2Boolean(x: Boolean) = java.lang.Boolean.valueOf(x) -+ @inline implicit def byte2Byte(x: Byte) = java.lang.Byte.valueOf(x) -+ @inline implicit def short2Short(x: Short) = java.lang.Short.valueOf(x) -+ @inline implicit def char2Character(x: Char) = java.lang.Character.valueOf(x) -+ @inline implicit def int2Integer(x: Int) = java.lang.Integer.valueOf(x) -+ @inline implicit def long2Long(x: Long) = java.lang.Long.valueOf(x) -+ @inline implicit def float2Float(x: Float) = java.lang.Float.valueOf(x) -+ @inline implicit def double2Double(x: Double) = java.lang.Double.valueOf(x) -+ @inline implicit def boolean2Boolean(x: Boolean) = java.lang.Boolean.valueOf(x) - -- implicit def Byte2byte(x: java.lang.Byte): Byte = x.byteValue -- implicit def Short2short(x: java.lang.Short): Short = x.shortValue -- implicit def Character2char(x: java.lang.Character): Char = x.charValue -- implicit def Integer2int(x: java.lang.Integer): Int = x.intValue -- implicit def Long2long(x: java.lang.Long): Long = x.longValue -- implicit def Float2float(x: java.lang.Float): Float = x.floatValue -- implicit def Double2double(x: java.lang.Double): Double = x.doubleValue -- implicit def Boolean2boolean(x: java.lang.Boolean): Boolean = x.booleanValue -+ @inline implicit def Byte2byte(x: java.lang.Byte): Byte = x.byteValue -+ @inline implicit def Short2short(x: java.lang.Short): Short = x.shortValue -+ @inline implicit def Character2char(x: java.lang.Character): Char = x.charValue -+ @inline implicit def Integer2int(x: java.lang.Integer): Int = x.intValue -+ @inline implicit def Long2long(x: java.lang.Long): Long = x.longValue -+ @inline implicit def Float2float(x: java.lang.Float): Float = x.floatValue -+ @inline implicit def Double2double(x: java.lang.Double): Double = x.doubleValue -+ @inline implicit def Boolean2boolean(x: java.lang.Boolean): Boolean = x.booleanValue - - // Type Constraints -------------------------------------------------------------- - -@@ -386,11 +389,11 @@ - */ - @implicitNotFound(msg = "Cannot prove that ${From} <:< ${To}.") - sealed abstract class <:<[-From, +To] extends (From => To) with Serializable -- private[this] final val singleton_<:< = new <:<[Any,Any] { def apply(x: Any): Any = x } -+ private[this] final lazy val singleton_<:< = new <:<[Any,Any] { def apply(x: Any): Any = x } - // The dollar prefix is to dodge accidental shadowing of this method - // by a user-defined method of the same name (SI-7788). - // The collections rely on this method. -- implicit def $conforms[A]: A <:< A = singleton_<:<.asInstanceOf[A <:< A] -+ @inline implicit def $conforms[A]: A <:< A = singleton_<:<.asInstanceOf[A <:< A] - - @deprecated("Use `implicitly[T <:< U]` or `identity` instead.", "2.11.0") - def conforms[A]: A <:< A = $conforms[A] -@@ -401,9 +404,9 @@ - */ - @implicitNotFound(msg = "Cannot prove that ${From} =:= ${To}.") - sealed abstract class =:=[From, To] extends (From => To) with Serializable -- private[this] final val singleton_=:= = new =:=[Any,Any] { def apply(x: Any): Any = x } -+ private[this] final lazy val singleton_=:= = new =:=[Any,Any] { def apply(x: Any): Any = x } - object =:= { -- implicit def tpEquals[A]: A =:= A = singleton_=:=.asInstanceOf[A =:= A] -+ @inline implicit def tpEquals[A]: A =:= A = singleton_=:=.asInstanceOf[A =:= A] - } - - /** A type for which there is always an implicit value. -@@ -416,7 +419,7 @@ - /** An implicit value yielding a `DummyImplicit`. - * @see [[scala.Array$]], method `fallbackCanBuildFrom` - */ -- implicit def dummyImplicit: DummyImplicit = new DummyImplicit -+ @inline implicit def dummyImplicit: DummyImplicit = new DummyImplicit - } - } - -@@ -481,33 +484,33 @@ - @inline implicit def doubleWrapper(x: Double) = new runtime.RichDouble(x) - @inline implicit def booleanWrapper(x: Boolean) = new runtime.RichBoolean(x) - -- implicit def genericWrapArray[T](xs: Array[T]): WrappedArray[T] = -+ @inline implicit def genericWrapArray[T](xs: Array[T]): WrappedArray[T] = - if (xs eq null) null - else WrappedArray.make(xs) - - // Since the JVM thinks arrays are covariant, one 0-length Array[AnyRef] - // is as good as another for all T <: AnyRef. Instead of creating 100,000,000 - // unique ones by way of this implicit, let's share one. -- implicit def wrapRefArray[T <: AnyRef](xs: Array[T]): WrappedArray[T] = { -+ @inline implicit def wrapRefArray[T <: AnyRef](xs: Array[T]): WrappedArray[T] = { - if (xs eq null) null - else if (xs.length == 0) WrappedArray.empty[T] - else new WrappedArray.ofRef[T](xs) - } - -- implicit def wrapIntArray(xs: Array[Int]): WrappedArray[Int] = if (xs ne null) new WrappedArray.ofInt(xs) else null -- implicit def wrapDoubleArray(xs: Array[Double]): WrappedArray[Double] = if (xs ne null) new WrappedArray.ofDouble(xs) else null -- implicit def wrapLongArray(xs: Array[Long]): WrappedArray[Long] = if (xs ne null) new WrappedArray.ofLong(xs) else null -- implicit def wrapFloatArray(xs: Array[Float]): WrappedArray[Float] = if (xs ne null) new WrappedArray.ofFloat(xs) else null -- implicit def wrapCharArray(xs: Array[Char]): WrappedArray[Char] = if (xs ne null) new WrappedArray.ofChar(xs) else null -- implicit def wrapByteArray(xs: Array[Byte]): WrappedArray[Byte] = if (xs ne null) new WrappedArray.ofByte(xs) else null -- implicit def wrapShortArray(xs: Array[Short]): WrappedArray[Short] = if (xs ne null) new WrappedArray.ofShort(xs) else null -- implicit def wrapBooleanArray(xs: Array[Boolean]): WrappedArray[Boolean] = if (xs ne null) new WrappedArray.ofBoolean(xs) else null -- implicit def wrapUnitArray(xs: Array[Unit]): WrappedArray[Unit] = if (xs ne null) new WrappedArray.ofUnit(xs) else null -+ @inline implicit def wrapIntArray(xs: Array[Int]): WrappedArray[Int] = if (xs ne null) new WrappedArray.ofInt(xs) else null -+ @inline implicit def wrapDoubleArray(xs: Array[Double]): WrappedArray[Double] = if (xs ne null) new WrappedArray.ofDouble(xs) else null -+ @inline implicit def wrapLongArray(xs: Array[Long]): WrappedArray[Long] = if (xs ne null) new WrappedArray.ofLong(xs) else null -+ @inline implicit def wrapFloatArray(xs: Array[Float]): WrappedArray[Float] = if (xs ne null) new WrappedArray.ofFloat(xs) else null -+ @inline implicit def wrapCharArray(xs: Array[Char]): WrappedArray[Char] = if (xs ne null) new WrappedArray.ofChar(xs) else null -+ @inline implicit def wrapByteArray(xs: Array[Byte]): WrappedArray[Byte] = if (xs ne null) new WrappedArray.ofByte(xs) else null -+ @inline implicit def wrapShortArray(xs: Array[Short]): WrappedArray[Short] = if (xs ne null) new WrappedArray.ofShort(xs) else null -+ @inline implicit def wrapBooleanArray(xs: Array[Boolean]): WrappedArray[Boolean] = if (xs ne null) new WrappedArray.ofBoolean(xs) else null -+ @inline implicit def wrapUnitArray(xs: Array[Unit]): WrappedArray[Unit] = if (xs ne null) new WrappedArray.ofUnit(xs) else null - -- implicit def wrapString(s: String): WrappedString = if (s ne null) new WrappedString(s) else null -- implicit def unwrapString(ws: WrappedString): String = if (ws ne null) ws.self else null -+ @inline implicit def wrapString(s: String): WrappedString = if (s ne null) new WrappedString(s) else null -+ @inline implicit def unwrapString(ws: WrappedString): String = if (ws ne null) ws.self else null - -- implicit def fallbackStringCanBuildFrom[T]: CanBuildFrom[String, T, immutable.IndexedSeq[T]] = -+ @inline implicit def fallbackStringCanBuildFrom[T]: CanBuildFrom[String, T, immutable.IndexedSeq[T]] = - new CanBuildFrom[String, T, immutable.IndexedSeq[T]] { - def apply(from: String) = immutable.IndexedSeq.newBuilder[T] - def apply() = immutable.IndexedSeq.newBuilder[T] diff --git a/scalalib/overrides-2.11/scala/collection/immutable/Set.scala.patch b/scalalib/overrides-2.11/scala/collection/immutable/Set.scala.patch deleted file mode 100644 index dd1d30d476..0000000000 --- a/scalalib/overrides-2.11/scala/collection/immutable/Set.scala.patch +++ /dev/null @@ -1,14 +0,0 @@ ---- 2.11.12/scala/collection/immutable/Set.scala -+++ overrides-2.11/scala/collection/immutable/Set.scala -@@ -61,8 +61,10 @@ - * @define coll immutable set - */ - object Set extends ImmutableSetFactory[Set] { -+ private[this] val ReusableCBF = setCanBuildFrom[Any] - /** $setCanBuildFromInfo */ -- implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, Set[A]] = setCanBuildFrom[A] -+ @inline implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, Set[A]] = ReusableCBF.asInstanceOf[CanBuildFrom[Coll, A, Set[A]]] -+ @inline override def empty[A]: Set[A] = EmptySet.asInstanceOf[Set[A]] - - /** An optimized representation for immutable empty sets */ - private object EmptySet extends AbstractSet[Any] with Set[Any] with Serializable { diff --git a/scalalib/overrides-2.11/scala/collection/immutable/Stream.scala.patch b/scalalib/overrides-2.11/scala/collection/immutable/Stream.scala.patch deleted file mode 100644 index bc8cbf08da..0000000000 --- a/scalalib/overrides-2.11/scala/collection/immutable/Stream.scala.patch +++ /dev/null @@ -1,33 +0,0 @@ ---- 2.11.12/scala/collection/immutable/Stream.scala -+++ overrides-2.11/scala/collection/immutable/Stream.scala -@@ -1147,10 +1147,15 @@ - */ - class StreamCanBuildFrom[A] extends GenericCanBuildFrom[A] - -- implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, Stream[A]] = new StreamCanBuildFrom[A] -+ @inline override def ReusableCBF: GenericCanBuildFrom[Nothing] = ReusableCBFInstance -+ private object ReusableCBFInstance extends GenericCanBuildFrom[Nothing] { -+ @inline override def apply() = newBuilder[Nothing] -+ } - -+ @inline implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, Stream[A]] = new StreamCanBuildFrom[A] -+ - /** Creates a new builder for a stream */ -- def newBuilder[A]: Builder[A, Stream[A]] = new StreamBuilder[A] -+ @inline def newBuilder[A]: Builder[A, Stream[A]] = new StreamBuilder[A] - - import scala.collection.{Iterable, Seq, IndexedSeq} - -@@ -1171,10 +1176,10 @@ - } - - /** The empty stream */ -- override def empty[A]: Stream[A] = Empty -+ @inline override def empty[A]: Stream[A] = Empty - - /** A stream consisting of given elements */ -- override def apply[A](xs: A*): Stream[A] = xs.toStream -+ @inline override def apply[A](xs: A*): Stream[A] = xs.toStream - - /** A wrapper class that adds `#::` for cons and `#:::` for concat as operations - * to streams. diff --git a/scalalib/overrides-2.11/scala/collection/mutable/DoubleLinkedList.scala.patch b/scalalib/overrides-2.11/scala/collection/mutable/DoubleLinkedList.scala.patch deleted file mode 100644 index 71aea0e886..0000000000 --- a/scalalib/overrides-2.11/scala/collection/mutable/DoubleLinkedList.scala.patch +++ /dev/null @@ -1,14 +0,0 @@ ---- 2.11.12/scala/collection/mutable/DoubleLinkedList.scala -+++ overrides-2.11/scala/collection/mutable/DoubleLinkedList.scala -@@ -81,9 +81,9 @@ - @deprecated("Low-level linked lists are deprecated.", "2.11.0") - object DoubleLinkedList extends SeqFactory[DoubleLinkedList] { - /** $genericCanBuildFromInfo */ -- implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, DoubleLinkedList[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]] -+ @inline implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, DoubleLinkedList[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]] - -- def newBuilder[A]: Builder[A, DoubleLinkedList[A]] = -+ @inline def newBuilder[A]: Builder[A, DoubleLinkedList[A]] = - new Builder[A, DoubleLinkedList[A]] { - def emptyList() = new DoubleLinkedList[A]() - var current = emptyList() diff --git a/scalalib/overrides-2.11/scala/collection/mutable/LinkedList.scala.patch b/scalalib/overrides-2.11/scala/collection/mutable/LinkedList.scala.patch deleted file mode 100644 index 6a268ce9e6..0000000000 --- a/scalalib/overrides-2.11/scala/collection/mutable/LinkedList.scala.patch +++ /dev/null @@ -1,20 +0,0 @@ ---- 2.11.12/scala/collection/mutable/LinkedList.scala -+++ overrides-2.11/scala/collection/mutable/LinkedList.scala -@@ -116,9 +116,14 @@ - */ - @deprecated("Low-level linked lists are deprecated.", "2.11.0") - object LinkedList extends SeqFactory[LinkedList] { -- override def empty[A]: LinkedList[A] = new LinkedList[A] -- implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, LinkedList[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]] -+ @inline override def ReusableCBF: GenericCanBuildFrom[Nothing] = ReusableCBFInstance -+ private object ReusableCBFInstance extends GenericCanBuildFrom[Nothing] { -+ @inline override def apply() = newBuilder[Nothing] -+ } - -- def newBuilder[A]: Builder[A, LinkedList[A]] = -+ @inline override def empty[A]: LinkedList[A] = new LinkedList[A] -+ @inline implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, LinkedList[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]] -+ -+ @inline def newBuilder[A]: Builder[A, LinkedList[A]] = - (new MutableList) mapResult ((l: MutableList[A]) => l.toLinkedList) - } diff --git a/scalalib/overrides-2.11/scala/collection/mutable/StringBuilder.scala.patch b/scalalib/overrides-2.11/scala/collection/mutable/StringBuilder.scala.patch deleted file mode 100644 index 176c7b5011..0000000000 --- a/scalalib/overrides-2.11/scala/collection/mutable/StringBuilder.scala.patch +++ /dev/null @@ -1,33 +0,0 @@ ---- 2.11.12/scala/collection/mutable/StringBuilder.scala 2022-01-14 13:49:05.000000000 +0200 -+++ overrides-2.11.12/scala/collection/mutable/StringBuilder.scala 2022-01-14 13:47:55.000000000 +0200 -@@ -14,6 +14,14 @@ - import scala.annotation.migration - import immutable.StringLike - -+// used for compilation of scala-native with jdk8, when -+// we need to have isEmpty overrided, for building with jdk17 -+trait StringBuilderIsEmptyProvider { -+ -+ def isEmpty: Boolean -+ -+} -+ - /** A builder for mutable sequence of characters. This class provides an API - * mostly compatible with `java.lang.StringBuilder`, except where there are - * conflicts with the Scala collections API (such as the `reverse` method.) -@@ -34,6 +42,7 @@ - with IndexedSeq[Char] - with StringLike[StringBuilder] - with Builder[Char, String] -+ with StringBuilderIsEmptyProvider - with Serializable { - - override protected[this] def thisCollection: StringBuilder = this -@@ -72,6 +81,7 @@ - arr - } - -+ override def isEmpty: Boolean = underlying.length()==0 - override def length: Int = underlying.length() - def length_=(n: Int) { underlying.setLength(n) } - diff --git a/scalalib/overrides-2.11/scala/concurrent/ExecutionContext.scala.patch b/scalalib/overrides-2.11/scala/concurrent/ExecutionContext.scala.patch deleted file mode 100644 index dd18cd529b..0000000000 --- a/scalalib/overrides-2.11/scala/concurrent/ExecutionContext.scala.patch +++ /dev/null @@ -1,12 +0,0 @@ ---- 2.11.12/scala/concurrent/ExecutionContext.scala -+++ overrides-2.11/scala/concurrent/ExecutionContext.scala -@@ -127,7 +127,8 @@ - * the thread pool uses a target number of worker threads equal to the number of - * [[https://docs.oracle.com/javase/8/docs/api/java/lang/Runtime.html#availableProcessors-- available processors]]. - */ -- implicit lazy val global: ExecutionContextExecutor = impl.ExecutionContextImpl.fromExecutor(null: Executor) -+ implicit lazy val global: ExecutionContextExecutor = -+ scala.scalanative.runtime.ExecutionContext.global - } - - /** Creates an `ExecutionContext` from the given `ExecutorService`. diff --git a/scalalib/overrides-2.11/scala/concurrent/impl/AbstractPromise.scala b/scalalib/overrides-2.11/scala/concurrent/impl/AbstractPromise.scala deleted file mode 100644 index 8ea135e4d7..0000000000 --- a/scalalib/overrides-2.11/scala/concurrent/impl/AbstractPromise.scala +++ /dev/null @@ -1,29 +0,0 @@ -package scala.concurrent.impl - -/** - * JavaScript specific implementation of AbstractPromise - * - * This basically implements a "CAS" in Scala for JavaScript. Its - * implementation is trivial because there is no multi-threading. - * - * @author Tobias Schlatter - */ -abstract class AbstractPromise { - - private var state: AnyRef = _ - - protected final - def updateState(oldState: AnyRef, newState: AnyRef): Boolean = { - if (state eq oldState) { - state = newState - true - } else false - } - - protected final def getState: AnyRef = state - -} - -object AbstractPromise { - protected def updater = ??? -} diff --git a/scalalib/overrides-2.11/scala/package.scala.patch b/scalalib/overrides-2.11/scala/package.scala.patch deleted file mode 100644 index adabf74635..0000000000 --- a/scalalib/overrides-2.11/scala/package.scala.patch +++ /dev/null @@ -1,120 +0,0 @@ ---- 2.11.12/scala/package.scala -+++ overrides-2.11/scala/package.scala -@@ -30,90 +30,90 @@ - type InterruptedException = java.lang.InterruptedException - - // A dummy used by the specialization annotation. -- val AnyRef = new Specializable { -+ lazy val AnyRef = new Specializable { - override def toString = "object AnyRef" - } - - type TraversableOnce[+A] = scala.collection.TraversableOnce[A] - - type Traversable[+A] = scala.collection.Traversable[A] -- val Traversable = scala.collection.Traversable -+ lazy val Traversable = scala.collection.Traversable - - type Iterable[+A] = scala.collection.Iterable[A] -- val Iterable = scala.collection.Iterable -+ lazy val Iterable = scala.collection.Iterable - - type Seq[+A] = scala.collection.Seq[A] -- val Seq = scala.collection.Seq -+ lazy val Seq = scala.collection.Seq - - type IndexedSeq[+A] = scala.collection.IndexedSeq[A] -- val IndexedSeq = scala.collection.IndexedSeq -+ lazy val IndexedSeq = scala.collection.IndexedSeq - - type Iterator[+A] = scala.collection.Iterator[A] -- val Iterator = scala.collection.Iterator -+ lazy val Iterator = scala.collection.Iterator - - type BufferedIterator[+A] = scala.collection.BufferedIterator[A] - - type List[+A] = scala.collection.immutable.List[A] -- val List = scala.collection.immutable.List -+ lazy val List = scala.collection.immutable.List - -- val Nil = scala.collection.immutable.Nil -+ lazy val Nil = scala.collection.immutable.Nil - - type ::[A] = scala.collection.immutable.::[A] -- val :: = scala.collection.immutable.:: -+ lazy val :: = scala.collection.immutable.:: - -- val +: = scala.collection.+: -- val :+ = scala.collection.:+ -+ lazy val +: = scala.collection.+: -+ lazy val :+ = scala.collection.:+ - - type Stream[+A] = scala.collection.immutable.Stream[A] -- val Stream = scala.collection.immutable.Stream -- val #:: = scala.collection.immutable.Stream.#:: -+ lazy val Stream = scala.collection.immutable.Stream -+ lazy val #:: = scala.collection.immutable.Stream.#:: - - type Vector[+A] = scala.collection.immutable.Vector[A] -- val Vector = scala.collection.immutable.Vector -+ lazy val Vector = scala.collection.immutable.Vector - - type StringBuilder = scala.collection.mutable.StringBuilder -- val StringBuilder = scala.collection.mutable.StringBuilder -+ lazy val StringBuilder = scala.collection.mutable.StringBuilder - - type Range = scala.collection.immutable.Range -- val Range = scala.collection.immutable.Range -+ lazy val Range = scala.collection.immutable.Range - - // Numeric types which were moved into scala.math.* - - type BigDecimal = scala.math.BigDecimal -- val BigDecimal = scala.math.BigDecimal -+ lazy val BigDecimal = scala.math.BigDecimal - - type BigInt = scala.math.BigInt -- val BigInt = scala.math.BigInt -+ lazy val BigInt = scala.math.BigInt - - type Equiv[T] = scala.math.Equiv[T] -- val Equiv = scala.math.Equiv -+ lazy val Equiv = scala.math.Equiv - - type Fractional[T] = scala.math.Fractional[T] -- val Fractional = scala.math.Fractional -+ lazy val Fractional = scala.math.Fractional - - type Integral[T] = scala.math.Integral[T] -- val Integral = scala.math.Integral -+ lazy val Integral = scala.math.Integral - - type Numeric[T] = scala.math.Numeric[T] -- val Numeric = scala.math.Numeric -+ lazy val Numeric = scala.math.Numeric - - type Ordered[T] = scala.math.Ordered[T] -- val Ordered = scala.math.Ordered -+ lazy val Ordered = scala.math.Ordered - - type Ordering[T] = scala.math.Ordering[T] -- val Ordering = scala.math.Ordering -+ lazy val Ordering = scala.math.Ordering - - type PartialOrdering[T] = scala.math.PartialOrdering[T] - type PartiallyOrdered[T] = scala.math.PartiallyOrdered[T] - - type Either[+A, +B] = scala.util.Either[A, B] -- val Either = scala.util.Either -+ lazy val Either = scala.util.Either - - type Left[+A, +B] = scala.util.Left[A, B] -- val Left = scala.util.Left -+ lazy val Left = scala.util.Left - - type Right[+A, +B] = scala.util.Right[A, B] -- val Right = scala.util.Right -+ lazy val Right = scala.util.Right - - // Annotations which we might move to annotation.* - /* diff --git a/scalalib/overrides-2.11/scala/reflect/ClassTag.scala.patch b/scalalib/overrides-2.11/scala/reflect/ClassTag.scala.patch deleted file mode 100644 index 33e93306d9..0000000000 --- a/scalalib/overrides-2.11/scala/reflect/ClassTag.scala.patch +++ /dev/null @@ -1,69 +0,0 @@ ---- 2.11.12/scala/reflect/ClassTag.scala -+++ overrides-2.11/scala/reflect/ClassTag.scala -@@ -115,27 +115,23 @@ - * Class tags corresponding to primitive types and constructor/extractor for ClassTags. - */ - object ClassTag { -- private val ObjectTYPE = classOf[java.lang.Object] -- private val NothingTYPE = classOf[scala.runtime.Nothing$] -- private val NullTYPE = classOf[scala.runtime.Null$] -+ @inline def Byte : ClassTag[scala.Byte] = Manifest.Byte -+ @inline def Short : ClassTag[scala.Short] = Manifest.Short -+ @inline def Char : ClassTag[scala.Char] = Manifest.Char -+ @inline def Int : ClassTag[scala.Int] = Manifest.Int -+ @inline def Long : ClassTag[scala.Long] = Manifest.Long -+ @inline def Float : ClassTag[scala.Float] = Manifest.Float -+ @inline def Double : ClassTag[scala.Double] = Manifest.Double -+ @inline def Boolean : ClassTag[scala.Boolean] = Manifest.Boolean -+ @inline def Unit : ClassTag[scala.Unit] = Manifest.Unit -+ @inline def Any : ClassTag[scala.Any] = Manifest.Any -+ @inline def Object : ClassTag[java.lang.Object] = Manifest.Object -+ @inline def AnyVal : ClassTag[scala.AnyVal] = Manifest.AnyVal -+ @inline def AnyRef : ClassTag[scala.AnyRef] = Manifest.AnyRef -+ @inline def Nothing : ClassTag[scala.Nothing] = Manifest.Nothing -+ @inline def Null : ClassTag[scala.Null] = Manifest.Null - -- val Byte : ClassTag[scala.Byte] = Manifest.Byte -- val Short : ClassTag[scala.Short] = Manifest.Short -- val Char : ClassTag[scala.Char] = Manifest.Char -- val Int : ClassTag[scala.Int] = Manifest.Int -- val Long : ClassTag[scala.Long] = Manifest.Long -- val Float : ClassTag[scala.Float] = Manifest.Float -- val Double : ClassTag[scala.Double] = Manifest.Double -- val Boolean : ClassTag[scala.Boolean] = Manifest.Boolean -- val Unit : ClassTag[scala.Unit] = Manifest.Unit -- val Any : ClassTag[scala.Any] = Manifest.Any -- val Object : ClassTag[java.lang.Object] = Manifest.Object -- val AnyVal : ClassTag[scala.AnyVal] = Manifest.AnyVal -- val AnyRef : ClassTag[scala.AnyRef] = Manifest.AnyRef -- val Nothing : ClassTag[scala.Nothing] = Manifest.Nothing -- val Null : ClassTag[scala.Null] = Manifest.Null -- -- def apply[T](runtimeClass1: jClass[_]): ClassTag[T] = -+ @inline def apply[T](runtimeClass1: jClass[_]): ClassTag[T] = - runtimeClass1 match { - case java.lang.Byte.TYPE => ClassTag.Byte.asInstanceOf[ClassTag[T]] - case java.lang.Short.TYPE => ClassTag.Short.asInstanceOf[ClassTag[T]] -@@ -146,11 +142,17 @@ - case java.lang.Double.TYPE => ClassTag.Double.asInstanceOf[ClassTag[T]] - case java.lang.Boolean.TYPE => ClassTag.Boolean.asInstanceOf[ClassTag[T]] - case java.lang.Void.TYPE => ClassTag.Unit.asInstanceOf[ClassTag[T]] -- case ObjectTYPE => ClassTag.Object.asInstanceOf[ClassTag[T]] -- case NothingTYPE => ClassTag.Nothing.asInstanceOf[ClassTag[T]] -- case NullTYPE => ClassTag.Null.asInstanceOf[ClassTag[T]] -- case _ => new ClassTag[T]{ def runtimeClass = runtimeClass1 } -+ case _ => -+ if (classOf[java.lang.Object] == runtimeClass1) { -+ ClassTag.Object.asInstanceOf[ClassTag[T]] -+ } else if (classOf[scala.runtime.Nothing$] == runtimeClass1) { -+ ClassTag.Nothing.asInstanceOf[ClassTag[T]] -+ } else if (classOf[scala.runtime.Null$] == runtimeClass1) { -+ ClassTag.Null.asInstanceOf[ClassTag[T]] -+ } else { -+ new ClassTag[T]{ def runtimeClass = runtimeClass1 } -+ } - } - -- def unapply[T](ctag: ClassTag[T]): Option[Class[_]] = Some(ctag.runtimeClass) -+ @inline def unapply[T](ctag: ClassTag[T]): Option[Class[_]] = Some(ctag.runtimeClass) - } diff --git a/scalalib/overrides-2.11/scala/reflect/Manifest.scala.patch b/scalalib/overrides-2.11/scala/reflect/Manifest.scala.patch deleted file mode 100644 index 9964dda30b..0000000000 --- a/scalalib/overrides-2.11/scala/reflect/Manifest.scala.patch +++ /dev/null @@ -1,146 +0,0 @@ ---- 2.11.12/scala/reflect/Manifest.scala -+++ overrides-2.11/scala/reflect/Manifest.scala -@@ -88,7 +88,23 @@ - def valueManifests: List[AnyValManifest[_]] = - List(Byte, Short, Char, Int, Long, Float, Double, Boolean, Unit) - -- val Byte: AnyValManifest[Byte] = new AnyValManifest[scala.Byte]("Byte") { -+ @inline def Byte: AnyValManifest[Byte] = ByteManifest -+ @inline def Short: AnyValManifest[Short] = ShortManifest -+ @inline def Char: AnyValManifest[Char] = CharManifest -+ @inline def Int: AnyValManifest[Int] = IntManifest -+ @inline def Long: AnyValManifest[Long] = LongManifest -+ @inline def Float: AnyValManifest[Float] = FloatManifest -+ @inline def Double: AnyValManifest[Double] = DoubleManifest -+ @inline def Boolean: AnyValManifest[Boolean] = BooleanManifest -+ @inline def Unit: AnyValManifest[Unit] = UnitManifest -+ @inline def Any: Manifest[scala.Any] = AnyManifest -+ @inline def Object: Manifest[java.lang.Object] = ObjectManifest -+ @inline def AnyRef: Manifest[scala.AnyRef] = Object.asInstanceOf[Manifest[scala.AnyRef]] -+ @inline def AnyVal: Manifest[scala.AnyVal] = AnyValManifest -+ @inline def Null: Manifest[scala.Null] = NullManifest -+ @inline def Nothing: Manifest[scala.Nothing] = NothingManifest -+ -+ private object ByteManifest extends AnyValManifest[scala.Byte]("Byte") { - def runtimeClass = java.lang.Byte.TYPE - override def newArray(len: Int): Array[Byte] = new Array[Byte](len) - override def newWrappedArray(len: Int): WrappedArray[Byte] = new WrappedArray.ofByte(new Array[Byte](len)) -@@ -96,7 +112,7 @@ - private def readResolve(): Any = Manifest.Byte - } - -- val Short: AnyValManifest[Short] = new AnyValManifest[scala.Short]("Short") { -+ private object ShortManifest extends AnyValManifest[scala.Short]("Short") { - def runtimeClass = java.lang.Short.TYPE - override def newArray(len: Int): Array[Short] = new Array[Short](len) - override def newWrappedArray(len: Int): WrappedArray[Short] = new WrappedArray.ofShort(new Array[Short](len)) -@@ -104,7 +120,7 @@ - private def readResolve(): Any = Manifest.Short - } - -- val Char: AnyValManifest[Char] = new AnyValManifest[scala.Char]("Char") { -+ private object CharManifest extends AnyValManifest[scala.Char]("Char") { - def runtimeClass = java.lang.Character.TYPE - override def newArray(len: Int): Array[Char] = new Array[Char](len) - override def newWrappedArray(len: Int): WrappedArray[Char] = new WrappedArray.ofChar(new Array[Char](len)) -@@ -112,7 +128,7 @@ - private def readResolve(): Any = Manifest.Char - } - -- val Int: AnyValManifest[Int] = new AnyValManifest[scala.Int]("Int") { -+ private object IntManifest extends AnyValManifest[scala.Int]("Int") { - def runtimeClass = java.lang.Integer.TYPE - override def newArray(len: Int): Array[Int] = new Array[Int](len) - override def newWrappedArray(len: Int): WrappedArray[Int] = new WrappedArray.ofInt(new Array[Int](len)) -@@ -120,7 +136,7 @@ - private def readResolve(): Any = Manifest.Int - } - -- val Long: AnyValManifest[Long] = new AnyValManifest[scala.Long]("Long") { -+ private object LongManifest extends AnyValManifest[scala.Long]("Long") { - def runtimeClass = java.lang.Long.TYPE - override def newArray(len: Int): Array[Long] = new Array[Long](len) - override def newWrappedArray(len: Int): WrappedArray[Long] = new WrappedArray.ofLong(new Array[Long](len)) -@@ -128,7 +144,7 @@ - private def readResolve(): Any = Manifest.Long - } - -- val Float: AnyValManifest[Float] = new AnyValManifest[scala.Float]("Float") { -+ private object FloatManifest extends AnyValManifest[scala.Float]("Float") { - def runtimeClass = java.lang.Float.TYPE - override def newArray(len: Int): Array[Float] = new Array[Float](len) - override def newWrappedArray(len: Int): WrappedArray[Float] = new WrappedArray.ofFloat(new Array[Float](len)) -@@ -136,7 +152,7 @@ - private def readResolve(): Any = Manifest.Float - } - -- val Double: AnyValManifest[Double] = new AnyValManifest[scala.Double]("Double") { -+ private object DoubleManifest extends AnyValManifest[scala.Double]("Double") { - def runtimeClass = java.lang.Double.TYPE - override def newArray(len: Int): Array[Double] = new Array[Double](len) - override def newWrappedArray(len: Int): WrappedArray[Double] = new WrappedArray.ofDouble(new Array[Double](len)) -@@ -144,7 +160,7 @@ - private def readResolve(): Any = Manifest.Double - } - -- val Boolean: AnyValManifest[Boolean] = new AnyValManifest[scala.Boolean]("Boolean") { -+ private object BooleanManifest extends AnyValManifest[scala.Boolean]("Boolean") { - def runtimeClass = java.lang.Boolean.TYPE - override def newArray(len: Int): Array[Boolean] = new Array[Boolean](len) - override def newWrappedArray(len: Int): WrappedArray[Boolean] = new WrappedArray.ofBoolean(new Array[Boolean](len)) -@@ -152,7 +168,7 @@ - private def readResolve(): Any = Manifest.Boolean - } - -- val Unit: AnyValManifest[Unit] = new AnyValManifest[scala.Unit]("Unit") { -+ private object UnitManifest extends AnyValManifest[scala.Unit]("Unit") { - def runtimeClass = java.lang.Void.TYPE - override def newArray(len: Int): Array[Unit] = new Array[Unit](len) - override def newWrappedArray(len: Int): WrappedArray[Unit] = new WrappedArray.ofUnit(new Array[Unit](len)) -@@ -163,38 +179,36 @@ - private def readResolve(): Any = Manifest.Unit - } - -- private val ObjectTYPE = classOf[java.lang.Object] -- private val NothingTYPE = classOf[scala.runtime.Nothing$] -- private val NullTYPE = classOf[scala.runtime.Null$] -+ @inline private def ObjectTYPE = classOf[java.lang.Object] -+ @inline private def NothingTYPE = classOf[scala.runtime.Nothing$] -+ @inline private def NullTYPE = classOf[scala.runtime.Null$] - -- val Any: Manifest[scala.Any] = new PhantomManifest[scala.Any](ObjectTYPE, "Any") { -+ private object AnyManifest extends PhantomManifest[scala.Any](ObjectTYPE, "Any") { - override def newArray(len: Int) = new Array[scala.Any](len) - override def <:<(that: ClassManifest[_]): Boolean = (that eq this) - private def readResolve(): Any = Manifest.Any - } - -- val Object: Manifest[java.lang.Object] = new PhantomManifest[java.lang.Object](ObjectTYPE, "Object") { -+ private object ObjectManifest extends PhantomManifest[java.lang.Object](ObjectTYPE, "Object") { - override def newArray(len: Int) = new Array[java.lang.Object](len) - override def <:<(that: ClassManifest[_]): Boolean = (that eq this) || (that eq Any) - private def readResolve(): Any = Manifest.Object - } - -- val AnyRef: Manifest[scala.AnyRef] = Object.asInstanceOf[Manifest[scala.AnyRef]] -- -- val AnyVal: Manifest[scala.AnyVal] = new PhantomManifest[scala.AnyVal](ObjectTYPE, "AnyVal") { -+ private object AnyValManifest extends PhantomManifest[scala.AnyVal](ObjectTYPE, "AnyVal") { - override def newArray(len: Int) = new Array[scala.AnyVal](len) - override def <:<(that: ClassManifest[_]): Boolean = (that eq this) || (that eq Any) - private def readResolve(): Any = Manifest.AnyVal - } - -- val Null: Manifest[scala.Null] = new PhantomManifest[scala.Null](NullTYPE, "Null") { -+ private object NullManifest extends PhantomManifest[scala.Null](NullTYPE, "Null") { - override def newArray(len: Int) = new Array[scala.Null](len) - override def <:<(that: ClassManifest[_]): Boolean = - (that ne null) && (that ne Nothing) && !(that <:< AnyVal) - private def readResolve(): Any = Manifest.Null - } - -- val Nothing: Manifest[scala.Nothing] = new PhantomManifest[scala.Nothing](NothingTYPE, "Nothing") { -+ private object NothingManifest extends PhantomManifest[scala.Nothing](NothingTYPE, "Nothing") { - override def newArray(len: Int) = new Array[scala.Nothing](len) - override def <:<(that: ClassManifest[_]): Boolean = (that ne null) - private def readResolve(): Any = Manifest.Nothing diff --git a/scalalib/overrides-2.11/scala/reflect/ScalaLongSignature.scala b/scalalib/overrides-2.11/scala/reflect/ScalaLongSignature.scala deleted file mode 100644 index aa2c661b3a..0000000000 --- a/scalalib/overrides-2.11/scala/reflect/ScalaLongSignature.scala +++ /dev/null @@ -1,3 +0,0 @@ -package scala.reflect - -class ScalaLongSignature diff --git a/scalalib/overrides-2.11/scala/reflect/ScalaSignature.scala b/scalalib/overrides-2.11/scala/reflect/ScalaSignature.scala deleted file mode 100644 index 4c13e7a6f5..0000000000 --- a/scalalib/overrides-2.11/scala/reflect/ScalaSignature.scala +++ /dev/null @@ -1,3 +0,0 @@ -package scala.reflect - -class ScalaSignature diff --git a/scalalib/overrides-2.11/scala/runtime/ScalaRunTime.scala.patch b/scalalib/overrides-2.11/scala/runtime/ScalaRunTime.scala.patch deleted file mode 100644 index 45ea6d9750..0000000000 --- a/scalalib/overrides-2.11/scala/runtime/ScalaRunTime.scala.patch +++ /dev/null @@ -1,91 +0,0 @@ ---- 2.11.12/scala/runtime/ScalaRunTime.scala -+++ overrides-2.11/scala/runtime/ScalaRunTime.scala -@@ -69,66 +69,38 @@ - classTag[T].runtimeClass.asInstanceOf[jClass[T]] - - /** Retrieve generic array element */ -- def array_apply(xs: AnyRef, idx: Int): Any = { -- xs match { -- case x: Array[AnyRef] => x(idx).asInstanceOf[Any] -- case x: Array[Int] => x(idx).asInstanceOf[Any] -- case x: Array[Double] => x(idx).asInstanceOf[Any] -- case x: Array[Long] => x(idx).asInstanceOf[Any] -- case x: Array[Float] => x(idx).asInstanceOf[Any] -- case x: Array[Char] => x(idx).asInstanceOf[Any] -- case x: Array[Byte] => x(idx).asInstanceOf[Any] -- case x: Array[Short] => x(idx).asInstanceOf[Any] -- case x: Array[Boolean] => x(idx).asInstanceOf[Any] -- case x: Array[Unit] => x(idx).asInstanceOf[Any] -- case null => throw new NullPointerException -+ @inline def array_apply(xs: AnyRef, idx: Int): Any = { -+ if (xs == null) { -+ throw new NullPointerException -+ } else { -+ xs.asInstanceOf[scala.scalanative.runtime.Array[Any]].apply(idx) - } - } - - /** update generic array element */ -- def array_update(xs: AnyRef, idx: Int, value: Any): Unit = { -- xs match { -- case x: Array[AnyRef] => x(idx) = value.asInstanceOf[AnyRef] -- case x: Array[Int] => x(idx) = value.asInstanceOf[Int] -- case x: Array[Double] => x(idx) = value.asInstanceOf[Double] -- case x: Array[Long] => x(idx) = value.asInstanceOf[Long] -- case x: Array[Float] => x(idx) = value.asInstanceOf[Float] -- case x: Array[Char] => x(idx) = value.asInstanceOf[Char] -- case x: Array[Byte] => x(idx) = value.asInstanceOf[Byte] -- case x: Array[Short] => x(idx) = value.asInstanceOf[Short] -- case x: Array[Boolean] => x(idx) = value.asInstanceOf[Boolean] -- case x: Array[Unit] => x(idx) = value.asInstanceOf[Unit] -- case null => throw new NullPointerException -+ @inline def array_update(xs: AnyRef, idx: Int, value: Any): Unit = { -+ if (xs == null) { -+ throw new NullPointerException -+ } else { -+ xs.asInstanceOf[scala.scalanative.runtime.Array[Any]].update(idx, value) - } - } - - /** Get generic array length */ -- def array_length(xs: AnyRef): Int = xs match { -- case x: Array[AnyRef] => x.length -- case x: Array[Int] => x.length -- case x: Array[Double] => x.length -- case x: Array[Long] => x.length -- case x: Array[Float] => x.length -- case x: Array[Char] => x.length -- case x: Array[Byte] => x.length -- case x: Array[Short] => x.length -- case x: Array[Boolean] => x.length -- case x: Array[Unit] => x.length -- case null => throw new NullPointerException -+ def array_length(xs: AnyRef): Int = { -+ if (xs == null) { -+ throw new NullPointerException -+ } else { -+ xs.asInstanceOf[scala.scalanative.runtime.Array[Any]].length -+ } - } - -- def array_clone(xs: AnyRef): AnyRef = xs match { -- case x: Array[AnyRef] => ArrayRuntime.cloneArray(x) -- case x: Array[Int] => ArrayRuntime.cloneArray(x) -- case x: Array[Double] => ArrayRuntime.cloneArray(x) -- case x: Array[Long] => ArrayRuntime.cloneArray(x) -- case x: Array[Float] => ArrayRuntime.cloneArray(x) -- case x: Array[Char] => ArrayRuntime.cloneArray(x) -- case x: Array[Byte] => ArrayRuntime.cloneArray(x) -- case x: Array[Short] => ArrayRuntime.cloneArray(x) -- case x: Array[Boolean] => ArrayRuntime.cloneArray(x) -- case x: Array[Unit] => x -- case null => throw new NullPointerException -+ def array_clone(xs: AnyRef): AnyRef = { -+ if (xs == null) { -+ throw new NullPointerException -+ } else { -+ xs.asInstanceOf[scala.scalanative.runtime.Array[Any]].clone() -+ } - } - - /** Convert an array to an object array. diff --git a/scripts/changelog.sc b/scripts/changelog.sc index 87cf7bec51..9a5a78e966 100644 --- a/scripts/changelog.sc +++ b/scripts/changelog.sc @@ -124,10 +124,6 @@ def template( | Scala release | | - | 2.11 - | 2.11.12 - | - | | 2.12 | | diff --git a/scripts/gyb.py b/scripts/gyb.py index e826e4dbb3..4c44e98d80 100755 --- a/scripts/gyb.py +++ b/scripts/gyb.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # GYB: Generate Your Boilerplate (improved names welcome; at least # this one's short). See -h output for instructions diff --git a/scripts/javalib.py b/scripts/javalib.py index b13bbe9726..6d085e7dd2 100644 --- a/scripts/javalib.py +++ b/scripts/javalib.py @@ -8,7 +8,7 @@ cwd = os.getcwd() -target = cwd + "/javalib/.2.11/target/scala-2.11/classes/" +target = cwd + "/javalib/.2.12/target/scala-2.12/classes/" paths = subprocess.check_output(["find", target, "-name", "*.nir"]) diff --git a/scripts/scalalib-patch-all.sc b/scripts/scalalib-patch-all.sc index 75a8d06bae..13a5ed9bf4 100644 --- a/scripts/scalalib-patch-all.sc +++ b/scripts/scalalib-patch-all.sc @@ -1,14 +1,13 @@ import $ivy.`com.lihaoyi::ammonite-ops:2.3.8`, ammonite.ops._, mainargs._ import $file.`scalalib-patch-tool` -val crossScala211 = List("2.11.12") val crossScala212 = List("2.12.13", "2.12.14", "2.12.15") val crossScala213 = List("2.13.4", "2.13.5", "2.13.6", "2.13.7") val commands = List("recreate", "create", "prune") for { - version <- crossScala211 ++ crossScala212 ++ crossScala213 + version <- crossScala212 ++ crossScala213 cmd <- commands _ = println(s"$cmd $version") res = %%("amm", "scripts/scalalib-patch-tool.sc", cmd, version)(pwd) diff --git a/scripts/travis_setup.sh b/scripts/travis_setup.sh deleted file mode 100755 index 69cd7fa81c..0000000000 --- a/scripts/travis_setup.sh +++ /dev/null @@ -1,42 +0,0 @@ -#!/usr/bin/env bash - -# Enable strict mode and fail the script on non-zero exit code, -# unresolved variable or pipe failure. -set -euo pipefail -IFS=$'\n\t' - -if [ "$(uname)" == "Darwin" ]; then - - brew update - brew install sbt - brew install bdw-gc - brew link bdw-gc - brew install jq - brew install re2 - brew install llvm@9 - export PATH="/usr/local/opt/llvm@9/bin:$PATH" - -else - - sudo apt-get update - - # Remove pre-bundled libunwind - sudo find /usr -name "*libunwind*" -delete - - # Use pre-bundled clang - export PATH=/usr/local/clang-5.0.0/bin:$PATH - export CXX=clang++ - - # Install Boehm GC and libunwind - sudo apt-get install libgc-dev libunwind8-dev - - # Build and install re2 from source - git clone https://code.googlesource.com/re2 - pushd re2 - git checkout 2017-03-01 - make -j4 test - sudo make install prefix=/usr - make testinstall prefix=/usr - popd - -fi diff --git a/testing-compiler/src/main/scala-2/scalanative/NIRCompiler.scala b/testing-compiler/src/main/scala-2/scalanative/NIRCompiler.scala index d51a52b9d0..53f865826d 100644 --- a/testing-compiler/src/main/scala-2/scalanative/NIRCompiler.scala +++ b/testing-compiler/src/main/scala-2/scalanative/NIRCompiler.scala @@ -31,10 +31,6 @@ class NIRCompiler(outputDir: Path) extends api.NIRCompiler { private def compile(sources: Seq[SourceFile]): Seq[Path] = { val global = getCompiler(options = ScalaNative) - if (util.Properties.versionNumberString.startsWith("2.11.")) { - // Enable SAM support - global.settings.Xexperimental.value = true - } import global._ val run = new Run run.compileSources(sources.toList) diff --git a/tools/src/main/scala/scala/scalanative/interflow/Inline.scala b/tools/src/main/scala/scala/scalanative/interflow/Inline.scala index f0e4af3ca1..83569d195b 100644 --- a/tools/src/main/scala/scala/scalanative/interflow/Inline.scala +++ b/tools/src/main/scala/scala/scalanative/interflow/Inline.scala @@ -31,7 +31,7 @@ trait Inline { self: Interflow => false } { defn => def isCtor = originalName(name) match { - case Global.Member(_, sig) if sig.isCtor || sig.isImplCtor => + case Global.Member(_, sig) if sig.isCtor => true case _ => false diff --git a/tools/src/test/scala/scala/scalanative/NativePlatform.scala b/tools/src/test/scala/scala/scalanative/NativePlatform.scala index 77c02f5e84..ed02f23bd7 100644 --- a/tools/src/test/scala/scala/scalanative/NativePlatform.scala +++ b/tools/src/test/scala/scala/scalanative/NativePlatform.scala @@ -3,6 +3,5 @@ package scala.scalanative import scala.scalanative.buildinfo.ScalaNativeBuildInfo._ private[scalanative] object NativePlatform { - def scalaUsesImplClasses: Boolean = nativeScalaVersion.startsWith("2.11.") def erasesEmptyTraitConstructor: Boolean = nativeScalaVersion.startsWith("3.") } diff --git a/tools/src/test/scala/scala/scalanative/linker/TraitReachabilitySuite.scala b/tools/src/test/scala/scala/scalanative/linker/TraitReachabilitySuite.scala index d23dd62e0c..34c34d6c9e 100644 --- a/tools/src/test/scala/scala/scalanative/linker/TraitReachabilitySuite.scala +++ b/tools/src/test/scala/scala/scalanative/linker/TraitReachabilitySuite.scala @@ -16,24 +16,6 @@ class TraitReachabilitySuite extends ReachabilitySuite { Sig.Method("main", Rt.ScalaMainSig.types, Sig.Scope.Public) val Parent: Global = g(ParentClsName) - // Scala 2.11.x - val ParentClass: Global = g(ParentClassClsName) - val ParentClassInit: Global = - g( - ParentClassClsName, - Sig.Method("$init$", Seq(Type.Ref(Parent), Type.Unit)) - ) - val ParentClassMain = g( - ParentClassClsName, - Sig.Method( - "main", - Type.Ref(Parent) +: Rt.ScalaMainSig.types, - Sig.Scope.Public - ) - ) - val ParentClassFoo: Global = - g(ParentClassClsName, Sig.Method("foo", Seq(Type.Ref(Parent), Type.Unit))) - // val ParentClassMain = g(ParentClassClsName, Sig.Method("main", Type.)) // Scala 2.12.x val ParentInit: Global = g(ParentClsName, Sig.Method("$init$", Seq(Type.Unit))) @@ -191,14 +173,7 @@ class TraitReachabilitySuite extends ReachabilitySuite { Object, ObjectInit ) ++ { - if (NativePlatform.scalaUsesImplClasses) { - Seq( - Parent, - ParentClass, - ParentClassInit, - ParentClassFoo - ) - } else if (NativePlatform.erasesEmptyTraitConstructor) { + if (NativePlatform.erasesEmptyTraitConstructor) { Seq(Parent, ParentFoo) } else { Seq( @@ -238,13 +213,7 @@ class TraitReachabilitySuite extends ReachabilitySuite { Object, ObjectInit ) ++ { - if (NativePlatform.scalaUsesImplClasses) { - Seq( - Parent, - ParentClass, - ParentClassInit - ) - } else if (NativePlatform.erasesEmptyTraitConstructor) { + if (NativePlatform.erasesEmptyTraitConstructor) { Seq(Parent) } else { Seq( @@ -272,15 +241,7 @@ class TraitReachabilitySuite extends ReachabilitySuite { Object, ObjectInit ) ++ { - if (NativePlatform.scalaUsesImplClasses) { - Seq( - Parent, - ParentClass, - ParentClassInit, - ParentClassMain, - TestModuleMain - ) - } else if (NativePlatform.erasesEmptyTraitConstructor) { + if (NativePlatform.erasesEmptyTraitConstructor) { Seq(ParentMain, TestModuleMain) } else { Seq( diff --git a/unit-tests/jvm/src/test/resources/BlacklistedTests.txt b/unit-tests/jvm/src/test/resources/BlacklistedTests.txt index 210691904f..4956736278 100644 --- a/unit-tests/jvm/src/test/resources/BlacklistedTests.txt +++ b/unit-tests/jvm/src/test/resources/BlacklistedTests.txt @@ -24,9 +24,6 @@ scala/AsInstanceOfTest.scala # Scala 2 specific scala/ReflectiveProxyTest.scala -# Tests that fail for scala 2.11 on JVM -scala/PrimitiveTest.scala - # Tests that fail for scala 2.13 on JVM scala/bugcompat/LongFloatPrimitiveTest.scala diff --git a/unit-tests/native/src/test/scala/scala/scalanative/unsafe/PtrBoxingTest.scala b/unit-tests/native/src/test/scala/scala/scalanative/unsafe/PtrBoxingTest.scala index fb34230f88..cb48ebab64 100644 --- a/unit-tests/native/src/test/scala/scala/scalanative/unsafe/PtrBoxingTest.scala +++ b/unit-tests/native/src/test/scala/scala/scalanative/unsafe/PtrBoxingTest.scala @@ -195,8 +195,8 @@ class PtrBoxingTest { x._1 = CFuncPtr0.fromScalaFunction(getInt _) x._2 = CFuncPtr1.fromScalaFunction(stringLength _) - val loadedGetInt: GetInt = x._1 - val loadedStringLength: StringLength = x._2 + val loadedGetInt = x._1 + val loadedStringLength = x._2 val testStr = toCString("hello_native") val expectedInt = 42 @@ -212,12 +212,7 @@ class PtrBoxingTest { } object PtrBoxingTest { - type Functions = CStruct2[GetInt, StringLength] - // In 2.11 this method needs to be statically known - - type GetInt = CFuncPtr0[Int] + type Functions = CStruct2[CFuncPtr0[Int], CFuncPtr1[CString, CSize]] def getInt(): Int = 42 - - type StringLength = CFuncPtr1[CString, CSize] def stringLength(str: CString): CSize = libc.string.strlen(str) } diff --git a/unit-tests/shared/src/test/scala-2.11/scala/annotation/nowarn.scala b/unit-tests/shared/src/test/scala-2.11/scala/annotation/nowarn.scala deleted file mode 100644 index 8251055f1f..0000000000 --- a/unit-tests/shared/src/test/scala-2.11/scala/annotation/nowarn.scala +++ /dev/null @@ -1,4 +0,0 @@ -package scala.annotation - -// Mock of nowarn annotations to allow cross-compilation with Scala 2.11 -class nowarn extends StaticAnnotation diff --git a/unit-tests/shared/src/test/scala/scala/AsInstanceOfTest.scala b/unit-tests/shared/src/test/scala/scala/AsInstanceOfTest.scala index 729f1aa6a1..6fa3a56680 100644 --- a/unit-tests/shared/src/test/scala/scala/AsInstanceOfTest.scala +++ b/unit-tests/shared/src/test/scala/scala/AsInstanceOfTest.scala @@ -9,7 +9,6 @@ import org.scalanative.testsuite.utils.AssertThrows.assertThrows import scala.scalanative.buildinfo.ScalaNativeBuildInfo.scalaVersion class AsInstanceOfTest { - val isScala211 = scalaVersion.startsWith("2.11.") val isScala3 = scalaVersion.startsWith("3.") class C @@ -41,13 +40,7 @@ class AsInstanceOfTest { assertThrows(expected, anyNull.asInstanceOf[Nothing]) } - @Test def nullAsInstanceOfUnitEqNull(): Unit = { - assumeTrue(isScala211) - assertTrue(anyNull.asInstanceOf[Unit] == anyNull) - } - @Test def nullAsInstanceOfUnitNotEqNull(): Unit = { - assumeFalse(isScala211) assertTrue(anyNull.asInstanceOf[Unit] != anyNull) } @@ -71,13 +64,7 @@ class AsInstanceOfTest { assertThrows(classOf[ClassCastException], any42.asInstanceOf[Nothing]) } - @Test def any42AsInstanceOfUnitThrows(): Unit = { - assumeTrue(isScala211) - assertThrows(classOf[ClassCastException], any42.asInstanceOf[Unit]) - } - @Test def any42AsInstanceOfUnitNotNull(): Unit = { - assumeFalse(isScala211) assertNotNull(any42.asInstanceOf[Unit]) } @@ -101,13 +88,7 @@ class AsInstanceOfTest { assertThrows(classOf[ClassCastException], anyC.asInstanceOf[Nothing]) } - @Test def cAsInstanceOfUnitThrows(): Unit = { - assumeTrue(isScala211) - assertThrows(classOf[ClassCastException], anyC.asInstanceOf[Unit]) - } - @Test def cAsInstanceOfUnitNotNull(): Unit = { - assumeFalse(isScala211) assertNotNull(c.asInstanceOf[Unit]) } } diff --git a/unit-tests/shared/src/test/scala/scala/HashCodeTest.scala b/unit-tests/shared/src/test/scala/scala/HashCodeTest.scala index ea098c7614..3568420c4c 100644 --- a/unit-tests/shared/src/test/scala/scala/HashCodeTest.scala +++ b/unit-tests/shared/src/test/scala/scala/HashCodeTest.scala @@ -7,10 +7,7 @@ import scala.scalanative.buildinfo.ScalaNativeBuildInfo.scalaVersion class HashCodeTest { case class MyData(string: String, num: Int) - def scala212orOlder: Boolean = { - scalaVersion.startsWith("2.11.") || - scalaVersion.startsWith("2.12.") - } + def scala212: Boolean = scalaVersion.startsWith("2.12.") @Test def hashCodeOfStringMatchesScalaJVM(): Unit = { assertTrue("hello".hashCode == 99162322) @@ -18,7 +15,7 @@ class HashCodeTest { @Test def hashCodeOfCaseClassMatchesScalaJVM(): Unit = { val expectedHashCode = - if (scala212orOlder) -1824015247 + if (scala212) -1824015247 else -715875225 assertTrue(MyData("hello", 12345).hashCode == expectedHashCode) } From aa2238e198d8f863b8f437a21e339d3ed1a32a92 Mon Sep 17 00:00:00 2001 From: 110416 Date: Wed, 14 Dec 2022 15:37:13 +0100 Subject: [PATCH 15/64] Improve: report error on extern in val def (#3033) * fix: test helper reported wrong source location * improve: report error on extern in val def part of #2498 * fix: strange compiler error using symbol.setter with immutable variable crashed linker. (cherry picked from commit faa72bb7b0ec3d11d31d4adf097f49afbd6f52a5) --- .../scalanative/nscplugin/NirGenStat.scala | 3 + .../scalanative/nscplugin/NirGenStat.scala | 4 +- .../nscplugin/PrepNativeInterop.scala | 7 +- .../scala/scalanative/NIRCompilerTest3.scala | 14 +++- .../scala/scalanative/NIRCompilerTest.scala | 84 +++++++++++++++++++ 5 files changed, 107 insertions(+), 5 deletions(-) diff --git a/nscplugin/src/main/scala-2/scala/scalanative/nscplugin/NirGenStat.scala b/nscplugin/src/main/scala-2/scala/scalanative/nscplugin/NirGenStat.scala index b61d505592..efc42974ba 100644 --- a/nscplugin/src/main/scala-2/scala/scalanative/nscplugin/NirGenStat.scala +++ b/nscplugin/src/main/scala-2/scala/scalanative/nscplugin/NirGenStat.scala @@ -176,6 +176,9 @@ trait NirGenStat[G <: nsc.Global with Singleton] { self: NirGenPhase[G] => for (f <- sym.info.decls if !f.isMethod && f.isTerm && !f.isModule) { + if (f.owner.isExternType && !f.isMutable) { + reporter.error(f.pos, "`extern` cannot be used in val definition") + } val ty = genType(f.tpe) val name = genFieldName(f) val pos: nir.Position = f.pos diff --git a/nscplugin/src/main/scala-3/scala/scalanative/nscplugin/NirGenStat.scala b/nscplugin/src/main/scala-3/scala/scalanative/nscplugin/NirGenStat.scala index 84359ce69b..44c1d566f2 100644 --- a/nscplugin/src/main/scala-3/scala/scalanative/nscplugin/NirGenStat.scala +++ b/nscplugin/src/main/scala-3/scala/scalanative/nscplugin/NirGenStat.scala @@ -109,10 +109,12 @@ trait NirGenStat(using Context) { if !f.isOneOf(Method | Module) && f.isTerm do given nir.Position = f.span - val isStatic = f.is(JavaStatic) || f.isScalaStatic val isExtern = f.isExtern val mutable = isStatic || f.is(Mutable) + if (isExtern && !mutable) { + report.error("`extern` cannot be used in val definition") + } val attrs = nir.Attrs(isExtern = f.isExtern) val ty = genType(f.info.resultType) val fieldName @ Global.Member(owner, sig) = genFieldName(f): @unchecked diff --git a/nscplugin/src/main/scala-3/scala/scalanative/nscplugin/PrepNativeInterop.scala b/nscplugin/src/main/scala-3/scala/scalanative/nscplugin/PrepNativeInterop.scala index ffd0b8d558..c910aec8de 100644 --- a/nscplugin/src/main/scala-3/scala/scalanative/nscplugin/PrepNativeInterop.scala +++ b/nscplugin/src/main/scala-3/scala/scalanative/nscplugin/PrepNativeInterop.scala @@ -13,6 +13,7 @@ import core.Types._ import core.StdNames._ import core.Constants.Constant import NirGenUtil.ContextCached +import dotty.tools.dotc.core.Flags /** This phase does: * - Rewrite calls to scala.Enumeration.Value (include name string) (Ported @@ -62,7 +63,11 @@ class PrepNativeInterop extends PluginPhase { if (isTopLevelExtern(vd) && !sym.hasAnnotation(defnNir.ExternClass)) { sym.addAnnotation(defnNir.ExternClass) - sym.setter.addAnnotation(defnNir.ExternClass) + if (vd.symbol.is( + Flags.Mutable + )) { + sym.setter.addAnnotation(defnNir.ExternClass) + } } vd diff --git a/tools/src/test/scala-3/scala/scalanative/NIRCompilerTest3.scala b/tools/src/test/scala-3/scala/scalanative/NIRCompilerTest3.scala index ade7ec5374..20a2926fb5 100644 --- a/tools/src/test/scala-3/scala/scalanative/NIRCompilerTest3.scala +++ b/tools/src/test/scala-3/scala/scalanative/NIRCompilerTest3.scala @@ -11,7 +11,7 @@ import scala.scalanative.linker.StaticForwardersSuite.compileAndLoad import scala.scalanative.nir.* class NIRCompilerTest3 extends AnyFlatSpec with Matchers with Inspectors { - def nativeCompilation(source: String): Unit = { + inline def nativeCompilation(source: String): Unit = { try scalanative.NIRCompiler(_.compile(source)) catch { case ex: CompilationFailedException => @@ -36,15 +36,23 @@ class NIRCompilerTest3 extends AnyFlatSpec with Matchers with Inspectors { |""".stripMargin)) }.getMessage should include("extern method foo needs result type") } + it should "report error for extern in top-level val definition" in { + intercept[CompilationFailedException] { + NIRCompiler(_.compile(""" + |import scala.scalanative.unsafe.extern + | + |val foo: Int = extern + |""".stripMargin)) + }.getMessage should include("extern` cannot be used in val definition") + } - it should "allow to define top level extern variable" in nativeCompilation( + it should "compile top-level extern var definition" in nativeCompilation( """ |import scala.scalanative.unsafe.extern | |var foo: Int = extern |""".stripMargin ) - it should "report error for top-level extern variable without result type" in { intercept[CompilationFailedException] { NIRCompiler(_.compile(""" diff --git a/tools/src/test/scala/scala/scalanative/NIRCompilerTest.scala b/tools/src/test/scala/scala/scalanative/NIRCompilerTest.scala index 5d8ad40c1a..7b02229fff 100644 --- a/tools/src/test/scala/scala/scalanative/NIRCompilerTest.scala +++ b/tools/src/test/scala/scala/scalanative/NIRCompilerTest.scala @@ -67,6 +67,90 @@ class NIRCompilerTest extends AnyFlatSpec with Matchers with Inspectors { val caught = intercept[CompilationFailedException] { NIRCompiler(_.compile(code)) } + } + it should "report error for extern in val definition" in { + // given + val code = + """import scala.scalanative.unsafe.extern + | + |@extern + |object Dummy { + | val foo: Int = extern + |}""".stripMargin + // when + val caught = intercept[CompilationFailedException] { + NIRCompiler(_.compile(code)) + } + caught.getMessage() should include( + "`extern` cannot be used in val definition" + ) + } + + it should "compile extern var definition" in { + // given + val code = + """import scala.scalanative.unsafe.extern + | + |@extern + |object Dummy { + | var foo: Int = extern + |}""".stripMargin + // when + NIRCompiler(_.compile(code)) + } + + it should "not allow members of extern object to reference other externs" in { + val code = + """import scala.scalanative.unsafe.extern + | + |@extern object Dummy { + | def foo(): Int = extern + | def bar(): Int = foo() + |} + |""".stripMargin + intercept[CompilationFailedException] { + NIRCompiler(_.compile(code)) + }.getMessage() should include( + "Referencing other extern symbols in not supported" + ) + } + + it should "allow to extend extern traits" in { + val code = + """import scala.scalanative.unsafe.extern + | + |@extern trait Dummy { + | var x: Int = extern + | def foo(): Int = extern + |} + | + |@extern trait Dummy2 extends Dummy { + | def bar(): Int = extern + |} + | + |@extern object Dummy extends Dummy + |@extern object Dummy2 extends Dummy2 + |""".stripMargin + + NIRCompiler(_.compile(code)) + } + + it should "not allow to mix extern object with regular traits" in { + val code = + """ + |import scala.scalanative.unsafe.extern + | + |trait Dummy { + | def foo(): Int = ??? + |} + | + |@extern object Dummy extends Dummy + |""".stripMargin + intercept[CompilationFailedException](NIRCompiler(_.compile(code))) + .getMessage() should include( + "Extern object can only extend extern traits" + ) + } // then caught.getMessage should include("extern method foo needs result type") From 17628cb15869866a611e9f1fc45a7d06d1929f32 Mon Sep 17 00:00:00 2001 From: LeeTibbert Date: Mon, 19 Dec 2022 10:29:14 +0100 Subject: [PATCH 16/64] Implement posixlib glob, fnmatch, & libgen on Unix (#3041) * Implement posixlib glob.h, fnmatch.h, & libgen.h on Unix * Fix breakage revealed in Round 1 * Fix Windows GlobTest * Restore trace.h, it is still in the 2018 Open Group list (cherry picked from commit d4ca516a97b20890cebff4ec76e4f326304cc5fe) --- docs/lib/posixlib.rst | 9 +- .../src/main/resources/scala-native/fnmatch.c | 20 +++ .../src/main/resources/scala-native/glob.c | 80 +++++++++++ .../scala/scalanative/posix/fnmatch.scala | 33 +++++ .../scala/scala/scalanative/posix/glob.scala | 119 ++++++++++++++++ .../scala/scalanative/posix/libgen.scala | 23 +++ .../scala/scalanative/posix/GlobTest.scala | 131 ++++++++++++++++++ 7 files changed, 412 insertions(+), 3 deletions(-) create mode 100644 posixlib/src/main/resources/scala-native/fnmatch.c create mode 100644 posixlib/src/main/resources/scala-native/glob.c create mode 100644 posixlib/src/main/scala/scala/scalanative/posix/fnmatch.scala create mode 100644 posixlib/src/main/scala/scala/scalanative/posix/glob.scala create mode 100644 posixlib/src/main/scala/scala/scalanative/posix/libgen.scala create mode 100644 unit-tests/native/src/test/scala/scala/scalanative/posix/GlobTest.scala diff --git a/docs/lib/posixlib.rst b/docs/lib/posixlib.rst index 92527c92eb..24f11b40bc 100644 --- a/docs/lib/posixlib.rst +++ b/docs/lib/posixlib.rst @@ -22,16 +22,16 @@ C Header Scala Native Module `fenv.h`_ N/A `float.h`_ scala.scalanative.libc.float_ `fmtmsg.h`_ N/A -`fnmatch.h`_ N/A +`fnmatch.h`_ scala.scalanative.posix.fnmatch_ `ftw.h`_ N/A `getopt.h`_ scala.scalanative.posix.getopt_ -`glob.h`_ N/A +`glob.h`_ scala.scalanative.posix.glob_ `grp.h`_ scala.scalanative.posix.grp_ `iconv.h`_ N/A `inttypes.h`_ scala.scalanative.posix.inttypes_ `iso646.h`_ N/A `langinfo.h`_ N/A -`libgen.h`_ N/A +`libgen.h`_ scala.scalanative.posix.libgen_ `limits.h`_ scala.scalanative.posix.limits_ `locale.h`_ N/A `math.h`_ scala.scalanative.libc.math_ @@ -186,10 +186,13 @@ C Header Scala Native Module .. _scala.scalanative.posix.errno: https://github.com/scala-native/scala-native/blob/main/posixlib/src/main/scala/scala/scalanative/posix/errno.scala .. _scala.scalanative.posix.fcntl: https://github.com/scala-native/scala-native/blob/main/posixlib/src/main/scala/scala/scalanative/posix/fcntl.scala .. _scala.scalanative.libc.float: https://github.com/scala-native/scala-native/blob/main/clib/src/main/scala/scala/scalanative/libc/float.scala +.. _scala.scalanative.posix.fnmatch: https://github.com/scala-native/scala-native/blob/main/clib/src/main/scala/scala/scalanative/libc/fnmatch.scala .. _scala.scalanative.posix.getopt: https://github.com/scala-native/scala-native/blob/main/posixlib/src/main/scala/scala/scalanative/posix/getopt.scala +.. _scala.scalanative.posix.glob: https://github.com/scala-native/scala-native/blob/main/posixlib/src/main/scala/scala/scalanative/posix/glob.scala .. _scala.scalanative.posix.grp: https://github.com/scala-native/scala-native/blob/main/posixlib/src/main/scala/scala/scalanative/posix/grp.scala .. _scala.scalanative.posix.inttypes: https://github.com/scala-native/scala-native/blob/main/posixlib/src/main/scala/scala/scalanative/posix/inttypes.scala .. _scala.scalanative.posix.limits: https://github.com/scala-native/scala-native/blob/main/posixlib/src/main/scala/scala/scalanative/posix/limits.scala +.. _scala.scalanative.posix.libgen: https://github.com/scala-native/scala-native/blob/main/posixlib/src/main/scala/scala/scalanative/posix/libgen.scala .. _scala.scalanative.libc.math: https://github.com/scala-native/scala-native/blob/main/clib/src/main/scala/scala/scalanative/libc/math.scala .. _scala.scalanative.posix.net.if: https://github.com/scala-native/scala-native/blob/main/posixlib/src/main/scala/scala/scalanative/posix/net/if.scala .. _scala.scalanative.posix.netdb: https://github.com/scala-native/scala-native/blob/main/posixlib/src/main/scala/scala/scalanative/posix/netdb.scala diff --git a/posixlib/src/main/resources/scala-native/fnmatch.c b/posixlib/src/main/resources/scala-native/fnmatch.c new file mode 100644 index 0000000000..a19735dd23 --- /dev/null +++ b/posixlib/src/main/resources/scala-native/fnmatch.c @@ -0,0 +1,20 @@ +#if defined(__unix__) || defined(__unix) || defined(unix) || \ + (defined(__APPLE__) && defined(__MACH__)) + +#include +#endif // Unix or Mac OS + +#if defined(_WIN32) // bogus values to keep linker happy +#define FNM_NOMATCH -1 +#define FNM_PATHNAME -1 +#define FNM_PERIOD -1 +#define FNM_NOESCAPE -1 +#endif // _WIN32 + +int scalanative_fnm_nomatch() { return FNM_NOMATCH; }; + +int scalanative_fnm_pathname() { return FNM_PATHNAME; }; + +int scalanative_fnm_period() { return FNM_PERIOD; }; + +int scalanative_fnm_noescape() { return FNM_NOESCAPE; }; diff --git a/posixlib/src/main/resources/scala-native/glob.c b/posixlib/src/main/resources/scala-native/glob.c new file mode 100644 index 0000000000..2da00f1f0c --- /dev/null +++ b/posixlib/src/main/resources/scala-native/glob.c @@ -0,0 +1,80 @@ +#if defined(__unix__) || defined(__unix) || defined(unix) || \ + (defined(__APPLE__) && defined(__MACH__)) + +#include +#include + +// Note Well: see corresponding comments in glob.scala +struct scalanative_glob_t { + size_t gl_pathc; // count of total paths so far + int gl_matchc; // count of paths matching pattern + size_t gl_offs; // Slots to reserve at the beginning of gl_pathv. + int gl_flags; // returned flags + char **gl_pathv; // Pointer to a list of matched pathnames. + char filler[56]; // macOS non-POSIX fields +}; + +#if !(defined __STDC_VERSION__) || (__STDC_VERSION__ < 201112L) +#ifndef SCALANATIVE_SUPPRESS_STRUCT_CHECK_WARNING +#warning "Size and order of C structures are not checked when -std < c11." +#endif +#else + +_Static_assert(sizeof(struct scalanative_glob_t) >= sizeof(glob_t), + "size mismatch: glob_t"); + +_Static_assert(offsetof(struct scalanative_glob_t, gl_pathc) == + offsetof(glob_t, gl_pathc), + "offset mismatch: glob_t gl_pathc"); + +_Static_assert(offsetof(struct scalanative_glob_t, gl_offs) == + offsetof(glob_t, gl_offs), + "offset mismatch: glob_t gl_offs"); + +#if defined(__linux__) +// gl_pathv is second element on Linux. +_Static_assert(sizeof(((struct scalanative_glob_t *)0)->gl_pathc) == + offsetof(glob_t, gl_pathv), + "offset mismatch: glob_t gl_pathv"); +#else // __APPLE__ +_Static_assert(offsetof(struct scalanative_glob_t, gl_pathv) == + offsetof(glob_t, gl_pathv), + "offset mismatch: glob_t gl_pathv"); +#endif // __APPLE__ +#endif // __STDC_VERSION__ +#endif // Unix or Mac OS + +#if defined(_WIN32) // bogus values to keep linker happy +#define GLOB_APPEND -1 +#define GLOB_DOOFFS -1 +#define GLOB_ERR -1 +#define GLOB_MARK -1 +#define GLOB_NOCHECK -1 +#define GLOB_NOESCAPE -1 +#define GLOB_NOSORT -1 +#define GLOB_ABORTED -1 +#define GLOB_NOMATCH -1 +#define GLOB_NOSPACE -1 +#endif // _WIN32 +// flags + +int scalanative_glob_append() { return GLOB_APPEND; }; + +int scalanative_glob_dooffs() { return GLOB_DOOFFS; }; + +int scalanative_glob_err() { return GLOB_ERR; }; + +int scalanative_glob_mark() { return GLOB_MARK; }; + +int scalanative_glob_nocheck() { return GLOB_NOCHECK; }; + +int scalanative_glob_noescape() { return GLOB_NOESCAPE; }; + +int scalanative_glob_nosort() { return GLOB_NOSORT; }; + +// error returns +int scalanative_glob_aborted() { return GLOB_ABORTED; }; + +int scalanative_glob_nomatch() { return GLOB_NOMATCH; }; + +int scalanative_glob_nospace() { return GLOB_NOSPACE; }; diff --git a/posixlib/src/main/scala/scala/scalanative/posix/fnmatch.scala b/posixlib/src/main/scala/scala/scalanative/posix/fnmatch.scala new file mode 100644 index 0000000000..3c318ed8d3 --- /dev/null +++ b/posixlib/src/main/scala/scala/scalanative/posix/fnmatch.scala @@ -0,0 +1,33 @@ +package scala.scalanative +package posix + +import scalanative.unsafe._ + +import scalanative.posix.sys.types + +/** POSIX fnmatch.h for Scala + * + * The Open Group Base Specifications + * [[https://pubs.opengroup.org/onlinepubs/9699919799 Issue 7, 2018]] edition. + */ + +@extern +object fnmatch { + // Symbolic constants + + @name("scalanative_fnm_nomatch") + def FNM_NOMATCH: CInt = extern + + @name("scalanative_fnm_pathname") + def FNM_PATHNAME: CInt = extern + + @name("scalanative_fnm_period") + def FNM_PERIOD: CInt = extern + + @name("scalanative_fnm_noescape") + def FNM_NOESCAPE: CInt = extern + + // Method + + def fnmatch(pattern: CString, string: CString, flags: CInt): CInt = extern +} diff --git a/posixlib/src/main/scala/scala/scalanative/posix/glob.scala b/posixlib/src/main/scala/scala/scalanative/posix/glob.scala new file mode 100644 index 0000000000..a88d54de24 --- /dev/null +++ b/posixlib/src/main/scala/scala/scalanative/posix/glob.scala @@ -0,0 +1,119 @@ +package scala.scalanative +package posix + +import scalanative.unsafe._ +import scalanative.unsafe.Nat._ +import scalanative.meta.LinktimeInfo.isLinux + +import scalanative.posix.sys.types + +/** POSIX glob.h for Scala + * + * The Open Group Base Specifications + * [[https://pubs.opengroup.org/onlinepubs/9699919799 Issue 7, 2018]] edition. + */ + +@extern +object glob { + + type size_t = types.size_t + + /* POSIX specification names the minimally required fields. + * It allows re-ordering and additional fields. + * + * Linux orders the fields in the same way as POSIX. macOS uses + * a different order. Use the macOS field order to correspond with the + * macOS size (below). globOps below handles the differing field orders. + * + * macOS sizeof(glob_t) is 88 bytes. Linux is 72. Declare Scala Native glob_t + * as the former size to cover both cases. glob.c has _Static_assert code + * to check Scala Native glob_t against operating system size & field order. + */ + type glob_t = CStruct6[ + size_t, // gl_pathc, count of total paths so far + CInt, // gl_matchc, count of paths matching pattern + size_t, // gl_offs, reserved at beginning of gl_pathv + CInt, // gl_flags, returned flags + Ptr[CString], // gl_pathv, list of paths matching pattern + CArray[CUnsignedChar, Nat.Digit2[_5, _6]] // macOS non-POSIX fields + ] + + type unixGlob_t = CStruct4[ + size_t, // gl_pathc, count of total paths so far + Ptr[CString], // gl_pathv, list of paths matching pattern + size_t, // gl_offs, reserved at beginning of gl_pathv + CArray[CUnsignedChar, Nat.Digit2[_6, _4]] // macOS non-POSIX fields + ] + + /// Symbolic constants + // flags + + @name("scalanative_glob_append") + def GLOB_APPEND: CInt = extern + + @name("scalanative_glob_dooffs") + def GLOB_DOOFFS: CInt = extern + + @name("scalanative_glob_err") + def GLOB_ERR: CInt = extern + + @name("scalanative_glob_mark") + def GLOB_MARK: CInt = extern + + @name("scalanative_glob_nocheck") + def GLOB_NOCHECK: CInt = extern + + @name("scalanative_glob_noescape") + def GLOB_NOESCAPE: CInt = extern + + @name("scalanative_glob_nosort") + def GLOB_NOSORT: CInt = extern + + // error returns + @name("scalanative_glob_aborted") + def GLOB_ABORTED: CInt = extern + + @name("scalanative_glob_nomatch") + def GLOB_NOMATCH: CInt = extern + + @name("scalanative_glob_nospace") + def GLOB_NOSPACE: CInt = extern + + /// Methods + + def glob( + pattern: CString, + flags: CInt, + errfunc: CFuncPtr2[CString, CInt, CInt], + pglob: Ptr[glob_t] + ): CInt = extern + + def globfree(pglob: Ptr[glob_t]): CInt = extern +} + +object globOps { + import glob.{glob_t, unixGlob_t, size_t} + + implicit class glob_tOps(val ptr: Ptr[glob_t]) extends AnyVal { + def gl_pathc: size_t = ptr._1 // Count of paths matched by pattern. + + // Pointer to a list of matched pathnames. + def gl_pathv: Ptr[CString] = + if (isLinux) ptr.asInstanceOf[Ptr[unixGlob_t]]._2 + else ptr._5 + + // Slots to reserve at the beginning of gl_pathv. + def gl_offs: size_t = ptr._3 + + // gl_pathc & gl_pathv are usually read-only; gl_offs get used for write. + def gl_pathc_=(v: size_t): Unit = ptr._1 = v + + def gl_pathv_=(v: Ptr[CString]): Unit = + if (isLinux) + ptr.asInstanceOf[Ptr[unixGlob_t]]._2 = v + else + ptr._5 = v + + def gl_offs_=(v: size_t): Unit = ptr._3 = v + } +} diff --git a/posixlib/src/main/scala/scala/scalanative/posix/libgen.scala b/posixlib/src/main/scala/scala/scalanative/posix/libgen.scala new file mode 100644 index 0000000000..57cbc1682b --- /dev/null +++ b/posixlib/src/main/scala/scala/scalanative/posix/libgen.scala @@ -0,0 +1,23 @@ +package scala.scalanative +package posix + +import scalanative.unsafe._ + +/** POSIX libgen.h for Scala + * + * The Open Group Base Specifications + * [[https://pubs.opengroup.org/onlinepubs/9699919799 Issue 7, 2018]] edition. + * + * A method with an XSI comment indicates it is defined in extended POSIX + * X/Open System Interfaces, not base POSIX. + */ + +@extern +object libgen { + + /** XSI */ + def basename(path: CString): CString = extern + + /** XSI */ + def dirname(path: CString): CString = extern +} diff --git a/unit-tests/native/src/test/scala/scala/scalanative/posix/GlobTest.scala b/unit-tests/native/src/test/scala/scala/scalanative/posix/GlobTest.scala new file mode 100644 index 0000000000..bf6e6c8c6b --- /dev/null +++ b/unit-tests/native/src/test/scala/scala/scalanative/posix/GlobTest.scala @@ -0,0 +1,131 @@ +package org.scalanative.testsuite.posixlib + +import org.junit.Test +import org.junit.Assert._ +import org.junit.Assume._ +import org.junit.{BeforeClass, AfterClass} + +import scala.scalanative.meta.LinktimeInfo.isWindows + +import java.nio.file.{Path, Paths} +import java.nio.file.Files + +import scala.scalanative.unsafe._ +import scala.scalanative.unsigned._ + +import scala.scalanative.posix.glob._ +import scala.scalanative.posix.globOps._ + +object GlobTest { + private var orgDir: Path = _ + private var posixlibDir: Path = _ + private var workDir: Path = _ + + private var createdFilePaths: List[Path] = _ + + private def createTestData(dir: Path): List[Path] = { + List("a.no", "b.yes", "c.no", "d.yes", "e.no").map(fname => + Files.createFile(dir.resolve(fname)) + ) + } + + @BeforeClass + def beforeClass(): Unit = { + if (!isWindows) { + orgDir = Files.createTempDirectory("org.scalanative.testsuite") + posixlibDir = orgDir.resolve("posixlib") + workDir = Files.createDirectories(posixlibDir.resolve("GlobTest")) + + createdFilePaths = createTestData(workDir) + } + } + + @AfterClass + def afterClass(): Unit = { + if (!isWindows) { + /* Delete items created by this test. + * Delete files within "GlobTest" directory and then the directory itself, + * its parent & grandparent. + */ + val deleteList = createdFilePaths :+ workDir :+ posixlibDir :+ orgDir + deleteList.foreach(p => Files.delete(p)) + } + } +} + +class GlobTest { + import GlobTest._ + + private def checkGlobStatus(status: Int, pattern: String): Unit = { + if (status != 0) { + val msg = + if (status == GLOB_ABORTED) "GLOB_ABORTED" + else if (status == GLOB_NOMATCH) "GLOB_NOMATCH" + else if (status == GLOB_NOSPACE) "GLOB_NOSPACE" + else s"Unknown code: ${status}" + + fail(s"glob(${pattern})failed: ${msg}") + } + } + + @Test def globExpectNotFound(): Unit = { + assumeTrue( + "glob.scala is not implemented on Windows", + !isWindows + ) + + if (!isWindows) Zone { implicit z => + val globP = stackalloc[glob_t]() + + val wdAbsP = workDir.toAbsolutePath() + val pattern = s"${wdAbsP}/*.NONEXISTENT" + + val status = glob(toCString(pattern), 0, null, globP) + + if (status != GLOB_NOMATCH) { + if (status != 0) checkGlobStatus(status, pattern) + else { + val found = fromCString(globP.gl_pathv(0)) + fail(s"Unexpected match, pattern: '${pattern}' found: '${found}'") + } + } + + globfree(globP) // should never get here, but if here, do not leak memory + + } // !isWindows + } + + @Test def globExpectFound(): Unit = { + assumeTrue( + "glob.scala is not implemented on Windows", + !isWindows + ) + + if (!isWindows) Zone { implicit z => + val globP = stackalloc[glob_t]() + + val wdAbsP = workDir.toAbsolutePath() + val pattern = s"${wdAbsP}/*.yes" + + val status = glob(toCString(pattern), 0, null, globP) + + try { + checkGlobStatus(status, pattern) + + assertEquals("Unexpected gl_pathc", 2, globP.gl_pathc.toInt) + + // by default glob() vector is sorted, sort expected to match. + val expected = Array("b.yes", "d.yes") + + for (j <- 0 until globP.gl_pathc.toInt) + assertEquals( + "Unexpected match found", + s"${wdAbsP}/${expected(j)}", + fromCString(globP.gl_pathv(j)) + ) + } finally { + globfree(globP) + } + } // !isWindows + } +} From 12a20a59009e3ea915b44085340c5d56bf043deb Mon Sep 17 00:00:00 2001 From: LeeTibbert Date: Mon, 19 Dec 2022 10:30:44 +0100 Subject: [PATCH 17/64] Implement wordexp.h on Unix (#3042) (cherry picked from commit 4c13b2412c09d804e590fb402b207ad99a9e288a) --- docs/lib/posixlib.rst | 4 +- .../src/main/resources/scala-native/wordexp.c | 74 ++++++++++ .../scala/scalanative/posix/wordexp.scala | 84 ++++++++++++ .../scala/scalanative/posix/WordexpTest.scala | 128 ++++++++++++++++++ 4 files changed, 289 insertions(+), 1 deletion(-) create mode 100644 posixlib/src/main/resources/scala-native/wordexp.c create mode 100644 posixlib/src/main/scala/scala/scalanative/posix/wordexp.scala create mode 100644 unit-tests/native/src/test/scala/scala/scalanative/posix/WordexpTest.scala diff --git a/docs/lib/posixlib.rst b/docs/lib/posixlib.rst index 24f11b40bc..18d48a3986 100644 --- a/docs/lib/posixlib.rst +++ b/docs/lib/posixlib.rst @@ -91,7 +91,7 @@ C Header Scala Native Module `utmpx.h`_ N/A `wchar.h`_ N/A `wctype.h`_ N/A -`wordexp.h`_ N/A +`wordexp.h`_ scala.scalanative.posix.wordexp_ ================= ================================== .. _aio.h: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/aio.h.html @@ -227,6 +227,8 @@ C Header Scala Native Module .. _scala.scalanative.posix.time: https://github.com/scala-native/scala-native/blob/main/posixlib/src/main/scala/scala/scalanative/posix/time.scala .. _scala.scalanative.posix.unistd: https://github.com/scala-native/scala-native/blob/main/posixlib/src/main/scala/scala/scalanative/posix/unistd.scala .. _scala.scalanative.posix.utime: https://github.com/scala-native/scala-native/blob/main/posixlib/src/main/scala/scala/scalanative/posix/utime.scala +.. _scala.scalanative.posix.wchar: https://github.com/scala-native/scala-native/blob/main/posixlib/src/main/scala/scala/scalanative/posix/wchar.scala +.. _scala.scalanative.posix.wordexp: https://github.com/scala-native/scala-native/blob/main/posixlib/src/main/scala/scala/scalanative/posix/wordexp.scala .. rubric Footnotes .. [#inet_ntoa] The argument to inet_ntoa() differs from the POSIX diff --git a/posixlib/src/main/resources/scala-native/wordexp.c b/posixlib/src/main/resources/scala-native/wordexp.c new file mode 100644 index 0000000000..5c1672defe --- /dev/null +++ b/posixlib/src/main/resources/scala-native/wordexp.c @@ -0,0 +1,74 @@ +#if defined(__unix__) || defined(__unix) || defined(unix) || \ + (defined(__APPLE__) && defined(__MACH__)) + +#include +#include + +struct scalanative_wordexp_t { + size_t we_wordc; // Count of words matched by 'words'. + char **we_wordv; // Pointer to list of expanded words. + size_t we_offs; // Slots to reserve at the beginning of we_wordv. +}; + +#if !(defined __STDC_VERSION__) || (__STDC_VERSION__ < 201112L) +#ifndef SCALANATIVE_SUPPRESS_STRUCT_CHECK_WARNING +#warning "Size and order of C structures are not checked when -std < c11." +#endif +#else + +_Static_assert(sizeof(struct scalanative_wordexp_t) >= sizeof(wordexp_t), + "size mismatch: wordexp_t"); + +_Static_assert(offsetof(struct scalanative_wordexp_t, we_wordc) == + offsetof(wordexp_t, we_wordc), + "offset mismatch: wordexp_t we_wordc"); + +_Static_assert(offsetof(struct scalanative_wordexp_t, we_wordv) == + offsetof(wordexp_t, we_wordv), + "offset mismatch: wordexp_t we_wordv"); + +_Static_assert(offsetof(struct scalanative_wordexp_t, we_offs) == + offsetof(wordexp_t, we_offs), + "offset mismatch: wordexp_t we_offs"); + +#endif // __STDC_VERSION__ +#endif // Unix or Mac OS + +#if defined(_WIN32) // bogus values to keep linker happy +#define WRDE_APPEND -1 +#define WRDE_DOOFFS -1 +#define WRDE_NOCMD -1 +#define WRDE_REUSE -1 +#define WRDE_SHOWERR -1 +#define WRDE_UNDEF -1 +#define WRDE_BADCHAR -1 +#define WRDE_BADVAL -1 +#define WRDE_CMDSUB -1 +#define WRDE_NOSPACE -1 +#define WRDE_SYNTAX -1 +#endif // _WIN32 + +// flags + +int scalanative_wrde_append() { return WRDE_APPEND; }; + +int scalanative_wrde_dooffs() { return WRDE_DOOFFS; }; + +int scalanative_wrde_nocmd() { return WRDE_NOCMD; }; + +int scalanative_wrde_reuse() { return WRDE_REUSE; }; + +int scalanative_wrde_showerr() { return WRDE_SHOWERR; }; + +int scalanative_wrde_undef() { return WRDE_UNDEF; }; + +// error returns +int scalanative_wrde_badchar() { return WRDE_BADCHAR; }; + +int scalanative_wrde_badval() { return WRDE_BADVAL; }; + +int scalanative_wrde_cmdsub() { return WRDE_CMDSUB; }; + +int scalanative_wrde_nospace() { return WRDE_NOSPACE; }; + +int scalanative_wrde_syntax() { return WRDE_SYNTAX; }; diff --git a/posixlib/src/main/scala/scala/scalanative/posix/wordexp.scala b/posixlib/src/main/scala/scala/scalanative/posix/wordexp.scala new file mode 100644 index 0000000000..ea78b5d27d --- /dev/null +++ b/posixlib/src/main/scala/scala/scalanative/posix/wordexp.scala @@ -0,0 +1,84 @@ +package scala.scalanative +package posix + +import scalanative.unsafe._ +import scalanative.unsafe.Nat._ + +import scalanative.posix.sys.types.size_t + +/** POSIX wordexp.h for Scala + * + * The Open Group Base Specifications + * [[https://pubs.opengroup.org/onlinepubs/9699919799 Issue 7, 2018]] edition. + */ + +@extern +object wordexp { + + type wordexp_t = CStruct3[ + size_t, // we_wordc Count of words matched by 'words'. + Ptr[CString], // we_wordv Pointer to list of expanded words. + size_t, // we_offs Slots to reserve at the beginning of we_wordv. + ] + + /// Symbolic constants + // flags + + @name("scalanative_wrde_append") + def WRDE_APPEND: CInt = extern + + @name("scalanative_wrde_dooffs") + def WRDE_DOOFFS: CInt = extern + + @name("scalanative_wrde_nocmd") + def WRDE_NOCMD: CInt = extern + + @name("scalanative_wrde_reuse") + def WRDE_REUSE: CInt = extern + + @name("scalanative_wrde_showerr") + def WRDE_SHOWERR: CInt = extern + + @name("scalanative_wrde_undef") + def WRDE_UNDEF: CInt = extern + + // error returns + @name("scalanative_wrde_badchar") + def WRDE_BADCHAR: CInt = extern + + @name("scalanative_wrde_badval") + def WRDE_BADVAL: CInt = extern + + @name("scalanative_wrde_cmdsub") + def WRDE_CMDSUB: CInt = extern + + @name("scalanative_wrde_nospace") + def WRDE_NOSPACE: CInt = extern + + @name("scalanative_wrde_syntax") + def WRDE_SYNTAX: CInt = extern + + /// Methods + + def wordexp( + pattern: CString, + expansion: Ptr[wordexp_t], + flags: CInt + ): CInt = extern + + def wordfree(wordexpP: Ptr[wordexp_t]): CInt = extern +} + +object wordexpOps { + import wordexp.wordexp_t + + implicit class wordexp_tOps(val ptr: Ptr[wordexp_t]) extends AnyVal { + def we_wordc: size_t = ptr._1 + def we_wordv: Ptr[CString] = ptr._2 + def we_offs: size_t = ptr._3 + + def we_wordc_=(v: size_t): Unit = ptr._1 = v + def we_wordv_=(v: Ptr[CString]): Unit = ptr._2 = v + def we_offs_=(v: size_t): Unit = ptr._3 = v + } +} diff --git a/unit-tests/native/src/test/scala/scala/scalanative/posix/WordexpTest.scala b/unit-tests/native/src/test/scala/scala/scalanative/posix/WordexpTest.scala new file mode 100644 index 0000000000..04ba3ea68d --- /dev/null +++ b/unit-tests/native/src/test/scala/scala/scalanative/posix/WordexpTest.scala @@ -0,0 +1,128 @@ +package org.scalanative.testsuite.posixlib + +import org.junit.Test +import org.junit.Assert._ +import org.junit.Assume._ + +import scala.scalanative.meta.LinktimeInfo.isWindows + +import scala.scalanative.unsafe._ +import scala.scalanative.unsigned._ + +import scala.scalanative.posix.stdlib + +import scala.scalanative.posix.wordexp._ +import scala.scalanative.posix.wordexpOps._ + +class WordexpTest { + + private def checkWordexpStatus(status: Int, pattern: String): Unit = { + if (status != 0) { + val msg = + if (status == WRDE_BADCHAR) "WRDE_BADCHAR" + else if (status == WRDE_BADVAL) "WRDE_BADVAL" + else if (status == WRDE_CMDSUB) "WRDE_CMDSUB" + else if (status == WRDE_NOSPACE) "WRDE_NOSPACE" + else if (status == WRDE_SYNTAX) "WRDE_SYNTAX" + else s"Unknown code: ${status}" + + fail(s"wordexp(${pattern})failed: ${msg}") + } + } + + @Test def wordexpExpectBadcharError(): Unit = { + assumeTrue( + "wordexp.scala is not implemented on Windows", + !isWindows + ) + if (!isWindows) Zone { implicit z => + val wrdeP = stackalloc[wordexp_t]() + + /* wordexp is defined as using the sh shell. That shell does not + * allow an out-of-place semicolon on the command line. Show that we + * are indeed using sh. + */ + val pattern = "prefix ; suffix" + val status = wordexp(toCString(pattern), wrdeP, 0) + + try { + assertEquals("Expected WRDE_BADCHAR error", WRDE_BADCHAR, status) + } finally { + wordfree(wrdeP) + } + } + } + + @Test def wordexpTildeExpansion: Unit = { + assumeTrue( + "wordexp.scala is not implemented on Windows", + !isWindows + ) + + if (!isWindows) Zone { implicit z => + val wrdeP = stackalloc[wordexp_t]() + + val pattern = "~" + val status = wordexp(toCString(pattern), wrdeP, 0) + + try { + checkWordexpStatus(status, pattern) + + assertEquals("Unexpected we_wordc", 1, wrdeP.we_wordc.toInt) + + val expected = System.getProperty("user.home", "Alabama") + + assertEquals( + s"Unexpected expansion of '${pattern}'", + expected, + fromCString(wrdeP.we_wordv(0)) + ) + } finally { + wordfree(wrdeP) + } + } // !isWindows + } + + @Test def wordexpVariableSubstitution: Unit = { + assumeTrue( + "wordexp.scala is not implemented on Windows", + !isWindows + ) + + /* The environment variable $HOME may not exist on all non-CI systems. + * Do a 'soft fail' on such systems. This allows running this test + * on systems where the variable does exist without hard failing in + * the wild. + */ + + val hasHomeEnvvar = stdlib.getenv(c"HOME") + + assumeTrue( + "Could not find environment variable named 'HOME'", + hasHomeEnvvar != null + ) + + if (!isWindows) Zone { implicit z => + val wrdeP = stackalloc[wordexp_t]() + + val pattern = "Phil $HOME Ochs" + val status = wordexp(toCString(pattern), wrdeP, 0) + + try { + checkWordexpStatus(status, pattern) + + assertEquals("Unexpected we_wordc", 3, wrdeP.we_wordc.toInt) + + val expected = System.getProperty("user.home", "Mississippi") + + assertEquals( + s"Unexpected expansion of '${pattern}'", + expected, + fromCString(wrdeP.we_wordv(1)) + ) + } finally { + wordfree(wrdeP) + } + } // !isWindows + } +} From 06f68b2217b807431a686649433972b95cf359d2 Mon Sep 17 00:00:00 2001 From: LeeTibbert Date: Mon, 19 Dec 2022 04:32:11 -0500 Subject: [PATCH 18/64] Reduce memory usage in posixlib spawn (#3040) (cherry picked from commit 1110c8e930117469e12717e2ddc3f2ebc94e55a3) --- .../scala/scala/scalanative/posix/spawn.scala | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/posixlib/src/main/scala/scala/scalanative/posix/spawn.scala b/posixlib/src/main/scala/scala/scalanative/posix/spawn.scala index 24b5e7ccbb..d6c799e3a8 100644 --- a/posixlib/src/main/scala/scala/scalanative/posix/spawn.scala +++ b/posixlib/src/main/scala/scala/scalanative/posix/spawn.scala @@ -20,15 +20,23 @@ object spawn { * types. They have no user accessible fields, not even the component Bytes. * Users of these types should leave them opaque: i.e. no read, no write. * - * The sizes here are from Linux 6.0. Code in spawn.c checks at compile-time - * that these sizes are greater than or equal to the equivalent OS types. + * The sizes here are from 64 bit Linux 6.0. Code in spawn.c checks at + * compile-time that these sizes are greater than or equal to the equivalent + * OS types. + * + * Use CUnsignedLongLong as array elements so that Array is sure to be + * 64 bit aligned; may be overkill. + * * Maintainers: If you change sizes, either here or in spawn.c, change * the other file also. */ - type posix_spawnattr_t = CArray[CUnsignedLong, Nat.Digit3[_3, _3, _6]] + // Overall required 336 bytes, 8 * 42 + type posix_spawnattr_t = CArray[CUnsignedLongLong, Nat.Digit2[_4, _2]] - type posix_spawn_file_actions_t = CArray[CUnsignedLong, Nat.Digit2[_8, _0]] + // Overall required 80 bytes, 8 * 10 + type posix_spawn_file_actions_t = + CArray[CUnsignedLongLong, Nat.Digit2[_1, _0]] type mode_t = types.mode_t type pid_t = types.pid_t From 50eecf943b60ecd5a5198cfd21bc94d114548b5b Mon Sep 17 00:00:00 2001 From: LeeTibbert Date: Tue, 20 Dec 2022 11:01:47 +0100 Subject: [PATCH 19/64] Implement some posixlib & clib locale related methods on Unix (#3034) * Implement some posixlib & clib locale related methods * scalafmt * Remove import which makes earlier Scala versions unhappy * Fix Windows link error * Fix Scala 2.11 & 2.12 unhappiness * Delete LocaleTest as it sometimes slays TimeTest * Incorporate reviewer suggestion * See if reworked LocaleTest is ready for prime time * Touchup LocaleTest; pig needs more lipstick * Fix LocalTest LC_ALL references * Fix LocalTest Linux/macOS en_US locale differences * Do not do locale save/restore dance on Windows; no LC_ALL there * LocaleTest must handle no en_US on Multi-arch CI * make clib.locale trait private to scalanative (cherry picked from commit cc56fc96b7ff4b143e024879bcf5fa820c361fab) --- clib/src/main/resources/scala-native/locale.c | 184 +++++++++++++++++ .../scala/scala/scalanative/libc/locale.scala | 161 +++++++++++++++ docs/lib/libc.rst | 9 +- docs/lib/posixlib.rst | 5 +- .../src/main/resources/scala-native/locale.c | 37 ++++ .../main/resources/scala-native/monetary.c | 40 ++++ .../scala/scalanative/posix/locale.scala | 98 ++++++++- .../scala/scalanative/posix/monetary.scala | 109 ++++++++++ .../scala/scalanative/posix/LocaleTest.scala | 195 ++++++++++++++++++ .../scalanative/posix/MonetaryTest.scala | 91 ++++++++ 10 files changed, 918 insertions(+), 11 deletions(-) create mode 100644 clib/src/main/resources/scala-native/locale.c create mode 100644 clib/src/main/scala/scala/scalanative/libc/locale.scala create mode 100644 posixlib/src/main/resources/scala-native/locale.c create mode 100644 posixlib/src/main/resources/scala-native/monetary.c create mode 100644 posixlib/src/main/scala/scala/scalanative/posix/monetary.scala create mode 100644 unit-tests/native/src/test/scala/scala/scalanative/posix/LocaleTest.scala create mode 100644 unit-tests/native/src/test/scala/scala/scalanative/posix/MonetaryTest.scala diff --git a/clib/src/main/resources/scala-native/locale.c b/clib/src/main/resources/scala-native/locale.c new file mode 100644 index 0000000000..65ff33c4c0 --- /dev/null +++ b/clib/src/main/resources/scala-native/locale.c @@ -0,0 +1,184 @@ +#ifdef _WIN32 +// No Windows support +#else +#if !(defined __STDC_VERSION__) || (__STDC_VERSION__ < 201112L) +#ifndef SCALANATIVE_SUPPRESS_STRUCT_CHECK_WARNING +#warning "Size and order of C structures are not checked when -std < c11." +#endif +#else // POSIX +#include +#include + +/* _Static_assert statements below verify that this layout is valid + * on Linux & mac_OS. Read the documentation but do not believe it too much. + * Trust the _Static_assert statements. + * + * This is the Linux physical layout. macOS swaps/exchanges the + * int_p_sep_by_space & int_n_cs_precedes fields. + * + * macOS "man localeconv" describes this layout. + * + * Linux "man lconv" describes a layout with int_curr_symbol after + * n_sign_position. _Static_assert below refutes that. + * + * POSIX 2018 describes its usual "which shall include at least the + * following members". As is its right, it then gives a list which + * has no correspondence this layout. + */ + +struct scalanative_lconv { + char *decimal_point; + char *thousands_sep; + char *grouping; + char *int_curr_symbol; + char *currency_symbol; + + char *mon_decimal_point; + char *mon_thousands_sep; + char *mon_grouping; + char *positive_sign; + char *negative_sign; + + char int_frac_digits; + char frac_digits; + char p_cs_precedes; + char p_sep_by_space; + char n_cs_precedes; + + char n_sep_by_space; + char p_sign_posn; + char n_sign_posn; + char int_p_cs_precedes; + char int_p_sep_by_space; // Linux, overlays macOS int_n_cs_precedes + + char int_n_cs_precedes; // Linux, overlays macOS int_p_sep_by_space + char int_n_sep_by_space; + char int_p_sign_posn; + char int_n_sign_posn; +}; + +_Static_assert(sizeof(struct scalanative_lconv) <= sizeof(struct lconv), + "Unexpected size: os lconv"); + +_Static_assert(offsetof(struct scalanative_lconv, decimal_point) == + offsetof(struct lconv, decimal_point), + "Unexpected offset: scalanative_lconv.decimal_point"); + +_Static_assert(offsetof(struct scalanative_lconv, thousands_sep) == + offsetof(struct lconv, thousands_sep), + "Unexpected offset: scalanative_lconv.thousands_sep"); + +_Static_assert(offsetof(struct scalanative_lconv, grouping) == + offsetof(struct lconv, grouping), + "Unexpected offset: scalanative_lconv.grouping"); + +_Static_assert(offsetof(struct scalanative_lconv, int_curr_symbol) == + offsetof(struct lconv, int_curr_symbol), + "Unexpected offset: scalanative_lconv.int_curr_symbol"); + +_Static_assert(offsetof(struct scalanative_lconv, currency_symbol) == + offsetof(struct lconv, currency_symbol), + "Unexpected offset: scalanative_lconv.currency_symbol"); + +_Static_assert(offsetof(struct scalanative_lconv, mon_decimal_point) == + offsetof(struct lconv, mon_decimal_point), + "Unexpected offset: scalanative_lconv.mon_decimal_point"); + +_Static_assert(offsetof(struct scalanative_lconv, mon_grouping) == + offsetof(struct lconv, mon_grouping), + "Unexpected offset: scalanative_lconv.mon_grouping"); + +_Static_assert(offsetof(struct scalanative_lconv, mon_thousands_sep) == + offsetof(struct lconv, mon_thousands_sep), + "Unexpected offset: scalanative_lconv.mon_thousands_sep"); + +_Static_assert(offsetof(struct scalanative_lconv, positive_sign) == + offsetof(struct lconv, positive_sign), + "Unexpected offset: scalanative_lconv.positive_sign"); + +_Static_assert(offsetof(struct scalanative_lconv, negative_sign) == + offsetof(struct lconv, negative_sign), + "Unexpected offset: scalanative_lconv.negative_sign"); + +_Static_assert(offsetof(struct scalanative_lconv, int_frac_digits) == + offsetof(struct lconv, int_frac_digits), + "Unexpected offset: scalanative_lconv.int_frac_digits"); + +_Static_assert(offsetof(struct scalanative_lconv, frac_digits) == + offsetof(struct lconv, frac_digits), + "Unexpected offset: scalanative_lconv,frac_digits"); + +_Static_assert(offsetof(struct scalanative_lconv, p_cs_precedes) == + offsetof(struct lconv, p_cs_precedes), + "Unexpected offset: scalanative_lconv.p_cs_precedes."); + +_Static_assert(offsetof(struct scalanative_lconv, p_sep_by_space) == + offsetof(struct lconv, p_sep_by_space), + "Unexpected offset: scalanative_lconv.p_sep_by_space"); + +_Static_assert(offsetof(struct scalanative_lconv, n_cs_precedes) == + offsetof(struct lconv, n_cs_precedes), + "Unexpected offset: scalanative_lconv.n_cs_precedes"); + +_Static_assert(offsetof(struct scalanative_lconv, n_sep_by_space) == + offsetof(struct lconv, n_sep_by_space), + "Unexpected offset: scalanative_lconv.n_sep_by_space"); + +_Static_assert(offsetof(struct scalanative_lconv, p_sign_posn) == + offsetof(struct lconv, p_sign_posn), + "Unexpected offset: scalanative_lconv.p_sign_posn"); + +_Static_assert(offsetof(struct scalanative_lconv, n_sign_posn) == + offsetof(struct lconv, n_sign_posn), + "Unexpected offset: scalanative_lconv.n_sign_posn"); + +_Static_assert(offsetof(struct scalanative_lconv, int_p_cs_precedes) == + offsetof(struct lconv, int_p_cs_precedes), + "Unexpected offset: scalanative_lconv.int_p_cs_precedes"); + +#ifdef __linux__ +_Static_assert(offsetof(struct scalanative_lconv, int_n_cs_precedes) == + offsetof(struct lconv, int_n_cs_precedes), + "Unexpected offset: scalanative_lconv.int_n_cs_precedes"); +_Static_assert(offsetof(struct scalanative_lconv, int_p_sep_by_space) == + offsetof(struct lconv, int_p_sep_by_space), + "Unexpected offset: scalanative_lconv.int_p_sep_by_space"); +#else // __APPLE__, etc. +// Be aware of the trickery with field names being swapped/exchanged. +_Static_assert(offsetof(struct scalanative_lconv, int_n_cs_precedes) == + offsetof(struct lconv, int_p_sep_by_space), + "Unexpected offset: scalanative_lconv.int_p_sep_by_space"); + +_Static_assert(offsetof(struct scalanative_lconv, int_p_sep_by_space) == + offsetof(struct lconv, int_n_cs_precedes), + "Unexpected offset: scalanative_lconv.int_n_cs_precedes"); +#endif // __APPLE__ + +_Static_assert(offsetof(struct scalanative_lconv, int_n_sep_by_space) == + offsetof(struct lconv, int_n_sep_by_space), + "Unexpected offset: scalanative_lconv.int_n_sep_by_space"); + +_Static_assert(offsetof(struct scalanative_lconv, int_p_sign_posn) == + offsetof(struct lconv, int_p_sign_posn), + "Unexpected offset: scalanative_lconv.int_p_sign_posn"); + +_Static_assert(offsetof(struct scalanative_lconv, int_n_sign_posn) == + offsetof(struct lconv, int_n_sign_posn), + "Unexpected offset: scalanative_lconv.int_n_sign_posn"); + +// Symbolic constants + +int scalanative_lc_all() { return LC_ALL; } + +int scalanative_lc_collate() { return LC_COLLATE; } + +int scalanative_lc_ctype() { return LC_CTYPE; } + +int scalanative_lc_monetary() { return LC_MONETARY; } + +int scalanative_lc_numeric() { return LC_NUMERIC; } + +int scalanative_lc_time() { return LC_TIME; } + +#endif // POSIX +#endif // ! _WIN32 diff --git a/clib/src/main/scala/scala/scalanative/libc/locale.scala b/clib/src/main/scala/scala/scalanative/libc/locale.scala new file mode 100644 index 0000000000..90690f6565 --- /dev/null +++ b/clib/src/main/scala/scala/scalanative/libc/locale.scala @@ -0,0 +1,161 @@ +package scala.scalanative +package libc + +import scalanative.unsafe._ +import scalanative.meta.LinktimeInfo.isLinux + +/** ISO/IEC C definitions for locale.h + * + * See https://en.cppreference.com/w/c/numeric/locale + */ +@extern object locale extends locale + +/** Definitions shared with POSIX */ +@extern private[scalanative] trait locale { + + // CStruct is limited to 22 fields, lconv wants 24, so group int_* & use Ops + + /* Be careful here! + * This is the Linux layout. localeOps handles the fact that macOS + * swaps/echanges the int_p_sep_by_space & int_n_cs_precedes fields. + */ + + type lconv = CStruct19[ + CString, // decimal_point + CString, // thousands_sep + CString, // grouping + CString, // int_curr_symbol + CString, // currency_symbol + + CString, // mon_decimal_point + CString, // mon_thousands_sep + CString, // mon_grouping + CString, // positive_sign + CString, // negative_sign + + Byte, // int_frac_digits + Byte, // frac_digits + Byte, // p_cs_precedes + Byte, // p_sep_by_space + Byte, // n_cs_precedes + + Byte, // n_sep_by_space + Byte, // p_sign_posn + Byte, // n_sign_posn + + CStruct6[ + Byte, // int_p_cs_precedes + Byte, // Linux int_p_sep_by_space, macOS int_n_cs_precedes + Byte, // Linux int_n_cs_precedes, macOS int_p_sep_by_space + Byte, // int_n_sep_by_space + Byte, // int_p_sign_posn + Byte // int_n_sign_posn + ] + ] + + // Macros + + @name("scalanative_lc_all") + def LC_ALL: CInt = extern + + @name("scalanative_lc_collate") + def LC_COLLATE: CInt = extern + + @name("scalanative_lc_ctype") + def LC_CTYPE: CInt = extern + + @name("scalanative_lc_monetary") + def LC_MONETARY: CInt = extern + + @name("scalanative_lc_numeric") + def LC_NUMERIC: CInt = extern + + @name("scalanative_lc_time") + def LC_TIME: CInt = extern + +// Methods + + def localeconv(): Ptr[lconv] = extern + + def setlocale(category: CInt, locale: CString): CString = extern +} + +object localeOpsImpl { + import locale.lconv + def decimal_point(ptr: Ptr[lconv]): CString = ptr._1 + def thousands_sep(ptr: Ptr[lconv]): CString = ptr._2 + def grouping(ptr: Ptr[lconv]): CString = ptr._3 + def int_curr_symbol(ptr: Ptr[lconv]): CString = ptr._4 + def currency_symbol(ptr: Ptr[lconv]): CString = ptr._5 + + def mon_decimal_point(ptr: Ptr[lconv]): CString = ptr._6 + def mon_thousands_sep(ptr: Ptr[lconv]): CString = ptr._7 + def mon_grouping(ptr: Ptr[lconv]): CString = ptr._8 + def positive_sign(ptr: Ptr[lconv]): CString = ptr._9 + def negative_sign(ptr: Ptr[lconv]): CString = ptr._10 + + def int_frac_digits(ptr: Ptr[lconv]): CChar = ptr._11 + def frac_digits(ptr: Ptr[lconv]): CChar = ptr._12 + def p_cs_precedes(ptr: Ptr[lconv]): CChar = ptr._13 + def p_sep_by_space(ptr: Ptr[lconv]): CChar = ptr._14 + def n_cs_precedes(ptr: Ptr[lconv]): CChar = ptr._15 + + def n_sep_by_space(ptr: Ptr[lconv]): CChar = ptr._16 + def p_sign_posn(ptr: Ptr[lconv]): CChar = ptr._17 + def n_sign_posn(ptr: Ptr[lconv]): CChar = ptr._18 + def int_p_cs_precedes(ptr: Ptr[lconv]): CChar = ptr._19._1 + def int_p_sep_by_space(ptr: Ptr[lconv]): CChar = + if (isLinux) ptr._19._2 + else ptr._19._3 // macOS & probably BSDs + + def int_n_cs_precedes(ptr: Ptr[lconv]): CChar = + if (isLinux) ptr._19._3 + else ptr._19._2 // macOS & probably BSDs + + def int_n_sep_by_space(ptr: Ptr[lconv]): CChar = ptr._19._4 + def int_p_sign_posn(ptr: Ptr[lconv]): CChar = ptr._19._5 + def int_n_sign_posn(ptr: Ptr[lconv]): CChar = ptr._19._6 + + /* Linux 'man localeconv' documents lconv not to be modified, + * so no corresponding 'set' Ops. + */ +} + +object localeOps { + import locale.lconv + + implicit class lconvOps(val ptr: Ptr[lconv]) extends AnyVal { + def decimal_point: CString = localeOpsImpl.decimal_point(ptr) + def thousands_sep: CString = localeOpsImpl.thousands_sep(ptr) + def grouping: CString = localeOpsImpl.grouping(ptr) + def int_curr_symbol: CString = localeOpsImpl.int_curr_symbol(ptr) + def currency_symbol: CString = localeOpsImpl.currency_symbol(ptr) + + def mon_decimal_point: CString = localeOpsImpl.mon_decimal_point(ptr) + def mon_thousands_sep: CString = localeOpsImpl.mon_thousands_sep(ptr) + def mon_grouping: CString = localeOpsImpl.mon_grouping(ptr) + def positive_sign: CString = localeOpsImpl.positive_sign(ptr) + def negative_sign: CString = localeOpsImpl.negative_sign(ptr) + + def int_frac_digits: CChar = localeOpsImpl.int_frac_digits(ptr) + def frac_digits: CChar = localeOpsImpl.frac_digits(ptr) + + def p_cs_precedes: CChar = localeOpsImpl.p_cs_precedes(ptr) + def p_sep_by_space: CChar = localeOpsImpl.p_sep_by_space(ptr) + def n_cs_precedes: CChar = localeOpsImpl.n_cs_precedes(ptr) + def n_sep_by_space: CChar = localeOpsImpl.n_sep_by_space(ptr) + def p_sign_posn: CChar = localeOpsImpl.p_sign_posn(ptr) + def n_sign_posn: CChar = localeOpsImpl.n_sign_posn(ptr) + + def int_p_cs_precedes: CChar = localeOpsImpl.int_p_cs_precedes(ptr) + def int_n_cs_precedes: CChar = localeOpsImpl.int_n_cs_precedes(ptr) + def int_p_sep_by_space: CChar = localeOpsImpl.int_p_sep_by_space(ptr) + def int_n_sep_by_space: CChar = localeOpsImpl.int_n_sep_by_space(ptr) + def int_p_sign_posn: CChar = localeOpsImpl.int_p_sign_posn(ptr) + def int_n_sign_posn: CChar = localeOpsImpl.int_n_sign_posn(ptr) + + /* Linux 'man localeconv' documents lconv not to be modified, + * so no corresponding 'set' Ops. + */ + } +} diff --git a/docs/lib/libc.rst b/docs/lib/libc.rst index ee13474e1e..480be7a20c 100644 --- a/docs/lib/libc.rst +++ b/docs/lib/libc.rst @@ -1,9 +1,11 @@ .. _libc: -C Standard Library -================== +ISO/IEC C Standard Library +========================== Scala Native provides bindings for a core subset of the +International Organization for Standardization/International +Electrotechnical Commission (ISO/IEC) `C standard library `_: ============== ================================== @@ -18,7 +20,7 @@ float.h_ scala.scalanative.libc.float_ inttypes.h_ N/A iso646.h_ N/A limits.h_ N/A -locale.h_ N/A +locale.h_ scala.scalanative.libc.locale_ math.h_ scala.scalanative.libc.math_ setjmp.h_ N/A signal.h_ scala.scalanative.libc.signal_ @@ -75,6 +77,7 @@ wctype.h_ N/A .. _scala.scalanative.libc.ctype: https://github.com/scala-native/scala-native/blob/main/clib/src/main/scala/scala/scalanative/libc/ctype.scala .. _scala.scalanative.libc.errno: https://github.com/scala-native/scala-native/blob/main/clib/src/main/scala/scala/scalanative/libc/errno.scala .. _scala.scalanative.libc.float: https://github.com/scala-native/scala-native/blob/main/clib/src/main/scala/scala/scalanative/libc/float.scala +.. _scala.scalanative.libc.locale: https://github.com/scala-native/scala-native/blob/main/clib/src/main/scala/scala/scalanative/libc/locale.scala .. _scala.scalanative.libc.math: https://github.com/scala-native/scala-native/blob/main/clib/src/main/scala/scala/scalanative/libc/math.scala .. _scala.scalanative.libc.stddef: https://github.com/scala-native/scala-native/blob/main/clib/src/main/scala/scala/scalanative/libc/stddef.scala .. _scala.scalanative.libc.stdio: https://github.com/scala-native/scala-native/blob/main/clib/src/main/scala/scala/scalanative/libc/stdio.scala diff --git a/docs/lib/posixlib.rst b/docs/lib/posixlib.rst index 18d48a3986..c9a7567e2a 100644 --- a/docs/lib/posixlib.rst +++ b/docs/lib/posixlib.rst @@ -35,7 +35,7 @@ C Header Scala Native Module `limits.h`_ scala.scalanative.posix.limits_ `locale.h`_ N/A `math.h`_ scala.scalanative.libc.math_ -`monetary.h`_ N/A +`monetary.h`_ scala.scalanative.posix.monetary_ [#monetary_varargs]_ `mqueue.h`_ N/A `ndbm.h`_ N/A `net/if.h`_ scala.scalanative.posix.net.if_ @@ -194,6 +194,7 @@ C Header Scala Native Module .. _scala.scalanative.posix.limits: https://github.com/scala-native/scala-native/blob/main/posixlib/src/main/scala/scala/scalanative/posix/limits.scala .. _scala.scalanative.posix.libgen: https://github.com/scala-native/scala-native/blob/main/posixlib/src/main/scala/scala/scalanative/posix/libgen.scala .. _scala.scalanative.libc.math: https://github.com/scala-native/scala-native/blob/main/clib/src/main/scala/scala/scalanative/libc/math.scala +.. _scala.scalanative.posix.monetary: https://github.com/scala-native/scala-native/blob/main/posixlib/src/main/scala/scala/scalanative/posix/monetaryh.scala .. _scala.scalanative.posix.net.if: https://github.com/scala-native/scala-native/blob/main/posixlib/src/main/scala/scala/scalanative/posix/net/if.scala .. _scala.scalanative.posix.netdb: https://github.com/scala-native/scala-native/blob/main/posixlib/src/main/scala/scala/scalanative/posix/netdb.scala .. _scala.scalanative.posix.netinet.in: https://github.com/scala-native/scala-native/blob/main/posixlib/src/main/scala/scala/scalanative/posix/netinet/in.scala @@ -236,4 +237,6 @@ C Header Scala Native Module passing structures by reference. See code for details and usage. +.. [#monetary_varargs] See file for limit on number of variable arguments. + Continue to :ref:`communitylib`. diff --git a/posixlib/src/main/resources/scala-native/locale.c b/posixlib/src/main/resources/scala-native/locale.c new file mode 100644 index 0000000000..d348b55dae --- /dev/null +++ b/posixlib/src/main/resources/scala-native/locale.c @@ -0,0 +1,37 @@ +#ifdef _WIN32 +// No Windows support +#else +#if !(defined __STDC_VERSION__) || (__STDC_VERSION__ < 201112L) +#ifndef SCALANATIVE_SUPPRESS_STRUCT_CHECK_WARNING +#warning "Size and order of C structures are not checked when -std < c11." +#endif +#else // POSIX +#include +#include + +#ifdef __APPLE__ +#include +#endif // __APPLE__ + +// Symbolic constants + +locale_t scalanative_lc_global_locale() { return LC_GLOBAL_LOCALE; } + +int scalanative_lc_messages() { return LC_MESSAGES; } + +int scalanative_lc_all_mask() { return (1 << LC_ALL); } + +int scalanative_lc_collate_mask() { return (1 << LC_COLLATE); } + +int scalanative_lc_ctype_mask() { return (1 << LC_CTYPE); } + +int scalanative_lc_monetary_mask() { return (1 << LC_MONETARY); } + +int scalanative_lc_messages_mask() { return (1 << LC_MESSAGES); } + +int scalanative_lc_numeric_mask() { return (1 << LC_NUMERIC); } + +int scalanative_lc_time_mask() { return (1 << LC_TIME); } + +#endif // POSIX +#endif // ! _WIN32 diff --git a/posixlib/src/main/resources/scala-native/monetary.c b/posixlib/src/main/resources/scala-native/monetary.c new file mode 100644 index 0000000000..6d44f3b507 --- /dev/null +++ b/posixlib/src/main/resources/scala-native/monetary.c @@ -0,0 +1,40 @@ +#ifdef _WIN32 +// No Windows support +#else +#if !(defined __STDC_VERSION__) || (__STDC_VERSION__ < 201112L) +#ifndef SCALANATIVE_SUPPRESS_STRUCT_CHECK_WARNING +#warning "Size and order of C structures are not checked when -std < c11." +#endif +#else // POSIX +#include +#include + +#include // FIXME + +#ifdef __APPLE__ +#include +#endif // __APPLE__ + +ssize_t scalanative_strfmon_10(char *restrict str, size_t max, + const char *restrict format, double arg0, + double arg1, double arg2, double arg3, + double arg4, double arg5, double arg6, + double arg7, double arg8, double arg9) { + + return strfmon(str, max, format, arg0, arg1, arg2, arg3, arg4, arg5, arg6, + arg7, arg8, arg9); +} + +ssize_t scalanative_strfmon_l_10(char *restrict str, size_t max, + locale_t locale, const char *restrict format, + double arg0, double arg1, double arg2, + double arg3, double arg4, double arg5, + double arg6, double arg7, double arg8, + double arg9) { + + return strfmon_l(str, max, locale, format, arg0, arg1, arg2, arg3, arg4, + arg5, arg6, arg7, arg8, arg9); +} + +#endif // POSIX +#endif // ! _WIN32 diff --git a/posixlib/src/main/scala/scala/scalanative/posix/locale.scala b/posixlib/src/main/scala/scala/scalanative/posix/locale.scala index 6ddc3a352b..c68c31ebdf 100644 --- a/posixlib/src/main/scala/scala/scalanative/posix/locale.scala +++ b/posixlib/src/main/scala/scala/scalanative/posix/locale.scala @@ -3,14 +3,98 @@ package posix import scala.scalanative.unsafe._ -@extern -object locale { +/** POSIX locale.h for Scala + * + * The Open Group Base Specifications + * [[https://pubs.opengroup.org/onlinepubs/9699919799 Issue 7, 2018]] edition. + * + * All declarations which do not have a more specific extension specifier are + * described by POSIX as being a CX extension. + */ - /** This file/object is a less-than-minimal implementation. It provides only - * the type local_t. This allows a common definition of the type to be used - * by the several files required by POSIX to define that type. - */ +@extern object locale extends libc.locale { - type locale_t = Ptr[Byte] + type locale_t = Ptr[Byte] // CX, so can get no simpler. +// Symbolic constants + + /** CX */ + @name("scalanative_lc_global_locale") + def LC_GLOBAL_LOCALE: locale_t = extern + + /** CX */ + @name("scalanative_lc_messages") + def LC_MESSAGES: CInt = extern + + @name("scalanative_lc_all_mask") + def LC_ALL_MASK: CInt = extern + + @name("scalanative_lc_collate_mask") + def LC_COLLATE_MASK: CInt = extern + + @name("scalanative_lc_ctype_mask") + def LC_CTYPE_MASK: CInt = extern + + @name("scalanative_lc_monetary_mask") + def LC_MONETARY_MASK: CInt = extern + + @name("scalanative_lc_messages_mask") + def LC_MESSAGES_MASK: CInt = extern + + @name("scalanative_lc_numeric_mask") + def LC_NUMERIC_MASK: CInt = extern + + @name("scalanative_lc_time_mask") + def LC_TIME_MASK: CInt = extern + +// Methods + + def duplocale(locobj: locale_t): locale_t = extern + + def freelocale(locobj: locale_t): CInt = extern + + def newlocale(categoryMask: CInt, locale: CString, base: locale_t): locale_t = + extern + + def uselocale(newloc: locale_t): locale_t = extern +} + +object localeOps { + import locale.lconv + import scalanative.libc.localeOpsImpl + + implicit class lconvOps(val ptr: Ptr[lconv]) extends AnyVal { + def decimal_point: CString = localeOpsImpl.decimal_point(ptr) + def thousands_sep: CString = localeOpsImpl.thousands_sep(ptr) + def grouping: CString = localeOpsImpl.grouping(ptr) + def int_curr_symbol: CString = localeOpsImpl.int_curr_symbol(ptr) + def currency_symbol: CString = localeOpsImpl.currency_symbol(ptr) + + def mon_decimal_point: CString = localeOpsImpl.mon_decimal_point(ptr) + def mon_thousands_sep: CString = localeOpsImpl.mon_thousands_sep(ptr) + def mon_grouping: CString = localeOpsImpl.mon_grouping(ptr) + def positive_sign: CString = localeOpsImpl.positive_sign(ptr) + def negative_sign: CString = localeOpsImpl.negative_sign(ptr) + + def int_frac_digits: CChar = localeOpsImpl.int_frac_digits(ptr) + def frac_digits: CChar = localeOpsImpl.frac_digits(ptr) + def p_cs_precedes: CChar = localeOpsImpl.p_cs_precedes(ptr) + def p_sep_by_space: CChar = localeOpsImpl.p_sep_by_space(ptr) + def n_cs_precedes: CChar = localeOpsImpl.n_cs_precedes(ptr) + + def n_sep_by_space: CChar = localeOpsImpl.n_sep_by_space(ptr) + def p_sign_posn: CChar = localeOpsImpl.p_sign_posn(ptr) + def n_sign_posn: CChar = localeOpsImpl.n_sign_posn(ptr) + def int_p_cs_precedes: CChar = localeOpsImpl.int_p_cs_precedes(ptr) + def int_p_sep_by_space: CChar = localeOpsImpl.int_p_sep_by_space(ptr) + + def int_n_cs_precedes: CChar = localeOpsImpl.int_n_cs_precedes(ptr) + def int_n_sep_by_space: CChar = localeOpsImpl.int_n_sep_by_space(ptr) + def int_p_sign_posn: CChar = localeOpsImpl.int_p_sign_posn(ptr) + def int_n_sign_posn: CChar = localeOpsImpl.int_n_sign_posn(ptr) + + /* Linux 'man localeconv' documents lconv not to be modified, + * so no corresponding 'set' Ops. + */ + } } diff --git a/posixlib/src/main/scala/scala/scalanative/posix/monetary.scala b/posixlib/src/main/scala/scala/scalanative/posix/monetary.scala new file mode 100644 index 0000000000..5a941d8603 --- /dev/null +++ b/posixlib/src/main/scala/scala/scalanative/posix/monetary.scala @@ -0,0 +1,109 @@ +package scala.scalanative +package posix + +import scalanative.unsafe._ + +import scalanative.posix.sys.types._ + +/** POSIX monetary.h for Scala + * + * The Open Group Base Specifications + * [[https://pubs.opengroup.org/onlinepubs/9699919799 Issue 7, 2018]] edition. + * + * POSIX defines strfmon() and strfmon_l() using the "..." form of C variable + * arguments. Scala Native "supports native interoperability with C’s variadic + * argument list type (i.e. va_list), but not ... varargs". + * + * This implementation supports up to 10 items in the variable arguments to + * strfmon() and strfmon_1(). + */ + +object monetary { + type locale_t = locale.locale_t + private final val maxOutArgs = 10 + + def strfmon( + str: CString, + max: size_t, + format: CString, + argsIn: Double* + ): ssize_t = Zone { implicit z => + val argsOut = new Array[Double](maxOutArgs) + val limit = Math.min(argsIn.size, maxOutArgs) + + for (j <- 0 until limit) + argsOut(j) = argsIn(j) + + // format: off + val nFormatted = monetaryExtern.strfmon_10(str, max, format, + argsOut(0), argsOut(1), + argsOut(2), argsOut(3), + argsOut(4), argsOut(5), + argsOut(6), argsOut(7), + argsOut(8), argsOut(9) + ) + // format: on + + nFormatted + } + + def strfmon_l( + str: CString, + max: size_t, + locale: locale_t, + format: CString, + argsIn: Double* + ): ssize_t = Zone { implicit z => + val argsOut = new Array[Double](maxOutArgs) + val limit = Math.min(argsIn.size, maxOutArgs) + + for (j <- 0 until limit) + argsOut(j) = argsIn(j) + + // format: off + val nFormatted = monetaryExtern.strfmon_l_10(str, max, locale, format, + argsOut(0), argsOut(1), + argsOut(2), argsOut(3), + argsOut(4), argsOut(5), + argsOut(6), argsOut(7), + argsOut(8), argsOut(9) + ) + // format: on + + nFormatted + } + +} + +@extern +object monetaryExtern { + + // format: off + @name("scalanative_strfmon_10") + def strfmon_10( + str: CString, + max: size_t, + format: CString, + arg0: Double, arg1: Double, + arg2: Double, arg3: Double, + arg4: Double, arg5: Double, + arg6: Double, arg7: Double, + arg8: Double, arg9: Double + ): ssize_t = extern + // format: on + + // format: off + @name("scalanative_strfmon_l_10") + def strfmon_l_10( + str: CString, + max: size_t, + locale: monetary.locale_t, + format: CString, + arg0: Double, arg1: Double, + arg2: Double, arg3: Double, + arg4: Double, arg5: Double, + arg6: Double, arg7: Double, + arg8: Double, arg9: Double + ): ssize_t = extern + // format: on +} diff --git a/unit-tests/native/src/test/scala/scala/scalanative/posix/LocaleTest.scala b/unit-tests/native/src/test/scala/scala/scalanative/posix/LocaleTest.scala new file mode 100644 index 0000000000..cb03369bcf --- /dev/null +++ b/unit-tests/native/src/test/scala/scala/scalanative/posix/LocaleTest.scala @@ -0,0 +1,195 @@ +package scala.scalanative.posixlib + +import org.junit.Test +import org.junit.Assert._ +import org.junit.Assume._ +import org.junit.{Before, After} + +import scala.scalanative.meta.LinktimeInfo.{isLinux, isWindows} + +import scala.scalanative.unsafe._ +import scala.scalanative.unsigned._ + +import scala.scalanative.posix.errno.errno +import scala.scalanative.posix.locale._ +import scala.scalanative.posix.localeOps._ +import scala.scalanative.posix.stdlib +import scala.scalanative.posix.string + +class LocaleTest { + + // See also MonetaryTest.scala where number of locale methods are exercised. + + var savedLocale: Option[CString] = None + + @Before + def before(): Unit = { + if (!isWindows) { + val entryLocale = setlocale(LC_ALL, null) + assertNotNull( + "setlocale() could not determine locale at start of test.", + entryLocale + ) + + // Save before setlocale() calls overwrite static buffer returned. + savedLocale = Some(string.strdup(entryLocale)) // note: no CString + + val currentLocale = { + val en_US = setlocale(LC_ALL, c"en_US") + if (en_US != null) en_US + else { + val en_USutf8 = setlocale(LC_ALL, c"en_US.utf8") // Linux + if (en_USutf8 != null) en_USutf8 + else setlocale(LC_ALL, c"en_US.UTF-8") // macOS + } + } + + if (currentLocale == null) + savedLocale = None // Oops, no change! Nothing to restore. + } + } + + @After + def after(): Unit = { + if (!isWindows) { + savedLocale.map { sl => + errno = 0 + // restore Locale as recorded on entry + val restoredLocale = setlocale(LC_ALL, sl) + + stdlib.free(sl) + + if (restoredLocale == null) + fail("setlocale() was unable to restore the locale.") + } + } + } + + @Test def localeconv_Using_en_US(): Unit = { + assumeTrue( + "locale.scala is not implemented on Windows", + !isWindows + ) + + // Multi-arch CI tests do not have an en_US locale; warn not fail + assumeTrue( + "setlocale() failed to set an en_US test locale", + savedLocale.isDefined + ) + + if (!isWindows) { + val currentLconv = localeconv() // documented as always succeeds. + + assertEquals( + "US decimal_point", + ".", + fromCString(currentLconv.decimal_point) + ) + + assertEquals( + "US thousands_sep", + ",", + fromCString(currentLconv.thousands_sep) + ) + + // Expect three byte-integers 3, 3, 0, meaning infinite group-by-three + assertEquals( + "US grouping", + "\u0003\u0003", + fromCString(currentLconv.grouping) + ) + + assertEquals( + "US int_curr_symbol", + "USD ", + fromCString(currentLconv.int_curr_symbol) + ) + + assertEquals( + "US currency_symbol", + "$", + fromCString(currentLconv.currency_symbol) + ) + + assertEquals( + "US mon_decimal_point", + ".", + fromCString(currentLconv.mon_decimal_point) + ) + + assertEquals( + "US mon_thousands_sep", + ",", + fromCString(currentLconv.mon_thousands_sep) + ) + + // Expect three byte-integers 3, 3, 0, meaning infinite group-by-3 + assertEquals( + "US mon_grouping", + "\u0003\u0003", + fromCString(currentLconv.mon_grouping) + ) + + assertEquals( + "US positive_sign", + "", + fromCString(currentLconv.positive_sign) + ) + + assertEquals( + "US negative_sign", + "-", + fromCString(currentLconv.negative_sign) + ) + + assertEquals("US int_frac_digits", 2, currentLconv.int_frac_digits) + + assertEquals("US frac_digits", 2, currentLconv.frac_digits) + + assertEquals("US p_cs_precedes", 1, currentLconv.p_cs_precedes) + + assertEquals("US p_sep_by_space", 0, currentLconv.p_sep_by_space) + + assertEquals("US n_cs_precedes", 1, currentLconv.n_cs_precedes) + + assertEquals("US n_sep_by_space", 0, currentLconv.n_sep_by_space) + + assertEquals("US p_sign_posn", 1, currentLconv.p_sign_posn) + + assertEquals("US n_sign_posn", 1, currentLconv.n_sign_posn) + + assertEquals("US int_p_cs_precedes", 1, currentLconv.int_p_cs_precedes) + + assertEquals("US int_n_cs_precedes", 1, currentLconv.int_n_cs_precedes) + + if (isLinux) { + assertEquals( + "US int_p_sep_by_space", + 1, + currentLconv.int_p_sep_by_space + ) + + assertEquals( + "US int_n_sep_by_space", + 1, + currentLconv.int_n_sep_by_space + ) + } else { + assertEquals( + "US int_p_sep_by_space", + 0, + currentLconv.int_p_sep_by_space + ) + assertEquals( + "US int_n_sep_by_space", + 0, + currentLconv.int_n_sep_by_space + ) + } + + assertEquals("US int_p_sign_posn", 1, currentLconv.int_p_sign_posn) + + assertEquals("US int_n_sign_posn", 1, currentLconv.int_n_sign_posn) + } + } +} diff --git a/unit-tests/native/src/test/scala/scala/scalanative/posix/MonetaryTest.scala b/unit-tests/native/src/test/scala/scala/scalanative/posix/MonetaryTest.scala new file mode 100644 index 0000000000..aaeaed288f --- /dev/null +++ b/unit-tests/native/src/test/scala/scala/scalanative/posix/MonetaryTest.scala @@ -0,0 +1,91 @@ +package posixlib + +import org.junit.Test +import org.junit.Assert._ +import org.junit.Assume._ +import org.junit.Before + +import scala.scalanative.meta.LinktimeInfo.isWindows + +/* Using both LinktimeInfo & runtime.Platform looks strange. + * It is a workaround to let this test run whilst I a suspected bug + * in LinktimeInfo is tracked down. + */ +import scalanative.runtime.Platform + +import scala.scalanative.unsafe._ +import scala.scalanative.unsigned._ + +import scala.scalanative.posix.errno.errno +import scala.scalanative.posix.locale._ +import scala.scalanative.posix.monetary._ + +class MonetaryTest { + + @Before + def before(): Unit = { + assumeTrue( + "monetary.scala is not implemented on Windows", + !isWindows + ) + } + + @Test def strfmon_l_Using_en_US(): Unit = + if (!isWindows) { + errno = 0 + + val locale = { + val nl = newlocale(LC_MONETARY_MASK, c"en_US", null) + if (errno == 0) nl + else { + errno = 0 + val unixNl = newlocale(LC_MONETARY_MASK, c"en_US.utf8", null) + if (errno == 0) unixNl + else { + errno = 0 + newlocale(LC_MONETARY_MASK, c"en_US.UTF-8", null) // macOS + } + } + } + + // multi-arch CI appears not to have any of these locales + assumeTrue( + "newlocale() failed to use one of en_US, en_US.utf8, " + + "or en_US.UTF-8.", + locale != null + ) + + try { + val max = 128.toUInt + val buf = stackalloc[Byte](max) + + // format arg adapted from Linux "man strfmon" + + val n = strfmon_l( + buf, + max, + locale, + c"[%^=*#6n] [%=*#6i]", + 1234.567, + 1234.567 + ) + + assertNotEquals(s"strfmon_l() failed with errno: ${errno}\n", -1, n) + + val expected = if (Platform.isLinux()) { + "[ $**1234.57] [ USD **1,234.57]" + } else { + "[ $**1234.57] [ USD**1,234.57]" + } + + assertEquals( + "Unexpected strfmon_l() result", + expected, + fromCString(buf) + ) + + } finally { + freelocale(locale) + } + } +} From a8a7d036acfad0885167142caf2f12990f81f145 Mon Sep 17 00:00:00 2001 From: 110416 Date: Tue, 20 Dec 2022 11:48:59 +0100 Subject: [PATCH 20/64] Report error on default arguments in extern method (#3045) * report error on default arguments in extern method (cherry picked from commit f5f4adf00033ebc34019b26d81bdb3ec1f83563a) --- .../scalanative/nscplugin/NirGenStat.scala | 29 +++++++++++--- .../scalanative/nscplugin/NirGenStat.scala | 20 ++++++++++ .../scala/scalanative/NIRCompilerTest.scala | 40 +++++++++++++++++++ 3 files changed, 84 insertions(+), 5 deletions(-) diff --git a/nscplugin/src/main/scala-2/scala/scalanative/nscplugin/NirGenStat.scala b/nscplugin/src/main/scala-2/scala/scalanative/nscplugin/NirGenStat.scala index efc42974ba..7b7bcac224 100644 --- a/nscplugin/src/main/scala-2/scala/scalanative/nscplugin/NirGenStat.scala +++ b/nscplugin/src/main/scala-2/scala/scalanative/nscplugin/NirGenStat.scala @@ -675,13 +675,32 @@ trait NirGenStat[G <: nsc.Global with Singleton] { self: NirGenPhase[G] => origSig: nir.Type, rhs: Tree ): Option[nir.Defn] = { + val rhs = dd.rhs + def externMethodDecl() = { + val externAttrs = Attrs(isExtern = true) + val externSig = genExternMethodSig(curMethodSym) + val externDefn = Defn.Declare(externAttrs, name, externSig)(rhs.pos) + Some(externDefn) + } + + def isCallingExternMethod(sym: Symbol) = + sym.owner.isExternType + + def isExternMethodAlias(target: Symbol) = + (name, genName(target)) match { + case (Global.Member(_, lsig), Global.Member(_, rsig)) => lsig == rsig + case _ => false + } + val defaultArgs = dd.symbol.paramss.flatten.filter(_.hasDefault) rhs match { + case _ if defaultArgs.nonEmpty => + reporter.error( + defaultArgs.head.pos, + "extern method cannot have default argument" + ) + None case Apply(ref: RefTree, Seq()) if ref.symbol == ExternMethod => - val moduleName = genTypeName(curClassSym) - val externAttrs = Attrs(isExtern = true) - val externSig = genExternMethodSig(curMethodSym) - val externDefn = Defn.Declare(externAttrs, name, externSig)(rhs.pos) - Some(externDefn) + externMethodDecl() case _ if curMethodSym.hasFlag(ACCESSOR) => None diff --git a/nscplugin/src/main/scala-3/scala/scalanative/nscplugin/NirGenStat.scala b/nscplugin/src/main/scala-3/scala/scalanative/nscplugin/NirGenStat.scala index 44c1d566f2..811184f6bc 100644 --- a/nscplugin/src/main/scala-3/scala/scalanative/nscplugin/NirGenStat.scala +++ b/nscplugin/src/main/scala-3/scala/scalanative/nscplugin/NirGenStat.scala @@ -20,6 +20,7 @@ import scala.scalanative.util.ScopedVar.{scoped, toValue} import scala.scalanative.util.unsupported import dotty.tools.FatalError import dotty.tools.dotc.report +import dotty.tools.dotc.core.NameKinds trait NirGenStat(using Context) { self: NirCodeGen => @@ -397,7 +398,26 @@ trait NirGenStat(using Context) { rhs: Tree ): Option[Defn] = { given nir.Position = rhs.span + def externMethodDecl() = { + val externAttrs = Attrs(isExtern = true) + val externSig = genExternMethodSig(curMethodSym) + val externDefn = Defn.Declare(externAttrs, name, externSig) + Some(externDefn) + } + + def isExternMethodAlias(target: Symbol) = (name, genName(target)) match { + case (Global.Member(_, lsig), Global.Member(_, rsig)) => lsig == rsig + case _ => false + } + val defaultArgs = dd.paramss.flatten.filter(_.symbol.is(HasDefault)) + rhs match { + case _ + if defaultArgs.nonEmpty || dd.name.is( + NameKinds.DefaultGetterName + ) => + report.error("extern method cannot have default argument") + None case Apply(ref: RefTree, Seq()) if ref.symbol == defnNir.UnsafePackage_extern => val moduleName = genTypeName(curClassSym) diff --git a/tools/src/test/scala/scala/scalanative/NIRCompilerTest.scala b/tools/src/test/scala/scala/scalanative/NIRCompilerTest.scala index 7b02229fff..ad3851b55e 100644 --- a/tools/src/test/scala/scala/scalanative/NIRCompilerTest.scala +++ b/tools/src/test/scala/scala/scalanative/NIRCompilerTest.scala @@ -233,6 +233,46 @@ class NIRCompilerTest extends AnyFlatSpec with Matchers with Inspectors { |""".stripMargin)) } + it should "report error on default argument in extern method" in { + intercept[CompilationFailedException] { + NIRCompiler(_.compile(""" + |import scala.scalanative.unsafe._ + |@extern + |object foo { + | def baz(a:Int = 1): Unit = extern + |} + |""".stripMargin)) + }.getMessage should include( + "extern method cannot have default argument" + ) + } + it should "report error on default argument mixed with general argument in extern method" in { + intercept[CompilationFailedException] { + NIRCompiler(_.compile(""" + |import scala.scalanative.unsafe._ + |@extern + |object foo { + | def baz(a: Double, b:Int = 1): Unit = extern + |} + |""".stripMargin)) + }.getMessage should include( + "extern method cannot have default argument" + ) + } + it should "report error on default arguments in extern method" in { + intercept[CompilationFailedException] { + NIRCompiler(_.compile(""" + |import scala.scalanative.unsafe._ + |@extern + |object foo { + | def baz(a: Double=1.0, b:Int = 1): Unit = extern + |} + |""".stripMargin)) + }.getMessage should include( + "extern method cannot have default argument" + ) + } + it should "report error when closing over local statein CFuncPtr" in { intercept[CompilationFailedException] { NIRCompiler( From 4f34b413d0654ecf92dbb35412e7bc85357b483b Mon Sep 17 00:00:00 2001 From: LeeTibbert Date: Wed, 21 Dec 2022 11:54:27 -0500 Subject: [PATCH 21/64] Make list of supported classes prettier & easier to read and visually search (#3022) * Make list of supported classes prettier & easier to read and manually search * Resolve merge conflicts * delete obsolete javalib documentation script (cherry picked from commit a1edc8925d45b16cd47ec9885f201105a5009cdb) --- docs/lib/javalib.rst | 1029 +++++++++++++++++++++--------------------- scripts/javalib.py | 22 - 2 files changed, 506 insertions(+), 545 deletions(-) delete mode 100644 scripts/javalib.py diff --git a/docs/lib/javalib.rst b/docs/lib/javalib.rst index 52f1094771..ce26593822 100644 --- a/docs/lib/javalib.rst +++ b/docs/lib/javalib.rst @@ -8,529 +8,512 @@ Scala Native supports a subset of the JDK core libraries reimplemented in Scala. Supported classes ----------------- -Here is the list of currently available classes: - -* ``java.io.BufferedInputStream`` -* ``java.io.BufferedOutputStream`` -* ``java.io.BufferedReader`` -* ``java.io.BufferedWriter`` -* ``java.io.ByteArrayInputStream`` -* ``java.io.ByteArrayOutputStream`` -* ``java.io.Closeable`` -* ``java.io.DataInput`` -* ``java.io.DataInputStream`` -* ``java.io.DataOutput`` -* ``java.io.DataOutputStream`` -* ``java.io.EOFException`` -* ``java.io.File`` -* ``java.io.FileDescriptor`` -* ``java.io.FileFilter`` -* ``java.io.FileInputStream`` -* ``java.io.FileNotFoundException`` -* ``java.io.FileOutputStream`` -* ``java.io.FileReader`` -* ``java.io.FileWriter`` -* ``java.io.FilenameFilter`` -* ``java.io.FilterInputStream`` -* ``java.io.FilterOutputStream`` -* ``java.io.FilterReader`` -* ``java.io.Flushable`` -* ``java.io.IOException`` -* ``java.io.InputStream`` -* ``java.io.InputStreamReader`` -* ``java.io.InterruptedIOException`` -* ``java.io.LineNumberReader`` -* ``java.io.NotSerializableException`` -* ``java.io.ObjectStreamException`` -* ``java.io.OutputStream`` -* ``java.io.OutputStreamWriter`` -* ``java.io.PrintStream`` -* ``java.io.PrintWriter`` -* ``java.io.PushbackInputStream`` -* ``java.io.PushbackReader`` -* ``java.io.RandomAccessFile`` -* ``java.io.Reader`` -* ``java.io.Serializable`` -* ``java.io.StringReader`` -* ``java.io.StringWriter`` -* ``java.io.SyncFailedException`` -* ``java.io.UTFDataFormatException`` -* ``java.io.UncheckedIOException`` -* ``java.io.UnsupportedEncodingException`` -* ``java.io.Writer`` -* ``java.lang.AbstractMethodError`` -* ``java.lang.AbstractStringBuilder`` -* ``java.lang.Appendable`` -* ``java.lang.ArithmeticException`` -* ``java.lang.ArrayIndexOutOfBoundsException`` -* ``java.lang.ArrayStoreException`` -* ``java.lang.AssertionError`` -* ``java.lang.AutoCloseable`` -* ``java.lang.Boolean`` -* ``java.lang.BootstrapMethodError`` -* ``java.lang.Byte`` -* ``java.lang.ByteCache`` -* ``java.lang.CharSequence`` -* ``java.lang.Character`` -* ``java.lang.Character$Subset`` -* ``java.lang.Character$UnicodeBlock`` -* ``java.lang.CharacterCache`` -* ``java.lang.ClassCastException`` -* ``java.lang.ClassCircularityError`` -* ``java.lang.ClassFormatError`` -* ``java.lang.ClassLoader`` -* ``java.lang.ClassNotFoundException`` -* ``java.lang.CloneNotSupportedException`` -* ``java.lang.Cloneable`` -* ``java.lang.Comparable`` -* ``java.lang.Double`` -* ``java.lang.Enum`` -* ``java.lang.EnumConstantNotPresentException`` -* ``java.lang.Error`` -* ``java.lang.Exception`` -* ``java.lang.ExceptionInInitializerError`` -* ``java.lang.Float`` -* ``java.lang.IllegalAccessError`` -* ``java.lang.IllegalAccessException`` -* ``java.lang.IllegalArgumentException`` -* ``java.lang.IllegalMonitorStateException`` -* ``java.lang.IllegalStateException`` -* ``java.lang.IllegalThreadStateException`` -* ``java.lang.IncompatibleClassChangeError`` -* ``java.lang.IndexOutOfBoundsException`` -* ``java.lang.InheritableThreadLocal`` -* ``java.lang.InstantiationError`` -* ``java.lang.InstantiationException`` -* ``java.lang.Integer`` -* ``java.lang.IntegerCache`` -* ``java.lang.IntegerDecimalScale`` -* ``java.lang.InternalError`` -* ``java.lang.InterruptedException`` -* ``java.lang.Iterable`` -* ``java.lang.LinkageError`` -* ``java.lang.Long`` -* ``java.lang.LongCache`` -* ``java.lang.Math`` -* ``java.lang.MathRand`` -* ``java.lang.NegativeArraySizeException`` -* ``java.lang.NoClassDefFoundError`` -* ``java.lang.NoSuchFieldError`` -* ``java.lang.NoSuchFieldException`` -* ``java.lang.NoSuchMethodError`` -* ``java.lang.NoSuchMethodException`` -* ``java.lang.NullPointerException`` -* ``java.lang.Number`` -* ``java.lang.NumberFormatException`` -* ``java.lang.OutOfMemoryError`` -* ``java.lang.Process`` -* ``java.lang.ProcessBuilder`` -* ``java.lang.ProcessBuilder$Redirect`` -* ``java.lang.ProcessBuilder$Redirect$Type`` -* ``java.lang.Readable`` -* ``java.lang.ReflectiveOperationException`` -* ``java.lang.RejectedExecutionException`` -* ``java.lang.Runnable`` -* ``java.lang.Runtime`` -* ``java.lang.Runtime$ProcessBuilderOps`` -* ``java.lang.RuntimeException`` -* ``java.lang.SecurityException`` -* ``java.lang.Short`` -* ``java.lang.ShortCache`` -* ``java.lang.StackOverflowError`` -* ``java.lang.StackTrace`` -* ``java.lang.StackTraceElement`` -* ``java.lang.StackTraceElement$Fail`` -* ``java.lang.String`` -* ``java.lang.StringBuffer`` -* ``java.lang.StringBuilder`` -* ``java.lang.StringIndexOutOfBoundsException`` -* ``java.lang.System`` -* ``java.lang.Thread`` -* ``java.lang.Thread$UncaughtExceptionHandler`` -* ``java.lang.ThreadDeath`` -* ``java.lang.ThreadLocal`` -* ``java.lang.Throwable`` -* ``java.lang.TypeNotPresentException`` -* ``java.lang.UnknownError`` -* ``java.lang.UnsatisfiedLinkError`` -* ``java.lang.UnsupportedClassVersionError`` -* ``java.lang.UnsupportedOperationException`` -* ``java.lang.VerifyError`` -* ``java.lang.VirtualMachineError`` -* ``java.lang.Void`` -* ``java.lang.annotation.Annotation`` -* ``java.lang.annotation.Retention`` -* ``java.lang.annotation.RetentionPolicy`` -* ``java.lang.constant.Constable`` -* ``java.lang.constant.ConstantDesc`` -* ``java.lang.ref.PhantomReference`` -* ``java.lang.ref.Reference`` -* ``java.lang.ref.ReferenceQueue`` -* ``java.lang.ref.SoftReference`` -* ``java.lang.ref.WeakReference`` -* ``java.lang.reflect.AccessibleObject`` -* ``java.lang.reflect.Array`` -* ``java.lang.reflect.Constructor`` -* ``java.lang.reflect.Executable`` -* ``java.lang.reflect.Field`` -* ``java.lang.reflect.InvocationTargetException`` -* ``java.lang.reflect.Method`` -* ``java.lang.reflect.UndeclaredThrowableException`` -* ``java.math.BigDecimal`` -* ``java.math.BigInteger`` -* ``java.math.BitLevel`` -* ``java.math.Conversion`` -* ``java.math.Division`` -* ``java.math.Elementary`` -* ``java.math.Logical`` -* ``java.math.MathContext`` -* ``java.math.Multiplication`` -* ``java.math.Primality`` -* ``java.math.RoundingMode`` -* ``java.net.BindException`` -* ``java.net.ConnectException`` -* ``java.net.Inet4Address`` -* ``java.net.Inet6Address`` -* ``java.net.InetAddress`` -* ``java.net.InetSocketAddress`` -* ``java.net.InterfaceAddress`` -* ``java.net.MalformedURLException`` -* ``java.net.NetworkInterface`` -* ``java.net.NoRouteToHostException`` -* ``java.net.PortUnreachableException`` -* ``java.net.ServerSocket`` -* ``java.net.Socket`` -* ``java.net.SocketAddress`` -* ``java.net.SocketException`` -* ``java.net.SocketImpl`` -* ``java.net.SocketInputStream`` -* ``java.net.SocketOption`` -* ``java.net.SocketOptions`` -* ``java.net.SocketOutputStream`` -* ``java.net.SocketTimeoutException`` -* ``java.net.URI`` -* ``java.net.URI$Helper`` -* ``java.net.URIEncoderDecoder`` -* ``java.net.URISyntaxException`` -* ``java.net.URL`` -* ``java.net.URLClassLoader`` -* ``java.net.URLConnection`` -* ``java.net.URLDecoder`` -* ``java.net.URLEncoder`` -* ``java.net.UnknownHostException`` -* ``java.net.UnknownServiceException`` -* ``java.nio.Buffer`` -* ``java.nio.BufferOverflowException`` -* ``java.nio.BufferUnderflowException`` -* ``java.nio.ByteBuffer`` -* ``java.nio.ByteOrder`` -* ``java.nio.CharBuffer`` -* ``java.nio.DoubleBuffer`` -* ``java.nio.FloatBuffer`` -* ``java.nio.IntBuffer`` -* ``java.nio.InvalidMarkException`` -* ``java.nio.LongBuffer`` -* ``java.nio.MappedByteBuffer`` -* ``java.nio.ReadOnlyBufferException`` -* ``java.nio.ShortBuffer`` -* ``java.nio.channels.ByteChannel`` -* ``java.nio.channels.Channel`` -* ``java.nio.channels.Channels`` -* ``java.nio.channels.ClosedChannelException`` -* ``java.nio.channels.FileChannel`` -* ``java.nio.channels.FileChannel$MapMode`` -* ``java.nio.channels.FileLock`` -* ``java.nio.channels.GatheringByteChannel`` -* ``java.nio.channels.InterruptibleChannel`` -* ``java.nio.channels.NonReadableChannelException`` -* ``java.nio.channels.NonWritableChannelException`` -* ``java.nio.channels.OverlappingFileLockException`` -* ``java.nio.channels.ReadableByteChannel`` -* ``java.nio.channels.ScatteringByteChannel`` -* ``java.nio.channels.SeekableByteChannel`` -* ``java.nio.channels.WritableByteChannel`` -* ``java.nio.channels.spi.AbstractInterruptibleChannel`` -* ``java.nio.charset.CharacterCodingException`` -* ``java.nio.charset.Charset`` -* ``java.nio.charset.CharsetDecoder`` -* ``java.nio.charset.CharsetEncoder`` -* ``java.nio.charset.CoderMalfunctionError`` -* ``java.nio.charset.CoderResult`` -* ``java.nio.charset.CodingErrorAction`` -* ``java.nio.charset.IllegalCharsetNameException`` -* ``java.nio.charset.MalformedInputException`` -* ``java.nio.charset.StandardCharsets`` -* ``java.nio.charset.UnmappableCharacterException`` -* ``java.nio.charset.UnsupportedCharsetException`` -* ``java.nio.file.AccessDeniedException`` -* ``java.nio.file.CopyOption`` -* ``java.nio.file.DirectoryIteratorException`` -* ``java.nio.file.DirectoryNotEmptyException`` -* ``java.nio.file.DirectoryStream`` -* ``java.nio.file.DirectoryStream$Filter`` -* ``java.nio.file.DirectoryStreamImpl`` -* ``java.nio.file.FileAlreadyExistsException`` -* ``java.nio.file.FileSystem`` -* ``java.nio.file.FileSystemException`` -* ``java.nio.file.FileSystemLoopException`` -* ``java.nio.file.FileSystemNotFoundException`` -* ``java.nio.file.FileSystems`` -* ``java.nio.file.FileVisitOption`` -* ``java.nio.file.FileVisitResult`` -* ``java.nio.file.FileVisitor`` -* ``java.nio.file.Files`` -* ``java.nio.file.Files$TerminateTraversalException`` -* ``java.nio.file.InvalidPathException`` -* ``java.nio.file.LinkOption`` -* ``java.nio.file.NoSuchFileException`` -* ``java.nio.file.NotDirectoryException`` -* ``java.nio.file.NotLinkException`` -* ``java.nio.file.OpenOption`` -* ``java.nio.file.Path`` -* ``java.nio.file.PathMatcher`` -* ``java.nio.file.Paths`` -* ``java.nio.file.RegexPathMatcher`` -* ``java.nio.file.SimpleFileVisitor`` -* ``java.nio.file.StandardCopyOption`` -* ``java.nio.file.StandardOpenOption`` -* ``java.nio.file.StandardWatchEventKinds`` -* ``java.nio.file.WatchEvent`` -* ``java.nio.file.WatchEvent$Kind`` -* ``java.nio.file.WatchEvent$Modifier`` -* ``java.nio.file.WatchKey`` -* ``java.nio.file.WatchService`` -* ``java.nio.file.Watchable`` -* ``java.nio.file.attribute.AclEntry`` -* ``java.nio.file.attribute.AclFileAttributeView`` -* ``java.nio.file.attribute.AttributeView`` -* ``java.nio.file.attribute.BasicFileAttributeView`` -* ``java.nio.file.attribute.BasicFileAttributes`` -* ``java.nio.file.attribute.DosFileAttributeView`` -* ``java.nio.file.attribute.DosFileAttributes`` -* ``java.nio.file.attribute.FileAttribute`` -* ``java.nio.file.attribute.FileAttributeView`` -* ``java.nio.file.attribute.FileOwnerAttributeView`` -* ``java.nio.file.attribute.FileStoreAttributeView`` -* ``java.nio.file.attribute.FileTime`` -* ``java.nio.file.attribute.GroupPrincipal`` -* ``java.nio.file.attribute.PosixFileAttributeView`` -* ``java.nio.file.attribute.PosixFileAttributes`` -* ``java.nio.file.attribute.PosixFilePermission`` -* ``java.nio.file.attribute.PosixFilePermissions`` -* ``java.nio.file.attribute.UserDefinedFileAttributeView`` -* ``java.nio.file.attribute.UserPrincipal`` -* ``java.nio.file.attribute.UserPrincipalLookupService`` -* ``java.nio.file.attribute.UserPrincipalNotFoundException`` -* ``java.nio.file.spi.FileSystemProvider`` -* ``java.rmi.Remote`` -* ``java.rmi.RemoteException`` -* ``java.security.AccessControlException`` -* ``java.security.CodeSigner`` -* ``java.security.DummyMessageDigest`` -* ``java.security.GeneralSecurityException`` -* ``java.security.MessageDigest`` -* ``java.security.MessageDigestSpi`` -* ``java.security.NoSuchAlgorithmException`` -* ``java.security.Principal`` -* ``java.security.Timestamp`` -* ``java.security.TimestampConstructorHelper`` -* ``java.security.cert.CertPath`` -* ``java.security.cert.Certificate`` -* ``java.security.cert.CertificateEncodingException`` -* ``java.security.cert.CertificateException`` -* ``java.security.cert.CertificateFactory`` -* ``java.security.cert.X509Certificate`` -* ``java.security.cert.X509Extension`` -* ``java.util.AbstractCollection`` -* ``java.util.AbstractList`` -* ``java.util.AbstractListView`` -* ``java.util.AbstractMap`` -* ``java.util.AbstractMap$SimpleEntry`` -* ``java.util.AbstractMap$SimpleImmutableEntry`` -* ``java.util.AbstractQueue`` -* ``java.util.AbstractRandomAccessListIterator`` -* ``java.util.AbstractSequentialList`` -* ``java.util.AbstractSet`` -* ``java.util.ArrayDeque`` -* ``java.util.ArrayList`` -* ``java.util.Arrays`` -* ``java.util.Arrays$AsRef`` -* ``java.util.BackedUpListIterator`` -* ``java.util.Base64`` -* ``java.util.Base64$Decoder`` -* ``java.util.Base64$DecodingInputStream`` -* ``java.util.Base64$Encoder`` -* ``java.util.Base64$EncodingOutputStream`` -* ``java.util.Base64$Wrapper`` -* ``java.util.BitSet`` -* ``java.util.Calendar`` -* ``java.util.Collection`` -* ``java.util.Collections`` -* ``java.util.Collections$CheckedCollection`` -* ``java.util.Collections$CheckedList`` -* ``java.util.Collections$CheckedListIterator`` -* ``java.util.Collections$CheckedMap`` -* ``java.util.Collections$CheckedSet`` -* ``java.util.Collections$CheckedSortedMap`` -* ``java.util.Collections$CheckedSortedSet`` -* ``java.util.Collections$EmptyIterator`` -* ``java.util.Collections$EmptyListIterator`` -* ``java.util.Collections$ImmutableList`` -* ``java.util.Collections$ImmutableMap`` -* ``java.util.Collections$ImmutableSet`` -* ``java.util.Collections$UnmodifiableCollection`` -* ``java.util.Collections$UnmodifiableIterator`` -* ``java.util.Collections$UnmodifiableList`` -* ``java.util.Collections$UnmodifiableListIterator`` -* ``java.util.Collections$UnmodifiableMap`` -* ``java.util.Collections$UnmodifiableSet`` -* ``java.util.Collections$UnmodifiableSortedMap`` -* ``java.util.Collections$UnmodifiableSortedSet`` -* ``java.util.Collections$WrappedCollection`` -* ``java.util.Collections$WrappedEquals`` -* ``java.util.Collections$WrappedIterator`` -* ``java.util.Collections$WrappedList`` -* ``java.util.Collections$WrappedListIterator`` -* ``java.util.Collections$WrappedMap`` -* ``java.util.Collections$WrappedSet`` -* ``java.util.Collections$WrappedSortedMap`` -* ``java.util.Collections$WrappedSortedSet`` -* ``java.util.Comparator`` -* ``java.util.ConcurrentModificationException`` -* ``java.util.Date`` -* ``java.util.Deque`` -* ``java.util.Dictionary`` -* ``java.util.DuplicateFormatFlagsException`` -* ``java.util.EmptyStackException`` -* ``java.util.EnumSet`` -* ``java.util.Enumeration`` -* ``java.util.FormatFlagsConversionMismatchException`` -* ``java.util.Formattable`` -* ``java.util.FormattableFlags`` -* ``java.util.Formatter`` -* ``java.util.Formatter$BigDecimalLayoutForm`` -* ``java.util.FormatterClosedException`` -* ``java.util.GregorianCalendar`` -* ``java.util.HashMap`` -* ``java.util.HashSet`` -* ``java.util.Hashtable`` -* ``java.util.Hashtable$UnboxedEntry$1`` -* ``java.util.IdentityHashMap`` -* ``java.util.IllegalFormatCodePointException`` -* ``java.util.IllegalFormatConversionException`` -* ``java.util.IllegalFormatException`` -* ``java.util.IllegalFormatFlagsException`` -* ``java.util.IllegalFormatPrecisionException`` -* ``java.util.IllegalFormatWidthException`` -* ``java.util.IllformedLocaleException`` -* ``java.util.InputMismatchException`` -* ``java.util.InvalidPropertiesFormatException`` -* ``java.util.Iterator`` -* ``java.util.LinkedHashMap`` -* ``java.util.LinkedHashSet`` -* ``java.util.LinkedList`` -* ``java.util.List`` -* ``java.util.ListIterator`` -* ``java.util.Map`` -* ``java.util.Map$Entry`` -* ``java.util.MissingFormatArgumentException`` -* ``java.util.MissingFormatWidthException`` -* ``java.util.MissingResourceException`` -* ``java.util.NavigableMap`` -* ``java.util.NavigableSet`` -* ``java.util.NoSuchElementException`` -* ``java.util.Objects`` -* ``java.util.Optional`` -* ``java.util.PriorityQueue`` -* ``java.util.Properties`` -* ``java.util.Queue`` -* ``java.util.Random`` -* ``java.util.RandomAccess`` -* ``java.util.RandomAccessListIterator`` -* ``java.util.ServiceConfigurationError`` -* ``java.util.Set`` -* ``java.util.SizeChangeEvent`` -* ``java.util.SortedMap`` -* ``java.util.SortedSet`` -* ``java.util.StringTokenizer`` -* ``java.util.TooManyListenersException`` -* ``java.util.TreeSet`` -* ``java.util.UUID`` -* ``java.util.UnknownFormatConversionException`` -* ``java.util.UnknownFormatFlagsException`` -* ``java.util.WeakHashMap`` -* ``java.util.concurrent.Callable`` -* ``java.util.concurrent.CancellationException`` -* ``java.util.concurrent.ConcurrentHashMap`` -* ``java.util.concurrent.ConcurrentHashMap$KeySetView`` -* ``java.util.concurrent.ConcurrentLinkedQueue`` -* ``java.util.concurrent.ConcurrentMap`` -* ``java.util.concurrent.ConcurrentSkipListSet`` -* ``java.util.concurrent.ExecutionException`` -* ``java.util.concurrent.Executor`` -* ``java.util.concurrent.RejectedExecutionException`` -* ``java.util.concurrent.Semaphore`` -* ``java.util.concurrent.ThreadFactory`` -* ``java.util.concurrent.ThreadLocalRandom`` -* ``java.util.concurrent.TimeUnit`` -* ``java.util.concurrent.TimeoutException`` -* ``java.util.concurrent.atomic.AtomicBoolean`` -* ``java.util.concurrent.atomic.AtomicInteger`` -* ``java.util.concurrent.atomic.AtomicLong`` -* ``java.util.concurrent.atomic.AtomicLongArray`` -* ``java.util.concurrent.atomic.AtomicReference`` -* ``java.util.concurrent.atomic.AtomicReferenceArray`` -* ``java.util.concurrent.atomic.LongAdder`` -* ``java.util.concurrent.locks.AbstractOwnableSynchronizer`` -* ``java.util.concurrent.locks.AbstractQueuedSynchronizer`` -* ``java.util.concurrent.locks.Lock`` -* ``java.util.concurrent.locks.ReentrantLock`` -* ``java.util.function.BiConsumer`` -* ``java.util.function.BiFunction`` -* ``java.util.function.BiPredicate`` -* ``java.util.function.BinaryOperator`` -* ``java.util.function.Consumer`` -* ``java.util.function.Function`` -* ``java.util.function.IntUnaryOperator`` -* ``java.util.function.Predicate`` -* ``java.util.function.Supplier`` -* ``java.util.function.UnaryOperator`` -* ``java.util.jar.Attributes`` -* ``java.util.jar.Attributes$Name`` -* ``java.util.jar.InitManifest`` -* ``java.util.jar.JarEntry`` -* ``java.util.jar.JarFile`` -* ``java.util.jar.JarInputStream`` -* ``java.util.jar.JarOutputStream`` -* ``java.util.jar.Manifest`` -* ``java.util.regex.MatchResult`` -* ``java.util.regex.Matcher`` -* ``java.util.regex.Pattern`` -* ``java.util.regex.PatternSyntaxException`` -* ``java.util.stream.BaseStream`` -* ``java.util.stream.CompositeStream`` -* ``java.util.stream.EmptyIterator`` -* ``java.util.stream.Stream`` -* ``java.util.stream.Stream$Builder`` -* ``java.util.zip.Adler32`` -* ``java.util.zip.CRC32`` -* ``java.util.zip.CheckedInputStream`` -* ``java.util.zip.CheckedOutputStream`` -* ``java.util.zip.Checksum`` -* ``java.util.zip.DataFormatException`` -* ``java.util.zip.Deflater`` -* ``java.util.zip.DeflaterOutputStream`` -* ``java.util.zip.GZIPInputStream`` -* ``java.util.zip.GZIPOutputStream`` -* ``java.util.zip.Inflater`` -* ``java.util.zip.InflaterInputStream`` -* ``java.util.zip.ZipConstants`` -* ``java.util.zip.ZipEntry`` -* ``java.util.zip.ZipException`` -* ``java.util.zip.ZipFile`` -* ``java.util.zip.ZipInputStream`` -* ``java.util.zip.ZipOutputStream`` - +The classes currently available are: + +java.io +""""""" +* ``BufferedInputStream`` +* ``BufferedOutputStream`` +* ``BufferedReader`` +* ``BufferedWriter`` +* ``ByteArrayInputStream`` +* ``ByteArrayOutputStream`` +* ``Closeable`` +* ``DataInput`` +* ``DataInputStream`` +* ``DataOutput`` +* ``DataOutputStream`` +* ``EOFException`` +* ``File`` +* ``FileDescriptor`` +* ``FileFilter`` +* ``FileInputStream`` +* ``FileNotFoundException`` +* ``FileOutputStream`` +* ``FileReader`` +* ``FileWriter`` +* ``FilenameFilter`` +* ``FilterInputStream`` +* ``FilterOutputStream`` +* ``FilterReader`` +* ``Flushable`` +* ``IOException`` +* ``InputStream`` +* ``InputStreamReader`` +* ``InterruptedIOException`` +* ``LineNumberReader`` +* ``NotSerializableException`` +* ``ObjectStreamException`` +* ``OutputStream`` +* ``OutputStreamWriter`` +* ``PrintStream`` +* ``PrintWriter`` +* ``PushbackInputStream`` +* ``PushbackReader`` +* ``RandomAccessFile`` +* ``Reader`` +* ``Serializable`` +* ``StringReader`` +* ``StringWriter`` +* ``SyncFailedException`` +* ``UTFDataFormatException`` +* ``UncheckedIOException`` +* ``UnsupportedEncodingException`` +* ``Writer`` + +java.lang +""""""""" +* ``AbstractMethodError`` +* ``AbstractStringBuilder`` +* ``Appendable`` +* ``ArithmeticException`` +* ``ArrayIndexOutOfBoundsException`` +* ``ArrayStoreException`` +* ``AssertionError`` +* ``AutoCloseable`` +* ``Boolean`` +* ``BootstrapMethodError`` +* ``Byte`` +* ``ByteCache`` +* ``CharSequence`` +* ``Character`` +* ``Character.Subset`` +* ``Character.UnicodeBlock`` +* ``CharacterCache`` +* ``ClassCastException`` +* ``ClassCircularityError`` +* ``ClassFormatError`` +* ``ClassLoader`` +* ``ClassNotFoundException`` +* ``CloneNotSupportedException`` +* ``Cloneable`` +* ``Comparable`` +* ``Double`` +* ``Enum`` +* ``EnumConstantNotPresentException`` +* ``Error`` +* ``Exception`` +* ``ExceptionInInitializerError`` +* ``Float`` +* ``IllegalAccessError`` +* ``IllegalAccessException`` +* ``IllegalArgumentException`` +* ``IllegalMonitorStateException`` +* ``IllegalStateException`` +* ``IllegalThreadStateException`` +* ``IncompatibleClassChangeError`` +* ``IndexOutOfBoundsException`` +* ``InheritableThreadLocal`` +* ``InstantiationError`` +* ``InstantiationException`` +* ``Integer`` +* ``IntegerCache`` +* ``IntegerDecimalScale`` +* ``InternalError`` +* ``InterruptedException`` +* ``Iterable`` +* ``LinkageError`` +* ``Long`` +* ``LongCache`` +* ``Math`` +* ``MathRand`` +* ``NegativeArraySizeException`` +* ``NoClassDefFoundError`` +* ``NoSuchFieldError`` +* ``NoSuchFieldException`` +* ``NoSuchMethodError`` +* ``NoSuchMethodException`` +* ``NullPointerException`` +* ``Number`` +* ``NumberFormatException`` +* ``OutOfMemoryError`` +* ``Process`` +* ``ProcessBuilder`` +* ``ProcessBuilder.Redirect`` +* ``ProcessBuilder.Redirect.Type`` +* ``Readable`` +* ``ReflectiveOperationException`` +* ``RejectedExecutionException`` +* ``Runnable`` +* ``Runtime`` +* ``RuntimeException`` +* ``SecurityException`` +* ``Short`` +* ``StackOverflowError`` +* ``StackTrace`` +* ``StackTraceElement`` +* ``String`` +* ``StringBuffer`` +* ``StringBuilder`` +* ``StringIndexOutOfBoundsException`` +* ``System`` +* ``Thread`` +* ``Thread.UncaughtExceptionHandler`` +* ``ThreadDeath`` +* ``ThreadLocal`` +* ``Throwable`` +* ``TypeNotPresentException`` +* ``UnknownError`` +* ``UnsatisfiedLinkError`` +* ``UnsupportedClassVersionError`` +* ``UnsupportedOperationException`` +* ``VerifyError`` +* ``VirtualMachineError`` +* ``Void`` +* ``annotation.Annotation`` +* ``annotation.Retention`` +* ``annotation.RetentionPolicy`` +* ``constant.Constable`` +* ``constant.ConstantDesc`` +* ``ref.PhantomReference`` +* ``ref.Reference`` +* ``ref.ReferenceQueue`` +* ``ref.SoftReference`` +* ``ref.WeakReference`` +* ``reflect.AccessibleObject`` +* ``reflect.Array`` +* ``reflect.Constructor`` +* ``reflect.Executable`` +* ``reflect.Field`` +* ``reflect.InvocationTargetException`` +* ``reflect.Method`` +* ``reflect.UndeclaredThrowableException`` + +java.math +""""""""" +* ``BigDecimal`` +* ``BigInteger`` +* ``BitLevel`` +* ``Conversion`` +* ``Division`` +* ``Elementary`` +* ``Logical`` +* ``MathContext`` +* ``Multiplication`` +* ``Primality`` +* ``RoundingMode`` + +java.net +"""""""" +* ``BindException`` +* ``ConnectException`` +* ``Inet4Address`` +* ``Inet6Address`` +* ``InetAddress`` +* ``InetAddressBase`` +* ``InetSocketAddress`` +* ``MalformedURLException`` +* ``NoRouteToHostException`` +* ``PortUnreachableException`` +* ``ServerSocket`` +* ``Socket`` +* ``SocketAddress`` +* ``SocketException`` +* ``SocketImpl`` +* ``SocketInputStream`` +* ``SocketOption`` +* ``SocketOptions`` +* ``SocketOutputStream`` +* ``SocketTimeoutException`` +* ``URI`` +* ``URIEncoderDecoder`` +* ``URISyntaxException`` +* ``URL`` +* ``URLClassLoader`` +* ``URLConnection`` +* ``URLDecoder`` +* ``URLEncoder`` +* ``UnknownHostException`` +* ``UnknownServiceException`` + +java.nio +""""""""" +* ``Buffer`` +* ``BufferOverflowException`` +* ``BufferUnderflowException`` +* ``ByteBuffer`` +* ``ByteOrder`` +* ``CharBuffer`` +* ``DoubleBuffer`` +* ``FloatBuffer`` +* ``IntBuffer`` +* ``InvalidMarkException`` +* ``LongBuffer`` +* ``MappedByteBuffer`` +* ``ReadOnlyBufferException`` +* ``ShortBuffer`` +* ``channels.ByteChannel`` +* ``channels.Channel`` +* ``channels.Channels`` +* ``channels.ClosedChannelException`` +* ``channels.FileChannel`` +* ``channels.FileChannel.MapMode`` +* ``channels.FileLock`` +* ``channels.GatheringByteChannel`` +* ``channels.InterruptibleChannel`` +* ``channels.NonReadableChannelException`` +* ``channels.NonWritableChannelException`` +* ``channels.OverlappingFileLockException`` +* ``channels.ReadableByteChannel`` +* ``channels.ScatteringByteChannel`` +* ``channels.SeekableByteChannel`` +* ``channels.WritableByteChannel`` +* ``channels.spi.AbstractInterruptibleChannel`` +* ``charset.CharacterCodingException`` +* ``charset.Charset`` +* ``charset.CharsetDecoder`` +* ``charset.CharsetEncoder`` +* ``charset.CoderMalfunctionError`` +* ``charset.CoderResult`` +* ``charset.CodingErrorAction`` +* ``charset.IllegalCharsetNameException`` +* ``charset.MalformedInputException`` +* ``charset.StandardCharsets`` +* ``charset.UnmappableCharacterException`` +* ``charset.UnsupportedCharsetException`` +* ``file.AccessDeniedException`` +* ``file.CopyOption`` +* ``file.DirectoryIteratorException`` +* ``file.DirectoryNotEmptyException`` +* ``file.DirectoryStream`` +* ``file.DirectoryStream.Filter`` +* ``file.DirectoryStreamImpl`` +* ``file.FileAlreadyExistsException`` +* ``file.FileSystem`` +* ``file.FileSystemException`` +* ``file.FileSystemLoopException`` +* ``file.FileSystemNotFoundException`` +* ``file.FileSystems`` +* ``file.FileVisitOption`` +* ``file.FileVisitResult`` +* ``file.FileVisitor`` +* ``file.Files`` +* ``file.InvalidPathException`` +* ``file.LinkOption`` +* ``file.NoSuchFileException`` +* ``file.NotDirectoryException`` +* ``file.NotLinkException`` +* ``file.OpenOption`` +* ``file.Path`` +* ``file.PathMatcher`` +* ``file.Paths`` +* ``file.RegexPathMatcher`` +* ``file.SimpleFileVisitor`` +* ``file.StandardCopyOption`` +* ``file.StandardOpenOption`` +* ``file.StandardWatchEventKinds`` +* ``file.WatchEvent`` +* ``file.WatchEvent.Kind`` +* ``file.WatchEvent.Modifier`` +* ``file.WatchKey`` +* ``file.WatchService`` +* ``file.Watchable`` +* ``file.attribute.AclEntry`` +* ``file.attribute.AclFileAttributeView`` +* ``file.attribute.AttributeView`` +* ``file.attribute.BasicFileAttributeView`` +* ``file.attribute.BasicFileAttributes`` +* ``file.attribute.DosFileAttributeView`` +* ``file.attribute.DosFileAttributes`` +* ``file.attribute.FileAttribute`` +* ``file.attribute.FileAttributeView`` +* ``file.attribute.FileOwnerAttributeView`` +* ``file.attribute.FileStoreAttributeView`` +* ``file.attribute.FileTime`` +* ``file.attribute.GroupPrincipal`` +* ``file.attribute.PosixFileAttributeView`` +* ``file.attribute.PosixFileAttributes`` +* ``file.attribute.PosixFilePermission`` +* ``file.attribute.PosixFilePermissions`` +* ``file.attribute.UserDefinedFileAttributeView`` +* ``file.attribute.UserPrincipal`` +* ``file.attribute.UserPrincipalLookupService`` +* ``file.attribute.UserPrincipalNotFoundException`` +* ``file.spi.FileSystemProvider`` + +java.rmi +"""""""" +* ``Remote`` +* ``RemoteException`` + +java.security +""""""""""""" +* ``AccessControlException`` +* ``CodeSigner`` +* ``DummyMessageDigest`` +* ``GeneralSecurityException`` +* ``MessageDigest`` +* ``MessageDigestSpi`` +* ``NoSuchAlgorithmException`` +* ``Principal`` +* ``Timestamp`` +* ``TimestampConstructorHelper`` +* ``cert.CertPath`` +* ``cert.Certificate`` +* ``cert.CertificateEncodingException`` +* ``cert.CertificateException`` +* ``cert.CertificateFactory`` +* ``cert.X509Certificate`` +* ``cert.X509Extension`` + + +java.util +""""""""" +* ``AbstractCollection`` +* ``AbstractList`` +* ``AbstractListView`` +* ``AbstractMap`` +* ``AbstractMap.SimpleEntry`` +* ``AbstractMap.SimpleImmutableEntry`` +* ``AbstractQueue`` +* ``AbstractRandomAccessListIterator`` +* ``AbstractSequentialList`` +* ``AbstractSet`` +* ``ArrayDeque`` +* ``ArrayList`` +* ``Arrays`` +* ``BackedUpListIterator`` +* ``Base64`` +* ``Base64.Decoder`` +* ``Base64.Encoder`` +* ``BitSet`` +* ``Calendar`` +* ``Collection`` +* ``Collections`` +* ``Comparator`` +* ``ConcurrentModificationException`` +* ``Date`` +* ``Deque`` +* ``Dictionary`` +* ``DuplicateFormatFlagsException`` +* ``EmptyStackException`` +* ``EnumSet`` +* ``Enumeration`` +* ``FormatFlagsConversionMismatchException`` +* ``Formattable`` +* ``FormattableFlags`` +* ``Formatter`` +* ``Formatter.BigDecimalLayoutForm`` +* ``FormatterClosedException`` +* ``GregorianCalendar`` +* ``HashMap`` +* ``HashSet`` +* ``Hashtable`` +* ``IdentityHashMap`` +* ``IllegalFormatCodePointException`` +* ``IllegalFormatConversionException`` +* ``IllegalFormatException`` +* ``IllegalFormatFlagsException`` +* ``IllegalFormatPrecisionException`` +* ``IllegalFormatWidthException`` +* ``IllformedLocaleException`` +* ``InputMismatchException`` +* ``InvalidPropertiesFormatException`` +* ``Iterator`` +* ``LinkedHashMap`` +* ``LinkedHashSet`` +* ``LinkedList`` +* ``List`` +* ``ListIterator`` +* ``MissingFormatArgumentException`` +* ``MissingFormatWidthException`` +* ``MissingResourceException`` +* ``NavigableMap`` +* ``NavigableSet`` +* ``NoSuchElementException`` +* ``Objects`` +* ``Optional`` +* ``PriorityQueue`` +* ``Properties`` +* ``Queue`` +* ``Random`` +* ``RandomAccess`` +* ``RandomAccessListIterator`` +* ``ServiceConfigurationError`` +* ``Set`` +* ``SizeChangeEvent`` +* ``SortedMap`` +* ``SortedSet`` +* ``StringTokenizer`` +* ``TooManyListenersException`` +* ``TreeSet`` +* ``UUID`` +* ``UnknownFormatConversionException`` +* ``UnknownFormatFlagsException`` +* ``WeakHashMap`` +* ``concurrent.Callable`` +* ``concurrent.CancellationException`` +* ``concurrent.ConcurrentHashMap`` +* ``concurrent.ConcurrentHashMap.KeySetView`` +* ``concurrent.ConcurrentLinkedQueue`` +* ``concurrent.ConcurrentMap`` +* ``concurrent.ConcurrentSkipListSet`` +* ``concurrent.ExecutionException`` +* ``concurrent.Executor`` +* ``concurrent.RejectedExecutionException`` +* ``concurrent.Semaphore`` +* ``concurrent.ThreadFactory`` +* ``concurrent.ThreadLocalRandom`` +* ``concurrent.TimeUnit`` +* ``concurrent.TimeoutException`` +* ``concurrent.atomic.AtomicBoolean`` +* ``concurrent.atomic.AtomicInteger`` +* ``concurrent.atomic.AtomicLong`` +* ``concurrent.atomic.AtomicLongArray`` +* ``concurrent.atomic.AtomicReference`` +* ``concurrent.atomic.AtomicReferenceArray`` +* ``concurrent.atomic.LongAdder`` +* ``concurrent.locks.AbstractOwnableSynchronizer`` +* ``concurrent.locks.AbstractQueuedSynchronizer`` +* ``concurrent.locks.Lock`` +* ``concurrent.locks.ReentrantLock`` +* ``function.BiConsumer`` +* ``function.BiFunction`` +* ``function.BiPredicate`` +* ``function.BinaryOperator`` +* ``function.Consumer`` +* ``function.Function`` +* ``function.IntUnaryOperator`` +* ``function.Predicate`` +* ``function.Supplier`` +* ``function.UnaryOperator`` +* ``jar.Attributes`` +* ``jar.Attributes.Name`` +* ``jar.InitManifest`` +* ``jar.JarEntry`` +* ``jar.JarFile`` +* ``jar.JarInputStream`` +* ``jar.JarOutputStream`` +* ``jar.Manifest`` +* ``regex.MatchResult`` +* ``regex.Matcher`` +* ``regex.Pattern`` +* ``regex.PatternSyntaxException`` +* ``stream.BaseStream`` +* ``stream.CompositeStream`` +* ``stream.EmptyIterator`` +* ``stream.Stream`` +* ``stream.Stream.Builder`` +* ``zip.Adler32`` +* ``zip.CRC32`` +* ``zip.CheckedInputStream`` +* ``zip.CheckedOutputStream`` +* ``zip.Checksum`` +* ``zip.DataFormatException`` +* ``zip.Deflater`` +* ``zip.DeflaterOutputStream`` +* ``zip.GZIPInputStream`` +* ``zip.GZIPOutputStream`` +* ``zip.Inflater`` +* ``zip.InflaterInputStream`` +* ``zip.ZipConstants`` +* ``zip.ZipEntry`` +* ``zip.ZipException`` +* ``zip.ZipFile`` +* ``zip.ZipInputStream`` +* ``zip.ZipOutputStream`` + + **Note:** This is an ongoing effort, some of the classes listed here might be partially implemented. Please consult `javalib sources `_ diff --git a/scripts/javalib.py b/scripts/javalib.py deleted file mode 100644 index 6d085e7dd2..0000000000 --- a/scripts/javalib.py +++ /dev/null @@ -1,22 +0,0 @@ -""" - Utility that lists all non-implementation specific classes in javalib. - - It must be run from the root of the Scala Native checkout. -""" - -import subprocess,os - -cwd = os.getcwd() - -target = cwd + "/javalib/.2.12/target/scala-2.12/classes/" - -paths = subprocess.check_output(["find", target, "-name", "*.nir"]) - -classes = sorted(list(set( - line.replace(target, "").replace(".nir", "").lstrip("/").rstrip("$").replace("/", ".") - for line in paths.split("\n") - if "$$anon" not in line and "java/" in line -))) - -for cls in classes: - print("* ``{}``".format(cls)) From 0ee3c4922c188bd8feb479fcf21365726bd9b826 Mon Sep 17 00:00:00 2001 From: LeeTibbert Date: Wed, 21 Dec 2022 11:55:40 -0500 Subject: [PATCH 22/64] Implement posixlib langinfo.h & nl_types.h on Unix (#3044) * Implement posixlib langinfo & nl_types on Unix * Fix Windows defect(s) * Add LanginfoTest (cherry picked from commit 29cad8b0f7ad102b1a9b819930aac72bb2189318) --- docs/lib/posixlib.rst | 6 +- .../main/resources/scala-native/langinfo.c | 174 ++++++++++++++++ .../main/resources/scala-native/nl_types.c | 14 ++ .../scala/scalanative/posix/langinfo.scala | 190 ++++++++++++++++++ .../scala/scalanative/posix/nl_types.scala | 38 ++++ .../scalanative/posix/LanginfoTest.scala | 175 ++++++++++++++++ 6 files changed, 595 insertions(+), 2 deletions(-) create mode 100644 posixlib/src/main/resources/scala-native/langinfo.c create mode 100644 posixlib/src/main/resources/scala-native/nl_types.c create mode 100644 posixlib/src/main/scala/scala/scalanative/posix/langinfo.scala create mode 100644 posixlib/src/main/scala/scala/scalanative/posix/nl_types.scala create mode 100644 unit-tests/native/src/test/scala/scala/scalanative/posix/LanginfoTest.scala diff --git a/docs/lib/posixlib.rst b/docs/lib/posixlib.rst index c9a7567e2a..cd54ee6784 100644 --- a/docs/lib/posixlib.rst +++ b/docs/lib/posixlib.rst @@ -30,7 +30,7 @@ C Header Scala Native Module `iconv.h`_ N/A `inttypes.h`_ scala.scalanative.posix.inttypes_ `iso646.h`_ N/A -`langinfo.h`_ N/A +`langinfo.h`_ scala.scalanative.posix.langinfo_ `libgen.h`_ scala.scalanative.posix.libgen_ `limits.h`_ scala.scalanative.posix.limits_ `locale.h`_ N/A @@ -42,7 +42,7 @@ C Header Scala Native Module `netdb.h`_ scala.scalanative.posix.netdb_ `netinet/in.h`_ scala.scalanative.posix.netinet.in_ `netinet/tcp.h`_ scala.scalanative.posix.netinet.tcp_ -`nl_types.h`_ N/A +`nl_types.h`_ scala.scalanative.posix.nl_types_ `poll.h`_ scala.scalanative.posix.poll_ `pthread.h`_ scala.scalanative.posix.pthread_ `pwd.h`_ scala.scalanative.posix.pwd_ @@ -191,6 +191,7 @@ C Header Scala Native Module .. _scala.scalanative.posix.glob: https://github.com/scala-native/scala-native/blob/main/posixlib/src/main/scala/scala/scalanative/posix/glob.scala .. _scala.scalanative.posix.grp: https://github.com/scala-native/scala-native/blob/main/posixlib/src/main/scala/scala/scalanative/posix/grp.scala .. _scala.scalanative.posix.inttypes: https://github.com/scala-native/scala-native/blob/main/posixlib/src/main/scala/scala/scalanative/posix/inttypes.scala +.. _scala.scalanative.posix.langinfo: https://github.com/scala-native/scala-native/blob/main/posixlib/src/main/scala/scala/scalanative/posix/langinfo.scala .. _scala.scalanative.posix.limits: https://github.com/scala-native/scala-native/blob/main/posixlib/src/main/scala/scala/scalanative/posix/limits.scala .. _scala.scalanative.posix.libgen: https://github.com/scala-native/scala-native/blob/main/posixlib/src/main/scala/scala/scalanative/posix/libgen.scala .. _scala.scalanative.libc.math: https://github.com/scala-native/scala-native/blob/main/clib/src/main/scala/scala/scalanative/libc/math.scala @@ -199,6 +200,7 @@ C Header Scala Native Module .. _scala.scalanative.posix.netdb: https://github.com/scala-native/scala-native/blob/main/posixlib/src/main/scala/scala/scalanative/posix/netdb.scala .. _scala.scalanative.posix.netinet.in: https://github.com/scala-native/scala-native/blob/main/posixlib/src/main/scala/scala/scalanative/posix/netinet/in.scala .. _scala.scalanative.posix.netinet.tcp: https://github.com/scala-native/scala-native/blob/main/posixlib/src/main/scala/scala/scalanative/posix/netinet/tcp.scala +.. _scala.scalanative.posix.nl_types: https://github.com/scala-native/scala-native/blob/main/posixlib/src/main/scala/scala/scalanative/posix/nl_types.scala .. _scala.scalanative.posix.poll: https://github.com/scala-native/scala-native/blob/main/posixlib/src/main/scala/scala/scalanative/posix/poll.scala .. _scala.scalanative.posix.pthread: https://github.com/scala-native/scala-native/blob/main/posixlib/src/main/scala/scala/scalanative/posix/pthread.scala .. _scala.scalanative.posix.pwd: https://github.com/scala-native/scala-native/blob/main/posixlib/src/main/scala/scala/scalanative/posix/pwd.scala diff --git a/posixlib/src/main/resources/scala-native/langinfo.c b/posixlib/src/main/resources/scala-native/langinfo.c new file mode 100644 index 0000000000..dd8fe245f6 --- /dev/null +++ b/posixlib/src/main/resources/scala-native/langinfo.c @@ -0,0 +1,174 @@ +#if defined(__unix__) || defined(__unix) || defined(unix) || \ + (defined(__APPLE__) && defined(__MACH__)) + +#include + +#endif // Unix or Mac OS + +#if defined(_WIN32) // bogus values to keep compiler happy +#define CODESET -1 +#define D_T_FMT -1 +#define D_FMT -1 +#define T_FMT -1 +#define T_FMT_AMPM -1 +#define AM_STR -1 +#define PM_STR -1 +#define DAY_1 -1 +#define DAY_2 -1 +#define DAY_3 -1 +#define DAY_4 -1 +#define DAY_5 -1 +#define DAY_6 -1 +#define DAY_7 -1 +#define ABDAY_1 -1 +#define ABDAY_2 -1 +#define ABDAY_3 -1 +#define ABDAY_4 -1 +#define ABDAY_5 -1 +#define ABDAY_6 -1 +#define ABDAY_7 -1 +#define MON_1 -1 +#define MON_2 -1 +#define MON_3 -1 +#define MON_4 -1 +#define MON_5 -1 +#define MON_6 -1 +#define MON_7 -1 +#define MON_8 -1 +#define MON_9 -1 +#define MON_10 -1 +#define MON_11 -1 +#define MON_12 -1 +#define ABMON_1 -1 +#define ABMON_2 -1 +#define ABMON_3 -1 +#define ABMON_4 -1 +#define ABMON_5 -1 +#define ABMON_6 -1 +#define ABMON_7 -1 +#define ABMON_8 -1 +#define ABMON_9 -1 +#define ABMON_10 -1 +#define ABMON_11 -1 +#define ABMON_12 -1 +#define ERA -1 +#define ERA_D_FMT -1 +#define ERA_D_T_FMT -1 +#define ERA_T_FMT -1 +#define ALT_DIGITS -1 +#define RADIXCHAR -1 +#define THOUSEP -1 +#define YESEXPR -1 +#define NOEXPR -1 +#define CRNCYSTR -1 +#endif // _WIN32 + +int scalanative_codeset() { return CODESET; }; + +int scalanative_d_t_fmt() { return D_T_FMT; }; + +int scalanative_d_fmt() { return D_FMT; }; + +int scalanative_t_fmt() { return T_FMT; }; + +int scalanative_t_fmt_ampm() { return T_FMT_AMPM; }; + +int scalanative_am_str() { return AM_STR; }; + +int scalanative_pm_str() { return PM_STR; }; + +int scalanative_day_1() { return DAY_1; }; + +int scalanative_day_2() { return DAY_2; }; + +int scalanative_day_3() { return DAY_3; }; + +int scalanative_day_4() { return DAY_4; }; + +int scalanative_day_5() { return DAY_5; }; + +int scalanative_day_6() { return DAY_6; }; + +int scalanative_day_7() { return DAY_7; }; + +int scalanative_abday_1() { return ABDAY_1; }; + +int scalanative_abday_2() { return ABDAY_2; }; + +int scalanative_abday_3() { return ABDAY_3; }; + +int scalanative_abday_4() { return ABDAY_4; }; + +int scalanative_abday_5() { return ABDAY_5; }; + +int scalanative_abday_6() { return ABDAY_6; }; + +int scalanative_abday_7() { return ABDAY_7; }; + +int scalanative_mon_1() { return MON_1; }; + +int scalanative_mon_2() { return MON_2; }; + +int scalanative_mon_3() { return MON_3; }; + +int scalanative_mon_4() { return MON_4; }; + +int scalanative_mon_5() { return MON_5; }; + +int scalanative_mon_6() { return MON_6; }; + +int scalanative_mon_7() { return MON_7; }; + +int scalanative_mon_8() { return MON_8; }; + +int scalanative_mon_9() { return MON_9; }; + +int scalanative_mon_10() { return MON_10; }; + +int scalanative_mon_11() { return MON_11; }; + +int scalanative_mon_12() { return MON_12; }; + +int scalanative_abmon_1() { return ABMON_1; }; + +int scalanative_abmon_2() { return ABMON_2; }; + +int scalanative_abmon_3() { return ABMON_3; }; + +int scalanative_abmon_4() { return ABMON_4; }; + +int scalanative_abmon_5() { return ABMON_5; }; + +int scalanative_abmon_6() { return ABMON_6; }; + +int scalanative_abmon_7() { return ABMON_7; }; + +int scalanative_abmon_8() { return ABMON_8; }; + +int scalanative_abmon_9() { return ABMON_9; }; + +int scalanative_abmon_10() { return ABMON_10; }; + +int scalanative_abmon_11() { return ABMON_11; }; + +int scalanative_abmon_12() { return ABMON_12; }; + +int scalanative_era() { return ERA; }; + +int scalanative_era_d_fmt() { return ERA_D_FMT; }; + +int scalanative_era_d_t_fmt() { return ERA_D_T_FMT; }; + +int scalanative_era_t_fmt() { return ERA_T_FMT; }; + +int scalanative_alt_digits() { return ALT_DIGITS; }; + +int scalanative_radixchar() { return RADIXCHAR; }; + +int scalanative_thousep() { return THOUSEP; }; + +int scalanative_yesexpr() { return YESEXPR; }; + +int scalanative_noexpr() { return NOEXPR; }; + +int scalanative_crncystr() { return CRNCYSTR; }; diff --git a/posixlib/src/main/resources/scala-native/nl_types.c b/posixlib/src/main/resources/scala-native/nl_types.c new file mode 100644 index 0000000000..83c80ea94e --- /dev/null +++ b/posixlib/src/main/resources/scala-native/nl_types.c @@ -0,0 +1,14 @@ +#if defined(__unix__) || defined(__unix) || defined(unix) || \ + (defined(__APPLE__) && defined(__MACH__)) + +#include + +#endif // Unix or Mac OS + +#if defined(_WIN32) // bogus values to keep linker happy +#define NL_SETD -1 +#define NL_CAT_LOCALE -1 +#endif // _WIN32 + +int scalanative_nl_setd() { return NL_SETD; }; +int scalanative_nl_cat_locale() { return NL_CAT_LOCALE; }; diff --git a/posixlib/src/main/scala/scala/scalanative/posix/langinfo.scala b/posixlib/src/main/scala/scala/scalanative/posix/langinfo.scala new file mode 100644 index 0000000000..cc9a1fe062 --- /dev/null +++ b/posixlib/src/main/scala/scala/scalanative/posix/langinfo.scala @@ -0,0 +1,190 @@ +package scala.scalanative +package posix + +import scala.scalanative.unsafe._ + +/** POSIX langinfo.h for Scala + * + * The Open Group Base Specifications + * [[https://pubs.opengroup.org/onlinepubs/9699919799 Issue 7, 2018]] edition. + */ + +@extern object langinfo { + + type locale_t = locale.locale_t + + type nl_item = nl_types.nl_item + +// Symbolic constants + + @name("scalanative_codeset") + def CODESET: CInt = extern + + @name("scalanative_d_t_fmt") + def D_T_FMT: CInt = extern + + @name("scalanative_d_fmt") + def D_FMT: CInt = extern + + @name("scalanative_t_fmt") + def T_FMT: CInt = extern + + @name("scalanative_t_fmt_ampm") + def T_FMT_AMPM: CInt = extern + + @name("scalanative_am_str") + def AM_STR: CInt = extern + + @name("scalanative_pm_str") + def PM_STR: CInt = extern + + @name("scalanative_day_1") + def DAY_1: CInt = extern + + @name("scalanative_day_2") + def DAY_2: CInt = extern + + @name("scalanative_day_3") + def DAY_3: CInt = extern + + @name("scalanative_day_4") + def DAY_4: CInt = extern + + @name("scalanative_day_5") + def DAY_5: CInt = extern + + @name("scalanative_day_6") + def DAY_6: CInt = extern + + @name("scalanative_day_7") + def DAY_7: CInt = extern + + @name("scalanative_abday_1") + def ABDAY_1: CInt = extern + + @name("scalanative_abday_2") + def ABDAY_2: CInt = extern + + @name("scalanative_abday_3") + def ABDAY_3: CInt = extern + + @name("scalanative_abday_4") + def ABDAY_4: CInt = extern + + @name("scalanative_abday_5") + def ABDAY_5: CInt = extern + + @name("scalanative_abday_6") + def ABDAY_6: CInt = extern + + @name("scalanative_abday_7") + def ABDAY_7: CInt = extern + + @name("scalanative_mon_1") + def MON_1: CInt = extern + + @name("scalanative_mon_2") + def MON_2: CInt = extern + + @name("scalanative_mon_3") + def MON_3: CInt = extern + + @name("scalanative_mon_4") + def MON_4: CInt = extern + + @name("scalanative_mon_5") + def MON_5: CInt = extern + + @name("scalanative_mon_6") + def MON_6: CInt = extern + + @name("scalanative_mon_7") + def MON_7: CInt = extern + + @name("scalanative_mon_8") + def MON_8: CInt = extern + + @name("scalanative_mon_9") + def MON_9: CInt = extern + + @name("scalanative_mon_10") + def MON_10: CInt = extern + + @name("scalanative_mon_11") + def MON_11: CInt = extern + + @name("scalanative_mon_12") + def MON_12: CInt = extern + + @name("scalanative_abmon_1") + def ABMON_1: CInt = extern + + @name("scalanative_abmon_2") + def ABMON_2: CInt = extern + + @name("scalanative_abmon_3") + def ABMON_3: CInt = extern + + @name("scalanative_abmon_4") + def ABMON_4: CInt = extern + + @name("scalanative_abmon_5") + def ABMON_5: CInt = extern + + @name("scalanative_abmon_6") + def ABMON_6: CInt = extern + + @name("scalanative_abmon_7") + def ABMON_7: CInt = extern + + @name("scalanative_abmon_8") + def ABMON_8: CInt = extern + + @name("scalanative_abmon_9") + def ABMON_9: CInt = extern + + @name("scalanative_abmon_10") + def ABMON_10: CInt = extern + + @name("scalanative_abmon_11") + def ABMON_11: CInt = extern + + @name("scalanative_abmon_12") + def ABMON_12: CInt = extern + + @name("scalanative_era") + def ERA: CInt = extern + + @name("scalanative_era_d_fmt") + def ERA_D_FMT: CInt = extern + + @name("scalanative_era_d_t_fmt") + def ERA_D_T_FMT: CInt = extern + + @name("scalanative_era_t_fmt") + def ERA_T_FMT: CInt = extern + + @name("scalanative_alt_digits") + def ALT_DIGITS: CInt = extern + + @name("scalanative_radixchar") + def RADIXCHAR: CInt = extern + + @name("scalanative_thousep") + def THOUSEP: CInt = extern + + @name("scalanative_yesexpr") + def YESEXPR: CInt = extern + + @name("scalanative_noexpr") + def NOEXPR: CInt = extern + + @name("scalanative_crncystr") + def CRNCYSTR: CInt = extern + +// Methods + + def nl_langinfo(item: nl_item): CString = extern + + def nl_langinfo_l(item: nl_item, locale: locale_t): CString = extern +} diff --git a/posixlib/src/main/scala/scala/scalanative/posix/nl_types.scala b/posixlib/src/main/scala/scala/scalanative/posix/nl_types.scala new file mode 100644 index 0000000000..a9c8ff1a93 --- /dev/null +++ b/posixlib/src/main/scala/scala/scalanative/posix/nl_types.scala @@ -0,0 +1,38 @@ +package scala.scalanative +package posix + +import scala.scalanative.unsafe._ + +/** POSIX nl_types.h for Scala + * + * The Open Group Base Specifications + * [[https://pubs.opengroup.org/onlinepubs/9699919799 Issue 7, 2018]] edition. + */ + +@extern object nl_types { + + type nl_catd = Ptr[Byte] // Scala Native idiom for void *. + + type nl_item = CInt + +// Symbolic constants + + @name("scalanative_nl_setd") + def NL_SETD: CInt = extern + + @name("scalanative_nl_cat_locale") + def NL_CAT_LOCALE: CInt = extern + +// Methods + + def catclose(catalog: nl_catd): CInt = extern + + def catgets( + catalog: nl_catd, + setNumber: CInt, + messageNumber: CInt, + message: CString + ): CString = extern + + def catopen(name: CString, flag: CInt): nl_catd = extern +} diff --git a/unit-tests/native/src/test/scala/scala/scalanative/posix/LanginfoTest.scala b/unit-tests/native/src/test/scala/scala/scalanative/posix/LanginfoTest.scala new file mode 100644 index 0000000000..3ce2b8d44d --- /dev/null +++ b/unit-tests/native/src/test/scala/scala/scalanative/posix/LanginfoTest.scala @@ -0,0 +1,175 @@ +package scala.scalanative.posixlib + +import org.junit.Test +import org.junit.Assert._ +import org.junit.Assume._ +import org.junit.{BeforeClass, AfterClass} + +import scala.scalanative.meta.LinktimeInfo.{isLinux, isMac, isWindows} + +import scala.scalanative.unsafe._ +import scala.scalanative.unsigned._ + +import scala.scalanative.posix.langinfo._ +import scala.scalanative.posix.locale.{setlocale, LC_ALL} +import scala.scalanative.posix.stdlib +import scala.scalanative.posix.string + +object LanginfoTest { + private var savedLocale: Option[CString] = None + + @BeforeClass + def beforeClass(): Unit = { + if (!isWindows) { + val entryLocale = setlocale(LC_ALL, null) + assertNotNull( + "setlocale() could not determine locale at start of test.", + entryLocale + ) + + // Save before setlocale() calls overwrite static buffer returned. + savedLocale = Some(string.strdup(entryLocale)) // note: no CString + + /* Require a known locale in order to simplify CI testing. + * "soft fail" is the locale is not available, such as in the wild. + */ + + val requiredLocale = if (isLinux) c"en_US.utf8" else c"en_US.UTF-8" + + if (setlocale(LC_ALL, requiredLocale) == null) + savedLocale = None // Oops, no change! Nothing to restore. Fail later. + } + } + + @AfterClass + def afterClass(): Unit = { + if (!isWindows) { + savedLocale.map { sl => + // Restore Locale as recorded on entry. + val restoredLocale = setlocale(LC_ALL, sl) + + stdlib.free(sl) + + if (restoredLocale == null) + fail("setlocale() was unable to restore the locale.") + } + } + } +} + +/* Can't tell the players without a program or this legend. + * The testing matrix is complex because locales and their configurations are + * highly variable. + * + * Testing is done on Linux & macOS when the required en_US.utf8 (Linux) or + * en_US.UTF-8 locale is available. + * + * - No testing at all is done on Windows (because not implemented). + * - The testing on CI multiarch machines "soft fails" because the + * required locale is not available. + * - No os specific testing is done on FreeBSD, for want of a suitable + * validation environment. + */ + +class LanginfoTest { + + case class LanginfoItem(name: String, code: nl_item, expected: String) + + def verify(item: LanginfoItem): Unit = { + assertEquals( + s"${item.name}", + item.expected, + fromCString(nl_langinfo(item.code)) + ) + } + + @Test def langinfo_Using_en_US_UTF8(): Unit = { + assumeTrue( + "langinfo.scala is not implemented on Windows", + !isWindows + ) + + /* Warn here instead of doing a hard fail. + * Multi-arch CI tests do not have an en_US locale. + * This may also be true of non-CI systems in the wild. + */ + assumeTrue( + "setlocale() failed to set an en_US.[utf8|UTF-8] test locale", + LanginfoTest.savedLocale.isDefined + ) + + if (!isWindows) { + val osSharedItems = Array( + LanginfoItem("CODESET", CODESET, "UTF-8"), + LanginfoItem("D_FMT", D_FMT, "%m/%d/%Y"), + LanginfoItem("T_FMT_AMPM", T_FMT_AMPM, "%I:%M:%S %p"), + LanginfoItem("AM_STR", AM_STR, "AM"), + LanginfoItem("PM_STR", PM_STR, "PM"), + LanginfoItem("DAY_1", DAY_1, "Sunday"), + LanginfoItem("DAY_2", DAY_2, "Monday"), + LanginfoItem("DAY_3", DAY_3, "Tuesday"), + LanginfoItem("DAY_4", DAY_4, "Wednesday"), + LanginfoItem("DAY_5", DAY_5, "Thursday"), + LanginfoItem("DAY_6", DAY_6, "Friday"), + LanginfoItem("DAY_7", DAY_7, "Saturday"), + LanginfoItem("ABDAY_1", ABDAY_1, "Sun"), + LanginfoItem("ABDAY_2", ABDAY_2, "Mon"), + LanginfoItem("ABDAY_3", ABDAY_3, "Tue"), + LanginfoItem("ABDAY_4", ABDAY_4, "Wed"), + LanginfoItem("ABDAY_5", ABDAY_5, "Thu"), + LanginfoItem("ABDAY_6", ABDAY_6, "Fri"), + LanginfoItem("ABDAY_7", ABDAY_7, "Sat"), + LanginfoItem("MON_1", MON_1, "January"), + LanginfoItem("MON_2", MON_2, "February"), + LanginfoItem("MON_3", MON_3, "March"), + LanginfoItem("MON_4", MON_4, "April"), + LanginfoItem("MON_5", MON_5, "May"), + LanginfoItem("MON_6", MON_6, "June"), + LanginfoItem("MON_7", MON_7, "July"), + LanginfoItem("MON_8", MON_8, "August"), + LanginfoItem("MON_9", MON_9, "September"), + LanginfoItem("MON_10", MON_10, "October"), + LanginfoItem("MON_11", MON_11, "November"), + LanginfoItem("MON_12", MON_12, "December"), + LanginfoItem("ABMON_1", ABMON_1, "Jan"), + LanginfoItem("ABMON_2", ABMON_2, "Feb"), + LanginfoItem("ABMON_3", ABMON_3, "Mar"), + LanginfoItem("ABMON_4", ABMON_4, "Apr"), + LanginfoItem("ABMON_5", ABMON_5, "May"), + LanginfoItem("ABMON_6", ABMON_6, "Jun"), + LanginfoItem("ABMON_7", ABMON_7, "Jul"), + LanginfoItem("ABMON_8", ABMON_8, "Aug"), + LanginfoItem("ABMON_9", ABMON_9, "Sep"), + LanginfoItem("ABMON_10", ABMON_10, "Oct"), + LanginfoItem("ABMON_11", ABMON_11, "Nov"), + LanginfoItem("ABMON_12", ABMON_12, "Dec"), + LanginfoItem("ERA", ERA, ""), + LanginfoItem("ERA_D_FMT", ERA_D_FMT, ""), + LanginfoItem("ERA_D_T_FMT", ERA_D_T_FMT, ""), + LanginfoItem("ERA_T_FMT", ERA_T_FMT, ""), + LanginfoItem("ALT_DIGITS", ALT_DIGITS, ""), + LanginfoItem("RADIXCHAR", RADIXCHAR, "."), + LanginfoItem("THOUSEP", THOUSEP, ","), // linux + LanginfoItem("CRNCYSTR", CRNCYSTR, "-$") + ) + + osSharedItems.foreach(verify(_)) + + if (isLinux) { + Array( + LanginfoItem("D_T_FMT", D_T_FMT, "%a %d %b %Y %r %Z"), + LanginfoItem("T_FMT", T_FMT, "%r"), + LanginfoItem("YESEXPR", YESEXPR, "^[+1yY]"), + LanginfoItem("NOEXPR", NOEXPR, "^[-0nN]") + ).foreach(verify(_)) + } else if (isMac) { + Array( + LanginfoItem("D_T_FMT", D_T_FMT, "%a %b %e %X %Y"), + LanginfoItem("T_FMT", T_FMT, "%H:%M:%S"), + LanginfoItem("YESEXPR", YESEXPR, "^[yYsS].*"), + LanginfoItem("NOEXPR", NOEXPR, "^[nN].*") + ).foreach(verify(_)) + } + } + } +} From 4373fd236765edadc1e39d107f1588126bc4fc35 Mon Sep 17 00:00:00 2001 From: Wojciech Mazur Date: Wed, 28 Dec 2022 00:00:16 +0100 Subject: [PATCH 23/64] Restore InetAddress fix for UnknownHostException (#3047) * Partial fix #3005: j.n.InetAddress now uses more UnknownHostExceptions (#3007) * Use integer value for ping -i argument Co-authored-by: LeeTibbert (cherry picked from commit 56c8b4eb9ed69f1d8ae3223d1548e803cf758c62) --- unit-tests/shared/src/test/scala/javalib/lang/ProcessTest.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unit-tests/shared/src/test/scala/javalib/lang/ProcessTest.scala b/unit-tests/shared/src/test/scala/javalib/lang/ProcessTest.scala index 64c129d469..683f936ad7 100644 --- a/unit-tests/shared/src/test/scala/javalib/lang/ProcessTest.scala +++ b/unit-tests/shared/src/test/scala/javalib/lang/ProcessTest.scala @@ -219,7 +219,7 @@ class ProcessTest { * in 10 seconds. When either SIGTERM or SIGKILL arrives, only the * necessary minimum time will have actually been taken. */ - val proc = processForCommand("ping", "-c", "2", "-i", "10.0", "127.0.0.1") + val proc = processForCommand("ping", "-c", "2", "-i", "10", "127.0.0.1") .start() // When process has produced a byte of output, it should be past 'exec'. From 334fd2bbb090d0071085e936ef9e064f71e4cc61 Mon Sep 17 00:00:00 2001 From: Wojciech Mazur Date: Thu, 29 Dec 2022 00:05:45 +0100 Subject: [PATCH 24/64] Allow to use inherited `org.junit.{Aftter,Before}Class` methods (#3055) * Allow usage of @{Before,After}Class annotations defined in parents * Restore running junitOutput tests * Restore removed deprecated org.junit.Assert methods * Revert spurious changes (cherry picked from commit 26a439ec01a953faec7216361d0579b4133cd647) --- .../junit/plugin/ScalaNativeJUnitPlugin.scala | 30 +++++++--- .../ScalaNativeJUnitBootstrappers.scala | 60 +++++++++++++++---- .../src/main/scala/org/junit/Assert.scala | 2 + .../BeforeAndAfterClassTestAssertions_.txt | 6 ++ .../BeforeAndAfterClassTestAssertions_a.txt | 6 ++ .../BeforeAndAfterClassTestAssertions_n.txt | 6 ++ .../BeforeAndAfterClassTestAssertions_na.txt | 6 ++ .../BeforeAndAfterClassTestAssertions_nv.txt | 6 ++ .../BeforeAndAfterClassTestAssertions_nva.txt | 6 ++ .../BeforeAndAfterClassTestAssertions_nvc.txt | 6 ++ ...BeforeAndAfterClassTestAssertions_nvca.txt | 6 ++ .../BeforeAndAfterClassTestAssertions_v.txt | 6 ++ .../BeforeAndAfterClassTestAssertions_va.txt | 6 ++ .../BeforeAndAfterClassTestAssertions_vc.txt | 6 ++ .../BeforeAndAfterClassTestAssertions_vs.txt | 6 ++ .../BeforeAndAfterClassTestAssertions_vsn.txt | 6 ++ .../scala/scalanative/junit/AsyncTest.scala | 6 +- .../junit/BeforeAndAfterClassTest.scala | 58 ++++++++++++++++++ .../scalanative/junit/utils/JUnitTest.scala | 10 ++-- project/Settings.scala | 4 +- 20 files changed, 220 insertions(+), 28 deletions(-) create mode 100644 junit-test/outputs/scala/scalanative/junit/BeforeAndAfterClassTestAssertions_.txt create mode 100644 junit-test/outputs/scala/scalanative/junit/BeforeAndAfterClassTestAssertions_a.txt create mode 100644 junit-test/outputs/scala/scalanative/junit/BeforeAndAfterClassTestAssertions_n.txt create mode 100644 junit-test/outputs/scala/scalanative/junit/BeforeAndAfterClassTestAssertions_na.txt create mode 100644 junit-test/outputs/scala/scalanative/junit/BeforeAndAfterClassTestAssertions_nv.txt create mode 100644 junit-test/outputs/scala/scalanative/junit/BeforeAndAfterClassTestAssertions_nva.txt create mode 100644 junit-test/outputs/scala/scalanative/junit/BeforeAndAfterClassTestAssertions_nvc.txt create mode 100644 junit-test/outputs/scala/scalanative/junit/BeforeAndAfterClassTestAssertions_nvca.txt create mode 100644 junit-test/outputs/scala/scalanative/junit/BeforeAndAfterClassTestAssertions_v.txt create mode 100644 junit-test/outputs/scala/scalanative/junit/BeforeAndAfterClassTestAssertions_va.txt create mode 100644 junit-test/outputs/scala/scalanative/junit/BeforeAndAfterClassTestAssertions_vc.txt create mode 100644 junit-test/outputs/scala/scalanative/junit/BeforeAndAfterClassTestAssertions_vs.txt create mode 100644 junit-test/outputs/scala/scalanative/junit/BeforeAndAfterClassTestAssertions_vsn.txt create mode 100644 junit-test/shared/src/test/scala/scala/scalanative/junit/BeforeAndAfterClassTest.scala diff --git a/junit-plugin/src/main/scala-2/scala/scalanative/junit/plugin/ScalaNativeJUnitPlugin.scala b/junit-plugin/src/main/scala-2/scala/scalanative/junit/plugin/ScalaNativeJUnitPlugin.scala index d27081bf31..b8955575c2 100644 --- a/junit-plugin/src/main/scala-2/scala/scalanative/junit/plugin/ScalaNativeJUnitPlugin.scala +++ b/junit-plugin/src/main/scala-2/scala/scalanative/junit/plugin/ScalaNativeJUnitPlugin.scala @@ -145,14 +145,16 @@ class ScalaNativeJUnitPlugin(val global: Global) extends NscPlugin { genCallOnModule( bootSym, Names.beforeClass, - testClass.companionModule, - JUnitAnnots.BeforeClass + testClass, + JUnitAnnots.BeforeClass, + callParentsFirst = true ), genCallOnModule( bootSym, Names.afterClass, - testClass.companionModule, - JUnitAnnots.AfterClass + testClass, + JUnitAnnots.AfterClass, + callParentsFirst = false ), genCallOnParam(bootSym, Names.before, testClass, JUnitAnnots.Before), genCallOnParam(bootSym, Names.after, testClass, JUnitAnnots.After), @@ -186,16 +188,28 @@ class ScalaNativeJUnitPlugin(val global: Global) extends NscPlugin { private def genCallOnModule( owner: ClassSymbol, name: TermName, - module: Symbol, - annot: Symbol + testClass: Symbol, + annot: Symbol, + callParentsFirst: Boolean ): DefDef = { val sym = owner.newMethodSymbol(name) sym.setInfoAndEnter(MethodType(Nil, definitions.UnitTpe)) + val symbols = { + val all = (testClass :: testClass.ancestors) + if (callParentsFirst) all.reverse + else all + } + + // Filter out annotations found in the companion of trait for compliance with the JVM val (publicCalls, nonPublicCalls) = - annotatedMethods(module, annot).partition(_.isPublic) + symbols + .filterNot(_.isTraitOrInterface) + .flatMap(sym => annotatedMethods(sym.companionModule, annot)) + .partition(_.isPublic) if (nonPublicCalls.nonEmpty) { + val module = testClass.companionModule.orElse(testClass) globalError( pos = module.pos, s"Methods marked with ${annot.nameString} annotation in $module must be public" @@ -203,7 +217,7 @@ class ScalaNativeJUnitPlugin(val global: Global) extends NscPlugin { } val calls = publicCalls - .map(gen.mkMethodCall(Ident(module), _, Nil, Nil)) + .map(gen.mkMethodCall(_, Nil, Nil)) .toList typer.typedDefDef(newDefDef(sym, Block(calls: _*))()) diff --git a/junit-plugin/src/main/scala-3/scala/scalanative/junit/plugin/ScalaNativeJUnitBootstrappers.scala b/junit-plugin/src/main/scala-3/scala/scalanative/junit/plugin/ScalaNativeJUnitBootstrappers.scala index c0d91636bf..f2f478499e 100644 --- a/junit-plugin/src/main/scala-3/scala/scalanative/junit/plugin/ScalaNativeJUnitBootstrappers.scala +++ b/junit-plugin/src/main/scala-3/scala/scalanative/junit/plugin/ScalaNativeJUnitBootstrappers.scala @@ -103,14 +103,16 @@ class ScalaNativeJUnitBootstrappers extends PluginPhase { genCallOnModule( classSym, junitNme.beforeClass, - testClass.companionModule, - junitdefn.BeforeClassAnnotClass + testClass, + junitdefn.BeforeClassAnnotClass, + callParentsFirst = true ), genCallOnModule( classSym, junitNme.afterClass, - testClass.companionModule, - junitdefn.AfterClassAnnotClass + testClass, + junitdefn.AfterClassAnnotClass, + callParentsFirst = false ), genCallOnParam( classSym, @@ -152,8 +154,9 @@ class ScalaNativeJUnitBootstrappers extends PluginPhase { private def genCallOnModule( owner: ClassSymbol, name: TermName, - module: Symbol, - annot: Symbol + testClass: Symbol, + annot: Symbol, + callParentsFirst: Boolean )(using Context): DefDef = { val sym = newSymbol( owner, @@ -162,15 +165,48 @@ class ScalaNativeJUnitBootstrappers extends PluginPhase { MethodType(Nil, Nil, defn.UnitType) ).entered + extension (sym: Symbol) + def isTraitOrInterface: Boolean = + sym.is(Trait) || sym.isAllOf(JavaInterface) + DefDef( sym, { - if (module.exists) { - val calls = annotatedMethods(module.moduleClass.asClass, annot) - .map(m => Apply(ref(module).select(m), Nil)) - Block(calls, unitLiteral) - } else { - unitLiteral + val allParents = List + .unfold(testClass.info.parents) { parents => + parents.flatMap(_.parents) match { + case Nil => None + case next => Some((parents ::: next), next) + } + } + .flatten + .distinct + + val symbols = { + val all = testClass.info :: allParents + if callParentsFirst then all.reverse else all } + + // Filter out annotations found in the companion of trait for compliance with the JVM + val (publicCalls, nonPublicCalls) = + symbols + .filterNot(_.classSymbol.isTraitOrInterface) + .map(_.classSymbol.companionModule) + .filter(_.exists) + .flatMap(s => annotatedMethods(s.moduleClass.asClass, annot)) + .partition(_.isPublic) + + if (nonPublicCalls.nonEmpty) { + val module = testClass.companionModule.orElse(testClass) + report.error( + s"Methods marked with ${annot.showName} annotation in $module must be public", + module.orElse(owner).srcPos + ) + } + + Block( + publicCalls.map(m => Apply(ref(m), Nil)), + unitLiteral + ) } ) } diff --git a/junit-runtime/src/main/scala/org/junit/Assert.scala b/junit-runtime/src/main/scala/org/junit/Assert.scala index 74762f5568..257fe97482 100644 --- a/junit-runtime/src/main/scala/org/junit/Assert.scala +++ b/junit-runtime/src/main/scala/org/junit/Assert.scala @@ -110,6 +110,7 @@ object Assert { def assertNotEquals(unexpected: Float, actual: Float, delta: Float): Unit = assertNotEquals(null, unexpected, actual, delta) + // This deprecation should not be removed, it mapping the deprecation in the JUnit library to match bevaiour on the JVM @deprecated( "Use assertEquals(double expected, double actual, double " + "epsilon) instead", @@ -123,6 +124,7 @@ object Assert { ) } + // This deprecation should not be removed, it mapping the deprecation in the JUnit library to match bevaiour on the JVM @deprecated( "Use assertEquals(String message, double expected, double " + "actual, double epsilon) instead", diff --git a/junit-test/outputs/scala/scalanative/junit/BeforeAndAfterClassTestAssertions_.txt b/junit-test/outputs/scala/scalanative/junit/BeforeAndAfterClassTestAssertions_.txt new file mode 100644 index 0000000000..2a6fa2cfb0 --- /dev/null +++ b/junit-test/outputs/scala/scalanative/junit/BeforeAndAfterClassTestAssertions_.txt @@ -0,0 +1,6 @@ +ldTest run started +ldTest scala.scalanative.junit.BeforeAndAfterClassTest.test started +ldTest scala.scalanative.junit.BeforeAndAfterClassTest.test finished, took